home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckv211.zip / ckctel.c < prev    next >
C/C++ Source or Header  |  2004-03-14  |  302KB  |  8,947 lines

  1. char *cktelv = "Telnet support, 8.0.269, 4 Mar 2004";
  2. #define CKCTEL_C
  3.  
  4. int sstelnet = 0;                       /* Do server-side Telnet negotiation */
  5.  
  6. /*  C K C T E L  --  Telnet support  */
  7.  
  8. /*
  9.   Authors:
  10.     Telnet protocol by Frank da Cruz and Jeffrey Altman.
  11.     Telnet Forward X by Jeffrey Altman
  12.     Telnet START_TLS support by Jeffrey Altman
  13.     Telnet AUTH and ENCRYPT support by Jeffrey Altman
  14.     Telnet COMPORT support by Jeffrey Altman
  15.     Telnet NEW-ENVIRONMENT support by Jeffrey Altman
  16.     Telnet NAWS support by Frank da Cruz and Jeffrey Altman
  17.     Telnet TERMTYPE support by Jeffrey Altman
  18.     Telnet KERMIT support by Jeffrey Altman
  19.     Other contributions as indicated in the code.
  20.  
  21.   Copyright (C) 1985, 2004,
  22.     Trustees of Columbia University in the City of New York.
  23.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  24.     copyright text in the ckcmai.c module for disclaimer and permissions.
  25. */
  26.  
  27. /*
  28.   NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
  29.   C-Kermit source files, must be compatible with C preprocessors that support
  30.   only #ifdef, #else, #endif, #define, and #undef.  Please do not use #if,
  31.   logical operators, or other preprocessor features in this module.  Also,
  32.   don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
  33. */
  34.  
  35. #include "ckcsym.h"
  36. #include "ckcdeb.h"
  37.  
  38. #ifdef TNCODE
  39. #include "ckcker.h"
  40. #define TELCMDS                         /* to define name array */
  41. #define TELOPTS                         /* to define name array */
  42. #define SLC_NAMES                       /* to define name array */
  43. #define ENCRYPT_NAMES
  44. #define AUTH_NAMES
  45. #define TELOPT_STATES
  46. #define TELOPT_MODES
  47. #define TNC_NAMES
  48. #include "ckcnet.h"
  49. #include "ckctel.h"
  50. #ifdef CK_AUTHENTICATION
  51. #include "ckuath.h"
  52. #endif /* CK_AUTHENTICATION */
  53. #ifdef CK_SSL
  54. #include "ck_ssl.h"
  55. #endif /* CK_SSL */
  56.  
  57. #ifndef NOTERM
  58. #ifdef OS2                              /* For terminal type name string */
  59. #include "ckuusr.h"
  60. #ifndef NT
  61. #include <os2.h>
  62. #undef COMMENT
  63. #else
  64. #define isascii __isascii
  65. #endif /* NT */
  66. #include "ckocon.h"
  67. extern int tt_type, max_tt;
  68. extern struct tt_info_rec tt_info[];
  69. #endif /* OS2 */
  70. #endif /* NOTERM */
  71.  
  72. #ifdef OS2
  73. #include <assert.h>
  74. #ifdef NT
  75. #include <setjmpex.h>
  76. #else /* NT */
  77. #include <setjmp.h>
  78. #endif /* NT */
  79. #include <signal.h>
  80. #include "ckcsig.h"
  81. #include "ckosyn.h"
  82. #endif /* OS2 */
  83.  
  84. #ifdef CK_NAWS                          /* Negotiate About Window Size */
  85. #ifdef RLOGCODE
  86. _PROTOTYP( int rlog_naws, (void) );
  87. #endif /* RLOGCODE */
  88. #endif /* CK_NAWS */
  89.  
  90. int tn_init = 0;                        /* Telnet protocol initialized flag */
  91. int tn_begun = 0;                       /* Telnet protocol started flag */
  92. static int tn_first = 1;                /* First time init flag */
  93. extern int tn_exit;                     /* Exit on disconnect */
  94. extern int inserver;                    /* Running as IKSD */
  95. char *tn_term = NULL;                   /* Terminal type override */
  96.  
  97. #ifdef CK_SNDLOC
  98. char *tn_loc = NULL;                    /* Location override */
  99. #endif /* CK_SNDLOC */
  100. int tn_nlm = TNL_CRLF;                  /* Telnet CR -> CR LF mode */
  101. int tn_b_nlm = TNL_CR;                  /* Telnet Binary CR RAW mode */
  102. int tn_b_meu = 0;                       /* Telnet Binary ME means U too */
  103. int tn_b_ume = 0;                       /* Telnet Binary U means ME too */
  104. int tn_wait_flg = 1;                    /* Telnet Wait for Negotiations */
  105. int tn_infinite = 0;                    /* Telnet Bug Infinite-Loop-Check */
  106. int tn_rem_echo = 1;                    /* We will echo if WILL ECHO */
  107. int tn_b_xfer = 0;                      /* Telnet Binary for Xfers? */
  108. int tn_sb_bug = 1;                      /* Telnet BUG - SB w/o WILL or DO */
  109. int tn_auth_krb5_des_bug = 1;           /* Telnet BUG - AUTH KRB5 DES */
  110.                                         /*              truncates long keys */
  111. int tn_no_encrypt_xfer = 0;             /* Turn off Telnet Encrypt? */
  112. int tn_delay_sb = 1;                    /* Delay SBs until safe */
  113. int tn_auth_how = TN_AUTH_HOW_ANY;
  114. int tn_auth_enc = TN_AUTH_ENC_ANY;
  115. int tn_deb = 0;                         /* Telnet Debug mode */
  116. int tn_sfu = 0;                         /* Microsoft SFU compatibility */
  117. #ifdef CK_FORWARD_X
  118. char * tn_fwdx_xauthority = NULL;       /* Xauthority File */
  119. int    fwdx_no_encrypt = 0;             /* Forward-X requires encryption */
  120. #endif /* CK_FORWARD_X */
  121.  
  122. #ifdef OS2
  123. int ttnum = -1;                         /* Last Telnet Terminal Type sent */
  124. int ttnumend = 0;                       /* Has end of list been found */
  125. #endif /* OS2 */
  126.  
  127. char tn_msg[TN_MSG_LEN];                /* Telnet data can be rather long */
  128. char hexbuf[TN_MSG_LEN];
  129. char tn_msg_out[TN_MSG_LEN];
  130. #ifdef CK_FORWARD_X
  131. CHAR fwdx_msg_out[TN_MSG_LEN];
  132. #endif /* CK_FORWARD_X */
  133.  
  134. /*
  135.   In order to prevent an infinite telnet negotiation loop we maintain a
  136.   count of the number of times the same telnet negotiation message is
  137.   sent. When this count hits MAXTNCNT, we do not send any more of the
  138.   message. The count is stored in the tncnts[][] array.
  139.  
  140.   The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
  141.   TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
  142.   negotiation message types (WILL, WONT, DO, DONT).  All telnet negotiations
  143.   are kept track of in this way.
  144.  
  145.   The count for a message is zeroed when the "opposite" message is sent.
  146.   WILL is the opposite of WONT, and DO is the opposite of DONT.
  147.   For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
  148.   and zeroes tncnts[TELOPT_SGA][1].
  149.  
  150.   The code that does this is in tn_sopt().
  151.  
  152.   rogersh@fsj.co.jp, 18/3/1995
  153.  
  154.   8/16/1998 - with the recent rewrite of the telnet state machine I don't
  155.   think this code is necessary anymore.  However, it can't do any harm so
  156.   I am leaving it in.    - Jeff
  157.  
  158.   12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
  159.   because the Telnet option list is no longer contiguous.  We also must
  160.   allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
  161.   for an invalid option number.
  162. */
  163.  
  164. #define MAXTNCNT 4      /* Permits 4 intermediate telnet firewalls/gateways */
  165.  
  166. char tncnts[NTELOPTS+1][4];             /* Counts */
  167. char tnopps[4] = { 1,0,3,2 };           /* Opposites */
  168.  
  169. #ifdef CK_ENVIRONMENT
  170. #ifdef CK_FORWARD_X
  171. #define TSBUFSIZ 2056
  172. #else /* CK_FORWARD_X */
  173. #define TSBUFSIZ 1024
  174. #endif /* CK_FORWARD_X */
  175. char tn_env_acct[64];
  176. char tn_env_disp[64];
  177. char tn_env_job[64];
  178. char tn_env_prnt[64];
  179. char tn_env_sys[64];
  180. char * tn_env_uservar[8][2];
  181. int tn_env_flg = 1;
  182. #else /* CK_ENVIRONMENT */
  183. #define TSBUFSIZ 41
  184. int tn_env_flg = 0;
  185. #endif /* CK_ENVIRONMENT */
  186.  
  187. #ifdef COMMENT
  188. /* SIGWINCH handler moved to ckuusx.c */
  189. #ifndef NOSIGWINCH
  190. #ifdef CK_NAWS                          /* Window size business */
  191. #ifdef UNIX
  192. #include <signal.h>
  193. #endif /* UNIX */
  194. #endif /* CK_NAWS */
  195. #endif /* NOSIGWINCH */
  196. #endif /* COMMENT */
  197.  
  198. CHAR sb[TSBUFSIZ];                      /* Buffer - incoming subnegotiations */
  199. CHAR sb_out[TSBUFSIZ];                  /* Buffer - outgoing subnegotiations */
  200.  
  201. int tn_duplex = 1;                      /* Local echo */
  202.  
  203. extern char uidbuf[];                   /* User ID buffer */
  204. extern int quiet, ttnet, ttnproto, debses, what, duplex, oldplex, local;
  205. extern int seslog, sessft, whyclosed;
  206. #ifdef OS2
  207. #ifndef NOTERM
  208. extern int tt_rows[], tt_cols[];
  209. extern int tt_status[VNUM];
  210. extern int scrninitialized[];
  211. #endif /* NOTERM */
  212. #else /* OS2 */
  213. extern int tt_rows, tt_cols;            /* Everybody has this */
  214. #endif /* OS2 */
  215. extern int cmd_cols, cmd_rows;
  216. extern char namecopy[];
  217. extern char myipaddr[];             /* Global copy of my IP address */
  218.  
  219. #ifndef TELOPT_MACRO
  220. int
  221. telopt_index(opt) int opt; {
  222.     if (opt >= 0 && opt <= TELOPT_STDERR)
  223.       return(opt);
  224.     else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
  225.       return(opt-88);
  226.     else if (opt == TELOPT_IBM_SAK)
  227.       return(opt-147);
  228.     else
  229.       return(NTELOPTS);
  230. }
  231.  
  232. int
  233. telopt_ok(opt) int opt; {
  234.     return((opt >= TELOPT_BINARY && opt <= TELOPT_STDERR) ||
  235.            (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
  236.            (opt == TELOPT_IBM_SAK));
  237. }
  238.  
  239. CHAR *
  240. telopt(opt) int opt; {
  241.     if (telopt_ok(opt))
  242.       return((CHAR *)telopts[telopt_index(opt)]);
  243.     else
  244.       return((CHAR *)"UNKNOWN");
  245. }
  246.  
  247. int
  248. telopt_mode_ok(opt) int opt; {
  249.     return((unsigned int)(opt) <= TN_NG_MU);
  250. }
  251.  
  252. CHAR *
  253. telopt_mode(opt) int opt; {
  254.     if (telopt_mode_ok(opt))
  255.       return((CHAR *)telopt_modes[opt-TN_NG_RF]);
  256.     else
  257.       return((CHAR *)"UNKNOWN");
  258. }
  259. #endif /* TELOPT_MACRO */
  260.  
  261. static int
  262. tn_outst(notquiet) int notquiet; {
  263.     int outstanding = 0;
  264.     int x = 0;
  265. #ifdef CK_ENCRYPTION
  266.     int e = 0;
  267.     int d = 0;
  268. #endif /* CK_ENCRYPTION */
  269.  
  270.     if (tn_wait_flg) {
  271.         for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
  272.             if (TELOPT_OK(x)) {
  273.                 if (TELOPT_UNANSWERED_WILL(x)) {
  274.                     if ( notquiet )
  275.                       printf("?Telnet waiting for response to WILL %s\r\n",
  276.                              TELOPT(x));
  277.                     debug(F111,"tn_outst","unanswered WILL",x);
  278.                     outstanding = 1;
  279.                     if ( !notquiet )
  280.                       break;
  281.                 }
  282.                 if (TELOPT_UNANSWERED_DO(x)) {
  283.                     if ( notquiet )
  284.                       printf("?Telnet waiting for response to DO %s\r\n",
  285.                              TELOPT(x));
  286.                     debug(F111,"tn_outst","unanswered DO",x);
  287.                     outstanding = 1;
  288.                     if ( !notquiet )
  289.                       break;
  290.                 }
  291.                 if (TELOPT_UNANSWERED_WONT(x)) {
  292.                     if ( notquiet )
  293.                       printf("?Telnet waiting for response to WONT %s\r\n",
  294.                              TELOPT(x));
  295.                     debug(F111,"tn_outst","unanswered WONT",x);
  296.                     outstanding = 1;
  297.                     if ( !notquiet )
  298.                       break;
  299.                 }
  300.                 if (TELOPT_UNANSWERED_DONT(x)) {
  301.                     if ( notquiet )
  302.                       printf("?Telnet waiting for response to DONT %s\r\n",
  303.                              TELOPT(x));
  304.                     debug(F111,"tn_outst","unanswered DONT",x);
  305.                     outstanding = 1;
  306.                     if ( !notquiet )
  307.                       break;
  308.                 }
  309.                 if (TELOPT_UNANSWERED_SB(x)) {
  310.                     if ( notquiet )
  311.                       printf("?Telnet waiting for response to SB %s\r\n",
  312.                              TELOPT(x));
  313.                     debug(F111,"tn_outst","unanswered SB",x);
  314.                     outstanding = 1;
  315.                     if ( !notquiet )
  316.                       break;
  317.                 }
  318.             }
  319.         }
  320. #ifdef CK_AUTHENTICATION
  321.         if (ck_tn_auth_in_progress()) {
  322.             if (TELOPT_ME(TELOPT_AUTHENTICATION)) {
  323.                 if (notquiet)
  324.                   printf("?Telnet waiting for WILL %s subnegotiation\r\n",
  325.                          TELOPT(TELOPT_AUTHENTICATION));
  326.                 debug(F111,
  327.                       "tn_outst",
  328.                       "ME authentication in progress",
  329.                       TELOPT_AUTHENTICATION
  330.                       );
  331.                 outstanding = 1;
  332.             } else if (TELOPT_U(TELOPT_AUTHENTICATION)) {
  333.                 if (notquiet)
  334.                   printf("?Telnet waiting for DO %s subnegotiation\r\n",
  335.                          TELOPT(TELOPT_AUTHENTICATION));
  336.                 debug(F111,
  337.                       "tn_outst",
  338.                       "U authentication in progress",
  339.                       TELOPT_AUTHENTICATION
  340.                       );
  341.                 outstanding = 1;
  342.             }
  343.         }
  344. #endif /* CK_AUTHENTICATION */
  345. #ifdef CK_ENCRYPTION
  346.         if (!outstanding) {
  347.             e = ck_tn_encrypting();
  348.             d = ck_tn_decrypting();
  349.             if (TELOPT_ME(TELOPT_ENCRYPTION)) {
  350.                 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
  351.                     !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
  352.                     ) {
  353.                     if ( notquiet )
  354.                       printf("?Telnet waiting for WILL %s subnegotiation\r\n",
  355.                              TELOPT(TELOPT_ENCRYPTION));
  356.                     debug(F111,
  357.                           "tn_outst",
  358.                           "encryption mode switch",
  359.                           TELOPT_ENCRYPTION
  360.                           );
  361.                     outstanding = 1;
  362.                 }
  363.             }
  364.             if (TELOPT_U(TELOPT_ENCRYPTION)) {
  365.                 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
  366.                     !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
  367.                     ) {
  368.                     if ( notquiet )
  369.                       printf("?Telnet waiting for DO %s subnegotiation\r\n",
  370.                              TELOPT(TELOPT_ENCRYPTION));
  371.                     debug(F111,
  372.                           "tn_outst",
  373.                           "decryption mode switch",
  374.                            TELOPT_ENCRYPTION
  375.                           );
  376.                     outstanding = 1;
  377.                 }
  378.             }
  379.         }
  380. #endif /* CK_ENCRYPTION */
  381.     } /* if (tn_wait_flg) */
  382.  
  383. #ifdef IKS_OPTION
  384.     /* Even if we are not waiting for Telnet options we must wait for */
  385.     /* Kermit Telnet Subnegotiations if we have sent a request to the */
  386.     /* other guy.  Otherwise we will get out of sync.                 */
  387.     if (!outstanding) {
  388.         if (TELOPT_U(TELOPT_KERMIT) &&
  389.             (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
  390.              TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
  391.              !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
  392.             ) {
  393.             if ( notquiet )
  394.               printf("?Telnet waiting for SB %s negotiation\r\n",
  395.                      TELOPT(TELOPT_KERMIT));
  396.             debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
  397.             outstanding = 1;
  398.         }
  399.     }
  400. #endif /* IKS_OPTION */
  401.  
  402. #ifdef TN_COMPORT
  403.     if (!outstanding) {
  404.         if (TELOPT_ME(TELOPT_COMPORT)) {
  405.             if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb) {
  406.                 if (notquiet)
  407.                     printf("?Telnet waiting for SB %s negotiation\r\n",
  408.                             TELOPT(TELOPT_COMPORT));
  409.                debug(F111,"tn_outst","ComPort SB in progress",TELOPT_COMPORT);
  410.                outstanding = 1;
  411.             }
  412.             if (TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms) {
  413.                 if (notquiet)
  414.               printf("?Telnet waiting for SB %s MODEM_STATUS negotiation\r\n",
  415.                             TELOPT(TELOPT_COMPORT));
  416.             debug(F111,"tn_outst","ComPort SB MS in progress",TELOPT_COMPORT);
  417.                outstanding = 1;
  418.             }
  419.         }
  420.     }
  421. #endif /* TN_COMPORT */
  422.     return(outstanding);
  423. }
  424.  
  425. int
  426. istncomport() {
  427. #ifdef TN_COMPORT
  428.     if (!local) return(0);
  429.     if (ttnet != NET_TCPB) return(0);
  430.     if (ttnproto != NP_TELNET) return(0);
  431.     if (TELOPT_ME(TELOPT_COMPORT))
  432.       return(1);
  433.     else
  434. #endif /* TN_COMPORT */
  435.       return(0);
  436. }
  437.  
  438. /* tn_wait() -- Wait for response to Telnet negotiation. */
  439. /*
  440.   Wait for up to <timeout> seconds for the response to arrive.
  441.   Place all non-telnet data into Telnet Wait Buffer.
  442.   If response does arrive return 1, else return 0.
  443. */
  444. #ifndef TN_WAIT_BUF_SZ
  445. #define TN_WAIT_BUF_SZ 4096
  446. #endif /* TN_WAIT_BUF_SZ */
  447. static char tn_wait_buf[TN_WAIT_BUF_SZ];
  448. static int  tn_wait_idx = 0;
  449. #ifndef TN_TIMEOUT
  450. #define TN_TIMEOUT 120
  451. #endif /* TN_TIMEOUT */
  452. static int tn_wait_tmo = TN_TIMEOUT;
  453.  
  454. #ifdef CKSPINNER
  455. VOID
  456. prtwait(state) int state; {
  457.     switch (state % 4) {
  458.       case 0:
  459.         printf("/");
  460.         break;
  461.       case 1:
  462.         printf("-");
  463.         break;
  464.       case 2:
  465.         printf("\\");
  466.         break;
  467.       case 3:
  468.         printf("|");
  469.         break;
  470.     }
  471. }
  472. #endif /* CKSPINNER */
  473.  
  474. static int nflag = 0;
  475.  
  476. int
  477. #ifdef CK_ANSIC
  478. tn_wait(char * where)
  479. #else
  480. tn_wait(where) char * where;
  481. #endif /* CK_ANSIC */
  482. /* tn_wait */ {
  483.     extern int ckxech, local;
  484.     int ch = 0, count = 0;
  485. #ifndef NOHINTS
  486.     int nohintgiven = 1;
  487.     extern int hints;
  488. #endif /* NOHINTS */
  489.     int outstanding;
  490. #ifdef TN_COMPORT
  491.     int savcarr;
  492.     extern int ttcarr;
  493. #endif /* TN_COMPORT */
  494.  
  495.     rtimer();
  496.  
  497.     debug(F110,"tn_wait waiting for",where,0);
  498.     tn_wait_tmo = TN_TIMEOUT;
  499.     debug(F111,"tn_wait","timeout",tn_wait_tmo);
  500.     outstanding = tn_outst(0);
  501.     debug(F111,"tn_wait","outstanding",outstanding);
  502.     debug(F111,"tn_wait","tn_wait_flg",tn_wait_flg);
  503.  
  504.     /* The following is meant to be !(||).  We only want to return */
  505.     /* immediately if both the tn_wait_flg && tn_outst() are false */
  506.     if (!(outstanding || tn_wait_flg))  /* If no need to wait */
  507.       return(1);                        /* Don't. */
  508.  
  509.     if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
  510.  
  511. #ifdef CKSPINNER
  512.     if (!sstelnet && !quiet)
  513.         prtwait(0);
  514. #endif /* CKSPINNER */
  515.  
  516.     /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
  517.     do {
  518. #ifdef NTSIG
  519.         ck_ih();
  520. #endif /* NTSIG */
  521.         ch = ttinc(1);
  522.         if (ch == -1) {                 /* Timed out */
  523.             if (!sstelnet && !quiet) {  /* Let user know... */
  524. #ifdef CKSPINNER
  525.                 printf("\b");
  526.                 prtwait(gtimer());
  527. #else
  528.                 if (nflag == 0) {
  529.                     printf(" Negotiations.");
  530.                     nflag++;
  531.                 }
  532.                 if (nflag > 0) {
  533.                     printf(".");
  534.                     nflag++;
  535.                     fflush(stdout);
  536.                 }
  537. #endif /* CKSPINNER */
  538.             }
  539.         } else if (ch < -1) {
  540.             printf("\r\n?Connection closed by peer.\r\n");
  541.             if (tn_deb || debses) tn_debug("<connection closed by peer>");
  542.             return(-1);
  543.         } else
  544.         switch (ch) {
  545.           case IAC:
  546. #ifdef CKSPINNER
  547.             if (!sstelnet && !quiet)
  548.               printf("\b");
  549. #endif /* CKSPINNER */
  550.             ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
  551. #ifdef CKSPINNER
  552.             if (!sstelnet && !quiet) {
  553.                 prtwait(gtimer());
  554.             }
  555. #endif /* CKSPINNER */
  556.             debug(F101,"tn_wait tn_doop","",ch);
  557.             switch (ch) {
  558.               case 1:
  559.                 duplex = 1;             /* Turn on echoing */
  560.                 if (inserver)
  561.                   ckxech = 1;
  562.                 break;
  563.               case 2:
  564.                 duplex = 0;             /* Turn off echoing */
  565.                 if (inserver)
  566.                   ckxech = 0;
  567.                 break;
  568.               case 3:
  569.                 tn_wait_buf[tn_wait_idx++] = IAC;
  570.                 break;
  571.               case 4:                   /* IKS event */
  572.               case 6:                   /* Logout */
  573.                 break;
  574.               case -1:
  575.         if (!quiet)
  576.                 printf("?Telnet Option negotiation error.\n");
  577.                 if (tn_deb || debses)
  578.                   tn_debug("<Telnet Option negotiation error>");
  579.                 return(-1);
  580.               case -2:
  581.                 printf("?Connection closed by peer.\n");
  582.                 if (tn_deb || debses) tn_debug("<Connection closed by peer>");
  583.         ttclos(0);
  584.                 return(-2);
  585.               default:
  586.                 if (ch < 0) {
  587.                   if (tn_deb || debses) tn_debug("<Unknown connection error>");
  588.                   return(ch);
  589.                 }
  590.             } /* switch */
  591.             break;
  592.           default:
  593. #ifdef CKSPINNER
  594.             if (!sstelnet && !quiet) {
  595.                 printf("\b");
  596.                 prtwait(gtimer());
  597.             }
  598. #endif /* CKSPINNER */
  599.             tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
  600.         } /* switch */
  601.  
  602.         outstanding = tn_outst(0);
  603.  
  604.         if ( outstanding && ch != IAC ) {
  605.             int timer = gtimer();
  606.             if ( timer > tn_wait_tmo ) {
  607.                 if (!sstelnet) {
  608.                     printf(
  609.                     "\r\n?Telnet Protocol Timeout - connection closed\r\n");
  610.                     if (tn_deb || debses)
  611.                         tn_debug(
  612.                         "<telnet protocol timeout - connection closed>");
  613.                     tn_outst(1);
  614.                 }
  615.                 /* if we do not close the connection, then we will block */
  616.                 /* the next time we hit a wait.  and if we don't we will */
  617.                 /* do the wrong thing if the host sends 0xFF and does    */
  618.                 /* not intend it to be an IAC.                           */
  619.                 ttclos(0);
  620.                 whyclosed = WC_TELOPT;
  621.                 return(-1);
  622.             }
  623. #ifndef NOHINTS
  624.             else if ( hints && timer > 30 && nohintgiven && !inserver ) {
  625. #ifdef CKSPINNER
  626.                                 printf("\b");
  627. #else /* CKSPINNER */
  628.                                 printf("\r\n");
  629. #endif /* CKSPINNER */
  630.       printf("*************************\r\n");
  631.         printf("The Telnet %s is not sending required responses.\r\n\r\n",
  632.                 sstelnet?"client":"server");
  633.       tn_outst(1);
  634.       printf("\nYou can continue to wait or you can cancel with Ctrl-C.\r\n");
  635.       printf("In case the Telnet server never responds as required,\r\n");
  636.       printf("you can try connecting to this host with TELNET /NOWAIT.\r\n");
  637.       printf("Use SET HINTS OFF to suppress further hints.\r\n");
  638.       printf("*************************\r\n");
  639.       nohintgiven = 0;
  640.             }
  641. #endif /* NOHINTS */
  642.         }
  643.  
  644. #ifdef TN_COMPORT
  645.         /* Must disable carrier detect check if we are using Telnet Comport */
  646.         savcarr = ttcarr;
  647.         ttscarr(CAR_OFF);
  648.         count = ttchk();
  649.         ttscarr(savcarr);
  650. #else /* TN_COMPORT */
  651.         count = ttchk();
  652. #endif /* TN_COMPORT */
  653.     } while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
  654.              (outstanding && count >= 0));
  655.  
  656.     if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  657.       if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
  658.       return(0);
  659.     }
  660.  
  661.     if (!sstelnet && !quiet) {
  662. #ifdef CKSPINNER
  663.         printf("\b \b");
  664. #else
  665.         if (nflag > 0) {
  666.             printf(" (OK)\n");
  667.             nflag = -1;
  668.         }
  669. #endif /* CKSPINNER */
  670.     }
  671.     if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
  672.     return(0);
  673. }
  674.  
  675. /* Push data from the Telnet Wait Buffer into the I/O Queue */
  676. /* Return 1 on success                                      */
  677.  
  678. int
  679. tn_push() {
  680. #ifdef NETLEBUF
  681.     extern int tt_push_inited;
  682. #endif /* NETLEBUF */
  683.     if (tn_wait_idx) {
  684.         hexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
  685. #ifdef NETLEBUF
  686.         if (!tt_push_inited)            /* Local handling */
  687.           le_init();
  688.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  689. #else                                   /* External handling... */
  690. #ifdef OS2                              /* K95 has its own way */
  691.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  692. #else
  693. #ifdef TTLEBUF                          /* UNIX, etc */
  694.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  695. #else
  696. /*
  697.   If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
  698.   the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
  699.   places in your ck?tio.c module.
  700. */
  701.         printf("tn_push called but not implemented - data lost.\n");
  702. #endif /* TTLEBUF */
  703. #endif /* OS2 */
  704. #endif /* NETLEBUF */
  705.         tn_wait_idx = 0;
  706.     }
  707.     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
  708.     return(1);
  709. }
  710.  
  711. /*  T N _ S O P T  */
  712. /*
  713.    Sends a telnet option, avoids loops.
  714.    Returns 1 if command was sent, 0 if not, -1 on error.
  715. */
  716. int
  717. tn_sopt(cmd,opt) int cmd, opt; {        /* TELNET SEND OPTION */
  718.     CHAR buf[5];
  719.     char msg[128];
  720.     int rc;
  721.  
  722.     if (ttnet != NET_TCPB) return(-1);  /* Must be TCP/IP */
  723.     if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
  724.     if (!TELCMD_OK(cmd)) return(-1);
  725.     if (TELOPT_OK(opt)) {
  726.         if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
  727.         if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
  728.         if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
  729.         if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
  730.     }
  731. #ifdef CK_SSL
  732.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  733.         return(0);
  734.     }
  735. #endif /* CK_SSL */
  736.  
  737.     if (cmd == DO && opt == TELOPT_AUTHENTICATION)
  738.       buf[0] = 0;
  739.  
  740.     if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about   */
  741.         int index = TELOPT_INDEX(opt);   /* preventing infinite loops */
  742.         int m = cmd - WILL;
  743.  
  744.         if (tncnts[index][m] > MAXTNCNT) {
  745. #ifdef DEBUG
  746.             if (tn_deb || debses || deblog) {
  747.                 ckmakmsg(msg,sizeof(msg),
  748.                            "TELNET negotiation loop ",
  749.                            TELCMD(cmd), " ",
  750.                            TELOPT(opt));
  751.                 debug(F101,msg,"",opt);
  752.                 if (tn_deb || debses) tn_debug(msg);
  753.             }
  754. #endif /* DEBUG */
  755.             return(0);
  756.         }
  757.         tncnts[index][m]++;
  758.         tncnts[index][tnopps[m]] = 0;
  759.     }
  760.     buf[0] = (CHAR) IAC;
  761.     buf[1] = (CHAR) (cmd & 0xff);
  762.     buf[2] = (CHAR) (opt & 0xff);
  763.     buf[3] = (CHAR) 0;
  764. #ifdef DEBUG
  765.     if ((tn_deb || debses || deblog) && cmd != SB)
  766.         ckmakmsg(msg,sizeof(msg),"TELNET SENT ",TELCMD(cmd)," ",
  767.                   TELOPT(opt));
  768. #endif /* DEBUG */
  769. #ifdef OS2
  770.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  771. #endif
  772.     debug(F101,msg,"",opt);
  773.     if ((tn_deb || debses) && cmd != SB)
  774.       tn_debug(msg);
  775.     rc = (ttol(buf,3) < 3);
  776. #ifdef OS2
  777.     ReleaseTelnetMutex();
  778. #endif
  779.     if (rc)
  780.         return(-1);
  781.  
  782.  
  783.     if (TELOPT_OK(opt)) {
  784.         if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
  785.           TELOPT_UNANSWERED_DO(opt) = 0;
  786.         if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
  787.           TELOPT_UNANSWERED_WILL(opt) = 0;
  788.         if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
  789.           TELOPT_UNANSWERED_DONT(opt) = 0;
  790.         if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
  791.           TELOPT_UNANSWERED_WONT(opt) = 0;
  792.     }
  793.     return(1);
  794. }
  795.  
  796. /* Send a telnet sub-option */
  797. /* Returns 1 if command was sent, 0 if not, -1 on error */
  798.  
  799. int
  800. tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
  801.     CHAR buf[256];
  802.     int n,m,rc;
  803.  
  804.     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
  805.     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
  806.     if (!TELOPT_OK(opt)) return(-1);
  807.     if (len < 0 || len > 250) {
  808.         debug(F111,"Unable to Send TELNET SB - data too long","len",len);
  809.         return(-1);                     /* Data too long */
  810.     }
  811. #ifdef CK_SSL
  812.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  813.         if (ttchk() < 0)
  814.           return(-1);
  815.         else
  816.           return(1);
  817.     }
  818. #endif /* CK_SSL */
  819.  
  820.     if (!data) len = 0;
  821.  
  822.     buf[0] = (CHAR) IAC;
  823.     buf[1] = (CHAR) (SB & 0xff);
  824.     buf[2] = (CHAR) (opt & 0xff);
  825.     buf[3] = (CHAR) (sub & 0xff);
  826.     if (data && len > 0) {
  827.         memcpy(&buf[4],data,len);
  828.     }
  829.     buf[4+len] = (CHAR) IAC;
  830.     buf[5+len] = (CHAR) SE;
  831.  
  832. #ifdef DEBUG
  833.     if (tn_deb || debses || deblog) {
  834.         if (opt == TELOPT_START_TLS && sub == 1)
  835.           ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  836.                     TELOPT(opt)," FOLLOWS IAC SE",NULL);
  837.         else if (opt == TELOPT_TTYPE && sub == 1)
  838.           ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ", TELOPT(opt),
  839.                     " SEND IAC SE",NULL);
  840.         else if (opt == TELOPT_TTYPE && sub == 0)
  841.           ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",TELOPT(opt)," IS ",
  842.                     (char *)data," IAC SE",NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  843.         else if (opt == TELOPT_NEWENVIRON) {
  844.             int i, quote;
  845.             ckmakmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  846.                      TELOPT(TELOPT_NEWENVIRON)," ",
  847.                      sub == TELQUAL_SEND ? "SEND" :
  848.                      sub == TELQUAL_IS ? "IS" :
  849.                      sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
  850.             for (i = 0, quote = 0; i < len; i++) {
  851.                 if (quote) {
  852.                     sprintf(hexbuf,"%02x",data[i]); /* safe but ugly */
  853.                     ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
  854.                     quote = 0;
  855.                 } else {
  856.                     switch (data[i]) {
  857.                       case TEL_ENV_USERVAR:
  858.                         ckstrncat(tn_msg_out," USERVAR ",TN_MSG_LEN);
  859.                         break;
  860.                       case TEL_ENV_VAR:
  861.                         ckstrncat(tn_msg_out," VAR ",TN_MSG_LEN);
  862.                         break;
  863.                       case TEL_ENV_VALUE:
  864.                         ckstrncat(tn_msg_out," VALUE ",TN_MSG_LEN);
  865.                         break;
  866.                       case TEL_ENV_ESC:
  867.                         ckstrncat(tn_msg_out," ESC ",TN_MSG_LEN);
  868.                         quote = 1;
  869.                         break;
  870.                       case IAC:
  871.                         ckstrncat(tn_msg_out," IAC ",TN_MSG_LEN);
  872.                         break;
  873.                       default:
  874.                         sprintf(hexbuf,"%c",data[i]); /* safe but ugly */
  875.                         ckstrncat(tn_msg_out,hexbuf,TN_MSG_LEN);
  876.                     }
  877.                 }
  878.             }
  879.             ckstrncat(tn_msg_out," IAC SE",TN_MSG_LEN);
  880.         } else {
  881.             sprintf(hexbuf,"%02x",sub);             /* safe but ugly */
  882.             ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  883.                       "TELNET SENT SB ",TELOPT(opt),
  884.                       " ",
  885.                       hexbuf,
  886.                       " <data> IAC SE",
  887.                        NULL,NULL,NULL,NULL,NULL,NULL,NULL
  888.                       );
  889.         }
  890.     }
  891. #endif /* DEBUG */
  892. #ifdef OS2
  893.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  894. #endif /* OS2 */
  895. #ifdef DEBUG
  896.     debug(F101,tn_msg_out,"",opt);
  897.     if (tn_deb || debses)
  898.       tn_debug(tn_msg_out);
  899. #endif /* DEBUG */
  900.     rc = (ttol(buf,6+len) < 6+len);
  901. #ifdef OS2
  902.     ReleaseTelnetMutex();
  903. #endif
  904.  
  905.     if (rc)
  906.       return(-1);
  907.     return(1);
  908. }
  909.  
  910. /*
  911.   tn_flui() -- Processes all waiting data for Telnet commands.
  912.   All non-Telnet data is to be stored into the Telnet Wait Buffer.
  913.   Returns 1 on success.
  914. */
  915. int
  916. tn_flui() {
  917.     extern int ckxech;
  918.     int x = 0;
  919.  
  920.     /* Wait up to 5 sec for responses to outstanding telnet negotiations */
  921.     while (x >= 0 && ttchk() > 0  && tn_wait_idx < TN_WAIT_BUF_SZ) {
  922.         x = ttinc(1);
  923.         switch (x) {
  924.           case IAC:
  925.             x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
  926.             debug(F101,"tn_flui tn_doop","",x);
  927.             switch (x) {
  928.               case 1:                   /* Turn on echoing */
  929.                 duplex = 1;
  930.                 if (inserver)
  931.                   ckxech = 1;
  932.                 break;
  933.               case 2:                   /* Turn off echoing */
  934.                 duplex = 0;
  935.                 if (inserver)
  936.                   ckxech = 0;
  937.                 break;
  938.               case 3:
  939.                 tn_wait_buf[tn_wait_idx++] = IAC;
  940.                 break;
  941.               case 4:                   /* IKS event */
  942.               case 6:                   /* Logout */
  943.                 break;
  944.             }
  945.             break;
  946.           default:
  947.             if (x >= 0)
  948.               tn_wait_buf[tn_wait_idx++] = x;
  949.         }
  950.     }
  951.     return(1);
  952. }
  953.  
  954. unsigned char *
  955. tn_get_display()
  956. {
  957.     char * disp = NULL;
  958.     static char tmploc[256];
  959.  
  960.     /* Must compute the DISPLAY string we are going to send to the host */
  961.     /* If one is not assigned, do not send a string unless the user has */
  962.     /* explicitedly requested we try to send one via X-Display Location */
  963.     /* But do not send a string at all if FORWARD_X is in use.          */
  964.  
  965.     debug(F110,"tn_get_display() myipaddr",myipaddr,0);
  966. #ifdef CK_ENVIRONMENT
  967.     debug(F110,"tn_get_display() tn_env_disp",tn_env_disp,0);
  968.     if (tn_env_disp[0]) {
  969.         int colon = ckindex(":",tn_env_disp,0,0,1);
  970.         if ( !colon ) {
  971.             ckmakmsg(tmploc,256,myipaddr,":",tn_env_disp,NULL);
  972.             disp = tmploc;
  973.         } else if ( ckindex("localhost:",tn_env_disp,0,0,0) ||
  974.                     ckindex("unix:",tn_env_disp,0,0,0) ||
  975.                     ckindex("127.0.0.1:",tn_env_disp,0,0,0) ||
  976.                     !ckstrcmp("0:",tn_env_disp,2,1) ||
  977.                     tn_env_disp[0] == ':' ) {
  978.             ckmakmsg(tmploc,256,myipaddr,":",&tn_env_disp[colon],NULL);
  979.             disp = tmploc;
  980.         } else
  981.             disp = tn_env_disp;
  982.     }
  983.     else
  984. #endif /* CK_ENVIRONMENT */
  985.         if (TELOPT_ME(TELOPT_XDISPLOC) ||
  986.               TELOPT_U(TELOPT_FORWARD_X)) {
  987.         ckmakmsg(tmploc,256,myipaddr,":0.0",NULL,NULL);
  988.         disp = tmploc;
  989.     }
  990.     debug(F110,"tn_get_display() returns",disp,0);
  991.     return((CHAR *)disp);
  992. }
  993.  
  994. #ifdef CK_FORWARD_X
  995. static Xauth fake_xauth = {0,0,NULL,0,NULL,0,NULL,0,NULL};
  996. static Xauth *real_xauth=NULL;
  997.  
  998. /*
  999.  * Author:  Jim Fulton, MIT X Consortium
  1000.  *
  1001.  * fwdx_parse_displayname -
  1002.  * display a display string up into its component parts
  1003.  */
  1004. #ifdef UNIX
  1005. #define UNIX_CONNECTION "unix"
  1006. #define UNIX_CONNECTION_LENGTH 4
  1007. #endif
  1008.  
  1009. /*
  1010.  * private utility routines
  1011.  */
  1012.  
  1013. static int
  1014. #ifdef CK_ANSIC
  1015. XmuGetHostname (char *buf, int maxlen)
  1016. #else
  1017. XmuGetHostname (buf, maxlen)
  1018.     char *buf;
  1019.     int maxlen;
  1020. #endif /* CK_ANSIC */
  1021. {
  1022.     int len;
  1023.  
  1024. #ifdef NEED_UTSNAME
  1025.     /*
  1026.      * same host name crock as in server and xinit.
  1027.      */
  1028.     struct utsname name;
  1029.  
  1030.     uname (&name);
  1031.     len = strlen (name.nodename);
  1032.     if (len >= maxlen) len = maxlen - 1;
  1033.     strncpy (buf, name.nodename, len);
  1034.     buf[len] = '\0';
  1035. #else
  1036.     buf[0] = '\0';
  1037.     (void) gethostname (buf, maxlen);
  1038.     buf [maxlen - 1] = '\0';
  1039.     len = strlen(buf);
  1040. #endif /* hpux */
  1041.     return len;
  1042. }
  1043.  
  1044. static char *
  1045. #ifdef CK_ANSIC
  1046. copystring (char *src, int len)
  1047. #else
  1048. copystring (src, len)
  1049.     char *src;
  1050.     int len;
  1051. #endif /* CK_ANSIC */
  1052. {
  1053.     char *cp;
  1054.  
  1055.     if (!src && len != 0) return NULL;
  1056.     cp = malloc (len + 1);
  1057.     if (cp) {
  1058.         if (src) strncpy (cp, src, len);
  1059.         cp[len] = '\0';
  1060.     }
  1061.     return cp;
  1062. }
  1063.  
  1064. static char *
  1065. #ifdef CK_ANSIC
  1066. get_local_hostname (char *buf, int maxlen)
  1067. #else
  1068. get_local_hostname (buf, maxlen)
  1069.     char *buf;
  1070.     int maxlen;
  1071. #endif
  1072. {
  1073.     buf[0] = '\0';
  1074.     (void) XmuGetHostname (buf, maxlen);
  1075.     return (buf[0] ? buf : NULL);
  1076. }
  1077.  
  1078. #ifndef UNIX
  1079. static char *
  1080. copyhostname ()
  1081. {
  1082.     char buf[256];
  1083.  
  1084.     return (get_local_hostname (buf, sizeof buf) ?
  1085.             copystring (buf, strlen (buf)) : NULL);
  1086. }
  1087. #endif
  1088.  
  1089.  
  1090. int
  1091. #ifdef CK_ANSIC
  1092. fwdx_parse_displayname (char *displayname, int *familyp, char **hostp,
  1093.                         int *dpynump, int *scrnump, char **restp)
  1094. #else
  1095. fwdx_parse_displayname (displayname, familyp, hostp, dpynump, scrnump, restp)
  1096.     char *displayname;
  1097.     int *familyp;                       /* return */
  1098.     char **hostp;                       /* return */
  1099.     int *dpynump, *scrnump;             /* return */
  1100.     char **restp;                       /* return */
  1101. #endif /* CK_ANSIC */
  1102. {
  1103.     char *ptr;                          /* work variables */
  1104.     int len;                            /* work variable */
  1105.     int family = -1;                    /* value to be returned */
  1106.     char *host = NULL;                  /* must free if set and error return */
  1107.     int dpynum = -1;                    /* value to be returned */
  1108.     int scrnum = 0;                     /* value to be returned */
  1109.     char *rest = NULL;                  /* must free if set and error return */
  1110.     int dnet = 0;                       /* if 1 then using DECnet */
  1111.  
  1112.                                         /* check the name */
  1113.     if (!displayname || !displayname[0])
  1114.         return 0;
  1115.                                         /* must have at least :number */
  1116.     ptr = (char *)strchr(displayname, ':');
  1117.     if (!ptr || !ptr[1]) return 0;
  1118.     if (ptr[1] == ':') {
  1119.         if (ptr[2] == '\0') return 0;
  1120.         dnet = 1;
  1121.     }
  1122.  
  1123.     /*
  1124.      * get the host string; if none is given, use the most effiecient path
  1125.      */
  1126.  
  1127.     len = (ptr - displayname);  /* length of host name */
  1128.     if (len == 0) {                     /* choose most efficient path */
  1129. #ifdef UNIX
  1130.         host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
  1131.         family = FamilyLocal;
  1132. #else
  1133.         if (dnet) {
  1134.             host = copystring ("0", 1);
  1135.             family = FamilyDECnet;
  1136.         } else {
  1137.             host = copyhostname ();
  1138.             family = FamilyInternet;
  1139.         }
  1140. #endif
  1141.     } else {
  1142.         host = copystring (displayname, len);
  1143.         if (dnet) {
  1144.             family = dnet;
  1145.         } else {
  1146. #ifdef UNIX
  1147.             if (host && strcmp (host, UNIX_CONNECTION) == 0)
  1148.               family = FamilyLocal;
  1149.             else
  1150. #endif
  1151.               family = FamilyInternet;
  1152.         }
  1153.     }
  1154.  
  1155.     if (!host) return 0;
  1156.  
  1157.  
  1158.     /*
  1159.      * get the display number; we know that there is something after the
  1160.      * colon (or colons) from above.  note that host is now set and must
  1161.      * be freed if there is an error.
  1162.      */
  1163.  
  1164.     if (dnet) ptr++;                    /* skip the extra DECnet colon */
  1165.     ptr++;                              /* move to start of display num */
  1166.     {
  1167.         register char *cp;
  1168.  
  1169.         for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
  1170.         len = (cp - ptr);
  1171.                                         /* check present and valid follow */
  1172.         if (len == 0 || (*cp && *cp != '.')) {
  1173.             free (host);
  1174.             return 0;
  1175.         }
  1176.  
  1177.         dpynum = atoi (ptr);            /* it will handle num. as well */
  1178.         ptr = cp;
  1179.     }
  1180.  
  1181.     /*
  1182.      * now get screen number if given; ptr may point to nul at this point
  1183.      */
  1184.     if (ptr[0] == '.') {
  1185.         register char *cp;
  1186.  
  1187.         ptr++;
  1188.         for (cp = ptr; *cp && isascii(*cp) && isdigit(*cp); cp++) ;
  1189.         len = (cp - ptr);
  1190.         if (len == 0 || (*cp && *cp != '.')) {  /* all prop name */
  1191.             free (host);
  1192.             return 0;
  1193.         }
  1194.  
  1195.         scrnum = atoi (ptr);            /* it will handle num. as well */
  1196.         ptr = cp;
  1197.     }
  1198.  
  1199.     /*
  1200.      * and finally, get any additional stuff that might be following the
  1201.      * the screen number; ptr must point to a period if there is anything
  1202.      */
  1203.  
  1204.     if (ptr[0] == '.') {
  1205.         ptr++;
  1206.         len = strlen (ptr);
  1207.         if (len > 0) {
  1208.             rest = copystring (ptr, len);
  1209.             if (!rest) {
  1210.                 free (host);
  1211.                 return 1;
  1212.             }
  1213.         }
  1214.     }
  1215.  
  1216.     /*
  1217.      * and we are done!
  1218.      */
  1219.  
  1220.     if ( familyp )
  1221.         *familyp = family;
  1222.     if ( hostp )
  1223.         *hostp = host;
  1224.     else
  1225.         free(host);
  1226.     if ( dpynump )
  1227.         *dpynump = dpynum;
  1228.     if ( scrnump )
  1229.         *scrnump = scrnum;
  1230.     if ( restp )
  1231.         *restp = rest;
  1232.     else
  1233.         free(rest);
  1234.     return 1;
  1235. }
  1236.  
  1237.  
  1238. int
  1239. #ifdef CK_ANSIC
  1240. fwdx_tn_sb( unsigned char * sb, int n )
  1241. #else
  1242. fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
  1243. #endif /* CK_ANSIC */
  1244. {
  1245.     unsigned short hchannel, nchannel;
  1246.     unsigned char * p;
  1247.     int i;
  1248.     int rc = -1;
  1249.  
  1250.     /* check to ensure we have negotiated Forward X */
  1251.     if ( sstelnet && !TELOPT_ME(TELOPT_FORWARD_X) ||
  1252.          !sstelnet && !TELOPT_U(TELOPT_FORWARD_X) ) {
  1253.         debug(F100,"fwdx_tn_sb() not negotiated","",0);
  1254.         return(0);
  1255.     }
  1256.  
  1257. #ifdef CK_SSL
  1258.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1259.         return(0);
  1260.     }
  1261. #endif /* CK_SSL */
  1262.  
  1263.     switch (sb[0]) {
  1264.     case FWDX_SCREEN:
  1265.         if (sstelnet && n == 4)
  1266.             rc = fwdx_create_listen_socket(sb[1]);
  1267.         break;
  1268.     case FWDX_OPEN:
  1269.         if ( !sstelnet && n >= 5 ) {
  1270.             p = (unsigned char *) &nchannel;
  1271.             i = 1;
  1272.             /* IAC quoting has been stripped in tn_sb() */
  1273.             p[0] = sb[i++];
  1274.             p[1] = sb[i++];
  1275.             hchannel = ntohs(nchannel);
  1276.             rc = fwdx_open_client_channel(hchannel);
  1277.             if ( rc < 0 ) {
  1278.                 /* Failed; Send CLOSE channel */
  1279.                 fwdx_send_close(hchannel);
  1280.                 rc = 0;         /* Do not consider this to be a telnet error */
  1281.             }
  1282. #ifdef NT
  1283.             if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
  1284.                 ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
  1285.                 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
  1286.             }
  1287. #endif /* NT */
  1288.         }
  1289.         break;
  1290.     case FWDX_CLOSE:
  1291.         p = (unsigned char *) &nchannel;
  1292.         i = 1;
  1293.         /* IAC quoting has been stripped in tn_sb() */
  1294.         p[0] = sb[i++];
  1295.         p[1] = sb[i++];
  1296.         hchannel = ntohs(nchannel);
  1297.         fwdx_close_channel(hchannel);
  1298.         rc = 0; /* no errors when closing */
  1299.         break;
  1300.     case FWDX_DATA:
  1301.         p = (unsigned char *) &nchannel;
  1302.         i = 1;
  1303.         /* IAC quoting has been stripped in tn_sb() */
  1304.         p[0] = sb[i++];
  1305.         p[1] = sb[i++];
  1306.         hchannel = ntohs(nchannel);
  1307.         rc = fwdx_send_xauth_to_xserver(hchannel,(char *)&sb[3],n-5);
  1308.         if ( rc >= 0 && n-5-rc > 0) {
  1309.             rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3+rc],n-5-rc);
  1310.             if ( rc < 0 ) {
  1311.                 /* Failed; Send CLOSE channel */
  1312.                 rc = fwdx_send_close(hchannel);
  1313.             }
  1314.         }
  1315.         break;
  1316.     case FWDX_OPTIONS:
  1317.         if ( sstelnet ) {
  1318. #ifndef FWDX_SERVER
  1319.             rc = 0;
  1320. #else
  1321.             rc = fwdx_server_accept_options((char*)&sb[2],n-3);
  1322. #endif
  1323.         } else {
  1324.             rc = fwdx_client_reply_options((char *)&sb[2],n-3);
  1325.             if ( rc >= 0 ) {
  1326.                 rc = tn_sndfwdx();
  1327.             }
  1328.         }
  1329.         break;
  1330.     case FWDX_OPT_DATA:
  1331.         switch ( sb[1] ) {
  1332.         default:
  1333.             rc = 0;             /* we don't recognize, not an error */
  1334.         }
  1335.         break;
  1336.  
  1337.     case FWDX_XOFF:
  1338.     case FWDX_XON:
  1339.         if ( !sstelnet ) {
  1340.             p = (unsigned char *) &nchannel;
  1341.             i = 1;
  1342.             /* IAC quoting has been stripped in tn_sb() */
  1343.             p[0] = sb[i++];
  1344.             p[1] = sb[i++];
  1345.             hchannel = ntohs(nchannel);
  1346.             TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[hchannel].suspend =
  1347.                 (sb[0] == FWDX_XOFF);
  1348.             rc = 0;
  1349.         }
  1350.         break;
  1351.     }
  1352.     return(rc < 0 ? -1 : 0);
  1353. }
  1354.  
  1355. int
  1356. #ifdef CK_ANSIC
  1357. fwdx_send_xauth_to_xserver(int channel, unsigned char * data, int len)
  1358. #else
  1359. fwdx_send_xauth_to_xserver(channel, data, len)
  1360.     int channel; unsigned char * data; int len;
  1361. #endif /* CK_ANSIC */
  1362. {
  1363.     int name_len, data_len, i;
  1364.  
  1365.     for (i = 0; i < MAXFWDX ; i++) {
  1366.         if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].id == channel)
  1367.             break;
  1368.     }
  1369.     if ( i == MAXFWDX )
  1370.         goto auth_err;
  1371.  
  1372.     if (!TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth)
  1373.         return(0);
  1374.  
  1375.     if (len < 12)
  1376.         goto auth_err;
  1377.  
  1378.     /* Parse the lengths of variable-length fields. */
  1379.     if (data[0] == 0x42) {              /* byte order MSB first. */
  1380.         /* Xauth packets appear to always have this format */
  1381.         if ( data[1] != 0x00 ||
  1382.              data[2] != 0x00 ||
  1383.              data[3] != 0x0B ||
  1384.              data[4] != 0x00 ||
  1385.              data[5] != 0x00 )
  1386.             goto auth_err;
  1387.  
  1388.         name_len = (data[6] << 8) + data[7];
  1389.         data_len = (data[8] << 8) + data[9];
  1390.     } else if (data[0] == 0x6c) {       /* Byte order LSB first. */
  1391.         /* Xauth packets appear to always have this format */
  1392.         if ( data[1] != 0x00 ||
  1393.              data[2] != 0x0B ||
  1394.              data[3] != 0x00 ||
  1395.              data[4] != 0x00 ||
  1396.              data[5] != 0x00 )
  1397.             goto auth_err;
  1398.  
  1399.         name_len = data[6] + (data[7] << 8);
  1400.         data_len = data[8] + (data[9] << 8);
  1401.     } else {
  1402.         /* bad byte order byte */
  1403.         goto auth_err;
  1404.     }
  1405.  
  1406.     /* Check if the whole packet is in buffer. */
  1407.     if (len < 12 + ((name_len + 3) & ~3) + ((data_len + 3) & ~3))
  1408.         goto auth_err;
  1409.     /* If the Telnet Server allows a real Xauth message to be sent */
  1410.     /* Then let the message be processed by the Xserver.           */
  1411.     if (name_len + data_len > 0) {
  1412.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
  1413.        return(0);
  1414.     }
  1415.     else
  1416.     /* If an empty Xauth message was received.  We are going to   */
  1417.     /* send our own Xauth message using the real Xauth data.  And */
  1418.     /* then send any other data in the buffer.                    */
  1419.     {
  1420.         int c, err, dpynum, scrnum, family, sb_len;
  1421.         char *display, *host = NULL, *rest = NULL;
  1422.         unsigned char *sb, *p;
  1423.  
  1424.         /* parse the local DISPLAY env var */
  1425.         display = getenv("DISPLAY");
  1426.         if ( !display )
  1427.             display = "127.0.0.1:0.0";
  1428.  
  1429.         if (fwdx_parse_displayname(display,
  1430.                                    &family, &host, &dpynum, &scrnum, &rest)) {
  1431.             char * disp_no = ckitoa(dpynum);    /* should be unsigned */
  1432.             if (family == FamilyLocal) {
  1433.                 /* call with address = "<local host name>" */
  1434.                 char address[300] = "localhost";
  1435.                 gethostname(address, sizeof(address) - 1);
  1436.                 real_xauth = XauGetAuthByAddr(family,
  1437.                                               strlen(address),
  1438.                                               address,
  1439.                                               strlen(disp_no),
  1440.                                               disp_no, 0, NULL);
  1441.             }
  1442.             else if (family == FamilyInternet) {
  1443.                 /* call with address = 4 bytes numeric ip addr (MSB) */
  1444.                 struct hostent *hi;
  1445.                 if (hi = gethostbyname(host))
  1446.                     real_xauth = XauGetAuthByAddr(family, 4,
  1447.                                                   hi->h_addr, strlen(disp_no),
  1448.                                                   disp_no, 0, NULL);
  1449.             }
  1450.         }
  1451.         if (host) free(host);
  1452.         if (rest) free(rest);
  1453.         if (!real_xauth) {
  1454.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
  1455.             return(0);
  1456.         }
  1457.  
  1458.         if (!strncmp(real_xauth->name,
  1459.                      "MIT-MAGIC-COOKIE-1",
  1460.                      real_xauth->name_length)) {
  1461.             char msg[64];
  1462.  
  1463.             name_len = real_xauth->name_length;
  1464.             data_len = 16;
  1465.  
  1466.             if ( data[0] == 0x42 ) {
  1467.                 msg[0] = 0x42; /* MSB order */
  1468.                 msg[1] = msg[2] = 0;
  1469.                 msg[3] = 0x0B;
  1470.                 msg[4] = msg[5] = 0;
  1471.                 msg[6] = (name_len >> 8);
  1472.                 msg[7] = (name_len & 0xFF);
  1473.                 msg[8] = (data_len >> 8);
  1474.                 msg[9] = (data_len & 0xFF);
  1475.             } else {
  1476.                 msg[0] = 0x6c; /* LSB order */
  1477.                 msg[1] = 0;
  1478.                 msg[2] = 0x0B;
  1479.                 msg[3] = msg[4] = msg[5] = 0;
  1480.                 msg[6] = (name_len & 0xFF);
  1481.                 msg[7] = (name_len >> 8);
  1482.                 msg[8] = (data_len & 0xFF);
  1483.                 msg[9] = (data_len >> 8);
  1484.             }
  1485.             msg[10] = msg[11] = 0;
  1486.             memcpy(&msg[12],real_xauth->name,18);
  1487.             msg[30] = msg[31] = 0;
  1488.             memcpy(&msg[32],real_xauth->data,16);
  1489.  
  1490.             if (fwdx_write_data_to_channel(channel,(char *)msg,48) < 0) {
  1491.   TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
  1492.                 return(-1);
  1493.             } else {
  1494.   TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
  1495.                 return(12);
  1496.             }
  1497.         } else {
  1498.   TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[i].need_to_send_xauth = 0;
  1499.             return(0);        /* we do not know how to handle this type yet */
  1500.         }
  1501.     }
  1502.  
  1503.   auth_err:
  1504.         debug(F100,"fwdx_send_xauth_to_xserver error","",0);
  1505.     return(-1);
  1506. }
  1507.  
  1508.  
  1509. #ifdef COMMENT
  1510. int
  1511. #ifdef CK_ANSIC
  1512. fwdx_authorize_channel(int channel, unsigned char * data, int len)
  1513. #else
  1514. fwdx_authorize_channel(channel, data, len)
  1515.     int channel; unsigned char * data; int len;
  1516. #endif /* CK_ANSIC */
  1517. {
  1518.     /* XXX maybe we should have some retry handling if not the whole first
  1519.     * authorization packet arrives complete
  1520.     */
  1521.     if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized ) {
  1522.         int name_len, data_len;
  1523.  
  1524.         if (len < 12)
  1525.             goto auth_err;
  1526.  
  1527.         /* Parse the lengths of variable-length fields. */
  1528.         if (data[0] == 0x42) {          /* byte order MSB first. */
  1529.             /* Xauth packets appear to always have this format */
  1530.             if ( data[1] != 0x00 ||
  1531.                  data[2] != 0x00 ||
  1532.                  data[3] != 0x0B ||
  1533.                  data[4] != 0x00 ||
  1534.                  data[5] != 0x00 )
  1535.                 goto auth_err;
  1536.  
  1537.             name_len = (data[6] << 8) + data[7];
  1538.             data_len = (data[8] << 8) + data[9];
  1539.         } else if (data[0] == 0x6c) {   /* Byte order LSB first. */
  1540.             /* Xauth packets appear to always have this format */
  1541.             if ( data[1] != 0x00 ||
  1542.                  data[2] != 0x0B ||
  1543.                  data[3] != 0x00 ||
  1544.                  data[4] != 0x00 ||
  1545.                  data[5] != 0x00 )
  1546.                 goto auth_err;
  1547.  
  1548.             name_len = data[6] + (data[7] << 8);
  1549.             data_len = data[8] + (data[9] << 8);
  1550.         } else {
  1551.             /* bad byte order byte */
  1552.             goto auth_err;
  1553.         }
  1554.         /* Check if authentication protocol matches. */
  1555.         if (name_len != fake_xauth.name_length ||
  1556.              memcmp(data + 12, fake_xauth.name, name_len) != 0) {
  1557.             /* connection uses different authentication protocol */
  1558.             goto auth_err;
  1559.         }
  1560.         /* Check if authentication data matches our fake data. */
  1561.         if (data_len != fake_xauth.data_length ||
  1562.              memcmp(data + 12 + ((name_len + 3) & ~3),
  1563.                      fake_xauth.data, fake_xauth.data_length) != 0) {
  1564.             /* auth data does not match fake data */
  1565.             goto auth_err;
  1566.         }
  1567.         /* substitute the fake data with real data if we have any */
  1568.         if (real_xauth && real_xauth->data)
  1569.             memcpy(data + 12 + ((name_len + 3) & ~3),
  1570.                    real_xauth->data, data_len);
  1571.  
  1572.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[channel].authorized = 1;
  1573.     }
  1574.     return(0);
  1575.   auth_err:
  1576.     return(-1);
  1577. }
  1578. #endif /* COMMENT */
  1579.  
  1580. int
  1581. #ifdef CK_ANSIC
  1582. fwdx_send_close(int channel)
  1583. #else
  1584. fwdx_send_close(channel) int channel;
  1585. #endif /* CK_ANSIC */
  1586. {
  1587.     unsigned short nchannel;
  1588.     int i,rc;
  1589.     CHAR * p;
  1590.  
  1591. #ifdef CK_SSL
  1592.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1593.         return(0);
  1594.     }
  1595. #endif /* CK_SSL */
  1596.  
  1597.     nchannel = htons(channel);
  1598.     p = (unsigned char *) &nchannel;
  1599.  
  1600.     i = 0;
  1601.     sb_out[i++] = (CHAR) IAC;               /* I Am a Command */
  1602.     sb_out[i++] = (CHAR) SB;                /* Subnegotiation */
  1603.     sb_out[i++] = TELOPT_FORWARD_X;         /* Forward X */
  1604.     sb_out[i++] = FWDX_CLOSE;               /* Open */
  1605.     sb_out[i++] = p[0];                     /* First Byte of Channel */
  1606.     if ( p[0] == IAC )
  1607.         sb_out[i++] = IAC;
  1608.     sb_out[i++] = p[1];                     /* Second Byte of Channel */
  1609.     if ( p[1] == IAC )
  1610.         sb_out[i++] = IAC;
  1611.     sb_out[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  1612.     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
  1613. #ifdef DEBUG
  1614.     if (deblog || tn_deb || debses) {
  1615.         ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  1616.                   TELOPT(TELOPT_FORWARD_X),
  1617.                   " CLOSE CHANNEL=",ckitoa(channel)," IAC SE",
  1618.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL
  1619.                   );
  1620.     }
  1621. #endif /* DEBUG */
  1622. #ifdef OS2
  1623.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1624. #endif
  1625. #ifdef DEBUG
  1626.     debug(F100,fwdx_msg_out,"",0);
  1627.     if (tn_deb || debses) tn_debug(fwdx_msg_out);
  1628. #endif /* DEBUG */
  1629.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  1630. #ifdef OS2
  1631.     ReleaseTelnetMutex();
  1632. #endif
  1633.     if (rc)
  1634.       return(-1);
  1635.     return(0);
  1636. }
  1637.  
  1638. int
  1639. #ifdef CK_ANSIC
  1640. fwdx_send_open(int channel)
  1641. #else /* CK_ANSIC */
  1642. fwdx_send_open(channel) int channel;
  1643. #endif /* CK_ANSIC */
  1644. {
  1645.     unsigned short nchannel;
  1646.     int i, rc;
  1647.     CHAR * p;
  1648.  
  1649. #ifdef CK_SSL
  1650.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1651.         return(0);
  1652.     }
  1653. #endif /* CK_SSL */
  1654.  
  1655.     nchannel = htons(channel);
  1656.     p = (unsigned char *) &nchannel;
  1657.  
  1658.     i = 0;
  1659.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  1660.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  1661.     sb_out[i++] = TELOPT_FORWARD_X;           /* Forward X */
  1662.     sb_out[i++] = FWDX_OPEN;                  /* Open */
  1663.     sb_out[i++] = p[0];                       /* First Byte of Channel */
  1664.     if ( p[0] == IAC )
  1665.         sb_out[i++] = IAC;
  1666.     sb_out[i++] = p[1];                       /* Second Byte of Channel */
  1667.     if ( p[1] == IAC )
  1668.         sb_out[i++] = IAC;
  1669.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  1670.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  1671. #ifdef DEBUG
  1672.     if (deblog || tn_deb || debses) {
  1673.         ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  1674.                   TELOPT(TELOPT_FORWARD_X),
  1675.                   " OPEN CHANNEL=",ckitoa(channel)," IAC SE",
  1676.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  1677.     }
  1678. #endif /* DEBUG */
  1679. #ifdef OS2
  1680.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1681. #endif
  1682. #ifdef DEBUG
  1683.     debug(F100,fwdx_msg_out,"",0);
  1684.     if (tn_deb || debses) tn_debug(fwdx_msg_out);
  1685. #endif /* DEBUG */
  1686.     rc = (ttol((CHAR *)sb_out,i) < 0);        /* Send it. */
  1687. #ifdef OS2
  1688.     ReleaseTelnetMutex();
  1689. #endif
  1690.     if (rc)
  1691.       return(-1);
  1692.     return(0);
  1693. }
  1694.  
  1695. int
  1696. #ifdef CK_ANSIC
  1697. fwdx_client_reply_options(char *opts, int n)
  1698. #else
  1699. fwdx_client_reply_options(opts, n) char *opts; int n;
  1700. #endif /* CK_ANSIC */
  1701. {
  1702.     int i,j,rc;
  1703.  
  1704. #ifdef CK_SSL
  1705.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1706.         return(0);
  1707.     }
  1708. #endif /* CK_SSL */
  1709.  
  1710.     i = 0;
  1711.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  1712.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  1713.     sb_out[i++] = TELOPT_FORWARD_X;           /* Forward X */
  1714.     sb_out[i++] = FWDX_OPTIONS;               /* Options */
  1715.  
  1716.     /* Look for the options we recognize and will support for this session */
  1717.     /* and reply with their bytes set                                      */
  1718.     for (j=0; j<n; j++,i++) {
  1719.         sb_out[i] = FWDX_OPT_NONE;          /* Add zero byte - no options */
  1720. #ifdef COMMENT
  1721.         /* If we had any options to support, this is how we would do it */
  1722.         if ( j == 0 ) {
  1723.             if (opts[j] & FWDX_OPT_XXXX) {
  1724.                 /* set flag to remember option is in use */
  1725.                 flag = 1;
  1726.                 sb_out[i] |= FWDX_OPT_XXXX;
  1727.             }
  1728.         }
  1729. #endif /* COMMENT */
  1730.     }
  1731.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  1732.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  1733. #ifdef DEBUG
  1734.     if (deblog || tn_deb || debses) {
  1735.         ckmakxmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  1736.                   TELOPT(TELOPT_FORWARD_X),
  1737.                   " OPTIONS ",ckctox(sb_out[4],1)," IAC SE",
  1738.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  1739.     }
  1740. #endif /* DEBUG */
  1741. #ifdef OS2
  1742.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1743. #endif
  1744. #ifdef DEBUG
  1745.     debug(F100,fwdx_msg_out,"",0);
  1746.     if (tn_deb || debses) tn_debug(fwdx_msg_out);
  1747. #endif /* DEBUG */
  1748.     rc = (ttol((CHAR *)sb_out,i) < 0);        /* Send it. */
  1749. #ifdef OS2
  1750.     ReleaseTelnetMutex();
  1751. #endif
  1752.     if (rc)
  1753.       return(-1);
  1754.     return(0);
  1755. }
  1756.  
  1757.  
  1758. int
  1759. fwdx_send_options() {
  1760.     int i, rc;
  1761.  
  1762. #ifdef CK_SSL
  1763.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1764.         return(0);
  1765.     }
  1766. #endif /* CK_SSL */
  1767.  
  1768.     i = 0;
  1769.     sb_out[i++] = (CHAR) IAC;               /* I Am a Command */
  1770.     sb_out[i++] = (CHAR) SB;                /* Subnegotiation */
  1771.     sb_out[i++] = TELOPT_FORWARD_X;         /* Forward X */
  1772.     sb_out[i++] = FWDX_OPTIONS;             /* Options */
  1773.     sb_out[i]   = FWDX_OPT_NONE;
  1774.     /* activate options here */
  1775.     i++;
  1776.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  1777.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  1778.  
  1779. #ifdef DEBUG
  1780.     if (deblog || tn_deb || debses) {
  1781.         ckmakmsg(fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  1782.                  TELOPT(TELOPT_FORWARD_X),
  1783.                  " OPTIONS 00 IAC SE",NULL);
  1784.     }
  1785. #endif /* DEBUG */
  1786. #ifdef OS2
  1787.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1788. #endif
  1789. #ifdef DEBUG
  1790.     debug(F100,fwdx_msg_out,"",0);
  1791.     if (tn_deb || debses) tn_debug(fwdx_msg_out);
  1792. #endif /* DEBUG */
  1793.     rc = (ttol((CHAR *)sb_out,i) < 0);        /* Send it. */
  1794. #ifdef OS2
  1795.     ReleaseTelnetMutex();
  1796. #endif
  1797.     if (rc)
  1798.       return(-1);
  1799.     return(0);
  1800. }
  1801.  
  1802. int
  1803. #ifdef CK_ANSIC
  1804. fwdx_send_data_from_channel(int channel, char * data, int len)
  1805. #else
  1806. fwdx_send_data_from_channel(channel, data, len)
  1807.     int channel; char * data; int len;
  1808. #endif
  1809. {
  1810.     unsigned short nchannel;
  1811.     /* static */ CHAR sb_priv[2048];
  1812.     CHAR * p;
  1813.     int i, j, j_sav, rc;
  1814.     unsigned int tmp;
  1815.  
  1816.     debug(F111,"fwdx_send_data_from_channel()","channel",channel);
  1817.  
  1818. #ifdef CK_SSL
  1819.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1820.         return(0);
  1821.     }
  1822. #endif /* CK_SSL */
  1823.  
  1824.     nchannel = htons(channel);
  1825.     p = (unsigned char *) &nchannel;
  1826.  
  1827.     j = 0;
  1828.     sb_priv[j++] = (CHAR) IAC;                 /* I Am a Command */
  1829.     sb_priv[j++] = (CHAR) SB;                  /* Subnegotiation */
  1830.     sb_priv[j++] = TELOPT_FORWARD_X;           /* Forward X */
  1831.     sb_priv[j++] = FWDX_DATA;                  /* Data */
  1832.     sb_priv[j++] = p[0];                       /* First Byte of Channel */
  1833.     if ( p[0] == IAC )
  1834.         sb_priv[j++] = IAC;
  1835.     sb_priv[j++] = p[1];                       /* Second Byte of Channel */
  1836.     if ( p[1] == IAC )
  1837.         sb_priv[j++] = IAC;
  1838.     j_sav = j;
  1839.  
  1840.     for (i = 0; i < len; i++) {
  1841.         tmp = (unsigned int)data[i];
  1842.         if ( tmp == IAC ) {
  1843.             sb_priv[j++] = IAC;
  1844.             sb_priv[j++] = IAC;
  1845.         } else {
  1846.             sb_priv[j++] = tmp;
  1847.         }
  1848.         if ( j >= 2045 && (i < len-1) ) {
  1849.             sb_priv[j++] = (CHAR) IAC;  /* End of Subnegotiation */
  1850.             sb_priv[j++] = (CHAR) SE;   /* marked by IAC SE */
  1851.  
  1852. #ifdef DEBUG
  1853.             if (deblog || tn_deb || debses) {
  1854.                 ckmakxmsg( fwdx_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  1855.                            TELOPT(TELOPT_FORWARD_X),
  1856.                            " DATA CHANNEL=",ckitoa(channel)," ",
  1857.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL );
  1858.                 tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[j_sav],j-(j_sav+2));
  1859.                 ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
  1860.             }
  1861. #endif /* DEBUG */
  1862. #ifdef OS2
  1863.             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1864. #endif
  1865. #ifdef DEBUG
  1866.             debug(F100,fwdx_msg_out,"",0);
  1867.             if (tn_deb || debses) tn_debug(fwdx_msg_out);
  1868. #endif /* DEBUG */
  1869.             rc = (ttol(sb_priv,j) < 0);                /* Send it. */
  1870. #ifdef OS2
  1871.             ReleaseTelnetMutex();
  1872. #endif
  1873.             if (rc) {
  1874.                 debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
  1875.                 return(-1);
  1876.             }
  1877.  
  1878.             j = 0;
  1879.             sb_priv[j++] = (CHAR) IAC;                 /* I Am a Command */
  1880.             sb_priv[j++] = (CHAR) SB;                  /* Subnegotiation */
  1881.             sb_priv[j++] = TELOPT_FORWARD_X;           /* Forward X */
  1882.             sb_priv[j++] = FWDX_DATA;                  /* Data */
  1883.             sb_priv[j++] = p[0];                       /* First Byte of Channel */
  1884.             if ( p[0] == IAC )
  1885.                 sb_priv[j++] = IAC;
  1886.             sb_priv[j++] = p[1];                       /* Second Byte of Channel */
  1887.             if ( p[1] == IAC )
  1888.                 sb_priv[j++] = IAC;
  1889.         }
  1890.     }
  1891.  
  1892.     sb_priv[j++] = (CHAR) IAC;                 /* End of Subnegotiation */
  1893.     sb_priv[j++] = (CHAR) SE;                  /* marked by IAC SE */
  1894.  
  1895. #ifdef DEBUG
  1896.     if (deblog || tn_deb || debses) {
  1897.         ckmakxmsg( fwdx_msg_out,TN_MSG_LEN,
  1898.                    "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
  1899.                    " DATA ",ckctox(p[0],1)," ",ckctox(p[1],1)," ",
  1900.                    NULL,NULL,NULL,NULL,NULL);
  1901.         tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[6],j-8);
  1902.         ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
  1903.     }
  1904. #endif /* DEBUG */
  1905. #ifdef OS2
  1906.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1907. #endif
  1908. #ifdef DEBUG
  1909.     debug(F100,fwdx_msg_out,"",0);
  1910.     if (tn_deb || debses) tn_debug(fwdx_msg_out);
  1911. #endif /* DEBUG */
  1912.     rc = (ttol(sb_priv,j) < 0);                /* Send it. */
  1913. #ifdef OS2
  1914.     ReleaseTelnetMutex();
  1915. #endif
  1916.     if ( rc ) {
  1917.         debug(F110,"fwdx_send_data_from_channel()","ttol() failed",0);
  1918.         return(-1);
  1919.     }
  1920.  
  1921.  
  1922.     return(0);
  1923. }
  1924.  
  1925. static unsigned char *
  1926. #ifdef CK_ANSIC
  1927. fwdx_add_quoted_twobyte(unsigned char *p, unsigned short twobyte)
  1928. #else
  1929. fwdx_add_quoted_twobyte(p, twobyte)
  1930.     unsigned char *p; unsigned short twobyte;
  1931. #endif /* CK_ANSIC */
  1932. /* adds the IAC quoted (MSB) representation of 'channel' at buffer pointer 'p',
  1933.  * returning pointer to new buffer position. NO OVERFLOW CHECK!
  1934.  */
  1935. {
  1936.     *p++ = (unsigned char)((twobyte >> 8) & 0xFF);
  1937.     if (*(p - 1) == 0xFF)
  1938.         *p++ = 0xFF;
  1939.     *p++ = (unsigned char)(twobyte & 0xFF);
  1940.     if (*(p - 1) == 0xFF)
  1941.         *p++ = 0xFF;
  1942.     return p;
  1943. }
  1944.  
  1945. int
  1946. #ifdef CK_ANSIC
  1947. fwdx_create_fake_xauth(char *name, int name_len, int data_len)
  1948. #else
  1949. fwdx_create_fake_xauth(name, name_len, data_len)
  1950.     char *name; int name_len; int data_len;
  1951. #endif /* CK_ANSIC */
  1952. {
  1953.     char stackdata[256];
  1954.     unsigned int c, n;
  1955.  
  1956.     if (!name_len || !data_len)
  1957.         return 1;
  1958.     fake_xauth.name = malloc(name_len);
  1959.     fake_xauth.data = malloc(data_len);
  1960.     if (!fake_xauth.name || !fake_xauth.data)
  1961.         return 2;
  1962.     fake_xauth.name_length = name_len;
  1963.     memcpy(fake_xauth.name, name, name_len);
  1964.     fake_xauth.data_length = data_len;
  1965.  
  1966.     /* try to make a random unsigned int to feed srand() */
  1967.     c = time(NULL);
  1968.     c *= getpid();
  1969.     for (n = 0; n < sizeof(stackdata); n++)
  1970.         c += stackdata[n];
  1971.     srand((unsigned int)c);
  1972.     for (c = 0; c < data_len; c++)
  1973.         fake_xauth.data[c] = (unsigned char)rand();
  1974.     return 0;
  1975. }
  1976.  
  1977. #ifdef COMMENT
  1978. /* No longer used */
  1979. int
  1980. fwdx_send_xauth(void)
  1981. {
  1982.     int c, err, dpynum, family, sb_len, rc;
  1983.     char *display, *host = NULL;
  1984.     unsigned char *sb_priv, *p;
  1985.  
  1986.     /* parse the local DISPLAY env var */
  1987.     if (!(display = tn_get_display()))
  1988.         return (-1);
  1989.     if (fwdx_parse_displayname(display, &family, &host, &dpynum, NULL, NULL)) {
  1990.         char * disp_no = ckitoa(dpynum);
  1991.         if (family == FamilyLocal) {
  1992.             /* call with address = "<local host name>" */
  1993.             char address[300] = "localhost";
  1994.             gethostname(address, sizeof(address) - 1);
  1995.             real_xauth = XauGetAuthByAddr(family,
  1996.                                           strlen(address),
  1997.                                           address,
  1998.                                           strlen(disp_no),
  1999.                                           disp_no, 0, NULL
  2000.                                           );
  2001.         }
  2002.         else if (family == FamilyInternet) {
  2003.             /* call with address = 4 bytes numeric ip addr (MSB) */
  2004.             struct hostent *hi;
  2005.             if (hi = gethostbyname(host))
  2006.                 real_xauth = XauGetAuthByAddr(family, 4,
  2007.                                               hi->h_addr,
  2008.                                               strlen(disp_no),
  2009.                                               disp_no, 0, NULL
  2010.                                               );
  2011.         }
  2012.     }
  2013.     if (host) {
  2014.         free(host);
  2015.         host = NULL;
  2016.     }
  2017.     if (real_xauth)
  2018.         err = fwdx_create_fake_xauth(real_xauth->name,
  2019.                                      real_xauth->name_length,
  2020.                                      real_xauth->data_length
  2021.                                      );
  2022.     else
  2023.       err = fwdx_create_fake_xauth("MIT-MAGIC-COOKIE-1",
  2024.                                    strlen("MIT-MAGIC-COOKIE-1"), 16);
  2025.     if (err)
  2026.         return(-1);
  2027.  
  2028.     /* allocate memory for the SB block, alloc for worst case              */
  2029.     /* the following sprintf() calls are safe due to length checking       */
  2030.     /* buffer is twice as big as the input just in case every byte was IAC */
  2031.     sb_len = 5 + 2 + 2 + fake_xauth.name_length + fake_xauth.data_length + 2;
  2032.     if (!(sb_priv = malloc(2 * sb_len)))
  2033.         return(-1);
  2034.     p = sb_priv;
  2035.     sprintf(p, "%c%c%c%c%c", IAC, SB, TELOPT_FORWARD_X,
  2036.             FWDX_OPT_DATA, FWDX_OPT_XAUTH);
  2037.     p += 5;
  2038.     p = fwdx_add_quoted_twobyte(p, fake_xauth.name_length);
  2039.     p = fwdx_add_quoted_twobyte(p, fake_xauth.data_length);
  2040.     for (c = 0; c < fake_xauth.name_length; c++) {
  2041.         *p++ = fake_xauth.name[c];
  2042.         if ((unsigned char)fake_xauth.name[c] == 0xFF)
  2043.             *p++ = 0xFF;
  2044.     }
  2045.     for (c = 0; c < fake_xauth.data_length; c++) {
  2046.         *p++ = fake_xauth.data[c];
  2047.         if ((unsigned char)fake_xauth.data[c] == 0xFF)
  2048.             *p++ = 0xFF;
  2049.     }
  2050.     sprintf(p, "%c%c", IAC, SE);
  2051.     p += 2;
  2052.  
  2053. #ifdef DEBUG
  2054.     if (deblog || tn_deb || debses) {
  2055.         sprintf(fwdx_msg_out,"TELNET SENT SB %s OPTION_DATA XAUTH ",
  2056.                  TELOPT(TELOPT_FORWARD_X));
  2057.         tn_hex(fwdx_msg_out,TN_MSG_LEN,&sb_priv[5],(p-sb_priv)-7);
  2058.         ckstrncat(fwdx_msg_out," IAC SE",TN_MSG_LEN);
  2059.     }
  2060. #endif /* DEBUG */
  2061.  
  2062.     /* Add Telnet Debug info here */
  2063. #ifdef OS2
  2064.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2065. #endif
  2066. #ifdef DEBUG
  2067.     debug(F100,fwdx_msg_out,"",0);
  2068.     if (tn_deb || debses) tn_debug(fwdx_msg_out);
  2069. #endif /* DEBUG */
  2070.     rc = ( ttol(sb_priv,p-sb_priv) < 0 );                /* Send it. */
  2071. #ifdef OS2
  2072.     ReleaseTelnetMutex();
  2073. #endif
  2074.     if (rc) {
  2075.         debug(F110,"fwdx_send_xauth()","ttol() failed",0);
  2076.         return(-1);
  2077.     }
  2078.  
  2079.  
  2080.     free(sb_priv);
  2081.     return(0);
  2082. }
  2083. #endif /* COMMENT */
  2084. #ifdef FWDX_SERVER
  2085. /* Only if we ever become a server - not yet ported to Kermit   */
  2086. /* And even so most of this code does not belong in this module */
  2087.  
  2088. int
  2089. fwdx_write_xauthfile(void)
  2090. {
  2091.     int dpynum, scrnum, family;
  2092.     char myhost[300], *host, *rest = NULL;
  2093.     FILE *file;
  2094.     struct sockaddr_in saddr;
  2095.     struct hostent *hi;
  2096.  
  2097.     if (!fwdx_display && !fwdx_xauthfile)
  2098.         return 1;
  2099.     if (!parse_displayname(fwdx_display,
  2100.                            &family, &host, &dpynum, &scrnum, &rest))
  2101.         return 2;
  2102.     if (rest) free(rest);
  2103.     if (host) free(host);
  2104.     if (family != FamilyInternet)
  2105.         return 3; /* every thing but FamilyInternet is unexpected */
  2106.  
  2107.     /* X connections to localhost:1 is actually treated as local unix sockets,
  2108.      * see the 'xauth' man page.
  2109.      */
  2110.     xauth.family = FamilyLocal;
  2111.     if (gethostname(myhost, sizeof(myhost) - 1))
  2112.         return 5;
  2113.     xauth.address_length = strlen(myhost);
  2114.     if (!(xauth.address = malloc(xauth.address_length)))
  2115.         return 5;
  2116.     memcpy(xauth.address, myhost, xauth.address_length);
  2117.  
  2118.     /* the display number is written as a string, not numeric */
  2119.     if (!(xauth.number = malloc(6)))
  2120.         return 6;
  2121.     snprintf(xauth.number, 5, "%u", dpynum);
  2122.     xauth.number_length = strlen(xauth.number);
  2123.     if (!(file = fopen(fwdx_xauthfile, "wb")))
  2124.         return 7;
  2125.     if (!XauWriteAuth(file, &xauth))
  2126.         return 8;
  2127.     fclose(file);
  2128.     setenv("XAUTHORITY", fwdx_xauthfile, 1);
  2129.     return 0;
  2130. }
  2131.  
  2132. int
  2133. fwdx_setup_xauth(unsigned char *sp, int len)
  2134. /* called with 'len' xauth bytes, starting at 'sp'
  2135.  * the data format is: <uint16 name_length> <uint16 data_length> <name> <data>
  2136.  */
  2137. {
  2138.     int xauthfd;
  2139.  
  2140.     if (!fwdx_options[FWDX_OPT_XAUTH])
  2141.         return 1;
  2142.     if (len < 4)
  2143.         return 2;
  2144.  
  2145.     /* setup the xauth struct */
  2146.     xauth.name_length = (sp[0] << 8) + sp[1];
  2147.     xauth.data_length = (sp[2] << 8) + sp[3];
  2148.     if (len != 4 + xauth.name_length + xauth.data_length)
  2149.         return 3;
  2150.     xauth.name = malloc(xauth.name_length);
  2151.     xauth.data = malloc(xauth.data_length);
  2152.     if (!xauth.name || !xauth.data)
  2153.         return 4;
  2154.     memcpy(xauth.name, sp + 4, xauth.name_length);
  2155.     memcpy(xauth.data, sp + 4 + xauth.name_length, xauth.data_length);
  2156.  
  2157.     /* Setup to always have a local .Xauthority. */
  2158.     fwdx_xauthfile = malloc(MAXPATHLEN+1);
  2159.     snprintf(fwdx_xauthfile, MAXPATHLEN, "/tmp/XauthXXXXXX");
  2160.     if ((xauthfd = mkstemp(fwdx_xauthfile)) != -1)
  2161.         /* we change file ownership later, when we know who is to be owner! */
  2162.         close(xauthfd);
  2163.     else {
  2164.         free(fwdx_xauthfile);
  2165.         fwdx_xauthfile = NULL;
  2166.         return 5;
  2167.     }
  2168. /* Must have the subshell's new DISPLAY env var to write xauth to xauthfile */
  2169.     if (fwdx_display)
  2170.         if (fwdx_write_xauthfile())
  2171.             return 6;
  2172.  
  2173.     return 0;
  2174. }
  2175.  
  2176. void fwdx_set_xauthfile_owner(int uid)
  2177. {
  2178.     struct passwd *pwd;
  2179.  
  2180.     if (!fwdx_xauthfile || !(pwd = getpwuid(uid)))
  2181.         return;
  2182.     chown(fwdx_xauthfile, pwd->pw_uid, pwd->pw_gid);
  2183. }
  2184.  
  2185. int
  2186. fwdx_server_accept_options(unsigned char *sp, int len)
  2187. /* called with 'len' option bytes, starting at 'sp' */
  2188. {
  2189.     int c;
  2190.  
  2191.     for (c = 0; c < len-2; c++) {
  2192.         if (c == 0) {
  2193.             if (sp[c] & FWDX_OPT_XAUTH)
  2194.                 flag = 1;
  2195.         }
  2196.     }
  2197.     return(0);
  2198. }
  2199. #endif /* FWDX_SERVER */
  2200. #endif /* CK_FORWARD_X */
  2201.  
  2202. #ifdef IKS_OPTION
  2203. /*
  2204.   iks_wait() -- Wait for an IKS subnegotiation response.
  2205.   sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
  2206.        state of the peer's Kermit server.
  2207.   flushok - specifies whether it is ok to throw away non-Telnet data
  2208.        if so, then we call ttflui() instead of tn_flui().
  2209.   Returns:
  2210.    1 if the desired state is achieved or if it is unknown.
  2211.    0 if the desired state is not achieved.
  2212. */
  2213. int
  2214. #ifdef CK_ANSIC
  2215. iks_wait(int sb, int flushok)
  2216. #else /* CK_ANSIC */
  2217. iks_wait(sb,flushok) int sb; int flushok;
  2218. #endif /* CK_ANSIC */
  2219. {
  2220.     int tn_wait_save = tn_wait_flg;
  2221.     int x;
  2222.  
  2223.     if (TELOPT_U(TELOPT_KERMIT)) {
  2224.         switch (sb) {
  2225.           case KERMIT_REQ_START:
  2226.             debug(F111,
  2227.                   "iks_wait KERMIT_REQ_START",
  2228.                   "u_start",
  2229.                   TELOPT_SB(TELOPT_KERMIT).kermit.u_start
  2230.                   );
  2231.             tn_siks(KERMIT_REQ_START);
  2232.             tn_wait_flg = 1;            /* Kermit Option MUST wait */
  2233.             do {
  2234.                 if (flushok)
  2235.                   tn_wait_idx = 0;
  2236.                 x = tn_wait("iks_wait() me_iks_req_start");
  2237.             } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
  2238.             tn_wait_flg = tn_wait_save;
  2239.             if (flushok)
  2240.               tn_wait_idx = 0;
  2241.             if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  2242.                 /*
  2243.                  * We are attempting to start a kermit server on the peer
  2244.                  * the most likely reason is because we want to perform a
  2245.                  * file transfer.  But there is a huge amount of non telnet
  2246.                  * negotiation data coming in and so we have not been able
  2247.                  * to find the response.  So we will lie and assume that
  2248.                  * response is 'yes'.  The worse that will happen is that
  2249.                  * a RESP_STOP is received after we enter protocol mode.
  2250.                  * And the protocol operation will be canceled.
  2251.                  */
  2252.                 tn_push();
  2253.                 return(1);
  2254.             } else {
  2255.                 tn_push();
  2256.                 return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
  2257.             }
  2258.           case KERMIT_REQ_STOP:
  2259.             debug(F111,
  2260.                   "iks_wait KERMIT_REQ_STOP",
  2261.                   "u_start",
  2262.                   TELOPT_SB(TELOPT_KERMIT).kermit.u_start
  2263.                   );
  2264.             tn_siks(KERMIT_REQ_STOP);
  2265.             tn_wait_flg = 1;            /* Kermit Option MUST wait */
  2266.             do {
  2267.                 if (flushok)
  2268.                   tn_wait_idx = 0;
  2269.                 x = tn_wait("iks_wait() me_iks_req_stop");
  2270.             } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
  2271.             tn_wait_flg = tn_wait_save;
  2272.             if (flushok)
  2273.               tn_wait_idx = 0;
  2274.  
  2275.             if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  2276.                 /*
  2277.                  * We are attempting to stop a kermit server on the peer
  2278.                  * the most likely reason being that we want to enter
  2279.                  * CONNECT mode.  But there is a huge amount of non telnet
  2280.                  * negotiation data coming in and so we have not been able
  2281.                  * to find the response.  So we will lie and assume that
  2282.                  * the answer is 'yes' and allow the CONNECT command to
  2283.                  * succeed.  The worst that happens is that CONNECT mode
  2284.                  * swallows the incoming data displaying it to the user
  2285.                  * and then it resumes Kermit client mode.
  2286.                  */
  2287.                 tn_push();
  2288.                 return(1);
  2289.             } else {
  2290.                 tn_push();
  2291.                 return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
  2292.             }
  2293.         }
  2294.         tn_push();
  2295.     }
  2296.     return(1);
  2297. }
  2298.  
  2299. int
  2300. #ifdef CK_ANSIC
  2301. iks_tn_sb(CHAR * sb, int n)
  2302. #else
  2303. iks_tn_sb(sb, n) CHAR * sb; int n;
  2304. #endif /* CK_ANSIC */
  2305. {
  2306.     extern int server;
  2307.     extern CHAR sstate;
  2308. #ifdef NOICP
  2309.     extern int autodl;
  2310.     int inautodl = 0, cmdadl = 1;
  2311. #else
  2312. #ifdef CK_AUTODL
  2313.     extern int autodl, inautodl, cmdadl;
  2314. #endif /* CK_AUTODL */
  2315. #endif /* NOICP */
  2316.     switch (sb[0]) {
  2317.       case KERMIT_START:                /* START */
  2318.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
  2319.         return(4);
  2320.  
  2321.       case KERMIT_STOP:                 /* STOP */
  2322.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  2323.         return(4);
  2324.  
  2325.       case KERMIT_REQ_START:            /* REQ-START */
  2326. #ifndef NOXFER
  2327.         if (inserver) {
  2328. #ifdef CK_AUTODL
  2329.             cmdadl = 1;                 /* Turn on packet detection */
  2330. #endif /* CK_AUTODL */
  2331.             TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
  2332.             tn_siks(KERMIT_RESP_START);
  2333.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
  2334.             tn_siks(KERMIT_RESP_START);
  2335.         } else {
  2336. #ifndef IKSDONLY
  2337. #ifdef CK_AUTODL
  2338. #ifdef OS2
  2339.             if (local && (IsConnectMode() && autodl) ||
  2340.                 (!IsConnectMode() && 
  2341.                   (inautodl || sstate == 'x' || sstate == 'v'))
  2342.                 )
  2343.               tn_siks(KERMIT_RESP_START); /* START */
  2344.             else
  2345.  
  2346. #else /* OS2 */
  2347.             if ((local && what == W_CONNECT && autodl) ||
  2348.                 (local && what != W_CONNECT &&
  2349.                   (inautodl || sstate == 'x' || sstate == 'v')
  2350.                 ))
  2351.               tn_siks(KERMIT_RESP_START); /* START */
  2352.             else
  2353. #endif /* OS2 */
  2354. #endif /* CK_AUTODL */
  2355. #endif /* IKSDONLY */
  2356.               tn_siks(KERMIT_RESP_STOP);
  2357.         }
  2358. #else /* NOXFER */
  2359.           tn_siks(KERMIT_RESP_STOP);
  2360. #endif /* NOXFER */
  2361.         return(4);
  2362.  
  2363.       case KERMIT_REQ_STOP:             /* REQ-STOP */
  2364.         /* The protocol requires that the request be responded to */
  2365.         /* either by changing states or by reporting the current  */
  2366.         /* state.  */
  2367.  
  2368.         /* We need to provide the user some way of dictating what */
  2369.         /* the policies should be.  For instance, if we are in    */
  2370.         /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
  2371.         /* what should the proper response be?                    */
  2372. #ifndef NOXFER
  2373.         if (inserver
  2374. #ifdef CK_AUTODL
  2375.             || !local && cmdadl
  2376. #endif /* CK_AUTODL */
  2377.             ) {
  2378. #ifdef CK_AUTODL
  2379.             cmdadl = 0;                 /* Turn off packet detection */
  2380. #endif /* CK_AUTODL */
  2381.             tn_siks(KERMIT_RESP_STOP);
  2382.         } else if (server) {
  2383.             extern int en_fin;
  2384.             if (en_fin) {               /* If the server is allowed to stop */
  2385.                 tn_siks(KERMIT_RESP_STOP);
  2386.             } else {                    /* We are not allowed to stop */
  2387.                 tn_siks(KERMIT_RESP_START);
  2388.             }
  2389.         }
  2390. #ifndef IKSDONLY
  2391. #ifdef CK_AUTODL
  2392. #ifdef OS2
  2393.         else if (local && (IsConnectMode() && autodl) ||
  2394.                    (!IsConnectMode() && inautodl)
  2395.                    ) {
  2396.             /* If we are a pseudo-server and the other side requests */
  2397.             /* that we stop, tell then that we have even though we   */
  2398.             /* have not.  Otherwise, the other side might refuse to  */
  2399.             /* enter SERVER mode.                                    */
  2400.  
  2401.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  2402.         }
  2403. #else /* OS2 */
  2404.         else if ((local && what == W_CONNECT && autodl) ||
  2405.                    (local && what != W_CONNECT && inautodl)
  2406.                    ) {
  2407.             /* If we are a pseudo-server and the other side requests */
  2408.             /* that we stop, tell then that we have even though we   */
  2409.             /* have not.  Otherwise, the other side might refuse to  */
  2410.             /* enter SERVER mode.                                    */
  2411.  
  2412.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  2413.         }
  2414. #endif /* OS2 */
  2415. #endif /* CK_AUTODL */
  2416. #endif /* IKSDONLY */
  2417.         else
  2418. #endif /* NOXFER */
  2419.         {
  2420.             /* If we are not currently in any mode that accepts */
  2421.             /* Kermit packets then of course report that we are */
  2422.             /* not being a Kermit server.                       */
  2423.  
  2424.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  2425.         }
  2426.         return(4);
  2427.  
  2428.       case KERMIT_SOP: {                /* SOP */
  2429. #ifndef NOXFER
  2430.           extern CHAR stchr;            /* Incoming SOP character */
  2431.           stchr = sb[1];
  2432. #endif /* NOXFER */
  2433.           TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
  2434.           return(4);
  2435.       }
  2436.  
  2437.       case KERMIT_RESP_START:           /* START */
  2438.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
  2439.         if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
  2440.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  2441.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
  2442.             /* If we have issued a request to stop a Kermit Server */
  2443.             /* and the response is Start, then we must report this */
  2444.             /* to the caller.                                      */
  2445.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  2446.         }
  2447.         return(4);
  2448.  
  2449.       case KERMIT_RESP_STOP:            /* STOP */
  2450.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  2451.         if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
  2452.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  2453.             /* If we have issued a request to start a Kermit Server */
  2454.             /* and the response is Stop, then we must report this   */
  2455.             /* to the caller.                                       */
  2456.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
  2457.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  2458.         }
  2459.         return(4);
  2460.  
  2461.       default:
  2462.         return(0);
  2463.  
  2464.     } /* switch (sb[0]) */
  2465. }
  2466. #endif /* IKS_OPTION */
  2467.  
  2468. /* Initialize telnet settings - set default values for ME and U modes */
  2469. int
  2470. tn_set_modes() {
  2471.     int opt,cmd;
  2472. #ifdef CK_FORWARD_X
  2473.     int x;
  2474. #endif /* CK_FORWARD_X */
  2475. #ifdef CK_ENVIRONMENT
  2476.     {
  2477.         int i,j;
  2478.         for (i = 0; i < 8; i++) {
  2479.             tn_env_uservar[i][0] = NULL;
  2480.             tn_env_uservar[i][1] = NULL;
  2481.         }
  2482.     }
  2483. #endif /* CK_ENVIRONMENT */
  2484.  
  2485.     /* initialize all options to refuse in both directions */
  2486.     for (opt = 0; opt < NTELOPTS; opt++) {
  2487.         TELOPT_ME(opt) = 0;
  2488.         TELOPT_U(opt)  = 0;
  2489.         TELOPT_UNANSWERED_WILL(opt) = 0;
  2490.         TELOPT_UNANSWERED_DO(opt)   = 0;
  2491.         TELOPT_UNANSWERED_WONT(opt) = 0;
  2492.         TELOPT_UNANSWERED_DONT(opt)   = 0;
  2493.         TELOPT_UNANSWERED_SB(opt)   = 0;
  2494.         TELOPT_ME_MODE(opt) = TN_NG_RF;
  2495.         TELOPT_U_MODE(opt) = TN_NG_RF;
  2496.         TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
  2497.         TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
  2498.         TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
  2499.         TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
  2500.         for (cmd = 0; cmd < 4; cmd ++)
  2501.           tncnts[TELOPT_INDEX(opt)][cmd] = 0;
  2502.     }
  2503. #ifdef IKS_OPTION
  2504.     TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  2505.     TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  2506.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  2507.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  2508.     TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
  2509. #endif /* IKS_OPTION */
  2510.  
  2511. #ifdef CK_ENCRYPTION
  2512.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  2513. #endif /* CK_ENCRYPTION */
  2514.  
  2515. #ifdef  CK_NAWS
  2516.     TELOPT_SB(TELOPT_NAWS).naws.x = 0;
  2517.     TELOPT_SB(TELOPT_NAWS).naws.y = 0;
  2518. #endif /* CK_NAWS */
  2519.  
  2520. #ifdef CK_SSL
  2521.     TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
  2522.     TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
  2523.     TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
  2524. #endif /* CK_SSL */
  2525.  
  2526.     /* Now set the ones we want to accept to the proper values */
  2527.     TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
  2528.     TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
  2529.     TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
  2530.     TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
  2531.  
  2532.     TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
  2533.     TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
  2534.     TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
  2535.     TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
  2536.  
  2537.     TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  2538.     TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  2539.     TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  2540.     TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  2541.  
  2542. #ifdef IKS_OPTION
  2543.     TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  2544.     TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  2545.     TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  2546.     TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  2547. #endif /* IKS_OPTION */
  2548.  
  2549. #ifdef CK_ENCRYPTION
  2550.     TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  2551.     TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  2552.     TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  2553.     TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  2554. #endif /* CK_ENCRYPTION */
  2555.  
  2556.     TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
  2557. #ifdef IKSD
  2558.     if ( !inserver )
  2559. #endif /* IKSD */
  2560.       TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
  2561.  
  2562. #ifdef CK_ENVIRONMENT
  2563.     TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
  2564. #endif /* CK_ENVIRONMENT */
  2565.  
  2566. #ifdef CK_AUTHENTICATION
  2567.     TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  2568. #endif /* CK_AUTHENTICATION */
  2569.  
  2570. #ifdef CK_SSL
  2571.     if (ck_ssleay_is_installed()) {
  2572.         TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
  2573.         TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
  2574.     }
  2575. #endif /* CK_SSL */
  2576.  
  2577. #ifdef CK_NAWS
  2578.     TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
  2579. #endif /* CK_NAWS */
  2580.  
  2581.     TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
  2582.     TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
  2583.  
  2584. #ifdef CK_ENVIRONMENT
  2585.     TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
  2586. #endif /* CK_ENVIRONMENT */
  2587.  
  2588. #ifdef CK_AUTHENTICATION
  2589.     TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  2590. #endif /* CK_AUTHENTICATION */
  2591.  
  2592. #ifdef CK_NAWS
  2593.     TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
  2594. #endif /* CK_NAWS */
  2595.  
  2596. #ifdef CK_SNDLOC
  2597.     TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
  2598. #endif /* CK_SNDLOC */
  2599.  
  2600. #ifdef CK_FORWARD_X
  2601.     TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_AC;
  2602.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
  2603.     for (x = 0; x < MAXFWDX; x++) {
  2604.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
  2605.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
  2606.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
  2607.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
  2608.     }
  2609. #endif /* CK_FORWARD_X */
  2610.  
  2611. #ifdef TN_COMPORT
  2612.     TELOPT_DEF_C_ME_MODE(TELOPT_COMPORT) = TN_NG_RQ;
  2613. #endif /* TN_COMPORT */
  2614.  
  2615.     /* Set the initial values for currently known mode */
  2616.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  2617.         if (TELOPT_OK(opt)) {
  2618.             TELOPT_ME_MODE(opt) = sstelnet ?
  2619.               TELOPT_DEF_S_ME_MODE(opt) :
  2620.                 TELOPT_DEF_C_ME_MODE(opt);
  2621.             TELOPT_U_MODE(opt) = sstelnet ?
  2622.               TELOPT_DEF_S_U_MODE(opt) :
  2623.                 TELOPT_DEF_C_U_MODE(opt);
  2624.         }
  2625.     }
  2626.     return(1);
  2627. }
  2628.  
  2629.  
  2630. /* Send Delayed Subnegotiations */
  2631.  
  2632. VOID
  2633. tn_sdsb() {
  2634.     if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
  2635.         tn_sttyp();
  2636.         TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
  2637.     }
  2638. #ifdef CK_ENVIRONMENT
  2639.     if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
  2640.         TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  2641.         tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
  2642.                  TELOPT_SB(TELOPT_NEWENVIRON).env.len);
  2643.         free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
  2644.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  2645.         TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
  2646.         TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
  2647.     }
  2648. #ifdef CK_XDISPLOC
  2649.     if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
  2650.         tn_sxdisploc();
  2651.         TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
  2652.     }
  2653. #endif /* CK_XDISPLOC */
  2654. #endif /* CK_ENVIRONMENT */
  2655. #ifdef CK_NAWS
  2656.     if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
  2657.         tn_snaws();
  2658.         TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
  2659.     }
  2660. #endif /* CK_NAWS */
  2661. #ifdef CK_SNDLOC
  2662.     if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
  2663.         tn_sndloc();
  2664.         TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
  2665.     }
  2666. #endif /* CK_SNDLOC */
  2667. #ifdef CK_FORWARD_X
  2668.     if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
  2669.         if ( sstelnet )
  2670.             fwdx_send_options();
  2671.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
  2672.     }
  2673. #endif /* CK_FORWARD_X */
  2674. #ifdef TN_COMPORT
  2675.     if (TELOPT_SB(TELOPT_COMPORT).comport.need_to_send) {
  2676.         tn_sndcomport();
  2677.         TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
  2678.     }
  2679. #endif /* TN_COMPORT */
  2680.  
  2681. }
  2682.  
  2683. int
  2684. tn_reset() {
  2685.     int x,opt,cmd;
  2686.  
  2687.     tn_wait_idx = 0;                    /* Clear the tn_push() buffer */
  2688.     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
  2689.  
  2690.     nflag = 0;
  2691.  
  2692.     /* Reset the TELNET OPTIONS counts */
  2693.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  2694.         if (TELOPT_OK(opt)) {
  2695.             TELOPT_ME(opt) = 0;
  2696.             TELOPT_U(opt)  = 0;
  2697.             TELOPT_UNANSWERED_WILL(opt) = 0;
  2698.             TELOPT_UNANSWERED_DO(opt)   = 0;
  2699.             TELOPT_UNANSWERED_WONT(opt) = 0;
  2700.             TELOPT_UNANSWERED_DONT(opt)   = 0;
  2701.             TELOPT_UNANSWERED_SB(opt)   = 0;
  2702.             TELOPT_ME_MODE(opt) = sstelnet ?
  2703.               TELOPT_DEF_S_ME_MODE(opt) :
  2704.                 TELOPT_DEF_C_ME_MODE(opt);
  2705.             TELOPT_U_MODE(opt) = sstelnet ?
  2706.               TELOPT_DEF_S_U_MODE(opt) :
  2707.                 TELOPT_DEF_C_U_MODE(opt);
  2708.  
  2709. #ifdef DEBUG
  2710.             if (deblog) {
  2711.                 switch (TELOPT_ME_MODE(opt)) {
  2712.                   case TN_NG_RF:
  2713.                     debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
  2714.                     break;
  2715.                   case TN_NG_AC:
  2716.                     debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
  2717.                     break;
  2718.                   case TN_NG_RQ:
  2719.                     debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
  2720.                     break;
  2721.                   case TN_NG_MU:
  2722.                     debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
  2723.                     break;
  2724.                 }
  2725.                 switch (TELOPT_U_MODE(opt)) {
  2726.                   case TN_NG_RF:
  2727.                     debug(F110,"tn_ini U  REFUSE ",TELOPT(opt),0);
  2728.                     break;
  2729.                   case TN_NG_AC:
  2730.                     debug(F110,"tn_ini U  ACCEPT ",TELOPT(opt),0);
  2731.                     break;
  2732.                   case TN_NG_RQ:
  2733.                     debug(F110,"tn_ini U  REQUEST",TELOPT(opt),0);
  2734.                     break;
  2735.                   case TN_NG_MU:
  2736.                     debug(F110,"tn_ini U  REQUIRE",TELOPT(opt),0);
  2737.                     break;
  2738.                 }
  2739.             }
  2740. #endif /* DEBUG */
  2741.             for (cmd = 0; cmd < 4; cmd ++)
  2742.               tncnts[TELOPT_INDEX(opt)][cmd] = 0;
  2743.         }
  2744.     }
  2745. #ifdef CK_ENVIRONMENT
  2746.     if (!tn_env_flg) {
  2747.         TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
  2748.         TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
  2749.     }
  2750. #endif /* CK_ENVIRONMENT */
  2751. #ifdef CK_SNDLOC
  2752.     if (!tn_loc)
  2753.         TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
  2754. #endif /* CK_SNDLOC */
  2755. #ifdef IKS_OPTION
  2756.     TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  2757.     TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  2758.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  2759.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  2760.     TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
  2761. #endif /* IKS_OPTION */
  2762. #ifdef CK_ENCRYPTION
  2763.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  2764.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
  2765. #endif /* CK_ENCRYPTION */
  2766. #ifdef  CK_NAWS
  2767.     TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
  2768.     TELOPT_SB(TELOPT_NAWS).naws.x = 0;
  2769.     TELOPT_SB(TELOPT_NAWS).naws.y = 0;
  2770. #endif /* CK_NAWS */
  2771.     TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
  2772.     TELOPT_SB(TELOPT_TTYPE).term.type[0] = '\0';
  2773. #ifdef CK_ENVIRONMENT
  2774.     TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
  2775.     if (tn_first)
  2776.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  2777.     else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  2778.         free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
  2779.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  2780.     }
  2781.     TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
  2782. #ifdef CK_XDISPLOC
  2783.     TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
  2784. #endif /* CK_XDISPLOC */
  2785. #endif /* CK_ENVIRONMENT */
  2786. #ifdef CK_SNDLOC
  2787.     TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
  2788. #endif /* CK_SNDLOC */
  2789. #ifdef CK_FORWARD_X
  2790.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
  2791.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
  2792.     for (x = 0; x < MAXFWDX; x++) {
  2793.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
  2794.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
  2795.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].need_to_send_xauth = 0;
  2796.        TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].suspend = 0;
  2797.     }
  2798.     /* Reset Xauth data */
  2799.     if ( real_xauth ) {
  2800.         XauDisposeAuth(real_xauth);
  2801.         real_xauth = NULL;
  2802.     }
  2803.     if ( fake_xauth.name )
  2804.         free(fake_xauth.name);
  2805.     if ( fake_xauth.data )
  2806.         free(fake_xauth.data);
  2807.     if ( fake_xauth.address )
  2808.         free(fake_xauth.address);
  2809.     if ( fake_xauth.number )
  2810.         free(fake_xauth.number);
  2811.     memset(&fake_xauth,0,sizeof(fake_xauth));
  2812. #ifdef NT
  2813.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
  2814. #endif /* NT */
  2815. #endif /* CK_FORWARD_X */
  2816. #ifdef CK_SSL
  2817.     if (tls_only_flag || ssl_only_flag) {
  2818.         TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  2819.         TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  2820.     }
  2821.     TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
  2822.     TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
  2823.     TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 0;
  2824. #endif /* CK_SSL */
  2825.  
  2826. #ifdef CK_ENCRYPTION
  2827.     if (!ck_crypt_is_installed()
  2828. #ifdef CK_SSL
  2829.         || tls_only_flag || ssl_only_flag
  2830. #endif /* CK_SSL */
  2831.         ) {
  2832.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2833.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2834.     }
  2835. #endif /* CK_ENCRYPTION */
  2836.  
  2837. #ifdef TN_COMPORT
  2838.     TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 0;
  2839.     TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  2840.     TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
  2841.     tnc_init();
  2842. #endif /* TN_COMPORT */
  2843.  
  2844.     tn_first = 0;                       /* No longer the first time init */
  2845.  
  2846. #ifdef OS2
  2847.     ttnum = -1;                         /* Reset TermType negotiation */
  2848.     ttnumend = 0;
  2849. #endif /* OS2 */
  2850.  
  2851.     return(0);
  2852. }
  2853.  
  2854. int
  2855. tn_start() {
  2856.     int wait, x, opt;
  2857.  
  2858.     if (tn_init && tn_begun)
  2859.         return(0);
  2860.     tn_begun = 1;
  2861.  
  2862.     debug(F111,"tn_start","sstelnet",sstelnet);
  2863.     wait = 0;
  2864.     if (tn_duplex)  {
  2865.         oldplex = duplex;               /* save old duplex value */
  2866.         duplex = 1;                     /* and set to half duplex for telnet */
  2867.     }
  2868. #ifdef CK_SSL
  2869.     if (!TELOPT_ME(TELOPT_START_TLS) &&
  2870.         TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
  2871.         if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
  2872.           return(-1);
  2873.         TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
  2874.         wait = 1;
  2875.     }
  2876.     if (!TELOPT_U(TELOPT_START_TLS) &&
  2877.         TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
  2878.         if (tn_sopt(DO, TELOPT_START_TLS) < 0)
  2879.           return(-1);
  2880.         TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
  2881.         wait = 1;
  2882.     }
  2883. #endif /* CK_SSL */
  2884.  
  2885. #ifdef CK_AUTHENTICATION
  2886.     debug(F110,"tn_ini() CK_AUTHENTICATION","",0);
  2887.     if (tn_init)                /* tn_ini() might be called recursively */
  2888.       return(0);
  2889.     if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
  2890.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
  2891.         if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
  2892.           return(-1);
  2893.         TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
  2894.         wait = 1;
  2895.     }
  2896.     if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
  2897.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
  2898.         if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
  2899.           return(-1);
  2900.         TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
  2901.         wait = 1;
  2902.     }
  2903. #ifdef CK_ENCRYPTION
  2904.     if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
  2905.          TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
  2906.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2907.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2908.     }
  2909. #endif /* CK_ENCRYPTION */
  2910. #endif /* CK_AUTHENTICATION */
  2911.  
  2912. #ifdef CK_NAWS
  2913. #ifndef NOLOCAL
  2914.     debug(F110,"tn_ini() CK_NAWS !NOLOCAL","",0);
  2915.     if (!sstelnet) {
  2916.         /* Console terminal screen rows and columns */
  2917. #ifdef OS2
  2918.         debug(F101,
  2919.               "tn_ini tt_rows 1",
  2920.               "",
  2921.               VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
  2922.               );
  2923.         debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
  2924.         /* Not known yet */
  2925.         if (VscrnGetWidth(VTERM) < 0 ||
  2926.             VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) < 0) {
  2927.             ttgwsiz();                  /* Try to find out */
  2928.         }
  2929.         debug(F101,
  2930.               "tn_ini tt_rows 2",
  2931.               "",
  2932.               VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0)
  2933.               );
  2934.         debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
  2935.         /* Now do we know? */
  2936.         if (VscrnGetWidth(VTERM) > 0 &&
  2937.             VscrnGetHeight(VTERM)-(tt_status[VTERM]?1:0) > 0) {
  2938.             if (!TELOPT_ME(TELOPT_NAWS) &&
  2939.                 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  2940.                 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
  2941.                   return(-1);
  2942.                 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
  2943.                 wait = 1;
  2944.             }
  2945.         }
  2946. #else /* OS2 */
  2947.         debug(F101,"tn_ini tt_rows 1","",tt_rows);
  2948.         debug(F101,"tn_ini tt_cols 1","",tt_cols);
  2949.         if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
  2950.             ttgwsiz();                  /* Try to find out */
  2951.         }
  2952.         debug(F101,"tn_ini tt_rows 2","",tt_rows);
  2953.         debug(F101,"tn_ini tt_cols 2","",tt_cols);
  2954.         if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
  2955.             if (!TELOPT_ME(TELOPT_NAWS) &&
  2956.                 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  2957.                 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
  2958.                   return(-1);
  2959.                 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
  2960.                 wait = 1;
  2961.             }
  2962.         }
  2963. #endif /* OS2 */
  2964.     } else
  2965. #endif /* NOLOCAL */
  2966.     {
  2967.         if (!TELOPT_U(TELOPT_NAWS) &&
  2968.             TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  2969.             if (tn_sopt(DO, TELOPT_NAWS) < 0)
  2970.               return(-1);
  2971.             TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
  2972.             wait = 1;
  2973.         }
  2974.     }
  2975. #endif /* CK_NAWS */
  2976.  
  2977.     if (!TELOPT_ME(TELOPT_SGA) &&
  2978.         TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
  2979.         if (tn_sopt(WILL, TELOPT_SGA) < 0)
  2980.           return(-1);
  2981.         TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
  2982.         wait = 1;
  2983.     }
  2984.     if (!TELOPT_U(TELOPT_SGA) &&
  2985.         TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
  2986.         if (tn_sopt(DO, TELOPT_SGA) < 0)
  2987.           return(-1);
  2988.         TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
  2989.         wait = 1;
  2990.     }
  2991.     if (!tn_duplex) {
  2992.         if (!TELOPT_U(TELOPT_ECHO) &&
  2993.             TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
  2994.             if (tn_sopt(DO, TELOPT_ECHO) < 0)
  2995.               return(-1);
  2996.             TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
  2997.             wait = 1;
  2998.         }
  2999.     }
  3000.     if (!TELOPT_ME(TELOPT_ECHO) &&
  3001.         TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
  3002.         if (tn_sopt(WILL, TELOPT_ECHO) < 0)
  3003.           return(-1);
  3004.         TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
  3005.         wait = 1;
  3006.     }
  3007.  
  3008.     debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
  3009. /*
  3010.   Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
  3011.   Also send WILL NAWS if we know our screen dimensions.
  3012. */
  3013.     if (!TELOPT_ME(TELOPT_TTYPE) &&
  3014.         TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
  3015.         if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
  3016.             debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
  3017.             return(-1);
  3018.         }
  3019.         TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
  3020.         wait = 1;
  3021.         debug(F100,"tn_ini sent WILL TTYPE ok","",0);
  3022.     }
  3023.     if (!TELOPT_U(TELOPT_TTYPE) &&
  3024.         TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
  3025.         if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
  3026.             debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
  3027.             return(-1);
  3028.         }
  3029.         TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
  3030.         wait = 1;
  3031.         debug(F100,"tn_ini sent DO TTYPE ok","",0);
  3032.     }
  3033.     if (!TELOPT_ME(TELOPT_BINARY) &&
  3034.         TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
  3035.         if (tn_sopt(WILL, TELOPT_BINARY) < 0)
  3036.           return(-1);
  3037.         TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
  3038.         wait = 1;
  3039.     }
  3040.     if (!TELOPT_U(TELOPT_BINARY) &&
  3041.         TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
  3042.         if (tn_sopt(DO, TELOPT_BINARY) < 0)
  3043.           return(-1);
  3044.         TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
  3045.         wait = 1;
  3046.     }
  3047. #ifdef CK_SNDLOC
  3048.     if (tn_loc) {
  3049.         if (!TELOPT_ME(TELOPT_SNDLOC) &&
  3050.             TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
  3051.             if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
  3052.               return(-1);
  3053.             TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
  3054.             wait = 1;
  3055.         }
  3056.     }
  3057. #endif /* CK_SNDLOC */
  3058. #ifdef CK_ENVIRONMENT
  3059. #ifdef CK_FORWARD_X
  3060.     if (!TELOPT_U(TELOPT_FORWARD_X) &&
  3061.          TELOPT_U_MODE(TELOPT_FORWARD_X) >= TN_NG_RQ) {
  3062.         if (tn_sopt(WILL, TELOPT_FORWARD_X) < 0)
  3063.             return(-1);
  3064.         TELOPT_UNANSWERED_WILL(TELOPT_FORWARD_X) = 1;
  3065.         wait = 1;
  3066.     }
  3067. #endif /* FORWARD_X */
  3068. #ifdef CK_XDISPLOC
  3069.     if (!TELOPT_ME(TELOPT_XDISPLOC) &&
  3070.          TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
  3071.         if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
  3072.             return(-1);
  3073.         TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
  3074.         wait = 1;
  3075.     }
  3076. #endif /* CK_XDISPLOC */
  3077.     /* Will send terminal environment. */
  3078.     if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
  3079.         TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
  3080.         if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
  3081.           return(-1);
  3082.         TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
  3083.         wait = 1;
  3084.     }
  3085.     if (!TELOPT_U(TELOPT_NEWENVIRON) &&
  3086.         TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
  3087.         if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
  3088.           return(-1);
  3089.         TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
  3090.         wait = 1;
  3091.     }
  3092. #endif /* CK_ENVIRONMENT */
  3093.  
  3094.     /* Take care of any other telnet options that require handling. */
  3095.  
  3096.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  3097.         switch (opt) {
  3098.           case TELOPT_AUTHENTICATION:
  3099.           case TELOPT_ENCRYPTION:
  3100.           case TELOPT_TTYPE:
  3101.           case TELOPT_NAWS:
  3102.           case TELOPT_BINARY:
  3103.           case TELOPT_NEWENVIRON:
  3104.           case TELOPT_SNDLOC:
  3105.           case TELOPT_XDISPLOC:
  3106.           case TELOPT_SGA:
  3107.           case TELOPT_ECHO:
  3108.           case TELOPT_KERMIT:
  3109.           case TELOPT_START_TLS:
  3110.           case TELOPT_FORWARD_X:
  3111.                 break;
  3112.             break;
  3113.           default:
  3114.             if (TELOPT_OK(opt)) {
  3115.                 if (!TELOPT_ME(opt) &&
  3116.                     TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
  3117.                     if (tn_sopt(WILL, opt) < 0)
  3118.                       return(-1);
  3119.                     TELOPT_UNANSWERED_WILL(opt) = 1;
  3120.                     wait = 1;
  3121.                 }
  3122.                 if (!TELOPT_U(opt) &&
  3123.                     TELOPT_U_MODE(opt) >= TN_NG_RQ) {
  3124.                     if (tn_sopt(DO, opt) < 0)
  3125.                       return(-1);
  3126.                     TELOPT_UNANSWERED_DO(opt) = 1;
  3127.                     wait = 1;
  3128.                 }
  3129.             }
  3130.         }
  3131.     }
  3132.     if (wait) {
  3133.         if (tn_wait("pre-encrypt") < 0) {
  3134.             tn_push();
  3135.             return(-1);
  3136.         }
  3137.         wait = 0;
  3138.     }
  3139.  
  3140. #ifdef CK_ENCRYPTION
  3141.     if (tn_init)                /* tn_ini() may be called recursively */
  3142.       return(0);
  3143.  
  3144.     if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
  3145.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
  3146.         if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
  3147.           return(-1);
  3148.         TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
  3149.         wait = 1;
  3150.     }
  3151.     if (!TELOPT_U(TELOPT_ENCRYPTION) &&
  3152.         TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
  3153.         if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
  3154.           return(-1);
  3155.         TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
  3156.         wait = 1;
  3157.     }
  3158.  
  3159.     /* If we are going to encrypt, we want to do it before we send any more */
  3160.     /* data, especially the terminal type and environment variables.        */
  3161.     if (wait) {
  3162.         if (tn_wait("post-encrypt") < 0) {
  3163.             tn_push();
  3164.             return(-1);
  3165.         }
  3166.         wait = 0;
  3167.     }
  3168. #endif /* CK_ENCRYPTION */
  3169.  
  3170.     tn_sdsb();
  3171.  
  3172.     if (tn_init)                   /* tn_ini() may be called recursively */
  3173.         return(0);
  3174.  
  3175. #ifdef IKS_OPTION
  3176.     /* Kermit Server negotiation must go last */
  3177.     /* Send U before ME */
  3178.  
  3179.     if (!TELOPT_U(TELOPT_KERMIT) &&
  3180.         TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
  3181.         if (tn_sopt(DO, TELOPT_KERMIT) < 0)
  3182.           return(-1);
  3183.         TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
  3184.         wait = 1;
  3185.     }
  3186.     if (!TELOPT_ME(TELOPT_KERMIT) &&
  3187.         TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
  3188.         if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
  3189.           return(-1);
  3190.         TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
  3191.         wait = 1;
  3192.     }
  3193. #endif /* IKS_OPTION */
  3194.  
  3195.     if (wait) {
  3196.         if (tn_wait("end of telnet negotiations") < 0) {
  3197.             tn_push();
  3198.             return(-1);
  3199.         }
  3200.         wait = 0;
  3201.     }
  3202.  
  3203.     tn_sdsb();                          /* Send delayed subnegotiations */
  3204.     tn_push();
  3205.     return(0);
  3206. }
  3207.  
  3208. /* Start a telnet connection. */
  3209. /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
  3210.  
  3211. int
  3212. tn_ini() {
  3213.     int x;
  3214.  
  3215.     debug(F101,"tn_ini ttnproto","",ttnproto);
  3216.     debug(F101,"tn_ini tn_init","",tn_init);
  3217.  
  3218.     if (ttnet != NET_TCPB)              /* Make sure connection is TCP/IP */
  3219.       return(0);
  3220.     if (tn_init)                        /* Have we done this already? */
  3221.       return(0);                        /* Don't do it again. */
  3222.  
  3223.     tn_reset();                         /* Reset telnet parameters */
  3224.     tn_begun = 0;                       /* Reset; will be set by tn_start() */
  3225.  
  3226.     switch ( ttnproto ) {
  3227.       case NP_RLOGIN:
  3228.       case NP_K4LOGIN:
  3229.       case NP_EK4LOGIN:
  3230.       case NP_K5LOGIN:
  3231.       case NP_EK5LOGIN:
  3232.       case NP_K5U2U:
  3233.         tn_init = 1;
  3234.         debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
  3235.         return(0);
  3236.       case NP_NONE:
  3237.       case NP_SSL:
  3238.       case NP_TLS:                      /* If not talking to a telnet port, */
  3239.         ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
  3240.         oldplex = duplex;               /* save old duplex value */
  3241.         duplex = 1;                     /* and set to half duplex for telnet */
  3242.         if (inserver)
  3243.           debug(F100,"tn_ini skipping telnet negotiations","",0);
  3244.           else
  3245.         tn_wait("tn_ini - waiting to see if telnet negotiations were sent");
  3246.     tn_push();
  3247.         return(0);
  3248.       case NP_TCPRAW:                   /* Raw socket requested. */
  3249.         debug(F100,"tn_ini telnet negotiations ignored","tn_init",tn_init);
  3250.         return(0);
  3251.       case NP_KERMIT:                   /* switching to Telnet protocol */
  3252.       case NP_SSL_TELNET:
  3253.       case NP_TLS_TELNET:
  3254.         debug(F101,"tn_ini switching from XXX to Telnet","",ttnproto);
  3255.         ttnproto = NP_TELNET;
  3256.         /* fall through */
  3257.       default:
  3258.         /* We are already using a variation on Telnet protocol */
  3259.         ;
  3260.     }
  3261.  
  3262.     x = tn_start();
  3263.     tn_init = 1;                        /* Remember successful completion. */
  3264.  
  3265.     /* Don't send anything else! */
  3266.     debug(F101,"tn_ini duplex","",duplex);
  3267.     debug(F101,"tn_ini done, tn_init","",tn_init);
  3268.     return(x);
  3269. }
  3270.  
  3271. int
  3272. #ifdef CK_ANSIC
  3273. tn_hex(CHAR * buf, int buflen, CHAR * data, int datalen)
  3274. #else /* CK_ANSIC */
  3275. tn_hex(buf, buflen, data, datalen)
  3276.     CHAR * buf;
  3277.     int buflen;
  3278.     CHAR * data;
  3279.     int datalen;
  3280. #endif /* CK_ANSIC */
  3281. {
  3282.     int i = 0, j = 0, k = 0;
  3283.     CHAR tmp[16];        /* in case value is treated as negative */
  3284. #ifdef COMMENT
  3285.     int was_hex = 1;
  3286.  
  3287.     for (k=0; k < datalen; k++) {
  3288.         if (data[k] < 32 || data[k] >= 127) {
  3289.             sprintf(tmp,"%s%02X ",was_hex?"":"\" ",data[k]);
  3290.             was_hex = 1;
  3291.         } else {
  3292.             sprintf(tmp,"%s%c",was_hex?"\"":"",data[k]);
  3293.             was_hex = 0;
  3294.         }
  3295.         ckstrncat((char *)buf,tmp,buflen);
  3296.     }
  3297.     if (!was_hex)
  3298.         ckstrncat((char *)buf,"\" ",buflen);
  3299. #else /* COMMENT */
  3300.     if (datalen <= 0 || data == NULL || buf == NULL || buflen <= 0)
  3301.         return(0);
  3302.  
  3303.     for (i = 0; i < datalen; i++) {
  3304.         ckstrncat((char *)buf,"\r\n  ",buflen);
  3305.         for (j = 0 ; (j < 16); j++) {
  3306.             if ((i + j) < datalen)
  3307.               sprintf((char *)tmp,
  3308.                       "%s%02x ",
  3309.                       (j == 8 ? "| " : ""),
  3310.                       (unsigned int) data[i + j]
  3311.                       );
  3312.             else
  3313.               sprintf((char *)tmp,
  3314.                       "%s   ",
  3315.                       (j == 8 ? "| " : "")
  3316.                       );
  3317.             ckstrncat((char *)buf,(char *)tmp,buflen);
  3318.         }
  3319.         ckstrncat((char *)buf," ",buflen);
  3320.         for (k = 0; (k < 16) && ((i + k) < datalen); k++) {
  3321.             sprintf((char *)tmp,
  3322.                      "%s%c",
  3323.                      (k == 8 ? " " : ""),
  3324.                      isprint((char)(data[i+k])) ? data[i+k] : '.'
  3325.                      );
  3326.             ckstrncat((char *)buf,(char *)tmp,buflen);
  3327.         }
  3328.         i += j - 1;
  3329.     } /* end for */
  3330.     ckstrncat((char *)buf,"\r\n  ",buflen);
  3331. #endif /* COMMENT */
  3332.     return(strlen((char *)buf));
  3333. }
  3334.  
  3335. VOID
  3336. tn_debug(s) char *s; {
  3337. #ifdef NOLOCAL
  3338.     return;
  3339. #else /* NOLOCAL */
  3340. #ifdef OS2
  3341.     void cwrite(unsigned short);
  3342.     char *p = s;
  3343.     _PROTOTYP (void os2bold, (void));
  3344.     extern int tt_type_mode;
  3345. #endif /* OS2 */
  3346.  
  3347.     if (!(tn_deb || debses))
  3348.       return;
  3349.     debug(F111,"tn_debug",s,what);
  3350. #ifdef OS2
  3351.     if (1) {
  3352.         extern unsigned char colorcmd;
  3353.         colorcmd ^= 0x8 ;
  3354.         printf("%s\r\n",s);
  3355.         colorcmd ^= 0x8 ;
  3356.     }
  3357.     if (!scrninitialized[VTERM]) {
  3358.         USHORT x,y;
  3359.         checkscreenmode();
  3360.         GetCurPos(&y, &x);
  3361.         SaveCmdMode(x+1,y+1);
  3362.         scrninit();
  3363.         RestoreCmdMode();
  3364.     }
  3365.  
  3366.     if ( ISVTNT(tt_type_mode) && ttnum != -1 && !debses )
  3367.         return;
  3368.  
  3369.     RequestVscrnMutex( VTERM, SEM_INDEFINITE_WAIT ) ;
  3370.  
  3371.     os2bold();                          /* Toggle boldness */
  3372.     while (*p)
  3373.       cwrite((CHAR) *p++);              /* Go boldly ... */
  3374.     os2bold();                          /* Toggle boldness back */
  3375.     if (debses) {
  3376.         debses = 0;
  3377.         cwrite((CHAR) '\015');
  3378.         cwrite((CHAR) '\012');
  3379.         debses = 1;
  3380.     } else {
  3381.         cwrite((CHAR) '\015');
  3382.         cwrite((CHAR) '\012');
  3383.     }
  3384.     ReleaseVscrnMutex(VTERM) ;
  3385. #else
  3386.     if (what != W_CONNECT && what != W_DIALING && 
  3387.         what != W_COMMAND && what != W_NOTHING)
  3388.       return;                           /* CONNECT/command must be active */
  3389.     conoll(s);
  3390. #endif /* OS2 */
  3391. #endif /* NOLOCAL */
  3392. }
  3393.  
  3394. /*
  3395.   Process in-band Telnet negotiation characters from the remote host.
  3396.   Call with the telnet IAC character and the current duplex setting
  3397.   (0 = remote echo, 1 = local echo), and a pointer to a function to call
  3398.   to read more characters.  Returns:
  3399.     6 if DO LOGOUT was received and accepted
  3400.     5 if the Kermit start of packet character has changed
  3401.     4 if state of remote Internet Kermit Service has changed
  3402.     3 if a quoted IAC was received
  3403.     2 if local echo must be changed to remote
  3404.     1 if remote echo must be changed to local
  3405.     0 if nothing happens or no action necessary
  3406.    -1 on failure (= internal or i/o error)
  3407. */
  3408. #ifdef IKS_OPTION
  3409. int
  3410. tn_siks(cmd) int cmd; {         /* TELNET SEND IKS SUB */
  3411.     CHAR buf[8];
  3412. #ifndef NOXFER
  3413.     extern CHAR mystch;                 /* Outgoing Start of Packet Char */
  3414. #else
  3415.     CHAR mystch = '\1';
  3416. #endif /* NOXFER */
  3417.     int n,m,rc;
  3418.  
  3419.     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
  3420.     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
  3421.     if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
  3422.       return(-1);
  3423.  
  3424. #ifdef CK_SSL
  3425.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  3426.         return(0);
  3427.     }
  3428. #endif /* CK_SSL */
  3429.     if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
  3430.         TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
  3431.     } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
  3432.         TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  3433.     } else if (cmd == KERMIT_REQ_STOP)
  3434.       TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
  3435.     else if (cmd == KERMIT_REQ_START)
  3436.       TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
  3437.  
  3438.     if (cmd == KERMIT_SOP) {
  3439.         buf[0] = (CHAR) IAC;
  3440.         buf[1] = (CHAR) SB;
  3441.         buf[2] = (CHAR) TELOPT_KERMIT;
  3442.         buf[3] = (CHAR) (cmd & 0xff);
  3443.         buf[4] = (CHAR) mystch;
  3444.         buf[5] = (CHAR) IAC;
  3445.         buf[6] = (CHAR) SE;
  3446.         buf[7] = (CHAR) 0;
  3447. #ifdef DEBUG
  3448.         if (tn_deb || debses || deblog)
  3449.             ckmakmsg( tn_msg_out,TN_MSG_LEN,"TELNET SENT SB KERMIT SOP ",
  3450.                       ckctox(mystch,1)," IAC SE",NULL);
  3451. #endif /* DEBUG */
  3452. #ifdef OS2
  3453.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3454. #endif
  3455. #ifdef DEBUG
  3456.         debug(F101,tn_msg_out,"",cmd);
  3457.         if (tn_deb || debses) tn_debug(tn_msg_out);
  3458. #endif /* DEBUG */
  3459.         rc = ( ttol(buf,7) < 7 );                /* Send it. */
  3460. #ifdef OS2
  3461.         ReleaseTelnetMutex();
  3462. #endif
  3463.     if (rc)
  3464.         return(-1);
  3465.     } else {
  3466.         buf[0] = (CHAR) IAC;
  3467.         buf[1] = (CHAR) SB;
  3468.         buf[2] = (CHAR) TELOPT_KERMIT;
  3469.         buf[3] = (CHAR) (cmd & 0xff);
  3470.         buf[4] = (CHAR) IAC;
  3471.         buf[5] = (CHAR) SE;
  3472.         buf[6] = (CHAR) 0;
  3473.  
  3474. #ifdef DEBUG
  3475.         if (tn_deb || debses || deblog) {
  3476.             char * s = 0;
  3477.             switch (cmd) {
  3478.               case KERMIT_START: s = "START"; break;
  3479.               case KERMIT_STOP: s = "STOP"; break;
  3480.               case KERMIT_REQ_START: s = "REQ-START"; break;
  3481.               case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
  3482.               case KERMIT_RESP_START: s = "RESP-START"; break;
  3483.               case KERMIT_RESP_STOP:  s = "RESP-STOP"; break;
  3484.             }
  3485.             ckmakmsg( tn_msg_out,TN_MSG_LEN,
  3486.                       "TELNET SENT SB kermit ",s," IAC SE",NULL);
  3487.         }
  3488. #endif /* DEBUG */
  3489. #ifdef OS2
  3490.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3491. #endif
  3492. #ifdef DEBUG
  3493.         debug(F101,tn_msg_out,"",cmd);
  3494.         if (tn_deb || debses) tn_debug(tn_msg_out);
  3495. #endif /* DEBUG */
  3496.         rc = ( ttol(buf,6) < 6 );                /* Send it. */
  3497. #ifdef OS2
  3498.         ReleaseTelnetMutex();
  3499. #endif
  3500.         if (rc)
  3501.             return(-1);
  3502.     }
  3503.     return(1);
  3504. }
  3505. #endif /* IKS_OPTION */
  3506.  
  3507. /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
  3508. /* returns <= 0 on error, 1 on success */
  3509. /* the length returned includes the IAC SE bytes */
  3510.  
  3511. int
  3512. #ifdef CK_ANSIC                         /* TELNET SB */
  3513. tn_sb( int opt, int * len, int (*fn)(int) )
  3514. #else
  3515. tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
  3516. #endif /* CK_ANSIC */
  3517. /* tn_sb */ {
  3518.     int c, x, y, n, m, flag;
  3519.     debug(F100,"Entering tn_sb()","",0);
  3520.     *len = 0;                   /* Initialize Len to 0 */
  3521.     n = flag = 0;               /* Flag for when done reading SB */
  3522.     while (n < TSBUFSIZ) {      /* Loop looking for IAC SE */
  3523.         if ((y = (*fn)(0)) < 0) /* Read a byte */
  3524.           return(y);
  3525.         y &= 0xff;              /* Make sure it's just 8 bits. */
  3526.         sb[n++] = (char) y;     /* Deposit in buffer. */
  3527.         if (seslog && sessft == XYFT_D) { /* Take care of session log */
  3528.             logchar((char) y);
  3529.         }
  3530.         if (y == IAC) {         /* If this is an IAC                */
  3531.             if (flag) {         /* If previous char was IAC         */
  3532.                 n--;            /* it's quoted, keep one IAC        */
  3533.                 flag = 0;       /* and turn off the flag.           */
  3534.             } else flag = 1;    /* Otherwise set the flag.          */
  3535.         } else if (flag) {      /* Something else following IAC     */
  3536.             if (y == SE)        /* If not SE, it's a protocol error */
  3537.               break;
  3538.             else if (y == DONT) { /* Used DONT instead of SE */
  3539.                 debug(F100,
  3540.                       "TELNET Subnegotiation error - used DONT instead of SE!",
  3541.                       ""
  3542.                       ,0
  3543.                       );
  3544.                 if (tn_deb || debses)
  3545.                   tn_debug(
  3546.                      "TELNET Subnegotiation error - used DONT instead of SE!");
  3547.                 flag = 3;
  3548.                 break;
  3549.             } else {            /* Other protocol error */
  3550.                 flag = 0;
  3551.                 break;
  3552.             }
  3553.         }
  3554.  
  3555. #ifdef CK_FORWARD_X
  3556.         if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
  3557.              n >= (TSBUFSIZ-4) && !flag ) {
  3558.             /* do not let the buffer over flow */
  3559.             /* write the data to the channel and continue processing */
  3560.             /* the incoming data until IAC SE is reached. */
  3561.             sb[n++] = IAC;
  3562.             sb[n++] = SE;
  3563.  
  3564. #ifdef DEBUG
  3565.             if ( deblog || tn_deb || debses ) {
  3566.                 int i;
  3567.                 ckmakmsg( tn_msg,TN_MSG_LEN,
  3568.                           "TELNET RCVD SB ",TELOPT(opt),
  3569.               " DATA(buffer-full) ",NULL);
  3570.                 tn_hex(tn_msg,TN_MSG_LEN,&sb[1],n-3);
  3571.                 if (flag == 2)
  3572.                     ckstrncat(tn_msg," SE",TN_MSG_LEN);
  3573.                 else if (flag == 3)
  3574.                     ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
  3575.                 else
  3576.                     ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
  3577.                 debug(F100,tn_msg,"",0);
  3578.                 if (tn_deb || debses)
  3579.                     tn_debug(tn_msg);
  3580.             }
  3581. #endif /* DEBUG */
  3582.  
  3583.             if ( fwdx_tn_sb(sb,n) < 0 ) {
  3584.                 debug(F100,"fxdx_tn_sb() failed","",0);
  3585.                 /* We can't return though because that would leave  */
  3586.                 /* data to be forwarded in the queue to the be sent */
  3587.                 /* to the terminal emulator.                        */
  3588.             }
  3589.             /* reset leave the msg type and channel number in place */
  3590.             n = 3;
  3591.         }
  3592. #endif /* CK_FORWARD_X */
  3593.     }
  3594.     debug(F111,"tn_sb end of while loop","flag",flag);
  3595.     if (!flag) {                        /* Make sure we got a valid SB */
  3596.         debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
  3597.         if (tn_deb || debses) {
  3598.             ckmakmsg( tn_msg, TN_MSG_LEN,
  3599.                       "TELNET ", TELOPT(opt),
  3600.                       " Subnegotiation prematurely broken",NULL
  3601.                       );
  3602.  
  3603.           tn_debug(tn_msg);
  3604.         }
  3605.         /* Was -1 but that would be an I/O error, so absorb it and go on. */
  3606.         return(0);
  3607.     }
  3608. #ifdef DEBUG
  3609.     if (deblog || tn_deb || debses) {
  3610.         int i;
  3611.         char * s[16];
  3612.         for (i = 0; i < 16; i++)
  3613.           s[i] = "";
  3614.         if (opt == TELOPT_NAWS) {
  3615.             i = 0;
  3616.         } else {
  3617.             i = 1;
  3618.             s[0] = "UNKNOWN";
  3619.  
  3620.             switch (sb[0]) {
  3621.               case 0:
  3622.                 if (opt == TELOPT_FORWARD_X)
  3623.                   s[0] = "SCREEN";
  3624.                 else if (opt == TELOPT_KERMIT)
  3625.                   s[0] = "START";
  3626.                 else if (opt == TELOPT_LFLOW)
  3627.                   s[0] = "OFF";
  3628.                 else if (opt == TELOPT_COMPORT)
  3629.                   s[0] = "SIGNATURE";
  3630.                 else
  3631.                   s[0] = "IS";
  3632.                 if (opt == TELOPT_ENCRYPTION) {
  3633.                     i++;
  3634.                     if (sb[1] < ENCTYPE_CNT) {
  3635.                         s[1] = enctype_names[sb[1]];
  3636.                         i++;
  3637.                         switch(sb[2]) {
  3638.                           case 1:
  3639.                             s[2] = "FB64_IV";
  3640.                             break;
  3641.                           case 2:
  3642.                             s[2] = "FB64_IV_OK";
  3643.                             break;
  3644.                           case 3:
  3645.                             s[2] = "FB64_IV_BAD";
  3646.                             break;
  3647.                           case 4:
  3648.                             s[2] = "FB64_CHALLENGE";
  3649.                             break;
  3650.                           case 5:
  3651.                             s[2] = "FB64_RESPONSE";
  3652.                             break;
  3653.                         }
  3654.                     } else {
  3655.                         s[1] = "UNKNOWN";
  3656.                     }
  3657.                 }
  3658.                 if (opt == TELOPT_AUTHENTICATION) {
  3659.                     i += 2;
  3660.                     s[1] = AUTHTYPE_NAME(sb[1]);
  3661.                     s[2] = AUTHMODE_NAME(sb[2]);
  3662.                     if (sb[1]) {
  3663.                         i++;
  3664.                         switch (sb[3]) {
  3665.                           case 0:
  3666.                             switch (sb[1]) {
  3667.                               case AUTHTYPE_NTLM:
  3668.                                 s[3] = "NTLM_AUTH";
  3669.                                 break;
  3670.                               default:
  3671.                                 s[3] = "AUTH";
  3672.                             }
  3673.                             break;
  3674.                           case 1:
  3675.                             switch (sb[1]) {
  3676.                               case AUTHTYPE_SSL:
  3677.                                 s[3] = "START";
  3678.                                 break;
  3679.                               case AUTHTYPE_NTLM:
  3680.                                 s[3] = "NTLM_CHALLENGE";
  3681.                                 break;
  3682.                               default:
  3683.                                 s[3] = "REJECT";
  3684.                             }
  3685.                             break;
  3686.                           case 2:
  3687.                             switch (sb[1]) {
  3688.                               case AUTHTYPE_NTLM:
  3689.                                 s[3] = "NTLM_RESPONSE";
  3690.                                 break;
  3691.                               default:
  3692.                                 s[3] = "ACCEPT";
  3693.                             }
  3694.                             break;
  3695.                           case 3:
  3696.                             switch (sb[1]) {
  3697.                               case AUTHTYPE_NTLM:
  3698.                                 s[3] = "NTLM_ACCEPT";
  3699.                                 break;
  3700.                               case 1:   /* KERBEROS_v4 */
  3701.                               case 5:   /* SRP */
  3702.                                 s[3] = "CHALLENGE";
  3703.                                 break;
  3704.                               case 2:   /* KERBEROS_v5 */
  3705.                                 s[3] = "RESPONSE";
  3706.                                 break;
  3707.                               case AUTHTYPE_SSL:
  3708.                                 s[3] = "REJECT";
  3709.                                 break;
  3710.                             }
  3711.                             break;
  3712.                           case 4:
  3713.                             switch (sb[1]) {
  3714.                               case AUTHTYPE_NTLM:
  3715.                                 s[3] = "NTLM_REJECT";
  3716.                                 break;
  3717.                               case 1:   /* KERBEROS_V4 */
  3718.                               case 5:   /* SRP */
  3719.                                 s[3] = "RESPONSE";
  3720.                                 break;
  3721.                               case 2:   /* KERBEROS_V5 */
  3722.                                 s[3] = "FORWARD";
  3723.                                 break;
  3724.                             }
  3725.                             break;
  3726.                           case 5:
  3727.                             switch (sb[1]) {
  3728.                               case 5:   /* SRP */
  3729.                                 s[3] = "FORWARD";
  3730.                                 break;
  3731.                               case 2:   /* KERBEROS_V5 */
  3732.                                 s[3] = "FORWARD_ACCEPT";
  3733.                                 break;
  3734.                             }
  3735.                             break;
  3736.                           case 6:
  3737.                             switch (sb[1]) {
  3738.                               case 5:   /* SRP */
  3739.                                 s[3] = "FORWARD_ACCEPT";
  3740.                                 break;
  3741.                               case 2: /* KERBEROS_V5 */
  3742.                                 s[3] = "FORWARD_REJECT";
  3743.                                 break;
  3744.                             }
  3745.                             break;
  3746.                           case 7:
  3747.                             switch (sb[1]) {
  3748.                               case 5:   /* SRP */
  3749.                                 s[3] = "FORWARD_REJECT";
  3750.                                 break;
  3751.                               case 2: /* KERBEROS_V5 */
  3752.                                 s[3] = "TLS_VERIFY";
  3753.                                 break;
  3754.                               }
  3755.                             break;
  3756.                           case 8:
  3757.                             switch (sb[1]) {
  3758.                               case 5: /* SRP */
  3759.                                 s[3] = "EXP";
  3760.                                 break;
  3761.                             }
  3762.                             break;
  3763.                           case 9:
  3764.                             switch (sb[1]) {
  3765.                               case 5: /* SRP */
  3766.                                 s[3] = "PARAMS";
  3767.                                 break;
  3768.                             }
  3769.                             break;
  3770.                         }
  3771.                     }
  3772.                 }
  3773.                 break;
  3774.               case 1:
  3775.                 switch (opt) {
  3776.                   case TELOPT_FORWARD_X:
  3777.                     s[0] = "OPEN";
  3778.                     break;
  3779.                   case TELOPT_LFLOW:
  3780.                     s[0] = "ON";
  3781.                     break;
  3782.                   case TELOPT_KERMIT:
  3783.                     s[0] = "STOP";
  3784.                     break;
  3785.                   case TELOPT_COMPORT:
  3786.                     s[0] = "SET-BAUDRATE";
  3787.                       break;
  3788.                   case TELOPT_AUTHENTICATION:
  3789.                     s[0] = "SEND";
  3790.                     hexbuf[0] = '\0';
  3791.                     for (; i < n-2; i += 2) {
  3792.                         if ( AUTHTYPE_NAME_OK(sb[i]) &&
  3793.                              AUTHMODE_NAME_OK(sb[i]))
  3794.                             ckmakmsg( tn_msg, TN_MSG_LEN,
  3795.                                       AUTHTYPE_NAME(sb[i])," ",
  3796.                                       AUTHMODE_NAME(sb[i+1])," "
  3797.                                       );
  3798.                         else
  3799.                           ckmakxmsg(tn_msg, TN_MSG_LEN,
  3800.                                     AUTHTYPE_NAME(sb[i]),
  3801.                                     "=",
  3802.                                     ckitoa(sb[i]),
  3803.                                     " ",
  3804.                                     AUTHMODE_NAME(sb[i+1]),
  3805.                                     "=",
  3806.                                     ckitoa(sb[i+1]),
  3807.                                     " ",
  3808.                                     NULL,NULL,NULL,NULL
  3809.                                     );
  3810.                         ckstrncat(hexbuf,tn_msg,sizeof(hexbuf));
  3811.                     }
  3812.                     s[1] = hexbuf;
  3813.                     break;
  3814.  
  3815.                   case TELOPT_ENCRYPTION:
  3816.                     s[0] = "SUPPORT";
  3817.                     while (i < n-2) {
  3818.                         s[i] = enctype_names[sb[i]];
  3819.                         i++;
  3820.                     }
  3821.                     break;
  3822.  
  3823.                   case TELOPT_START_TLS:
  3824.                     s[0] = "FOLLOWS";
  3825.                     break;
  3826.                   default:
  3827.                     s[0] = "SEND";
  3828.                 }
  3829.                 break;
  3830.  
  3831.               case 2:
  3832.                 switch (opt) {
  3833.                 case TELOPT_FORWARD_X:
  3834.                     s[0] = "CLOSE";
  3835.                     break;
  3836.                   case TELOPT_LFLOW:
  3837.                     s[0] = "RESTART-ANY";
  3838.                     break;
  3839.                   case TELOPT_KERMIT:
  3840.                     s[0] = "REQ-START";
  3841.                     break;
  3842.                   case TELOPT_COMPORT:
  3843.                     s[0] = "SET-DATASIZE";
  3844.                     break;
  3845.                   case TELOPT_NEWENVIRON:
  3846.                     s[0] = "INFO";
  3847.                     break;
  3848.                   case TELOPT_AUTHENTICATION:
  3849.                     s[0] = "REPLY";
  3850.                     i=4;
  3851.                     s[1] = AUTHTYPE_NAME(sb[1]);
  3852.                     s[2] = AUTHMODE_NAME(sb[2]);
  3853.                     switch (sb[3]) {
  3854.                       case 0:
  3855.                         switch (sb[1]) {
  3856.                           case AUTHTYPE_NTLM:
  3857.                             s[3] = "NTLM_AUTH";
  3858.                             break;
  3859.                           default:
  3860.                             s[3] = "AUTH";
  3861.                         }
  3862.                         break;
  3863.                       case 1:
  3864.                         switch (sb[1]) {
  3865.                           case AUTHTYPE_NTLM:
  3866.                             s[3] = "NTLM_CHALLENGE";
  3867.                             break;
  3868.                           default:
  3869.                             s[3] = "REJECT";
  3870.                         }
  3871.                         break;
  3872.                       case 2:
  3873.                         switch (sb[1]) {
  3874.                           case AUTHTYPE_NTLM:
  3875.                             s[3] = "NTLM_RESPONSE";
  3876.                             break;
  3877.                           default:
  3878.                             s[3] = "ACCEPT";
  3879.                         }
  3880.                         break;
  3881.                       case 3:
  3882.                         switch (sb[1]) {
  3883.                           case AUTHTYPE_NTLM:
  3884.                             s[3] = "NTLM_ACCEPT";
  3885.                             break;
  3886.                           case AUTHTYPE_KERBEROS_V4:
  3887.                           case AUTHTYPE_SRP:
  3888.                             s[3] = "CHALLENGE";
  3889.                             break;
  3890.                           case AUTHTYPE_KERBEROS_V5:
  3891.                             s[3] = "RESPONSE";
  3892.                             break;
  3893.                         }
  3894.                         break;
  3895.                       case 4:
  3896.                         switch (sb[1]) {
  3897.                           case AUTHTYPE_NTLM:
  3898.                             s[3] = "NTLM_REJECT";
  3899.                             break;
  3900.                           case AUTHTYPE_KERBEROS_V4:
  3901.                           case AUTHTYPE_SRP:
  3902.                             s[3] = "RESPONSE";
  3903.                             break;
  3904.                           case AUTHTYPE_KERBEROS_V5:
  3905.                             s[3] = "FORWARD";
  3906.                             break;
  3907.                         }
  3908.                         break;
  3909.                       case 5:
  3910.                         switch (sb[1]) {
  3911.                           case AUTHTYPE_SRP:
  3912.                             s[3] = "FORWARD";
  3913.                             break;
  3914.                           case AUTHTYPE_KERBEROS_V5:
  3915.                             s[3] = "FORWARD_ACCEPT";
  3916.                             break;
  3917.                         }
  3918.                         break;
  3919.                       case 6:
  3920.                         switch (sb[1]) {
  3921.                           case AUTHTYPE_SRP:
  3922.                             s[3] = "FORWARD_ACCEPT";
  3923.                             break;
  3924.                           case AUTHTYPE_KERBEROS_V5:
  3925.                             s[3] = "FORWARD_REJECT";
  3926.                             break;
  3927.                         }
  3928.                         break;
  3929.                       case 7:
  3930.                         switch (sb[1]) {
  3931.                           case AUTHTYPE_SRP:
  3932.                             s[3] = "FORWARD_REJECT";
  3933.                             break;
  3934.                           case AUTHTYPE_KERBEROS_V5:
  3935.                             s[3] = "TLS_VERIFY";
  3936.                             break;
  3937.                         }
  3938.                         break;
  3939.                       case 8:
  3940.                         switch (sb[1]) {
  3941.                           case AUTHTYPE_SRP:
  3942.                             s[3] = "EXP";
  3943.                             break;
  3944.                         }
  3945.                         break;
  3946.                       case 9:
  3947.                         switch (sb[1]) {
  3948.                           case AUTHTYPE_SRP:
  3949.                             s[3] = "PARAMS";
  3950.                             break;
  3951.                         }
  3952.                         break;
  3953.                     }
  3954.                     break;
  3955.                   case TELOPT_ENCRYPTION:
  3956.                     s[0] = "REPLY";
  3957.                     s[1] = enctype_names[sb[1]];
  3958.                     i++;
  3959.                     switch (sb[2]) {
  3960.                       case 1:
  3961.                         i++;
  3962.                         s[2] = "FB64_IV";
  3963.                         break;
  3964.                       case 2:
  3965.                         i++;
  3966.                         s[2] = "FB64_IV_OK";
  3967.                         break;
  3968.                       case 3:
  3969.                         i++;
  3970.                         s[2] = "FB64_IV_BAD";
  3971.                         break;
  3972.                       case 4:
  3973.                         i++;
  3974.                         s[2] = "FB64_CHALLENGE";
  3975.                         break;
  3976.                       case 5:
  3977.                         i++;
  3978.                         s[2] = "FB64_RESPONSE";
  3979.                         break;
  3980.                     }
  3981.                     break;
  3982.                 }
  3983.                 break;
  3984.               case 3:
  3985.                 switch (opt) {
  3986.                   case TELOPT_FORWARD_X:
  3987.                     s[0] = "DATA";
  3988.                     break;
  3989.                   case TELOPT_LFLOW:
  3990.                     s[0] = "RESTART-XON";
  3991.                     break;
  3992.                   case TELOPT_KERMIT:
  3993.                     s[0] = "REQ-STOP";
  3994.                     break;
  3995.                   case TELOPT_COMPORT:
  3996.                       s[0] = "SET-PARITY";
  3997.                       break;
  3998.                   case TELOPT_AUTHENTICATION:
  3999.                     s[0] = "NAME";
  4000.                     break;
  4001.                   case TELOPT_ENCRYPTION:
  4002.                     s[0] = "START";
  4003.                     break;
  4004.                 }
  4005.                 break;
  4006.               case 4:
  4007.                 switch (opt) {
  4008.                   case TELOPT_FORWARD_X:
  4009.                     s[0] = "OPTIONS";
  4010.                     break;
  4011.                   case TELOPT_KERMIT:
  4012.                     s[0] = "SOP";
  4013.                     break;
  4014.                   case TELOPT_COMPORT:
  4015.                       s[0] = "SET-STOPSIZE";
  4016.                       break;
  4017.                   case TELOPT_ENCRYPTION:
  4018.                     s[0] = "END";
  4019.                     break;
  4020.                 }
  4021.                 break;
  4022.               case 5:
  4023.                 switch (opt) {
  4024.                 case TELOPT_FORWARD_X:
  4025.                     s[0] = "OPTION_DATA";
  4026.                     break;
  4027.                 case TELOPT_ENCRYPTION:
  4028.                     s[0] = "REQUEST-START";
  4029.                     break;
  4030.                 case TELOPT_COMPORT:
  4031.                     s[0] = "SET-CONTROL";
  4032.                     break;
  4033.                 }
  4034.                 break;
  4035.               case 6:
  4036.                 switch (opt) {
  4037.                   case TELOPT_FORWARD_X:
  4038.                     s[0] = "XOFF";
  4039.                     break;
  4040.                   case TELOPT_ENCRYPTION:
  4041.                     s[0] = "REQUEST-END";
  4042.                     break;
  4043.                   case TELOPT_COMPORT:
  4044.                       s[0] = "NOTIFY-LINESTATE";
  4045.                       break;
  4046.                   }
  4047.                 break;
  4048.               case 7:
  4049.                 switch (opt) {
  4050.                   case TELOPT_FORWARD_X:
  4051.                     s[0] = "XON";
  4052.                     break;
  4053.                   case TELOPT_ENCRYPTION:
  4054.                     s[0] = "ENC-KEYID";
  4055.                     break;
  4056.                   case TELOPT_COMPORT:
  4057.                       s[0] = "NOTIFY-MODEMSTATE";
  4058.                       break;
  4059.                   }
  4060.                 break;
  4061.               case 8:
  4062.                 switch (opt) {
  4063.                   case TELOPT_KERMIT:
  4064.                     s[0] = "RESP-START";
  4065.                     break;
  4066.                   case TELOPT_ENCRYPTION:
  4067.                     s[0] = "DEC-KEYID";
  4068.                     break;
  4069.                   case TELOPT_COMPORT:
  4070.                       s[0] = "FLOWCONTROL-SUSPEND";
  4071.                       break;
  4072.                   }
  4073.                 break;
  4074.               case 9:
  4075.                 switch (opt) {
  4076.                   case TELOPT_KERMIT:
  4077.                     s[0] = "RESP-STOP";
  4078.                     break;
  4079.                   case TELOPT_COMPORT:
  4080.                       s[0] = "FLOWCONTROL-RESUME";
  4081.                       break;
  4082.                   }
  4083.                 break;
  4084.               case 10:
  4085.                   switch (opt) {
  4086.                   case TELOPT_COMPORT:
  4087.                     s[0] = "SET-LINESTATE-MASK";
  4088.                     break;
  4089.                   }
  4090.                   break;
  4091.             case 11:
  4092.                   switch (opt) {
  4093.                   case TELOPT_COMPORT:
  4094.                       s[0] = "SET-MODEMSTATE-MASK";
  4095.                       break;
  4096.                   }
  4097.                   break;
  4098.             case 12:
  4099.                   switch (opt) {
  4100.                   case TELOPT_COMPORT:
  4101.                       s[0] = "PURGE-DATA";
  4102.                       break;
  4103.                   }
  4104.                   break;
  4105.  
  4106.  
  4107.             case 100:
  4108.                   switch (opt) {
  4109.                   case TELOPT_COMPORT:
  4110.                       s[0] = "S_SIGNATURE";
  4111.                       break;
  4112.                   }
  4113.                   break;
  4114.             case 101:
  4115.                   switch (opt) {
  4116.                   case TELOPT_COMPORT:
  4117.                       s[0] = "S_SET-BAUDRATE";
  4118.                       break;
  4119.                   }
  4120.                   break;
  4121.             case 102:
  4122.                   switch (opt) {
  4123.                   case TELOPT_COMPORT:
  4124.                       s[0] = "S_SET-DATASIZE";
  4125.                       break;
  4126.                   }
  4127.                   break;
  4128.             case 103:
  4129.                   switch (opt) {
  4130.                   case TELOPT_COMPORT:
  4131.                       s[0] = "S_SET-PARITY";
  4132.                       break;
  4133.                   }
  4134.                   break;
  4135.             case 104:
  4136.                   switch (opt) {
  4137.                   case TELOPT_COMPORT:
  4138.                       s[0] = "S_SET-STOPSIZE";
  4139.                       break;
  4140.                   }
  4141.                   break;
  4142.             case 105:
  4143.                   switch (opt) {
  4144.                   case TELOPT_COMPORT:
  4145.                       s[0] = "S_SET-CONTROL";
  4146.                       break;
  4147.                   }
  4148.                   break;
  4149.             case 106:
  4150.                   switch (opt) {
  4151.                   case TELOPT_COMPORT:
  4152.                       s[0] = "S_NOTIFY-LINESTATE";
  4153.                       break;
  4154.                   }
  4155.                   break;
  4156.             case 107:
  4157.                   switch (opt) {
  4158.                   case TELOPT_COMPORT:
  4159.                       s[0] = "S_NOTIFY-MODEMSTATE";
  4160.                       break;
  4161.                   }
  4162.                   break;
  4163.             case 108:
  4164.                   switch (opt) {
  4165.                   case TELOPT_COMPORT:
  4166.                       s[0] = "S_FLOWCONTROL-SUSPEND";
  4167.                       break;
  4168.                   }
  4169.                   break;
  4170.             case 109:
  4171.                   switch (opt) {
  4172.                   case TELOPT_COMPORT:
  4173.                       s[0] = "S_FLOWCONTROL-RESUME";
  4174.                       break;
  4175.                   }
  4176.                   break;
  4177.             case 110:
  4178.                   switch (opt) {
  4179.                   case TELOPT_COMPORT:
  4180.                       s[0] = "S_SET-LINESTATE-MASK";
  4181.                       break;
  4182.                   }
  4183.                   break;
  4184.             case 111:
  4185.                   switch (opt) {
  4186.                   case TELOPT_COMPORT:
  4187.                       s[0] = "S_SET-MODEMSTATE-MASK";
  4188.                       break;
  4189.                   }
  4190.                   break;
  4191.             case 112:
  4192.                   switch (opt) {
  4193.                   case TELOPT_COMPORT:
  4194.                       s[0] = "S_PURGE-DATA";
  4195.                       break;
  4196.                   }
  4197.                   break;
  4198.               }
  4199.         }
  4200. #ifdef M_XENIX
  4201.         {
  4202.           int len, param, param_len;
  4203.           ckmakmsg( tn_msg, TN_MSG_LEN,
  4204.                     "TELNET RCVD SB ",
  4205.                     TELOPT(opt)," ",NULL);
  4206.           len = strlen(tn_msg);
  4207.           for (param = 0; param <= 15; param++) {
  4208.             param_len = strlen(s[param]);
  4209.             if (param_len > 0) {
  4210.               strcpy(&tn_msg[len], s[param]);
  4211.               len += param_len;
  4212.               tn_msg[len++] = ' ';
  4213.             }
  4214.           }
  4215.           tn_msg[len] = '\0';
  4216.         }
  4217. #else /* M_XENIX */
  4218.         ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD SB ",TELOPT(opt)," ",
  4219.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  4220.         {
  4221.             int i;
  4222.             for (i = 0; i < 16; i++) {
  4223.                 if (s[i][0]) {
  4224.                     ckstrncat(tn_msg,s[i],TN_MSG_LEN);
  4225.                     ckstrncat(tn_msg," ",TN_MSG_LEN);
  4226.                 }
  4227.             }
  4228.         }
  4229. #endif /* M_XENIX */
  4230.         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&sb[i],n-2-i);
  4231.         if (flag == 2)
  4232.           ckstrncat(tn_msg," SE",TN_MSG_LEN);
  4233.         else if (flag == 3)
  4234.           ckstrncat(tn_msg," IAC DONT",TN_MSG_LEN);
  4235.         else
  4236.           ckstrncat(tn_msg," IAC SE",TN_MSG_LEN);
  4237.         debug(F100,tn_msg,"",0);
  4238.         if (tn_deb || debses)
  4239.           tn_debug(tn_msg);
  4240.     }
  4241.     debug(F111,"tn_sb","len",n);
  4242. #endif /* DEBUG */
  4243.     *len = n;           /* return length */
  4244.     return(1);          /* success */
  4245. }
  4246.  
  4247. static char rows_buf[16] = { 0, 0 }; /* LINES Environment variable */
  4248. static char cols_buf[16] = { 0, 0 }; /* COLUMNS Enviornment variable */
  4249. static char term_buf[64] = { 0, 0 }; /* TERM Environment variable */
  4250.  
  4251. #ifdef CK_CURSES
  4252. #ifndef VMS
  4253. #ifndef COHERENT
  4254. _PROTOTYP(int tgetent,(char *, char *));
  4255. #endif /* COHERENT */
  4256. #else
  4257. #ifdef __DECC
  4258. _PROTOTYP(int tgetent,(char *, char *));
  4259. #endif /* __DECC */
  4260. #endif /* VMS */
  4261. extern char * trmbuf;                   /* Real curses */
  4262. #endif /* CK_CURSES */
  4263.  
  4264. #ifdef CK_ENCRYPTION
  4265. static int
  4266. tn_no_encrypt()
  4267. {
  4268.     /* Prevent Encryption from being negotiated */
  4269.     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  4270.     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  4271.  
  4272.     /* Cancel any negotiation that might have started */
  4273.     ck_tn_enc_stop();
  4274.  
  4275.     if (TELOPT_ME(TELOPT_ENCRYPTION) ||
  4276.          TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION)) {
  4277.         TELOPT_ME(TELOPT_ENCRYPTION) = 0;
  4278.         if (tn_sopt(WONT,TELOPT_ENCRYPTION) < 0)
  4279.             return(-1);
  4280.         TELOPT_UNANSWERED_WONT(TELOPT_ENCRYPTION) = 1;
  4281.     }
  4282.     if (TELOPT_U(TELOPT_ENCRYPTION) ||
  4283.          TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION)) {
  4284.         TELOPT_U(TELOPT_ENCRYPTION) = 0;
  4285.         if (tn_sopt(DONT,TELOPT_ENCRYPTION) < 0)
  4286.             return(-1);
  4287.         TELOPT_UNANSWERED_DONT(TELOPT_ENCRYPTION) = 1;
  4288.     }
  4289.     return(0);
  4290. }
  4291. #endif /* CK_ENCRYPTION */
  4292.  
  4293. /* The following note came from the old SGA negotiation code.  This should */
  4294. /* no longer be necessary with the New Telnet negotiation state machine.   */
  4295. /*
  4296.   Note: The following is proper behavior, and required for talking to the
  4297.   Apertus interface to the NOTIS library system, e.g. at Iowa State U:
  4298.   scholar.iastate.edu.  Without this reply, the server hangs forever.  This
  4299.   code should not be loop-inducing, since C-Kermit never sends WILL SGA as
  4300.   an initial bid, so if DO SGA comes, it is never an ACK.
  4301. */
  4302. /*
  4303.   Return values:
  4304.   -1 = Telnet Option negotiation error
  4305.   -2 = Connection closed by peer
  4306.   -3 = Connection closed by us
  4307.   0  = Success
  4308.   1  = Echoing on
  4309.   2  = Echoing off
  4310.   3  = Quoted IAC
  4311.   4  = IKS Event
  4312.   5  = (unassigned)
  4313.   6  = Logout
  4314. */
  4315.  
  4316. static int
  4317. #ifdef CK_ANSIC                         /* TELNET DO OPTION */
  4318. tn_xdoop(CHAR z, int echo, int (*fn)(int))
  4319. #else
  4320. tn_xdoop(z, echo, fn) CHAR z; int echo; int (*fn)();
  4321. #endif /* CK_ANSIC */
  4322. /* tn_xdoop */ {
  4323.     int c, x, y, n, m;
  4324. #ifdef IKS_OPTION
  4325.     extern int server;
  4326. #ifdef NOICP
  4327.     extern int autodl;
  4328.     int inautodl = 0, cmdadl = 1;
  4329. #else
  4330. #ifdef CK_AUTODL
  4331.     extern int autodl, inautodl, cmdadl;
  4332. #endif /* CK_AUTODL */
  4333. #endif /* NOICP */
  4334. #endif /* IKS_OPTION */
  4335.  
  4336.  
  4337. /* Have IAC, read command character. */
  4338.  
  4339.     while ((c = (*fn)(0)) == -1);       /* Read command character */
  4340.     if (c < 0)
  4341.       return(c);
  4342.     c &= 0xFF;                          /* Strip high bits */
  4343.  
  4344.     if (!TELCMD_OK(c)) {
  4345. #ifdef DEBUG
  4346.         if (tn_deb || debses || deblog) {
  4347.             ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD UNKNOWN (",
  4348.                      ckitoa(c),")",NULL);
  4349.             debug(F101,tn_msg,"",c);
  4350.             if (tn_deb || debses)
  4351.               tn_debug(tn_msg);
  4352.         }
  4353. #endif /* DEBUG */
  4354.         return(0);
  4355.     }
  4356.     if (ttnproto == NP_NONE) {
  4357.         debug(F100,"tn_doop discovered a Telnet command",
  4358.               "ttnproto = NP_TELNET",0);
  4359.         ttnproto = NP_TELNET;
  4360.     }
  4361.     if (seslog && sessft == XYFT_D) {   /* Copy to session log, if any. */
  4362.         logchar((char)z);
  4363.         logchar((char)c);
  4364.     }
  4365.  
  4366.     if (c == (CHAR) IAC)                /* Quoted IAC */
  4367.       return(3);
  4368.  
  4369.     if (c < SB) {                       /* Other command with no arguments. */
  4370. #ifdef DEBUG
  4371.         if (deblog || tn_deb || debses) {
  4372.             ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c),NULL,NULL);
  4373.             debug(F101,tn_msg,"",c);
  4374.             if (tn_deb || debses) tn_debug(tn_msg);
  4375.         }
  4376. #endif /* DEBUG */
  4377.         switch (c) {                    /* What we would like to do here    */
  4378.           case TN_GA:                   /* Is substitute ASCII characters   */
  4379.             break;                      /* for the Telnet Command so that   */
  4380.           case TN_EL:                   /* the command may be processed by  */
  4381.             break;                      /* either the internal emulator or  */
  4382.           case TN_EC:                   /* by the superior process or shell */
  4383.             break;
  4384.           case TN_AYT:
  4385. #ifdef OS2
  4386.             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  4387. #endif
  4388.             ttol((CHAR *)"[Yes]\015\012",7);
  4389. #ifdef OS2
  4390.             ReleaseTelnetMutex();
  4391. #endif
  4392.             break;
  4393.           case TN_AO:
  4394. #ifdef BETADEBUG
  4395.             bleep(BP_NOTE);
  4396. #endif /* BETADEBUG */
  4397.             break;
  4398.           case TN_IP:
  4399.             break;
  4400.           case BREAK:
  4401.             break;
  4402.           case TN_DM:
  4403.             break;
  4404.           case TN_NOP:
  4405.             break;
  4406.           case SE:
  4407.             break;
  4408.           case TN_EOR:
  4409.             break;
  4410.           case TN_ABORT:
  4411.             break;
  4412.           case TN_SUSP:
  4413.             break;
  4414.           case TN_EOF:
  4415.             break;
  4416.           case TN_SAK:
  4417.             break;
  4418.         }
  4419.         return(0);
  4420.     }
  4421.  
  4422. /* SB, WILL, WONT, DO, or DONT need more bytes... */
  4423.  
  4424.     if ((x = (*fn)(0)) < 0)             /* Get the option. */
  4425.       return(x);
  4426.     x &= 0xff;                          /* Trim to 8 bits. */
  4427.  
  4428.     if (seslog && sessft == XYFT_D) {   /* Session log */
  4429.         logchar((char) x);
  4430.     }
  4431. #ifdef DEBUG
  4432.     if ((deblog || tn_deb || debses) && c != SB) {
  4433.         ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET RCVD ",TELCMD(c)," ",TELOPT(x));
  4434.         debug(F101,tn_msg,"",x);
  4435.         if (tn_deb || debses) tn_debug(tn_msg);
  4436.     }
  4437. #endif /* DEBUG */
  4438.     /* Now handle the command */
  4439.     switch (c) {
  4440.       case WILL:
  4441. #ifdef CK_SSL
  4442.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  4443.             return(0);
  4444. #endif /* CK_SSL */
  4445. #ifdef CK_FORWARD_X
  4446.           if (x == TELOPT_FORWARD_X) {
  4447.               if (!fwdx_server_avail() || !(fwdx_no_encrypt ||
  4448. #ifdef CK_SSL
  4449.                  (ssl_active_flag || tls_active_flag)
  4450. #else /* CK_SSL */
  4451.                  0
  4452. #endif /* CK_SSL */
  4453.                  ||
  4454. #ifdef CK_ENCRYPTION
  4455.                  (ck_tn_encrypting() && ck_tn_decrypting())
  4456. #else /* CK_ENCRYPTION */
  4457.                  0
  4458. #endif /* CK_ENCRYPTION */
  4459.                  )) {
  4460.                   TELOPT_U_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
  4461.                   TELOPT_ME_MODE(TELOPT_FORWARD_X) = TN_NG_RF;
  4462.               }
  4463.           }
  4464. #endif /* CK_FORWARD_X */
  4465.         if (!TELOPT_OK(x) || TELOPT_U_MODE(x) == TN_NG_RF) {
  4466.             if (tn_sopt(DONT,x) < 0)
  4467.               return(-1);
  4468.             if (TELOPT_UNANSWERED_DO(x))
  4469.                 TELOPT_UNANSWERED_DO(x) = 0;
  4470.         } else if (!TELOPT_U(x)) {
  4471.             if (!TELOPT_UNANSWERED_DO(x)) {
  4472.                 if (tn_sopt(DO,x) < 0)
  4473.                   return -1;
  4474.             }
  4475.             if (TELOPT_UNANSWERED_DO(x))
  4476.                 TELOPT_UNANSWERED_DO(x) = 0;
  4477.             TELOPT_U(x) = 1;
  4478.  
  4479.             switch (x) {
  4480. #ifdef CK_SSL
  4481.               case TELOPT_START_TLS:
  4482.                 /*
  4483.                    If my proposal is accepted, at this point the Telnet
  4484.                    protocol is turned off and a TLS negotiation takes
  4485.                    place.
  4486.  
  4487.                    Start by sending SB START_TLS FOLLOWS  to signal
  4488.                    we are ready.  Wait for the peer to send the same
  4489.                    and then start the TLS negotiation.
  4490.  
  4491.                    If the TLS negotiation succeeds we call tn_ini()
  4492.                    again to reset the telnet state machine and restart
  4493.                    the negotiation process over the now secure link.
  4494.  
  4495.                    If the TLS negotiation fails, we call ttclos()
  4496.                    to terminate the connection.
  4497.  
  4498.                    Only the server should receive a WILL START_TLS
  4499.                  */
  4500.                 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
  4501.                 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
  4502.                 break;
  4503. #endif /* CK_SSL */
  4504.  
  4505. #ifdef CK_AUTHENTICATION
  4506.               case TELOPT_AUTHENTICATION: {
  4507.                   /* We now have to perform a SB SEND to identify the  */
  4508.                   /* supported authentication types to the other side. */
  4509.                   extern int authentication_version;
  4510.  
  4511. #ifdef CK_SSL
  4512.                   /* if we have an outstanding DO START_TLS then we must 
  4513.                    * wait for the response before we determine what to do
  4514.                    */
  4515.                   if (TELOPT_UNANSWERED_DO(TELOPT_START_TLS)) {
  4516.                       TELOPT_SB(TELOPT_START_TLS).start_tls.auth_request = 1;
  4517.                       break;
  4518.                   }
  4519. #endif /* CK_SSL */
  4520.                   authentication_version = AUTHTYPE_AUTO;
  4521.                   ck_tn_auth_request();
  4522.                   break;
  4523.               }
  4524. #endif /* CK_AUTHENTICATION */
  4525. #ifdef CK_ENCRYPTION
  4526.               case TELOPT_ENCRYPTION:
  4527.                 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
  4528.                       TELOPT_U(TELOPT_AUTHENTICATION))
  4529.                     ) {
  4530.                     if (tn_sopt(DONT,x) < 0)
  4531.                       return(-1);
  4532.                     TELOPT_U(x) = 0;
  4533.                 } else {
  4534.                     if (ck_tn_auth_in_progress()) {
  4535.                         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 1;
  4536.                     } else {
  4537.                         /* Perform subnegotiation */
  4538.                         ck_encrypt_send_support();
  4539.                     }
  4540.                     if (!(TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x))
  4541.                         && TELOPT_ME_MODE(x) != TN_NG_RF) {
  4542.                         if (tn_sopt(WILL, x) < 0)
  4543.                           return(-1);
  4544.                         TELOPT_UNANSWERED_WILL(x) = 1;
  4545.                     }
  4546.                 }
  4547.                 break;
  4548. #endif /* CK_ENCRYPTION */
  4549. #ifdef IKS_OPTION
  4550.               case TELOPT_KERMIT:
  4551.                 if (!TELOPT_ME(x)) {
  4552.                     /* Tell the other side what Start of Packet Character */
  4553.                     tn_siks(KERMIT_SOP); /* SOP */
  4554.  
  4555.                     if (!TELOPT_UNANSWERED_WILL(x) &&
  4556.                         TELOPT_ME_MODE(x) != TN_NG_RF) {
  4557.                         if (tn_sopt(WILL, x) < 0)
  4558.                           return(-1);
  4559.                         TELOPT_UNANSWERED_WILL(x) = 1;
  4560.                     }
  4561.                 }
  4562.                 break;
  4563. #endif /* IKS_OPTION */
  4564.               case TELOPT_BINARY:
  4565.                 if (!TELOPT_ME(x)) {
  4566.                     if (!TELOPT_UNANSWERED_WILL(x) &&
  4567.                         TELOPT_ME_MODE(x) >= TN_NG_RQ) {
  4568.                         if (tn_sopt(WILL, x) < 0)
  4569.                           return(-1);
  4570.                         TELOPT_UNANSWERED_WILL(x) = 1;
  4571.                     }
  4572.                 }
  4573.                 break;
  4574.               case TELOPT_ECHO:
  4575.                 if (echo) {
  4576.                     if (TELOPT_UNANSWERED_DO(x))
  4577.                       TELOPT_UNANSWERED_DO(x) = 0;
  4578.                     return(2);
  4579.                 }
  4580.                 break;
  4581.               case TELOPT_TTYPE:
  4582.                 /* SB TTYPE SEND */
  4583.                 tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
  4584.                 TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
  4585.                 break;
  4586. #ifdef CK_ENVIRONMENT
  4587.               case TELOPT_NEWENVIRON:   /* SB NEW-ENVIRON SEND */
  4588.                 {
  4589.                   char request[6];      /* request it */
  4590.                   sprintf(request,"%cUSER",TEL_ENV_VAR);        /* safe */
  4591.                   tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_SEND,request,
  4592.                             strlen(request));
  4593.                   TELOPT_UNANSWERED_SB(TELOPT_NEWENVIRON)=1;
  4594.                 }
  4595.                 break;
  4596. #endif /* CK_ENVIRONMENT */
  4597.             } /* switch */
  4598.         } else {
  4599.             if (TELOPT_UNANSWERED_DO(x))
  4600.                 TELOPT_UNANSWERED_DO(x) = 0;
  4601.         }
  4602.         break;
  4603.       case WONT:
  4604. #ifdef CK_SSL
  4605.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  4606.             return(0);
  4607. #endif /* CK_SSL */
  4608.         if (TELOPT_U(x) || TELOPT_UNANSWERED_DO(x)) {
  4609.             /* David Borman says we should not respond DONT when
  4610.              * the WONT is a response to a DO that we sent.
  4611.              * Nor should we send one if the state is already WONT
  4612.              * such as when we do not recognize the option since
  4613.              * options are initialized in the WONT/DONT state.
  4614.              */
  4615.             if (!(TELOPT_UNANSWERED_DO(x) || TELOPT_UNANSWERED_DONT(x)))
  4616.               if (tn_sopt(DONT,x) < 0)
  4617.                 return(-1);
  4618.             if (TELOPT_UNANSWERED_DONT(x))
  4619.                 TELOPT_UNANSWERED_DONT(x) = 0;
  4620.             if (TELOPT_UNANSWERED_DO(x))
  4621.                 TELOPT_UNANSWERED_DO(x) = 0;
  4622.             if (TELOPT_U(x)) {
  4623.                 TELOPT_U(x) = 0;
  4624.             }
  4625.             switch(x) {
  4626. #ifdef CK_SSL
  4627.             case TELOPT_START_TLS:
  4628.                 if (sstelnet) {
  4629.                     if (TELOPT_U_MODE(x) == TN_NG_MU) {
  4630.                         printf("Telnet Start-TLS refused.\n");
  4631.                         ttclos(0);
  4632.                         whyclosed = WC_TELOPT;
  4633.                         return(-3);
  4634.                     }
  4635.                     if (TELOPT_SB(x).start_tls.auth_request) {
  4636.                         extern int authentication_version;
  4637.                         TELOPT_SB(x).start_tls.auth_request = 0;
  4638.                         authentication_version = AUTHTYPE_AUTO;
  4639.                         ck_tn_auth_request();
  4640.                     }
  4641.                 }
  4642.                 break;
  4643. #endif /* CK_SSL */
  4644. #ifdef CK_AUTHENTICATION
  4645.               case TELOPT_AUTHENTICATION:
  4646.                 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
  4647.                     printf("Telnet authentication refused.\n");
  4648.                     ttclos(0);
  4649.                     whyclosed = WC_TELOPT;
  4650.                     return(-3);
  4651.                 } else if (TELOPT_U_MODE(x) == TN_NG_RQ) {
  4652.                     TELOPT_U_MODE(x) = TN_NG_AC;
  4653.                 }
  4654.                 if (ck_tn_auth_in_progress())
  4655.                   printf("Telnet authentication refused.\n");
  4656. #ifdef CK_ENCRYPTION
  4657.                 if (sstelnet) {
  4658.                     if (tn_no_encrypt()<0)
  4659.                         return(-1);
  4660.                 }
  4661. #endif /* CK_ENCRYPTION */
  4662.                 break;
  4663. #endif /* CK_AUTHENTICATION */
  4664. #ifdef CK_ENCRYPTION
  4665.               case TELOPT_ENCRYPTION:
  4666.                 ck_tn_enc_stop();
  4667.                 break;
  4668. #endif /* CK_ENCRYPTION */
  4669. #ifdef IKS_OPTION
  4670.               case TELOPT_KERMIT:
  4671.                 TELOPT_SB(x).kermit.u_start = 0;
  4672.                 TELOPT_SB(x).kermit.me_req_start = 0;
  4673.                 TELOPT_SB(x).kermit.me_req_stop = 0;
  4674.                 break;
  4675. #endif /* IKS_OPTION */
  4676.               case TELOPT_NAWS: {
  4677.                   /* The client does not support NAWS. */
  4678.                   /* Assume a height of 24 and a width of 80 */
  4679.                   if (sstelnet
  4680. #ifdef IKSD
  4681.                    || inserver
  4682. #endif /* IKSD */
  4683.                    ) {
  4684.                       int w = 80, h = 24;
  4685. #ifndef NOLOCAL
  4686.                       if (tcp_incoming) {
  4687. #ifdef OS2
  4688.                           tt_cols[VTERM] = w;
  4689.                           tt_rows[VTERM] = h;
  4690.                           VscrnSetWidth(VTERM, w);
  4691.                           VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
  4692. #else /* OS2 */
  4693.                           tt_cols = w;
  4694.                           tt_rows = h;
  4695. #endif /* OS2 */
  4696.                       } else {
  4697. #ifdef OS2
  4698.                           tt_cols[VCMD] = w;
  4699.                           tt_rows[VCMD] = h;
  4700.                           VscrnSetWidth(VCMD, w);
  4701.                           VscrnSetHeight(VCMD, h);
  4702. #endif /* OS2 */
  4703.                           cmd_cols = w;
  4704.                           cmd_rows = h;
  4705.                       }
  4706. #else /* NOLOCAL */
  4707.                       cmd_cols = w;
  4708.                       cmd_rows = h;
  4709. #endif /* NOLOCAL */
  4710.                       /* Add LINES and COLUMNS to the environment */
  4711.                       ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),
  4712.                                 NULL,NULL);
  4713.                       ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),
  4714.                                 NULL,NULL);
  4715. #ifdef OS2ORUNIX
  4716. #ifndef NOPUTENV
  4717.                       putenv(rows_buf);
  4718.                       putenv(cols_buf);
  4719. #endif /* NOPUTENV */
  4720. #endif /* OS2ORUNIX */
  4721.                   }
  4722.                   break;
  4723.               }
  4724.               case TELOPT_ECHO:
  4725.                 if (!echo) {
  4726.                     if (TELOPT_UNANSWERED_DO(x))
  4727.                       TELOPT_UNANSWERED_DO(x) = 0;
  4728.                     return(1);
  4729.                 }
  4730.                 break;
  4731.             }
  4732.         } else {
  4733.             if (TELOPT_UNANSWERED_DONT(x))
  4734.                 TELOPT_UNANSWERED_DONT(x) = 0;
  4735.             if (TELOPT_UNANSWERED_DO(x))
  4736.                 TELOPT_UNANSWERED_DO(x) = 0;
  4737.         }
  4738.         if (TELOPT_U_MODE(x) == TN_NG_MU) {
  4739.             ckmakmsg( tn_msg,TN_MSG_LEN,
  4740.                       "Peer refuses TELNET DO ",TELOPT(x),
  4741.                       " negotiations - terminating connection",NULL
  4742.                     );
  4743.             debug(F100,tn_msg,"",0);
  4744.             if (tn_deb || debses) tn_debug(tn_msg);
  4745.             printf("%s\n",tn_msg);
  4746.             ttclos(0);
  4747.             whyclosed = WC_TELOPT;
  4748.             return(-3);
  4749.         }
  4750. #ifdef COMMENT
  4751.         if (x == TELOPT_ECHO && !echo) /* Special handling for echo */
  4752.           return(1);                   /* because we allow 'duplex' */
  4753. #endif /* COMMENT */
  4754.         break;
  4755.  
  4756.       case DO:
  4757. #ifdef CK_SSL
  4758.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  4759.             return(0);
  4760. #endif /* CK_SSL */
  4761.         if (!TELOPT_OK(x) || TELOPT_ME_MODE(x) == TN_NG_RF) {
  4762.             if (tn_sopt(WONT,x) < 0)
  4763.               return(-1);
  4764.             if (TELOPT_UNANSWERED_WILL(x))
  4765.                 TELOPT_UNANSWERED_WILL(x) = 0;
  4766.         } else if (!TELOPT_ME(x)) {
  4767.             if (!TELOPT_UNANSWERED_WILL(x)) {
  4768.                 if (tn_sopt(WILL,x) < 0)
  4769.                   return(-1);
  4770.             }
  4771.             if (TELOPT_UNANSWERED_WILL(x))
  4772.                 TELOPT_UNANSWERED_WILL(x) = 0;
  4773.             TELOPT_ME(x) = 1;
  4774.  
  4775.             switch (x) {
  4776. #ifdef CK_SSL
  4777.               case TELOPT_START_TLS:
  4778.                 /*
  4779.                    If my proposal is accepted at this point the Telnet
  4780.                    protocol is turned off and a TLS negotiation takes
  4781.                    place.
  4782.  
  4783.                    Start by sending SB START_TLS FOLLOWS  to signal
  4784.                    we are ready.  Wait for the peer to send the same
  4785.                    and then start the TLS negotiation.
  4786.  
  4787.                    If the TLS negotiation succeeds we call tn_ini()
  4788.                    again to reset the telnet state machine and restart
  4789.                    the negotiation process over the now secure link.
  4790.  
  4791.                    If the TLS negotiation fails, we call ttclos()
  4792.                    to terminate the connection.  Then we set the
  4793.                    U_MODE and ME_MODE for TELOPT_START_TLS to REFUSE
  4794.                    and then call ttopen() to create a new connection
  4795.                    to the same host but this time do not attempt
  4796.                    TLS security.
  4797.  
  4798.                    Only the client should receive DO START_TLS.
  4799.                 */
  4800.                 tn_ssbopt(TELOPT_START_TLS,1,NULL,0);
  4801.                 TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 1;
  4802.                 break;
  4803. #endif /* CK_SSL */
  4804.  
  4805. #ifdef CK_AUTHENTICATION
  4806.               case TELOPT_AUTHENTICATION: {
  4807.                   /* We don't know what authentication we are using yet */
  4808.                   /* but it is not NULL until a failure is detected so */
  4809.                   /* use AUTO in the meantime. */
  4810.                   extern int authentication_version;
  4811.                   authentication_version = AUTHTYPE_AUTO;
  4812.                   break;
  4813.               }
  4814. #endif /* CK_AUTHENTICATION */
  4815. #ifdef CK_ENCRYPTION
  4816.               case TELOPT_ENCRYPTION:
  4817.                 if (!(TELOPT_ME(TELOPT_AUTHENTICATION) ||
  4818.                       TELOPT_U(TELOPT_AUTHENTICATION))
  4819.                     ) {
  4820.                     if (tn_sopt(WONT,x) < 0)
  4821.                       return(-1);
  4822.                     TELOPT_ME(x) = 0;
  4823.                 } else {
  4824.                     if (!(TELOPT_U(x) || TELOPT_UNANSWERED_DO(x))
  4825.                         && TELOPT_U_MODE(x) != TN_NG_RF) {
  4826.                         if (tn_sopt(DO, x) < 0)
  4827.                           return(-1);
  4828.                         TELOPT_UNANSWERED_DO(x) = 1;
  4829.                     }
  4830.                 }
  4831.                 break;
  4832. #endif /* CK_ENCRYPTION */
  4833. #ifdef IKS_OPTION
  4834.               case TELOPT_KERMIT:
  4835. /* If currently processing Kermit server packets, must tell the other side */
  4836.  
  4837.                 debug(F111,"tn_doop","what",what);
  4838.                 debug(F111,"tn_doop","server",server);
  4839. #ifdef CK_AUTODL
  4840.                 debug(F111,"tn_doop","autodl",autodl);
  4841.                 debug(F111,"tn_doop","inautodl",inautodl);
  4842.                 debug(F111,"tn_doop","cmdadl",cmdadl);
  4843. #endif /* CK_AUTODL */
  4844.  
  4845.                 if (server
  4846. #ifdef CK_AUTODL
  4847.                     || (local && ((what == W_CONNECT && autodl) ||
  4848.                                   (what != W_CONNECT && inautodl)))
  4849.                     || (!local && cmdadl)
  4850. #endif /* CK_AUTODL */
  4851.                     ) {
  4852.                     tn_siks(KERMIT_START);      /* START */
  4853.                 }
  4854.                 if (!TELOPT_U(x)) {
  4855.                     /* Tell the other side what Start of Packet Character */
  4856.                     tn_siks(KERMIT_SOP);             /* SOP */
  4857.                     if (!TELOPT_UNANSWERED_DO(x) &&
  4858.                         TELOPT_U_MODE(x) != TN_NG_RF) {
  4859.                         if (tn_sopt(DO, x) < 0)
  4860.                           return(-1);
  4861.                         TELOPT_UNANSWERED_DO(x) = 1;
  4862.                     }
  4863.                 }
  4864.                 break;
  4865. #endif /* IKS_OPTION */
  4866.  
  4867.               case TELOPT_BINARY:
  4868.                 if (!TELOPT_U(x)) {
  4869.                     if (!TELOPT_UNANSWERED_DO(x) &&
  4870.                         TELOPT_U_MODE(x) >= TN_NG_RQ) {
  4871.                         if (tn_sopt(DO, x) < 0)
  4872.                           return(-1);
  4873.                         TELOPT_UNANSWERED_DO(x) = 1;
  4874.                     }
  4875.                 }
  4876.                 break;
  4877.               case TELOPT_NAWS:
  4878. #ifdef CK_NAWS
  4879.                 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
  4880.                     if (tn_snaws() < 0)
  4881.                         return(-1);
  4882.                 } else {
  4883.                     TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 1;
  4884.                 }
  4885. #endif /* CK_NAWS */
  4886.                 break;
  4887.               case TELOPT_LOGOUT:
  4888.                 ttclos(0);              /* And then hangup */
  4889.                 whyclosed = WC_TELOPT;
  4890.                 return(6);
  4891. #ifdef CK_SNDLOC
  4892.                case TELOPT_SNDLOC:
  4893.                   if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
  4894.                       if (tn_sndloc() < 0)
  4895.                           return(-1);
  4896.                   } else {
  4897.                       TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 1;
  4898.                   }
  4899.                   break;
  4900. #endif /* CK_SNDLOC */
  4901. #ifdef CK_FORWARD_X
  4902.                case TELOPT_FORWARD_X:
  4903.                   if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
  4904.                       if (fwdx_send_options() < 0) {
  4905.                           if (tn_sopt(DONT,x) < 0)
  4906.                               return(-1);
  4907.                           TELOPT_UNANSWERED_DONT(x) = 1;
  4908.                       }
  4909.                   } else {
  4910.                       TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 1;
  4911.                   }
  4912.                   break;
  4913. #endif /* CK_FORWARD_X */
  4914. #ifdef TN_COMPORT
  4915.               case TELOPT_COMPORT: {
  4916.                 extern int reliable;
  4917.                 if (!tn_delay_sb || !tn_outst(0) || tn_init) {
  4918.                     if (tn_sndcomport() < 0)
  4919.                       return(-1);
  4920.                 } else {
  4921.                     TELOPT_SB(TELOPT_COMPORT).comport.need_to_send = 1;
  4922.                 }
  4923.                 /* Telnet -> Serial -> ??? is not a reliable connection. */
  4924.                 reliable = SET_OFF;
  4925.                 break;
  4926.               }
  4927. #endif /* TN_COMPORT */
  4928.             } /* switch */
  4929.         } else {
  4930.           if (TELOPT_UNANSWERED_WILL(x))
  4931.             TELOPT_UNANSWERED_WILL(x) = 0;
  4932.         }
  4933.         break;
  4934.  
  4935.       case DONT:
  4936. #ifdef CK_SSL
  4937.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  4938.             return(0);
  4939. #endif /* CK_SSL */
  4940.         if (TELOPT_ME(x) || TELOPT_UNANSWERED_WILL(x)) {
  4941.             /* David Borman says we should not respond WONT when
  4942.              * the DONT is a response to a WILL that we sent.
  4943.              * Nor should we send one if the state is already WONT
  4944.              * such as when we do not recognize the option since
  4945.              * options are initialized in the WONT/DONT state.
  4946.              */
  4947.             if (!(TELOPT_UNANSWERED_WILL(x) || TELOPT_UNANSWERED_WONT(x)))
  4948.               if (tn_sopt(WONT,x) < 0)
  4949.                 return(-1);
  4950.  
  4951.             if (TELOPT_UNANSWERED_WILL(x))
  4952.                 TELOPT_UNANSWERED_WILL(x) = 0;
  4953.             if (TELOPT_UNANSWERED_WONT(x))
  4954.                 TELOPT_UNANSWERED_WONT(x) = 0;
  4955.             if (TELOPT_ME(x))
  4956.               TELOPT_ME(x) = 0;
  4957.  
  4958.             switch (x) {
  4959. #ifdef CK_SSL
  4960.             case TELOPT_START_TLS:
  4961.                 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
  4962.                     printf("Telnet Start-TLS refused.\n");
  4963.                     ttclos(0);
  4964.                     whyclosed = WC_TELOPT;
  4965.                     return(-3);
  4966.                 }
  4967.                 break;
  4968. #endif /* CK_SSL */
  4969. #ifdef CK_AUTHENTICATION
  4970.               case TELOPT_AUTHENTICATION:
  4971.                 if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
  4972. #ifdef CK_SSL
  4973.                     if (tls_active_flag) {
  4974.                         TELOPT_ME_MODE(x) = TN_NG_AC;
  4975.                         break;
  4976.                     } else
  4977. #endif /* CK_SSL */
  4978.                     {
  4979.                         printf("Telnet authentication refused.\n");
  4980.                         ttclos(0);
  4981.                         whyclosed = WC_TELOPT;
  4982.                         return(-3);
  4983.                     }
  4984.                 } else if (TELOPT_ME_MODE(x) == TN_NG_RQ) {
  4985.                     TELOPT_ME_MODE(x) = TN_NG_AC;
  4986.                 }
  4987.                 if (ck_tn_auth_in_progress())
  4988.                   printf("Telnet authentication refused.\n");
  4989. #ifdef CK_ENCRYPTION
  4990.                 if (!sstelnet) {
  4991.                     if (tn_no_encrypt()<0)
  4992.                         return(-1);
  4993.                 }
  4994. #endif /* CK_ENCRYPTION */
  4995.                 break;
  4996. #endif /* CK_AUTHENTICATION */
  4997.               case TELOPT_ENCRYPTION:
  4998. #ifdef CK_ENCRYPTION
  4999.                 ck_tn_enc_stop();
  5000. #endif /* CK_ENCRYPTION */
  5001.                 break;
  5002.               case TELOPT_KERMIT:
  5003. #ifdef IKS_OPTION
  5004.                 TELOPT_SB(x).kermit.me_start = 0;
  5005. #endif /* IKS_OPTION */
  5006.                 break;
  5007.               default:
  5008.                 break;
  5009.             } /* switch */
  5010.         } else {
  5011.           if (TELOPT_UNANSWERED_WILL(x))
  5012.               TELOPT_UNANSWERED_WILL(x) = 0;
  5013.           if (TELOPT_UNANSWERED_WONT(x))
  5014.               TELOPT_UNANSWERED_WONT(x) = 0;
  5015.         }
  5016.         if (TELOPT_ME_MODE(x) == TN_NG_MU) {
  5017.             ckmakmsg( tn_msg,TN_MSG_LEN,
  5018.                       "Peer refuses TELNET WILL ",TELOPT(x),
  5019.                       " negotiations - terminating connection",
  5020.                       NULL
  5021.                       );
  5022.             debug(F100,tn_msg,"",0);
  5023.             if (tn_deb || debses) tn_debug(tn_msg);
  5024.             printf("%s\n",tn_msg);
  5025.             ttclos(0);
  5026.             whyclosed = WC_TELOPT;
  5027.             return(-3);
  5028.         }
  5029.         break;
  5030.       case SB:
  5031.         if ((y = tn_sb(x,&n,fn)) <= 0)
  5032.           return(y);
  5033.  
  5034. #ifdef CK_SSL
  5035.         /* Do not process subnegotiations other than START_TLS after we */
  5036.         /* have agreed to begin the TLS negotiation sequence.           */
  5037.         if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows &&
  5038.              x != TELOPT_START_TLS)
  5039.             break;
  5040. #endif /* CK_SSL */
  5041.  
  5042.         if (!TELOPT_OK(x)) {
  5043.             hexdump("unknown telnet subnegotiation",sb,n);
  5044.             break;
  5045.         } else if ( !(TELOPT_ME(x) || TELOPT_U(x)) ) {
  5046.             hexdump("telnet option not negotiated",sb,n);
  5047.             if (!tn_sb_bug)
  5048.                 break;
  5049.             if (TELOPT_UNANSWERED_WILL(x)) {
  5050.                 TELOPT_UNANSWERED_WILL(x) = 0;
  5051.                 TELOPT_U(x) = 1;
  5052.                 ckmakmsg(tn_msg,TN_MSG_LEN,
  5053.                          "TELNET DO ",TELOPT(x),
  5054.                          "(implied by receipt of SB - protocol error ignored)",
  5055.                          NULL
  5056.                          );
  5057.                 debug(F100,tn_msg,"",0);
  5058.                 if (tn_deb || debses) tn_debug(tn_msg);
  5059.             }
  5060.             if (TELOPT_UNANSWERED_DO(x)) {
  5061.                 TELOPT_UNANSWERED_DO(x) = 0;
  5062.                 TELOPT_ME(x) = 1;
  5063.                 ckmakmsg(tn_msg,TN_MSG_LEN,"TELNET WILL ",TELOPT(x),
  5064.                         " (implied by receipt of SB - protocol error ignored)",
  5065.                         NULL);
  5066.                 debug(F100,tn_msg,"",0);
  5067.                 if (tn_deb || debses) tn_debug(tn_msg);
  5068.              }
  5069.         }
  5070.  
  5071.         TELOPT_UNANSWERED_SB(x)=0;
  5072.         switch (x) {
  5073. #ifdef CK_FORWARD_X
  5074.           case TELOPT_FORWARD_X:
  5075.             return(fwdx_tn_sb(sb, n));
  5076. #endif /* CK_FORWARD_X */
  5077. #ifdef CK_SSL
  5078.           case TELOPT_START_TLS: {
  5079.               /*
  5080.                  the other side is saying SB START_TLS FOLLOWS
  5081.                  the incoming channel is now ready for starting the
  5082.                  TLS negotiation.
  5083.                  */
  5084.               int def_tls_u_mode, def_tls_me_mode;
  5085.               int def_enc_u_mode, def_enc_me_mode;
  5086.               int rc = 0;
  5087.  
  5088.                           if (sb[0] != 1) {
  5089.                                   break;
  5090.                           }
  5091.  
  5092.               TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 1;
  5093.               /* Preserve the default modes and make sure we will */
  5094.               /* refuse START_TLS when we retry. */
  5095.               if (sstelnet) {
  5096.                   def_tls_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_START_TLS);
  5097.                   def_tls_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS);
  5098.                   TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  5099.                   TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
  5100. #ifdef CK_ENCRYPTION
  5101.                   def_enc_u_mode = TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION);
  5102.                   def_enc_me_mode = TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION);
  5103.                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  5104.                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
  5105. #endif /* CK_ENCRYPTION */
  5106.               } else {
  5107.                   def_tls_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_START_TLS);
  5108.                   def_tls_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS);
  5109.                   TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  5110.                   TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS)= TN_NG_RF;
  5111. #ifdef CK_ENCRYPTION
  5112.                   def_enc_u_mode = TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION);
  5113.                   def_enc_me_mode = TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION);
  5114.                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  5115.                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION)= TN_NG_RF;
  5116. #endif /* CK_ENCRYPTION */
  5117.               }
  5118.               /* Negotiate TLS */
  5119.               ttnproto = NP_TLS;
  5120.               tn_init = 0;
  5121.               tn_begun = 0;
  5122.               if (ck_tn_tls_negotiate()<0) {
  5123.                   /* we failed.  disconnect and if we are the client */
  5124.                   /* then reconnect and try without START_TLS.       */
  5125.                   extern char * line;
  5126.                   int x = -1;
  5127.                   extern int mdmtyp;
  5128.  
  5129.                   if (sstelnet) {
  5130.                       printf("TLS failed:  Disconnecting.\n");
  5131.                       TELOPT_DEF_S_U_MODE(TELOPT_START_TLS)  = def_tls_u_mode;
  5132.                       TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
  5133. #ifdef CK_ENCRYPTION
  5134.                      TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  5135.                      TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  5136. #endif /* CK_ENCRYPTION */
  5137.                       ttclos(0);
  5138.                       whyclosed = WC_TELOPT;
  5139.                       ttnproto = NP_TELNET;
  5140.                       rc = -3;
  5141.                   } else {
  5142. #ifndef NOLOCAL
  5143.                       extern tls_norestore;
  5144. #endif /* NOLOCAL */
  5145.                       printf("TLS failed:  Disconnecting...\n");
  5146. #ifdef CK_ENCRYPTION
  5147.                      TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  5148.                      TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  5149. #endif /* CK_ENCRYPTION */
  5150.                       /* if START_TLS is not REQUIRED, then retry without it */
  5151.                       if ( def_tls_me_mode != TN_NG_MU ) {
  5152.                           extern char ttname[];
  5153. #ifndef NOLOCAL
  5154.                           tls_norestore = 1;
  5155. #endif /* NOLOCAL */
  5156.                           ttclos(0);
  5157.                           whyclosed = WC_TELOPT;
  5158. #ifndef NOLOCAL
  5159.                           tls_norestore = 0;
  5160. #endif /* NOLOCAL */
  5161.                           ttnproto = NP_TELNET;
  5162.                           printf("Reconnecting without TLS.\n");
  5163.                           sleep(2);
  5164.                           if (ttopen(ttname,&x,mdmtyp,0)<0)
  5165.                               rc = -3;
  5166.                       } else {
  5167.                           TELOPT_DEF_C_U_MODE(TELOPT_START_TLS) =
  5168.                             def_tls_u_mode;
  5169.                           TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) =
  5170.                             def_tls_me_mode;
  5171.                           ttclos(0);
  5172.                           whyclosed = WC_TELOPT;
  5173.                           ttnproto = NP_TELNET;
  5174.                           rc = -3;
  5175.                       }
  5176.                   }
  5177.               } else {
  5178. #ifdef CK_AUTHENTICATION
  5179.                   /* we succeeded.  restart telnet negotiations from */
  5180.                   /* the beginning.  However, if we have received a  */
  5181.                   /* client certificate and we are a server, then do */
  5182.                   /* not offer TELOPT_AUTH.                          */
  5183.                   if ( ck_tn_auth_valid() == AUTH_VALID ) {
  5184.                       TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_AC;
  5185.                       TELOPT_DEF_S_ME_MODE(TELOPT_AUTHENTICATION)= TN_NG_AC;
  5186.                   }
  5187. #endif /* CK_AUTHENTICATION */
  5188.                   ttnproto = NP_TELNET;
  5189.                   if (tn_ini() < 0)
  5190.                     if (ttchk() < 0)
  5191.                       rc = -1;
  5192.               }
  5193.               /* Restore the default modes */
  5194.               if (sstelnet) {
  5195.                   TELOPT_DEF_S_U_MODE(TELOPT_START_TLS)  = def_tls_u_mode;
  5196.                   TELOPT_DEF_S_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
  5197. #ifdef CK_ENCRYPTION
  5198.                   TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  5199.                   TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  5200. #endif /* CK_ENCRYPTION */
  5201.               } else {
  5202.                   TELOPT_DEF_C_U_MODE(TELOPT_START_TLS)  = def_tls_u_mode;
  5203.                   TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = def_tls_me_mode;
  5204. #ifdef CK_ENCRYPTION
  5205.                   TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION)  = def_enc_u_mode;
  5206.                   TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = def_enc_me_mode;
  5207. #endif /* CK_ENCRYPTION */
  5208.               }
  5209.               return(rc);
  5210.           }
  5211. #endif /* CK_SSL */
  5212. #ifdef CK_AUTHENTICATION
  5213.           case TELOPT_AUTHENTICATION:
  5214.             if (ck_tn_sb_auth((char *)sb,n) < 0) {
  5215.                 if (sstelnet && TELOPT_U_MODE(x) == TN_NG_MU) {
  5216.                     ttclos(0);
  5217.                     whyclosed = WC_TELOPT;
  5218.                     return(-3);
  5219.                 } else if (!sstelnet && TELOPT_ME_MODE(x) == TN_NG_MU) {
  5220.                     ttclos(0);
  5221.                     whyclosed = WC_TELOPT;
  5222.                     return(-3);
  5223.                 } else {
  5224.                     if (TELOPT_ME_MODE(x) == TN_NG_RQ)
  5225.                       TELOPT_ME_MODE(x) = TN_NG_AC;
  5226.                     if (TELOPT_U_MODE(x) == TN_NG_RQ)
  5227.                       TELOPT_U_MODE(x) = TN_NG_AC;
  5228.                 }
  5229.                 if (TELOPT_ME(x)) {
  5230.                     TELOPT_ME(x) = 0;
  5231.                     if (tn_sopt(WONT,x) < 0)
  5232.                       return(-1);
  5233.                 }
  5234.                 if (TELOPT_U(x)) {
  5235.                     TELOPT_U(x) = 0;
  5236.                     if (tn_sopt(DONT,x) < 0)
  5237.                       return(-1);
  5238.                 }
  5239. #ifdef CK_ENCRYPTION
  5240.                 if (tn_no_encrypt()<0)
  5241.                     return(-1);
  5242. #endif /* CK_ENCRYPTION */
  5243.             } else {
  5244. #ifdef CK_ENCRYPTION
  5245.                 if (!ck_tn_auth_in_progress()) { /* we are finished */
  5246.                     if (ck_tn_authenticated() == AUTHTYPE_SSL) {
  5247.                         /* TLS was successful.  Disable ENCRYPTION */
  5248.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  5249.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  5250.                     }
  5251.                     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send) {
  5252.                         ck_encrypt_send_support();
  5253.                         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
  5254.                     }
  5255.                 }
  5256. #endif /* CK_ENCRYPTION */
  5257.             }
  5258.             break;
  5259. #endif /* CK_AUTHENTICATION */
  5260. #ifdef CK_ENCRYPTION
  5261.           case TELOPT_ENCRYPTION:
  5262.             if (ck_tn_sb_encrypt(sb, n) < 0) {
  5263.                 if (TELOPT_U_MODE(x) == TN_NG_MU ||
  5264.                     TELOPT_ME_MODE(x) == TN_NG_MU)
  5265.                   {
  5266.                       ttclos(0);
  5267.                       whyclosed = WC_TELOPT;
  5268.                       return(-3);
  5269.                 } else {
  5270.                     if (TELOPT_ME_MODE(x) == TN_NG_RQ)
  5271.                       TELOPT_ME_MODE(x) = TN_NG_AC;
  5272.                     if (TELOPT_U_MODE(x) == TN_NG_RQ)
  5273.                       TELOPT_U_MODE(x) = TN_NG_AC;
  5274.                 }
  5275.                 if (TELOPT_ME(x)) {
  5276.                     TELOPT_ME(x) = 0;
  5277.                     if (tn_sopt(WONT,x) < 0)
  5278.                       return(-1);
  5279.                 }
  5280.                 if (TELOPT_U(x)) {
  5281.                     TELOPT_U(x) = 0;
  5282.                     if (tn_sopt(DONT,x) < 0)
  5283.                       return(-1);
  5284.                 }
  5285.             }
  5286.             break;
  5287. #endif /* CK_ENCRYPTION */
  5288. #ifdef IKS_OPTION
  5289.           case TELOPT_KERMIT:
  5290.             return(iks_tn_sb(sb, n-2));
  5291. #endif /* IKS_OPTION */
  5292. #ifdef TN_COMPORT
  5293.           case TELOPT_COMPORT:
  5294.             return(tnc_tn_sb(sb, n-2));
  5295. #endif /* TN_COMPORT */
  5296.           case TELOPT_TTYPE:
  5297.             switch (sb[0]) {
  5298.               case TELQUAL_SEND:        /* SEND terminal type? */
  5299.                 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
  5300.                     if (tn_sttyp() < 0) /* Yes, so send it. */
  5301.                         return(-1);
  5302.                 } else {
  5303.                     TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 1;
  5304.                 }
  5305.                 break;
  5306.               case TELQUAL_IS: {        /* IS terminal type? */
  5307.                   /* IS terminal type -- remote gave us its current type */
  5308.                   int i = 0;
  5309. #ifndef OS2
  5310.                   CHAR oldterm[64], *p;
  5311. #endif /* OS2 */
  5312.                   /* Isolate the specified terminal type string */
  5313.                   while (sb[i++] != IAC) {
  5314.                       if (i == 40 ||    /* max len of term string - RFC */
  5315.                           sb[i] == IAC) {
  5316.                           sb[i] = '\0';
  5317.                           break;
  5318.                       }
  5319.                   }
  5320. #ifdef OS2
  5321. #ifndef NOTERM
  5322.                   strupr(&(sb[1]));     /* Upper case it */
  5323.                   for (i = 0; i <= max_tt; i++) { /* find it in our list */
  5324.                       if (!strcmp(&(sb[1]),tt_info[i].x_name)
  5325.                           && i != TT_VTNT) /* can't support VTNT as server */
  5326.                         {
  5327.                           /* Set terminal type to the one chosen */
  5328.                           if (i != tt_type)
  5329.                             settermtype(i,0);
  5330.                           break;
  5331.                       }
  5332.                   }
  5333.                   if (i > max_tt &&
  5334.                       strcmp(&(sb[1]),TELOPT_SB(TELOPT_TTYPE).term.type)) {
  5335.                       /* Couldn't find the specified term type */
  5336.                       sb[40] = '\0';
  5337.                       strcpy(TELOPT_SB(TELOPT_TTYPE).term.type,&(sb[1]));
  5338.                       /* SB TTYPE SEND */
  5339.                       tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
  5340.                       TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
  5341.                   }
  5342. #endif /* NOTERM */
  5343. #else /* OS2 */
  5344.                   p = (CHAR *) getenv("TERM");
  5345.                   if (p)
  5346.                     ckstrncpy((char *)oldterm,(char *)p,63);
  5347.                   else
  5348.                     oldterm[0] = '\0';
  5349.                   cklower((char *)&(sb[1])); /* Lower case new term */
  5350.                   ckmakmsg(term_buf,64,"TERM=",(char *)&(sb[1]),NULL,NULL);
  5351. #ifdef OS2ORUNIX
  5352. #ifndef NOPUTENV
  5353.                   putenv(term_buf);
  5354. #endif /* NOPUTENV */
  5355. #endif /* OS2ORUNIX */
  5356. #ifdef CK_CURSES
  5357. #ifndef MYCURSES
  5358. #ifndef COHERENT
  5359.                   if (trmbuf) {
  5360.                       if (tgetent(trmbuf,(char *)&sb[1]) < 1) {
  5361.                           /* Unsupported terminal.  If new and old terminal */
  5362.                           /* types do not match, ask for another type. */
  5363.                           if (strcmp((char *)oldterm,(char *)&sb[1])) {
  5364.                               /* SB TTYPE SEND */
  5365.                               tn_ssbopt(TELOPT_TTYPE,TELQUAL_SEND,NULL,0);
  5366.                               TELOPT_UNANSWERED_SB(TELOPT_TTYPE)=1;
  5367.                           }
  5368.                       }
  5369.                   }
  5370. #endif /* COHERENT */
  5371. #endif /* MYCURSES */
  5372. #endif /* CK_CURSES */
  5373. #endif /* OS2 */
  5374.               }
  5375.             }
  5376.             break;
  5377. #ifdef CK_ENVIRONMENT
  5378. #ifdef CK_XDISPLOC
  5379.           case TELOPT_XDISPLOC:         /* Send X-Display Location */
  5380.             if (sb[0] == TELQUAL_SEND) {/* SEND X-Display Loc? */
  5381.                 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
  5382.                     if (tn_sxdisploc() < 0)     /* Yes, so send it. */
  5383.                         return(-1);
  5384.                 } else {
  5385.                     TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 1;
  5386.                 }
  5387.             }
  5388.             /* IS -- X Display Location (not supported) */
  5389.             else if (sb[0] == TELQUAL_IS) {
  5390.                 int i = 0;
  5391.                 /* Isolate the specified X-display string */
  5392.                 while (sb[i++] != IAC) {
  5393.                     if (i >= TSBUFSIZ)
  5394.                       return (-1);
  5395.                     if (sb[i] == IAC) {
  5396.                         sb[i] = '\0';
  5397.                         break;
  5398.                     }
  5399.                 }
  5400.                 debug(F110,"TELNET SB XDISPLOC IS",&sb[1],0);
  5401.             }
  5402.             break;
  5403. #endif /* CK_XDISPLOC */
  5404. #endif /* CK_ENVIRONMENT */
  5405.           case TELOPT_NAWS:
  5406.               if (sstelnet
  5407. #ifdef IKSD
  5408.                    || inserver
  5409. #endif /* IKSD */
  5410.                    ) {
  5411.                   int w = 0, h = 0;
  5412.                   int i = 0;
  5413.                   /* At this point sb[] should contain width and height */
  5414.                   if (sb[i] == IAC) i++;
  5415.                   w = (sb[i++] << 8);   /* save upper height */
  5416.                   if (sb[i] == IAC) i++;
  5417.                   w += sb[i++];         /* save the width */
  5418.                   if (sb[i] == IAC) i++;
  5419.                   h = (sb[i++] << 8);   /* save upper height */
  5420.                   if (sb[i] == IAC) i++;
  5421.                   h += sb[i++];
  5422.                   debug(F111,"tn_doop NAWS SB","width",w);
  5423.                   debug(F111,"tn_doop NAWS SB","height",h);
  5424.  
  5425.                   if (w == 0)
  5426.                     w = 80;
  5427.                   if (h == 0)
  5428.                     h = 24;
  5429. #ifndef NOLOCAL
  5430.                   if (tcp_incoming || inserver) {
  5431. #ifdef OS2
  5432.                       tt_cols[VTERM] = w;
  5433.                       tt_rows[VTERM] = h;
  5434.                       VscrnSetWidth(VTERM, w);
  5435.                       VscrnSetHeight(VTERM, h+(tt_status[VTERM]?1:0));
  5436. #ifdef IKSD
  5437.                       if (inserver) {
  5438.                           cmd_cols = tt_cols[VCMD] = w;
  5439.                           cmd_rows = tt_rows[VCMD] = h;
  5440.                           VscrnSetWidth(VCMD, w);
  5441.                           VscrnSetHeight(VCMD, h);
  5442.                       }
  5443. #endif /* IKSD */
  5444. #else /* OS2 */
  5445.                       tt_cols = w;
  5446.                       tt_rows = h;
  5447. #endif /* OS2 */
  5448.                   } else {
  5449. #ifdef OS2
  5450.                       tt_cols[VCMD] = w;
  5451.                       tt_rows[VCMD] = h;
  5452.                       VscrnSetWidth(VCMD, w);
  5453.                       VscrnSetHeight(VCMD, h);
  5454. #endif /* OS2 */
  5455.                       cmd_cols = w;
  5456.                       cmd_rows = h;
  5457.                   }
  5458. #else /* NOLOCAL */
  5459.                   cmd_cols = w;
  5460.                   cmd_rows = h;
  5461. #endif /* NOLOCAL */
  5462.  
  5463.                   /* Add LINES and COLUMNS to the environment */
  5464.                   ckmakmsg((char *)rows_buf,16,"LINES=",ckitoa(h),NULL,NULL);
  5465.                   ckmakmsg((char *)cols_buf,16,"COLUMNS=",ckitoa(w),NULL,NULL);
  5466. #ifdef OS2ORUNIX
  5467. #ifndef NOPUTENV
  5468.                   putenv(rows_buf);
  5469.                   putenv(cols_buf);
  5470. #endif /* NOPUTENV */
  5471. #endif /* OS2ORUNIX */
  5472.               }
  5473.               break;
  5474. #ifdef CK_ENVIRONMENT
  5475.           case TELOPT_NEWENVIRON:
  5476.             switch (sb[0]) {
  5477.               case TELQUAL_IS:                  /* IS */
  5478.               case TELQUAL_INFO:                /* INFO */
  5479.                 if (sb[0] == TELQUAL_IS)
  5480.                   debug(F101,"tn_doop NEW-ENV SB IS","",n-3);
  5481.                 else
  5482.                   debug(F101,"tn_doop NEW-ENV SB INFO","",n-3);
  5483.                 if (sstelnet || inserver) { /* Yes, receive it. */
  5484.                     if (tn_rnenv((CHAR *)&sb[1],n-3) < 0)
  5485.                       return(-1);
  5486.                 }
  5487.                 break;
  5488.               case TELQUAL_SEND:        /* SEND */
  5489.                 if ( sstelnet || inserver )         /* ignore if server */
  5490.                     break;
  5491.                 /* We need to take the sb[] and build a structure */
  5492.                 /* containing all of the variables and types that */
  5493.                 /* we are supposed to keep track of and send to   */
  5494.                 /* the host, then call tn_snenv().                  */
  5495.                 /* Or we can punt ...                               */
  5496.                 if ( !tn_delay_sb || !tn_outst(0) || tn_init ) {
  5497.                   if (tn_snenv((CHAR *)&sb[1],n-3) < 0) /* Yes, send it. */
  5498.                      return(-1);
  5499.                 } else {
  5500. #ifndef VMS
  5501.                   CHAR * xxx;
  5502.                   xxx = (CHAR *) malloc(n-1);
  5503. #else
  5504.                   unsigned char * xxx;
  5505.                   xxx = (unsigned char *) malloc(n-1);
  5506. #endif /* VMS */
  5507.                   /* Postpone sending until end of tn_ini() */
  5508.                   TELOPT_SB(TELOPT_NEWENVIRON).env.str = xxx;
  5509.                   if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  5510.                   memcpy((char *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
  5511.                             (char *)&sb[1],n-3);
  5512.                   TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-3] = IAC;
  5513.                   TELOPT_SB(TELOPT_NEWENVIRON).env.str[n-2] = '\0';
  5514.                   TELOPT_SB(TELOPT_NEWENVIRON).env.len = n-3;
  5515.                   TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 1;
  5516.                   }
  5517.                 }
  5518.                 break;
  5519.               }
  5520.               break;
  5521. #endif /* CK_ENVIRONMENT */
  5522. #ifdef CK_SNDLOC
  5523.           case TELOPT_SNDLOC: {
  5524.               if ( deblog ) {
  5525.                   sb[n-2] = '\0';
  5526.                   debug(F110,"TELNET Send-Location",sb,0);
  5527.               }
  5528.               break;
  5529.           }
  5530. #endif /* CK_SNDLOC */
  5531.           } /* switch */
  5532.         break;
  5533.     }
  5534.     return(0);
  5535. }
  5536.  
  5537. int
  5538. #ifdef CK_ANSIC                         /* TELNET DO OPTION */
  5539. tn_doop(CHAR z, int echo, int (*fn)(int))
  5540. #else
  5541. tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
  5542. #endif /* CK_ANSIC */
  5543. /* tn_doop */ {
  5544.     int x=0, y=0;
  5545.  
  5546.     if (z != (CHAR) IAC) {
  5547.         debug(F101,"tn_doop bad call","",z);
  5548.         return(-1);
  5549.     }
  5550.     if (ttnet != NET_TCPB)              /* Check network type */
  5551.       return(0);
  5552.     if (ttnproto != NP_TELNET &&
  5553.          ttnproto != NP_NONE)           /* Check protocol */
  5554.         return(0);
  5555.  
  5556.     x = tn_xdoop(z,echo,fn);
  5557.     if (x >= 0 && !tn_begun) {
  5558.         y = tn_start();
  5559.     }
  5560.     return(y < 0 ? y : x);
  5561. }
  5562.  
  5563. #ifdef CK_ENVIRONMENT
  5564.  
  5565. /* Telnet receive new environment */
  5566. /* Returns -1 on error, 0 if nothing happens, 1 on success */
  5567. /* In order for this code to work, sb[len] == IAC          */
  5568. /* We currently only support the USER environment variable */
  5569.  
  5570. int
  5571. #ifdef CK_ANSIC
  5572. tn_rnenv(CHAR * sb, int len)
  5573. #else
  5574. tn_rnenv(sb, len) CHAR * sb; int len;
  5575. #endif /* CK_ANSIC */
  5576. /* tn_rnenv */ {                        /* Receive new environment */
  5577.     char varname[17];
  5578.     char value[65];
  5579.     char * reply = 0, * s = 0;
  5580.     int i,j,k,n;                                /* Worker. */
  5581.     int type = 0; /* 0 for NONE, 1 for VAR, 2 for USERVAR, */
  5582.                   /* 3 for VALUE in progress */
  5583.  
  5584.     if (ttnet != NET_TCPB) return(0);
  5585.     if (ttnproto != NP_TELNET) return(0);
  5586.     if (sb == NULL) return(-1);
  5587.  
  5588.     if (len == 0) return(1);
  5589.  
  5590.     /*
  5591.     Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
  5592.     follow here until done...
  5593.     */
  5594.     for (i = 0, j = 0, k = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
  5595.         switch (sb[i]) {
  5596.         case TEL_ENV_VAR:               /* VAR */
  5597.         case TEL_ENV_USERVAR:           /* USERVAR */
  5598.         case IAC:                       /* End of the list */
  5599.             switch (type) {
  5600.               case 0:                   /* Nothing in progress */
  5601.                 /* If we get IAC only, then that means there were */
  5602.                 /* no environment variables to send.  we are done */
  5603.                 if (j == 0 && sb[i] == IAC)
  5604.                     return(1);
  5605.               case 1:                   /* VAR in progress */
  5606.               case 2:                   /* USERVAR in progress */
  5607.               case 3:                   /* VALUE in progress */
  5608.                 value[k] = '\0';
  5609.                 varname[j] = '\0';
  5610.                 debug(F111,"tn_rnenv varname",varname,type);
  5611.                 debug(F111,"tn_rnenv value",value,type);
  5612.                 if (!strcmp(varname,"USER")) {
  5613. #ifdef CK_AUTHENTICATION
  5614.                     if (ck_tn_auth_valid() != AUTH_VALID) {
  5615.                         extern char szUserNameRequested[];
  5616.                         debug(F100,"tn_rnenv != AUTH_VALID","",0);
  5617.                         ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
  5618.                         ckstrncpy(uidbuf,value,UIDBUFLEN);
  5619. #ifdef CK_SSL
  5620.                         if (ssl_active_flag) {
  5621.                             if ( tls_is_user_valid(ssl_con, uidbuf) ) {
  5622.                                 extern char szUserNameAuthenticated[];
  5623.                                 ckstrncpy(szUserNameAuthenticated,uidbuf,
  5624.                                            UIDBUFLEN);
  5625.                                 auth_finished(AUTH_VALID);
  5626.                             }
  5627.                         } else if (tls_active_flag) {
  5628.                             if ( tls_is_user_valid(tls_con, uidbuf) ) {
  5629.                                 extern char szUserNameAuthenticated[];
  5630.                                 ckstrncpy(szUserNameAuthenticated,uidbuf,
  5631.                                            UIDBUFLEN);
  5632.                                 auth_finished(AUTH_VALID);
  5633.                             }
  5634.                         }
  5635. #endif /* CK_SSL */
  5636.                     } else {    /* AUTH_VALID */
  5637.                         int x = 0;
  5638.                         debug(F110,"tn_rnenv AUTH_VALID uidbuf",uidbuf,0);
  5639.  
  5640. #ifdef OS2
  5641.                         x = ckstrcmp(value,uidbuf,-1,0); /* case insensitive */
  5642. #ifdef NT
  5643.                         /* NTLM authentication returns names of the form */
  5644.                         /* DOMAIN\user.  We need to check to see of the  */
  5645.                         /* USER VAR contains a domain name or not.  If   */
  5646.                         /* not, then we do not want to change state if   */
  5647.                         /* the uidbuf matches the USER VAR when the      */
  5648.                         /* DOMAIN is ignored.                            */
  5649.                         if ( x && ck_tn_authenticated() == AUTHTYPE_NTLM ) {
  5650.                             char * s1=NULL, * s2=NULL;
  5651.                             int    len1, len2, i;
  5652.  
  5653.                             len1 = strlen(value);
  5654.                             for ( i=len1-1 ; i>=0 ; i--) {
  5655.                                 if ( value[i] == '\\' ) {
  5656.                                     s1 = &value[i+1];   /* DOMAIN found */
  5657.                                     break;
  5658.                                 }
  5659.                             }
  5660.  
  5661.                             if ( s1 == NULL ) {
  5662.                                 len2 = strlen(uidbuf);
  5663.                                 for ( i=len2-1 ; i>=0 ; i--) {
  5664.                                     if ( uidbuf[i] == '\\' ) {
  5665.                                         s2 = &uidbuf[i+1];   /* DOMAIN found */
  5666.                                         break;
  5667.                                     }
  5668.                                 }
  5669.  
  5670.                                 if ( s2 )
  5671.                                     x = ckstrcmp(value,s2,-1,0);
  5672.                             }
  5673.                         }
  5674. #endif /* NT */
  5675. #else /* OS2 */
  5676.                         x = ckstrcmp(value,uidbuf,-1,1); /* case sensitive */
  5677. #endif /* OS2 */
  5678.                         if ( x ) {
  5679.                             extern char szUserNameRequested[];
  5680.                             ckstrncpy(uidbuf,value,UIDBUFLEN);
  5681.                             ckstrncpy(szUserNameRequested,value,UIDBUFLEN);
  5682.                             auth_finished(AUTH_USER);
  5683. #ifdef CK_SSL
  5684.                             if (ssl_active_flag || tls_active_flag) {
  5685.                                 if ( tls_is_user_valid(ssl_con, uidbuf) )
  5686.                                     auth_finished(AUTH_VALID);
  5687.                             }
  5688. #endif /* CK_SSL */
  5689.                         }
  5690.                     }
  5691. #else /* CK_AUTHENTICATION */
  5692.                     ckstrncpy(uidbuf,value,UIDBUFLEN);
  5693. #endif /* CK_AUTHENTICATION */
  5694.                 }
  5695.                 break;
  5696.             }
  5697.             varname[0] = '\0';
  5698.             value[0] = '\0';
  5699.             j = 0;
  5700.             k = 0;
  5701.             type = (sb[i] == TEL_ENV_USERVAR ? 2 :      /* USERVAR */
  5702.                     sb[i] == TEL_ENV_VAR ? 1 :  /* VAR */
  5703.                      0
  5704.                      );
  5705.             break;
  5706.         case TEL_ENV_VALUE: /* VALUE */
  5707.             if ( type == 1 || type == 2 )
  5708.                 type = 3;
  5709.             break;
  5710.         case TEL_ENV_ESC:       /* ESC */
  5711.             /* Take next character literally */
  5712.             if ( ++i >= len )
  5713.                 break;
  5714.             /* otherwise, fallthrough so byte will be added to string. */
  5715.         default:
  5716.             switch (type) {
  5717.             case 1:     /* VAR in progress */
  5718.             case 2:     /* USERVAR in progress */
  5719.                 if ( j < 16 )
  5720.                     varname[j++] = sb[i];
  5721.                 break;
  5722.             case 3:
  5723.                 if ( k < 64 )
  5724.                     value[k++] = sb[i];
  5725.                 break;
  5726.             }
  5727.         }
  5728.     }
  5729.     return(0);
  5730. }
  5731.  
  5732. /* These are for Microsoft SFU version 2 Telnet Server */
  5733. #define SFUTLNTVER "SFUTLNTVER"
  5734. #define SFUTLNTMODE "SFUTLNTMODE"
  5735. #define SFUTLNTVER_VALUE  "2"
  5736. #define SFUTLNTMODE_VALUE "console"    /* The other value is "stream" */
  5737.  
  5738. /* Telnet send new environment */
  5739. /* Returns -1 on error, 0 if nothing happens, 1 on success */
  5740. /* In order for this code to work, sb[len] == IAC          */
  5741.  
  5742. int
  5743. #ifdef CK_ANSIC
  5744. tn_snenv(CHAR * sb, int len)
  5745. #else
  5746. tn_snenv(sb, len) CHAR * sb; int len;
  5747. #endif /* CK_ANSIC */
  5748. /* tn_snenv */ {                        /* Send new environment */
  5749.     char varname[16];
  5750.     char * reply = 0, * s = 0;
  5751.     int i,j,n;                          /* Worker. */
  5752.     int type = 0;       /* 0 for NONE, 1 for VAR, 2 for USERVAR in progress */
  5753.     extern int ck_lcname;
  5754.     char localuidbuf[UIDBUFLEN];    /* (Initialized just below) */
  5755.     char * uu = uidbuf;
  5756.     char * disp = NULL;
  5757.  
  5758.     localuidbuf[0] = '\0';
  5759.     if (ttnet != NET_TCPB) return(0);
  5760.     if (ttnproto != NP_TELNET) return(0);
  5761.     if (!sb) return(-1);
  5762.  
  5763. #ifdef CK_SSL
  5764.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  5765.         return(0);
  5766.     }
  5767. #endif /* CK_SSL */
  5768.  
  5769. #ifdef CK_FORWARD_X
  5770.     if (TELOPT_U(TELOPT_FORWARD_X)) {
  5771.         disp = NULL;
  5772.     } else
  5773. #endif /* CK_FORWARD_X */
  5774.         disp = (char *)tn_get_display();
  5775.  
  5776.     if (ck_lcname) {
  5777.         ckstrncpy(localuidbuf,uidbuf,UIDBUFLEN);
  5778.         cklower(localuidbuf);
  5779.         uu = localuidbuf;
  5780.     }
  5781.  
  5782.     hexdump((CHAR *)"tn_snenv sb[]",sb,len);
  5783.     debug(F110,"tn_snenv uidbuf",uidbuf,0);
  5784.     debug(F110,"tn_snenv localuidbuf",localuidbuf,0);
  5785.     debug(F110,"tn_snenv tn_env_sys",tn_env_sys,0);
  5786.     debug(F110,"tn_snenv tn_env_disp",tn_env_disp,0);
  5787.     debug(F110,"tn_snenv disp",disp,0);
  5788.  
  5789.     /* First determine the size of the buffer we will need */
  5790.     for (i = 0, j = 0, n = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
  5791.         switch (sb[i]) {
  5792.           case TEL_ENV_VAR:             /* VAR */
  5793.           case TEL_ENV_USERVAR:         /* USERVAR */
  5794.         case IAC:                     /* End of the list */
  5795.             switch (type) {
  5796.             case 0:                   /* Nothing in progress */
  5797.                 /* If we get IAC only, then that means send all */
  5798.                 /* VAR and USERVAR.                             */
  5799.                 if (!(j == 0 && sb[i] == IAC))
  5800.                   break;
  5801.             case 1:                   /* VAR in progress */
  5802.                 varname[j] = '\0' ;
  5803.                 if (!varname[0]) {      /* Send All */
  5804.                     if (uu[0])
  5805.                       n += strlen(uu) + 4 + 2;
  5806.                     if (tn_env_job[0])
  5807.                       n += strlen(tn_env_job) + 3 + 2;
  5808.                     if (tn_env_acct[0])
  5809.                       n += strlen(tn_env_acct) + 4 + 2;
  5810.                     if (tn_env_prnt[0])
  5811.                       n += strlen(tn_env_prnt) + 7 + 2;
  5812.                     if (tn_env_sys[0])
  5813.                       n += strlen(tn_env_sys) + 10 + 2;
  5814.                     if (disp)
  5815.                       n += strlen(disp) + 7 + 2;
  5816.                 } else if (!strcmp(varname,"USER") && uu[0])
  5817.                   n += strlen(uu) + 4 + 2;
  5818.                 else if (!strcmp(varname,"JOB") && tn_env_job[0])
  5819.                   n += strlen(tn_env_job) + 3 + 2;
  5820.                 else if (!strcmp(varname,"ACCT") && tn_env_acct[0])
  5821.                   n += strlen(tn_env_acct) + 4 + 2;
  5822.                 else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0])
  5823.                   n += strlen(tn_env_prnt) + 7 + 2;
  5824.                 else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0])
  5825.                   n += strlen(tn_env_sys) + 10 + 2;
  5826.                 else if (!strcmp(varname,"DISPLAY") && disp)
  5827.                   n += strlen(disp) + 7 + 2;
  5828.                 /* If we get IAC only, then that means send all */
  5829.                 /* VAR and USERVAR.                             */
  5830.                   if (!(j == 0 && sb[i] == IAC))
  5831.                       break;
  5832.             case 2:                   /* USERVAR in progress */
  5833.                 varname[j] = '\0' ;
  5834.                 if (!varname[0]) {      /* Send All */
  5835.                     int x;
  5836.                     for ( x=0 ; x<8 ; x++ ) {
  5837.                         if ( tn_env_uservar[x][0] &&
  5838.                              tn_env_uservar[x][1] )
  5839.                             n += strlen(tn_env_uservar[x][0])
  5840.                                 + strlen(tn_env_uservar[x][1]) + 2;
  5841.                     }
  5842.                     if ( tn_sfu ) {
  5843.                         /* For compatibility with Microsoft Telnet Server */
  5844.                         n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
  5845.                         n += strlen(SFUTLNTMODE) +
  5846.                           strlen(SFUTLNTMODE_VALUE) + 2;
  5847.                     }
  5848. #ifdef CK_SNDLOC
  5849.                     if ( tn_loc && tn_loc[0] )
  5850.                         n += strlen("LOCATION") + strlen(tn_loc) + 2;
  5851. #endif /* CK_SNDLOC */
  5852.                 }
  5853.                 else if (tn_sfu && !strcmp(varname,SFUTLNTVER))
  5854.                     n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
  5855.                 else if (tn_sfu && !strcmp(varname,SFUTLNTMODE))
  5856.                     n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
  5857. #ifdef CK_SNDLOC
  5858.                 else if ( tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION"))
  5859.                     n += strlen("LOCATION") + strlen(tn_loc) + 2;
  5860. #endif /* CK_SNDLOC */
  5861.                 else {
  5862.                     int x;
  5863.                     for ( x=0 ; x<8 ; x++ ) {
  5864.                         if ( tn_env_uservar[x][0] &&
  5865.                              tn_env_uservar[x][1] &&
  5866.                              !strcmp(varname,tn_env_uservar[x][0]))
  5867.                             n += strlen(tn_env_uservar[x][0])
  5868.                                 + strlen(tn_env_uservar[x][1]) + 2;
  5869.                     }
  5870.                 }
  5871.                 break;
  5872.             }
  5873.             varname[0] = '\0';
  5874.             j = 0;
  5875.             type = (sb[i] == TEL_ENV_USERVAR ? 2 :      /* USERVAR */
  5876.                     sb[i] == TEL_ENV_VAR ? 1 :          /* VAR */
  5877.                     0
  5878.                    );
  5879.             break;
  5880.           case TEL_ENV_VALUE:           /* VALUE */
  5881.             /* Protocol Error */
  5882.             debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
  5883.             if (tn_deb || debses)
  5884.               tn_debug("TELNET Subnegotiation error - VALUE in SEND");
  5885.             return(0);
  5886.           case TEL_ENV_ESC:     /* ESC */
  5887.             if (++i >= len)
  5888.               break;
  5889.           default:
  5890.             if (j < 16 )
  5891.               varname[j++] = sb[i];
  5892.         }
  5893.     }
  5894.     reply = malloc(n + 16);              /* Leave room for IAC stuff */
  5895.     if (!reply) {
  5896.         debug(F100, "TELNET Subnegotiation error - malloc failed", "",0);
  5897.         if (tn_deb || debses)
  5898.           tn_debug("TELNET Subnegotiation error - malloc failed");
  5899.  
  5900.         /* Send a return packet with no variables so that the host */
  5901.         /* may continue with additional negotiations               */
  5902.         if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,"",0) < 0)
  5903.           return(-1);
  5904.         return(0);
  5905.     }
  5906.  
  5907.     /* Now construct the real reply */
  5908.  
  5909.     n = 0;                              /* Start at beginning of buffer */
  5910. /*
  5911.   Pairs of <type> [VAR=0, VALUE=1, ESC=2, USERVAR=3] <value> "unterminated"
  5912.   follow here until done...
  5913. */
  5914.     for (i = 0, j = 0, type = 0, varname[0]= '\0'; i <= len; i++) {
  5915.         switch (sb[i]) {
  5916.           case TEL_ENV_VAR:             /* VAR */
  5917.           case TEL_ENV_USERVAR:         /* USERVAR */
  5918.           case IAC:                     /* End of the list */
  5919.             switch (type) {
  5920.               case 0:                   /* Nothing in progress */
  5921.                 /* If we get IAC only, then that means send all */
  5922.                 /* VAR and USERVAR.                             */
  5923.                 if (!(j == 0 && sb[i] == IAC))
  5924.                   break;
  5925.               case 1:                   /* VAR in progress */
  5926.                 varname[j] = '\0';
  5927.                 if (!varname[0]) {
  5928.                     /* Send All */
  5929.                     if (uu[0]) {
  5930.                         reply[n] = TEL_ENV_VAR; /* VAR */
  5931.                         strcpy(&reply[n+1],"USER");
  5932.                         reply[n+5] = TEL_ENV_VALUE;             /* VALUE */
  5933.                         strcpy(&reply[n+6],uu);
  5934.                         n += strlen(uu) + 4 + 2;
  5935.                     }
  5936.                     if (tn_env_job[0]) {
  5937.                         reply[n] = TEL_ENV_VAR; /* VAR */
  5938.                         strcpy(&reply[n+1],"JOB");
  5939.                         reply[n+4] = TEL_ENV_VALUE;     /* VALUE */
  5940.                         strcpy(&reply[n+5],tn_env_job);
  5941.                         n += strlen(tn_env_job) + 3 + 2;
  5942.                     }
  5943.                     if (tn_env_acct[0]) {
  5944.                         reply[n] = TEL_ENV_VAR; /* VAR */
  5945.                         strcpy(&reply[n+1],"ACCT");
  5946.                         reply[n+5] = TEL_ENV_VALUE;     /* VALUE */
  5947.                         strcpy(&reply[n+6],tn_env_acct);
  5948.                         n += strlen(tn_env_acct) + 4 + 2;
  5949.                     }
  5950.                     if (tn_env_prnt[0]) {
  5951.                         reply[n] = TEL_ENV_VAR; /* VAR */
  5952.                         strcpy(&reply[n+1],"PRINTER");
  5953.                         reply[n+8] = TEL_ENV_VALUE;     /* VALUE */
  5954.                         strcpy(&reply[n+9],tn_env_prnt);
  5955.                         n += strlen(tn_env_prnt) + 7 + 2;
  5956.                     }
  5957.                     if (tn_env_sys[0]) {
  5958.                         reply[n] = TEL_ENV_VAR; /* VAR */
  5959.                         strcpy(&reply[n+1],"SYSTEMTYPE");
  5960.                         reply[n+11] = TEL_ENV_VALUE; /* VALUE */
  5961.                         strcpy(&reply[n+12],tn_env_sys);
  5962.                         n += strlen(tn_env_sys) + 10 + 2;
  5963.                     }
  5964.                     if (disp) {
  5965.                         reply[n] = TEL_ENV_VAR; /* VAR */
  5966.                         strcpy(&reply[n+1],"DISPLAY");
  5967.                         reply[n+8] = TEL_ENV_VALUE;     /* VALUE */
  5968.                         strcpy(&reply[n+9],disp);
  5969.                         n += strlen(disp) + 7 + 2;
  5970.                     }
  5971.                 } else if (!strcmp(varname,"USER") && uu[0]) {
  5972.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  5973.                     strcpy(&reply[n+1],"USER");
  5974.                     reply[n+5] = TEL_ENV_VALUE; /* VALUE */
  5975.                     strcpy(&reply[n+6],uu);
  5976.                     n += strlen(uu) + 4 + 2;
  5977.                 } else if (!strcmp(varname,"JOB") && tn_env_job[0]) {
  5978.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  5979.                     strcpy(&reply[n+1],"JOB");
  5980.                     reply[n+4] = TEL_ENV_VALUE; /* VALUE */
  5981.                     strcpy(&reply[n+5],tn_env_job);
  5982.                     n += strlen(tn_env_job) + 3 + 2;
  5983.                 } else if (!strcmp(varname,"ACCT") && tn_env_acct[0]) {
  5984.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  5985.                     strcpy(&reply[n+1],"ACCT");
  5986.                     reply[n+5] = TEL_ENV_VALUE; /* VALUE */
  5987.                     strcpy(&reply[n+6],tn_env_acct);
  5988.                     n += strlen(tn_env_acct) + 4 + 2;
  5989.                 } else if (!strcmp(varname,"PRINTER") && tn_env_prnt[0]) {
  5990.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  5991.                     strcpy(&reply[n+1],"PRINTER");
  5992.                     reply[n+8] = TEL_ENV_VALUE; /* VALUE */
  5993.                     strcpy(&reply[n+9],tn_env_prnt);
  5994.                     n += strlen(tn_env_prnt) + 7 + 2;
  5995.                 } else if (!strcmp(varname,"SYSTEMTYPE") && tn_env_sys[0]) {
  5996.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  5997.                     strcpy(&reply[n+1],"SYSTEMTYPE");
  5998.                     reply[n+11] = TEL_ENV_VALUE;        /* VALUE */
  5999.                     strcpy(&reply[n+12],tn_env_sys);
  6000.                     n += strlen(tn_env_sys) + 10 + 2;
  6001.                 } else if (!strcmp(varname,"DISPLAY") && disp) {
  6002.                     reply[n] = TEL_ENV_VAR;     /* VAR */
  6003.                     strcpy(&reply[n+1],"DISPLAY");
  6004.                     reply[n+8] = TEL_ENV_VALUE; /* VALUE */
  6005.                     strcpy(&reply[n+9],disp);
  6006.                     n += strlen(disp) + 7 + 2;
  6007.                 }
  6008.                   /* If we get IAC only, then that means send all */
  6009.                   /* VAR and USERVAR.                             */
  6010.                   if (!(j == 0 && sb[i] == IAC))
  6011.                       break;
  6012.             case 2:     /* USERVAR in progress */
  6013.                   varname[j] = '\0';
  6014.                   if (!varname[0]) {
  6015.                       /* Send All */
  6016.                       int x,y;
  6017.                       for ( x=0 ; x<8 ; x++ ) {
  6018.                           if ( tn_env_uservar[x][0] &&
  6019.                                tn_env_uservar[x][1] ) {
  6020.                               reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6021.                               y = strlen(tn_env_uservar[x][0]);
  6022.                               strcpy(&reply[n+1],tn_env_uservar[x][0]);
  6023.                               reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
  6024.                               strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
  6025.                               n += y+strlen(tn_env_uservar[x][1])+2;
  6026.                           }
  6027.                       }
  6028.                       if ( tn_sfu ) {
  6029.                           /* Compatibility with Microsoft Telnet Server */
  6030.                           reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6031.                           strcpy(&reply[n+1],SFUTLNTVER);
  6032.                           reply[n+11] = TEL_ENV_VALUE; /* VALUE */
  6033.                           strcpy(&reply[n+12],SFUTLNTVER_VALUE);
  6034.                           n += strlen(SFUTLNTVER)+strlen(SFUTLNTVER_VALUE)+2;
  6035.  
  6036.                           reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6037.                           strcpy(&reply[n+1],SFUTLNTMODE);
  6038.                           reply[n+12] = TEL_ENV_VALUE; /* VALUE */
  6039.                           strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
  6040.                           n += strlen(SFUTLNTMODE)+strlen(SFUTLNTMODE_VALUE)+2;
  6041.                       }
  6042.                       if (tn_loc && tn_loc[0]) {
  6043.                           reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6044.                           strcpy(&reply[n+1],"LOCATION");
  6045.                           reply[n+9] = TEL_ENV_VALUE; /* VALUE */
  6046.                           strcpy(&reply[n+10],tn_loc);
  6047.                           n += strlen("LOCATION") + strlen(tn_loc) + 2;
  6048.                       }
  6049.                   }  else if (tn_sfu && !strcmp(varname,SFUTLNTVER)) {
  6050.                       reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6051.                       strcpy(&reply[n+1],SFUTLNTVER);
  6052.                       reply[n+11] = TEL_ENV_VALUE; /* VALUE */
  6053.                       strcpy(&reply[n+12],SFUTLNTVER_VALUE);
  6054.                       n += strlen(SFUTLNTVER) + strlen(SFUTLNTVER_VALUE) + 2;
  6055.                   }  else if (tn_sfu && !strcmp(varname,SFUTLNTMODE)) {
  6056.                       reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6057.                       strcpy(&reply[n+1],SFUTLNTMODE);
  6058.                       reply[n+12] = TEL_ENV_VALUE; /* VALUE */
  6059.                       strcpy(&reply[n+13],SFUTLNTMODE_VALUE);
  6060.                       n += strlen(SFUTLNTMODE) + strlen(SFUTLNTMODE_VALUE) + 2;
  6061.                   }
  6062. #ifdef CK_SNDLOC
  6063.                   else if (tn_loc && tn_loc[0] && !strcmp(varname,"LOCATION")){
  6064.                       reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6065.                       strcpy(&reply[n+1],"LOCATION");
  6066.                       reply[n+9] = TEL_ENV_VALUE; /* VALUE */
  6067.                       strcpy(&reply[n+10],tn_loc);
  6068.                       n += strlen("LOCATION") + strlen(tn_loc) + 2;
  6069.                   }
  6070. #endif /* CK_SNDLOC */
  6071.                   else {
  6072.                       int x,y;
  6073.                       for ( x=0 ; x<8 ; x++ ) {
  6074.                           if ( tn_env_uservar[x][0] &&
  6075.                                tn_env_uservar[x][1] &&
  6076.                                !strcmp(varname,tn_env_uservar[x][0])) {
  6077.                               reply[n] = TEL_ENV_USERVAR;     /* VAR */
  6078.                               y = strlen(tn_env_uservar[x][0]);
  6079.                               strcpy(&reply[n+1],tn_env_uservar[x][0]);
  6080.                               reply[n+y+1] = TEL_ENV_VALUE; /* VALUE */
  6081.                               strcpy(&reply[n+y+2],tn_env_uservar[x][1]);
  6082.                               n += y+strlen(tn_env_uservar[x][1])+2;
  6083.                           }
  6084.                       }
  6085.                   }
  6086.                 break;
  6087.             }
  6088.             varname[0] = '\0';
  6089.             j = 0;
  6090.             type = (sb[i] == TEL_ENV_USERVAR ? 2 :      /* USERVAR */
  6091.                     sb[i] == TEL_ENV_VAR ? 1 :  /* VAR */
  6092.                     0
  6093.                    );
  6094.             break;
  6095.           case TEL_ENV_VALUE: /* VALUE */
  6096.             /* Protocol Error */
  6097.             debug(F100, "TELNET Subnegotiation error - VALUE in SEND", "",0);
  6098.             if (tn_deb || debses)
  6099.               tn_debug("TELNET Subnegotiation error - VALUE in SEND");
  6100.             return(0);  /* Was -1 but that would be taken as */
  6101.                         /* an I/O error, so absorb it and go on. */
  6102.           case TEL_ENV_ESC:     /* ESC */
  6103.             /* Not sure what this for.  Quote next character? */
  6104.             break;
  6105.           default:
  6106.             varname[j++] = sb[i];
  6107.         }
  6108.     }
  6109.     if (tn_ssbopt(TELOPT_NEWENVIRON,TELQUAL_IS,reply,n) < 0) {
  6110.         free(reply);
  6111.         return(-1);
  6112.     }
  6113.     free(reply);
  6114.     return(1);
  6115. }
  6116. #endif /* CK_ENVIRONMENT */
  6117.  
  6118. /* Telnet send terminal type */
  6119. /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
  6120.  
  6121. int
  6122. tn_sttyp() {                            /* Send telnet terminal type. */
  6123.     char *ttn;                          /* Name of terminal type. */
  6124. #ifdef OS2
  6125.     static int alias = -1;              /* which alias are we using ? */
  6126.     int settype = 0;
  6127. #endif /* OS2 */
  6128.     int i, rc;                          /* Worker. */
  6129.     int tntermflg = 0;
  6130.  
  6131.     if (ttnet != NET_TCPB) return(0);
  6132.     if (ttnproto != NP_TELNET) return(0);
  6133.  
  6134.     if (!TELOPT_ME(TELOPT_TTYPE)) return(0);
  6135.  
  6136. #ifdef CK_SSL
  6137.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6138.         return(0);
  6139.     }
  6140. #endif /* CK_SSL */
  6141.     ttn = NULL;
  6142.  
  6143. #ifndef NOTERM
  6144. #ifdef OS2
  6145.     if (!tn_term) {
  6146.         if (ttnum == -1) {
  6147.             ttnum = tt_type;
  6148.             settype = 0;
  6149.             alias = -1;
  6150.         } else if (ttnumend) {
  6151.             ttnumend = 0;
  6152.             settype = 0;
  6153.         } else {
  6154.             if (tt_info[tt_type].x_aliases[++alias] == NULL)  {
  6155.                 if (--tt_type < 0)
  6156.                   tt_type = max_tt;
  6157.                 if (ttnum == tt_type)
  6158.                   ttnumend = 1;
  6159.                 settype = 1;
  6160.                 alias = -1;
  6161.             }
  6162.         }
  6163.         if (tt_type >= 0 && tt_type <= max_tt) {
  6164.             if (alias == -1)
  6165.               ttn = tt_info[tt_type].x_name;
  6166.             else
  6167.               ttn = tt_info[tt_type].x_aliases[alias];
  6168.         } else
  6169.           ttn = NULL;
  6170.     }
  6171.     else settype = 0;
  6172. #endif /* OS2 */
  6173. #endif /* NOTERM */
  6174.  
  6175.     if (tn_term) {                      /* Terminal type override? */
  6176.         debug(F110,"tn_sttyp",tn_term,0);
  6177.         if (*tn_term) {
  6178.             ttn = tn_term;
  6179.             tntermflg = 1;
  6180.         }
  6181.     } else debug(F100,"tn_sttyp no term override","",0);
  6182.  
  6183. #ifndef datageneral
  6184.     if (!ttn) {                         /* If no override, */
  6185.         ttn = getenv("TERM");           /* get it from the environment. */
  6186.     }
  6187. #endif /* datageneral */
  6188.     if ((ttn == ((char *)0)) || ((int)strlen(ttn) >= TSBUFSIZ))
  6189.       ttn = "UNKNOWN";
  6190.     sb_out[0] = (CHAR) IAC;                 /* I Am a Command */
  6191.     sb_out[1] = (CHAR) SB;                  /* Subnegotiation */
  6192.     sb_out[2] = TELOPT_TTYPE;               /* Terminal Type */
  6193.     sb_out[3] = (CHAR) 0;                   /* Is... */
  6194.     for (i = 4; *ttn; ttn++,i++) {      /* Copy and uppercase it */
  6195. #ifdef VMS
  6196.         if (!tntermflg && *ttn == '-' &&
  6197.             (!strcmp(ttn,"-80") || !strcmp(ttn,"-132")))
  6198.           break;
  6199.         else
  6200. #endif /* VMS */
  6201.           sb_out[i] = (char) ((!tntermflg && islower(*ttn)) ?
  6202.                               toupper(*ttn) :
  6203.                               *ttn);
  6204.     }
  6205.     ttn = (char *)sb_out;                   /* Point back to beginning */
  6206. #ifdef DEBUG
  6207.     if (deblog || tn_deb || debses) {
  6208.         sb_out[i] = '\0';                   /* For debugging */
  6209.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB ",
  6210.                  TELOPT(TELOPT_TTYPE)," IS ",(char *)sb_out+4," IAC SE",
  6211.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6212.     }
  6213. #endif /* DEBUG */
  6214.     sb_out[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  6215.     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
  6216. #ifdef OS2
  6217.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  6218. #endif
  6219. #ifdef DEBUG
  6220.     debug(F100,tn_msg_out,"",0);
  6221.     if (tn_deb || debses) tn_debug(tn_msg_out);
  6222. #endif /* DEBUG */
  6223.     rc = (ttol((CHAR *)sb_out,i) < 0);       /* Send it. */
  6224. #ifdef OS2
  6225.     ReleaseTelnetMutex();
  6226. #endif
  6227.     if (rc)
  6228.         return(-1);
  6229. #ifndef NOTERM
  6230. #ifdef OS2
  6231.     if (settype)
  6232.         settermtype(tt_type,0);
  6233.     else {
  6234.         ipadl25();
  6235.         VscrnIsDirty(VTERM);
  6236.     }
  6237. #endif /* OS2 */
  6238. #endif /* NOTERM */
  6239.     return(1);
  6240. }
  6241.  
  6242. #ifdef CK_ENVIRONMENT
  6243. #ifdef CK_XDISPLOC
  6244.  
  6245. /* Telnet send xdisplay location */
  6246. /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
  6247.  
  6248. int
  6249. tn_sxdisploc() {                        /* Send telnet X display location. */
  6250.     char * disp=NULL;
  6251.     int i,rc;
  6252.  
  6253.     if (ttnet != NET_TCPB) return(0);
  6254.     if (ttnproto != NP_TELNET) return(0);
  6255.  
  6256.     if (!TELOPT_ME(TELOPT_XDISPLOC)) return(0);
  6257.  
  6258. #ifdef CK_SSL
  6259.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6260.         return(0);
  6261.     }
  6262. #endif /* CK_SSL */
  6263.  
  6264. #ifdef CK_FORWARD_X
  6265.     if (TELOPT_U(TELOPT_FORWARD_X)) {
  6266.         disp = NULL;
  6267.     } else
  6268. #endif /* CK_FORWARD_X */
  6269.         disp = (char *)tn_get_display();
  6270.     debug(F110,"tn_sxdisploc",disp,0);
  6271.  
  6272.     if (!disp) {
  6273.         /* Can't do both, send WONT */
  6274.         if (tn_sopt(WONT,TELOPT_XDISPLOC) < 0)
  6275.             return(-1);
  6276.         TELOPT_UNANSWERED_WONT(TELOPT_XDISPLOC) = 1;
  6277.         return(0);
  6278.     }
  6279.  
  6280.     sb_out[0] = (CHAR) IAC;                 /* I Am a Command */
  6281.     sb_out[1] = (CHAR) SB;                  /* Subnegotiation */
  6282.     sb_out[2] = TELOPT_XDISPLOC;            /* X-Display Location */
  6283.     sb_out[3] = (CHAR) 0;                   /* Is... */
  6284.     for (i = 4; *disp; disp++,i++) {      /* Copy and uppercase it */
  6285.         sb_out[i] = (char) *disp;
  6286.     }
  6287. #ifdef DEBUG
  6288.     if (deblog || tn_deb || debses) {
  6289.         sb_out[i] = '\0';                   /* For debugging */
  6290.         ckmakxmsg( tn_msg_out,TN_MSG_LEN,
  6291.                   "TELNET SENT SB ",TELOPT(TELOPT_XDISPLOC),
  6292.                   " IS ",(char *)sb_out+4," IAC SE",
  6293.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6294.     }
  6295. #endif /* DEBUG */
  6296.     sb_out[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  6297.     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
  6298. #ifdef OS2
  6299.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  6300. #endif
  6301. #ifdef DEBUG
  6302.     debug(F100,tn_msg_out,"",0);
  6303.     if (tn_deb || debses) tn_debug(tn_msg_out);
  6304. #endif /* DEBUG */
  6305.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  6306. #ifdef OS2
  6307.     ReleaseTelnetMutex();
  6308. #endif
  6309.     if (rc)
  6310.         return(-1);
  6311.     return(1);
  6312. }
  6313. #endif /* CK_XDISPLOC */
  6314. #endif /* CK_ENVIRONMENT */
  6315.  
  6316. #ifdef CK_FORWARD_X
  6317. int
  6318. tn_sndfwdx() {                          /* Send Fwd X Screen number to host */
  6319.     unsigned char screen = 0;
  6320.     char * disp;
  6321.     int i,rc;
  6322.  
  6323.     if (!TELOPT_U(TELOPT_FORWARD_X)) return(0);
  6324. #ifdef CK_SSL
  6325.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6326.         return(0);
  6327.     }
  6328. #endif /* CK_SSL */
  6329.  
  6330.     /*
  6331.      * The format of the DISPLAY variable is [<host>:]<display>[.<screen>]
  6332.      * where <host> is an optional DNS name or ip address with a default of
  6333.      * the localhost; the screen defaults to 0
  6334.      */
  6335.  
  6336.     disp = tn_get_display();
  6337.     if (disp) {
  6338.         int colon,dot;
  6339.         colon = ckindex(":",disp,0,0,1);
  6340.         dot   = ckindex(".",&disp[colon],0,0,1);
  6341.  
  6342.         if ( dot ) {
  6343.             screen = atoi(&disp[colon+dot]);
  6344.         }
  6345.     } else {
  6346.         screen = 0;
  6347.     }
  6348.  
  6349.     i = 0;
  6350.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  6351.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  6352.     sb_out[i++] = TELOPT_FORWARD_X;           /* Forward X */
  6353.     sb_out[i++] = FWDX_SCREEN;                /* Screen */
  6354.     sb_out[i++] = screen;
  6355.     if ( screen == IAC )
  6356.         sb_out[i++] = IAC;
  6357.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  6358.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  6359. #ifdef DEBUG
  6360.     if (deblog || tn_deb || debses) {
  6361.         ckmakxmsg( tn_msg_out,TN_MSG_LEN,
  6362.                    "TELNET SENT SB ",TELOPT(TELOPT_FORWARD_X),
  6363.                    " SCREEN ",ckctox(screen,1)," IAC SE",
  6364.                    NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6365.     }
  6366. #endif /* DEBUG */
  6367. #ifdef OS2
  6368.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  6369. #endif
  6370. #ifdef DEBUG
  6371.     debug(F100,tn_msg_out,"",0);
  6372.     if (tn_deb || debses) tn_debug(tn_msg_out);
  6373. #endif /* DEBUG */
  6374.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  6375. #ifdef OS2
  6376.     ReleaseTelnetMutex();
  6377. #endif
  6378.     if (rc)
  6379.         return(-1);
  6380.     return(0);
  6381. }
  6382. #endif /* CK_FORWARD_X */
  6383.  
  6384. #ifdef CK_SNDLOC
  6385. int
  6386. tn_sndloc() {                           /* Send location. */
  6387.     int i,rc;                              /* Worker. */
  6388.     char *ttloc;
  6389.  
  6390.     if (!TELOPT_ME(TELOPT_SNDLOC)) return(0);
  6391.  
  6392. #ifdef CK_SSL
  6393.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6394.         return(0);
  6395.     }
  6396. #endif /* CK_SSL */
  6397.     ttloc = (tn_loc ? tn_loc : "");     /* In case we are being called even */
  6398.                                         /* though there is no location. */
  6399.     sb_out[0] = (CHAR) IAC;                 /* I Am a Command */
  6400.     sb_out[1] = (CHAR) SB;                  /* Subnegotiation */
  6401.     sb_out[2] = TELOPT_SNDLOC;              /* Location */
  6402.     for (i = 3; *ttloc && i < TSBUFSIZ; ttloc++,i++) /* Copy it */
  6403.       sb_out[i] = (char) *ttloc;
  6404.     sb_out[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  6405.     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
  6406.  
  6407. #ifdef DEBUG
  6408.     if (deblog || tn_deb || debses) {
  6409.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  6410.                   "TELNET SENT SB ",TELOPT(TELOPT_SNDLOC)," ",(char *)sb_out+3,
  6411.                   " IAC SE", NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6412.     }
  6413. #endif /* DEBUG */
  6414. #ifdef OS2
  6415.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  6416. #endif
  6417. #ifdef DEBUG
  6418.     debug(F100,tn_msg_out,"",0);
  6419.     if (tn_deb || debses) tn_debug(tn_msg_out);
  6420. #endif /* DEBUG */
  6421.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  6422. #ifdef OS2
  6423.     ReleaseTelnetMutex();
  6424. #endif
  6425.     if (rc)
  6426.         return(-1);
  6427.     sb_out[i-2] = '\0';                     /* For debugging */
  6428.     return(0);
  6429. }
  6430. #endif /* CK_SNDLOC */
  6431.  
  6432. #ifdef CK_NAWS                  /*  NAWS = Negotiate About Window Size  */
  6433. int
  6434. tn_snaws() {                    /*  Send terminal width and height, RFC 1073 */
  6435. #ifndef NOLOCAL
  6436.     CHAR sb_out[24];            /*  multiple threads */
  6437.     int i = 0,rc;
  6438. #ifdef OS2
  6439.     int x = VscrnGetWidth(VTERM),
  6440.     y = VscrnGetHeight(VTERM) - (tt_status[VTERM] ? 1 : 0);
  6441. #else /* OS2 */
  6442.     int x = tt_cols, y = tt_rows;
  6443. #endif /* OS2 */
  6444.  
  6445.     if (ttnet != NET_TCPB) return(0);
  6446.     if (ttnproto != NP_TELNET) return(0);
  6447.     if (!TELOPT_ME(TELOPT_NAWS)) return(0);
  6448.  
  6449. #ifdef CK_SSL
  6450.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6451.         return(0);
  6452.     }
  6453. #endif /* CK_SSL */
  6454.     if (x < 0) x = 0;
  6455.     if (y < 0) y = 0;
  6456.  
  6457.     if (x == TELOPT_SB(TELOPT_NAWS).naws.x && /* Only send if changed */
  6458.         y == TELOPT_SB(TELOPT_NAWS).naws.y
  6459.         )
  6460.       return(0);
  6461.     TELOPT_SB(TELOPT_NAWS).naws.x = x;  /* Remember the size     */
  6462.     TELOPT_SB(TELOPT_NAWS).naws.y = y;
  6463.  
  6464.     sb_out[i++] = (CHAR) IAC;               /* Send the subnegotiation */
  6465.     sb_out[i++] = (CHAR) SB;
  6466.     sb_out[i++] = TELOPT_NAWS;
  6467.     sb_out[i++] = (CHAR) (x >> 8) & 0xff;
  6468.     if ((CHAR) sb_out[i-1] == (CHAR) IAC)   /* IAC in data must be doubled */
  6469.       sb_out[i++] = (CHAR) IAC;
  6470.     sb_out[i++] = (CHAR) (x & 0xff);
  6471.     if ((CHAR) sb_out[i-1] == (CHAR) IAC)
  6472.       sb_out[i++] = (CHAR) IAC;
  6473.     sb_out[i++] = (CHAR) (y >> 8) & 0xff;
  6474.     if ((CHAR) sb_out[i-1] == (CHAR) IAC)
  6475.       sb_out[i++] = (CHAR) IAC;
  6476.     sb_out[i++] = (CHAR) (y & 0xff);
  6477.     if ((CHAR) sb_out[i-1] == (CHAR) IAC)
  6478.       sb_out[i++] = (CHAR) IAC;
  6479.     sb_out[i++] = (CHAR) IAC;
  6480.     sb_out[i++] = (CHAR) SE;
  6481. #ifdef DEBUG
  6482.     if (deblog || tn_deb || debses) {
  6483.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,"TELNET SENT SB NAWS ",
  6484.                   ckitoa(x)," ",ckitoa(y)," IAC SE",
  6485.                    NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6486.     }
  6487. #endif /* DEBUG */
  6488. #ifdef OS2
  6489.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  6490. #endif
  6491. #ifdef DEBUG
  6492.     debug(F100,tn_msg_out,"",0);
  6493.     if (tn_deb || debses) tn_debug(tn_msg_out);
  6494. #endif /* DEBUG */
  6495.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  6496. #ifdef OS2
  6497.     ReleaseTelnetMutex();
  6498. #endif
  6499.     if (rc)
  6500.         return(-1);
  6501. #endif /* NOLOCAL */
  6502.     return (0);
  6503. }
  6504. #endif /* CK_NAWS */
  6505.  
  6506. #ifdef TN_COMPORT
  6507. static char * tnc_signature = NULL;
  6508. static int tnc_ls_mask = 0;
  6509. static int tnc_ls = 0;
  6510. static int tnc_ms_mask = 255;
  6511. static int tnc_ms = 0;
  6512. static int tnc_oflow = 0;
  6513. static int tnc_iflow = 0;
  6514. static int tnc_bps = 0;
  6515. static int tnc_datasize = 0;
  6516. static int tnc_parity = 0;
  6517. static int tnc_stopbit = 0;
  6518. static int tnc_break = 0;
  6519. static int tnc_dtr = 0;
  6520. static int tnc_rts = 0;
  6521. static int tnc_suspend_xmit = 0;
  6522. static int tnc_bps_index = -1;
  6523.  
  6524. int
  6525. #ifdef CK_ANSIC
  6526. tnc_init(void)
  6527. #else /* CK_ANSIC */
  6528. tnc_init()
  6529. #endif /* CK_ANSIC */
  6530. /* tnc_init */ {
  6531.     debug(F100,"tnc_init","",0);
  6532.  
  6533.     if (tnc_signature) {
  6534.         free(tnc_signature);
  6535.         tnc_signature = NULL;
  6536.     }
  6537.     tnc_ls_mask = 0;
  6538.     tnc_ls = 0;
  6539.     tnc_ms_mask = 255;
  6540.     tnc_ms = 0;
  6541.     tnc_oflow = 0;
  6542.     tnc_iflow = 0;
  6543.     tnc_bps = 0;
  6544.     tnc_datasize = 0;
  6545.     tnc_parity = 0;
  6546.     tnc_stopbit = 0;
  6547.     tnc_break = 0;
  6548.     tnc_dtr = 0;
  6549.     tnc_rts = 0;
  6550.     tnc_suspend_xmit = 0;
  6551.     tnc_bps_index = -1;
  6552.     return(0);
  6553. }
  6554.  
  6555. int
  6556. #ifdef CK_ANSIC
  6557. tn_sndcomport(void)
  6558. #else /* CK_ANSIC */
  6559. tn_sndcomport()
  6560. #endif /* CK_ANSIC */
  6561. /* tn_sndcomport */ {
  6562.     int baud, datasize, parity, stopsize, oflow, iflow;
  6563.     CONST char * signature;
  6564.  
  6565.     debug(F100,"tnc_sndcomport","",0);
  6566.     signature = tnc_get_signature();
  6567.     baud = tnc_get_baud();
  6568.     datasize = tnc_get_datasize();
  6569.     parity = tnc_get_parity();
  6570.     stopsize = tnc_get_stopsize();
  6571.     oflow = tnc_get_oflow();
  6572.     iflow = tnc_get_iflow();
  6573.     tnc_set_ls_mask(255);
  6574.     tnc_set_ms_mask(255);
  6575.     return(0);
  6576. }
  6577.  
  6578. int
  6579. #ifdef CK_ANSIC
  6580. tnc_wait(CHAR * msg, int ms)
  6581. #else /* CK_ANSIC */
  6582. tnc_wait(msg, ms) CHAR * msg; int ms;
  6583. #endif /* CK_ANSIC */
  6584. /* tnc_wait */ {
  6585.     int rc, tn_wait_save = tn_wait_flg;
  6586.     debug(F111,"tnc_wait","begin",ms);
  6587.     if ( ms )
  6588.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 1;
  6589.     else
  6590.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 1;
  6591.     tn_wait_flg = 1;
  6592.     rc = tn_wait((char *)msg);
  6593.     tn_push();
  6594.     debug(F110,"tnc_wait","end",0);
  6595.     tn_wait_flg = tn_wait_save;
  6596.     return(rc);
  6597. }
  6598.  
  6599. /* Returns -1 on error, 0 on success */
  6600. /* In order for this code to work, sb[len] == IAC          */
  6601.  
  6602. int
  6603. #ifdef CK_ANSIC
  6604. tnc_tn_sb(CHAR * sb, int len)
  6605. #else
  6606. tnc_tn_sb(sb, len) CHAR * sb; int len;
  6607. #endif /* CK_ANSIC */
  6608. /* tnc_tn_sb */ {
  6609.     if (ttnet != NET_TCPB) return(0);
  6610.     if (ttnproto != NP_TELNET) return(0);
  6611.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  6612.  
  6613.     if (!sb) return(-1);
  6614.  
  6615. #ifdef CK_SSL
  6616.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6617.         return(0);
  6618.     }
  6619. #endif /* CK_SSL */
  6620.  
  6621.     debug(F111,"tnc_tn_sb","sb[0]",sb[0]);
  6622.     debug(F111,"tnc_tn_sb","len",len);
  6623.  
  6624.     switch (sb[0]) {
  6625.       case TNC_C2S_SIGNATURE:
  6626.       case TNC_S2C_SIGNATURE:
  6627.         debug(F111,"tnc_tn_sb","signature",len);
  6628.         if (len == 1) {
  6629.             tnc_send_signature("Kermit Telnet Com Port Option");
  6630.         } else {
  6631.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6632.             if (tnc_signature)
  6633.               free(tnc_signature);
  6634.             tnc_signature = malloc(len);
  6635.             if (tnc_signature) {
  6636.                 memcpy(tnc_signature,&sb[1],len-1);
  6637.                 tnc_signature[len-1] = '\0';
  6638.             }
  6639.         }
  6640.         break;
  6641.  
  6642.       case TNC_C2S_SET_BAUDRATE:
  6643.       case TNC_S2C_SET_BAUDRATE: {
  6644.           long baudrate;
  6645.           char * br = (char *)&baudrate;
  6646.           TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6647.           if (len == 2) {
  6648.             /* Actual behavior of the Access Server... */
  6649.             debug(F111,"tnc_tn_sb","baudrate index",sb[1]);
  6650.             tnc_bps_index = 1;
  6651.             switch (sb[1]) {
  6652.             case TNC_BPS_300:
  6653.               tnc_bps = 300;
  6654.               break;
  6655.             case TNC_BPS_600:
  6656.               tnc_bps = 600;
  6657.               break;
  6658.             case TNC_BPS_1200:
  6659.               tnc_bps = 1200;
  6660.               break;
  6661.             case TNC_BPS_2400:
  6662.               tnc_bps = 2400;
  6663.               break;
  6664.             case TNC_BPS_4800:
  6665.               tnc_bps = 4800;
  6666.               break;
  6667.             case TNC_BPS_9600:
  6668.               tnc_bps = 9600;
  6669.               break;
  6670.             case TNC_BPS_14400:
  6671.               tnc_bps = 14400;
  6672.               break;
  6673.             case TNC_BPS_19200:
  6674.               tnc_bps = 19200;
  6675.               break;
  6676.             case TNC_BPS_28800:
  6677.               tnc_bps = 28800;
  6678.               break;
  6679.             case TNC_BPS_38400:
  6680.               tnc_bps = 38400;
  6681.               break;
  6682.             case TNC_BPS_57600:
  6683.               tnc_bps = 57600;
  6684.               break;
  6685.             case TNC_BPS_115200:
  6686.               tnc_bps = 115200;
  6687.               break;
  6688.             case TNC_BPS_230400:
  6689.               tnc_bps = 230400;
  6690.               break;
  6691.             case TNC_BPS_460800:
  6692.               tnc_bps = 460800;
  6693.               break;
  6694.             default:
  6695.               tnc_bps = -1;
  6696.             }
  6697.           } else if (len == 5) {
  6698.             /* This section attempts to follow RFC 2217 */
  6699.               tnc_bps_index = 0;
  6700.               br[0] = sb[1];
  6701.               br[1] = sb[2];
  6702.               br[2] = sb[3];
  6703.               br[3] = sb[4];
  6704. #ifdef datageneral
  6705.               /* AOS/VS doesn't have ntohl() but MV's are big-endian */
  6706.               tnc_bps = baudrate;
  6707. #else
  6708.               tnc_bps = ntohl(baudrate);
  6709. #endif /* datageneral */
  6710.               debug(F111,"tnc_tn_sb","baudrate rfc",tnc_bps);
  6711.           } else {
  6712.               debug(F111,"tnc_tn_sb","baudrate invalid len",len);
  6713.               return(-1);
  6714.           }
  6715.           break;
  6716.       }
  6717.       case TNC_C2S_SET_DATASIZE:
  6718.       case TNC_S2C_SET_DATASIZE:
  6719.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6720.         if (len < 2)
  6721.           return(-1);
  6722.         tnc_datasize = sb[1];
  6723.         debug(F111,"tnc_tn_sb","datasize",sb[1]);
  6724.         break;
  6725.  
  6726.       case TNC_C2S_SET_PARITY:
  6727.       case TNC_S2C_SET_PARITY:
  6728.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6729.         if (len < 2)
  6730.           return(-1);
  6731.         tnc_parity = sb[1];
  6732.         debug(F111,"tnc_tn_sb","parity",sb[1]);
  6733.         break;
  6734.  
  6735.       case TNC_C2S_SET_STOPSIZE:
  6736.       case TNC_S2C_SET_STOPSIZE:
  6737.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6738.         if (len < 2)
  6739.           return(-1);
  6740.         tnc_stopbit = sb[1];
  6741.         debug(F111,"tnc_tn_sb","stopsize",sb[1]);
  6742.         break;
  6743.  
  6744.       case TNC_C2S_SET_CONTROL:
  6745.       case TNC_S2C_SET_CONTROL:
  6746.         if (len < 2) {
  6747.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6748.             return(-1);
  6749.         }
  6750.  
  6751. #ifdef COMMENT
  6752.         /* This line should be removed when testing is complete. */
  6753.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6754. #endif /* COMMENT */
  6755.  
  6756.         switch ( sb[1] ) {
  6757.           case TNC_CTL_OFLOW_REQUEST:
  6758.             /* determine local outbound flow control and send to peer */
  6759.         /* Cisco IOS returns 0 (TNC_CTL_OFLOW_REQUEST) when attempting */
  6760.         /* to set the inbound flow control if it is not supported      */
  6761.         /* separately from outbound flow control.  So must reset       */
  6762.         /* wait for sb flag.                                           */
  6763.             debug(F110,"tnc_tn_sb","oflow request",0);
  6764.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6765.             break;
  6766.           case TNC_CTL_OFLOW_NONE:
  6767.           case TNC_CTL_OFLOW_XON_XOFF:
  6768.           case TNC_CTL_OFLOW_RTS_CTS:
  6769.           case TNC_CTL_OFLOW_DCD:
  6770.           case TNC_CTL_OFLOW_DSR:
  6771.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6772.             tnc_oflow = sb[1];
  6773.             debug(F111,"tnc_tn_sb","oflow",sb[1]);
  6774.             break;
  6775.           case TNC_CTL_BREAK_REQUEST:
  6776.             /* determine local break state and send to peer */
  6777.             debug(F110,"tnc_tn_sb","break request",0);
  6778.             break;
  6779.           case TNC_CTL_BREAK_ON:
  6780.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6781.             tnc_break = 1;
  6782.             debug(F110,"tnc_tn_sb","break on",0);
  6783.             break;
  6784.  
  6785.           case TNC_CTL_BREAK_OFF:
  6786.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6787.             tnc_break = 0;
  6788.             debug(F110,"tnc_tn_sb","break off",0);
  6789.             break;
  6790.  
  6791.           case TNC_CTL_DTR_REQUEST:
  6792.             /* determine local dtr state and send to peer */
  6793.             debug(F110,"tnc_tn_sb","dtr request",0);
  6794.             break;
  6795.  
  6796.           case TNC_CTL_DTR_ON:
  6797.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6798.             tnc_dtr = 1;
  6799.             debug(F110,"tnc_tn_sb","dtr on",0);
  6800.             break;
  6801.  
  6802.           case TNC_CTL_DTR_OFF:
  6803.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6804.             tnc_dtr = 0;
  6805.             debug(F110,"tnc_tn_sb","dtr off",0);
  6806.             break;
  6807.  
  6808.           case TNC_CTL_RTS_REQUEST:
  6809.             /* determine local rts state and send to peer */
  6810.             debug(F110,"tnc_tn_sb","rts request",0);
  6811.             break;
  6812.  
  6813.           case TNC_CTL_RTS_ON:
  6814.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6815.             tnc_rts = 1;
  6816.             debug(F110,"tnc_tn_sb","rts on",0);
  6817.             break;
  6818.  
  6819.           case TNC_CTL_RTS_OFF:
  6820.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6821.             tnc_rts = 0;
  6822.             debug(F110,"tnc_tn_sb","rts off",0);
  6823.             break;
  6824.  
  6825.           case TNC_CTL_IFLOW_REQUEST:
  6826.             /* determine local inbound flow control and send to peer */
  6827.             debug(F110,"tnc_tn_sb","iflow request",0);
  6828.             break;
  6829.  
  6830.           case TNC_CTL_IFLOW_NONE:
  6831.           case TNC_CTL_IFLOW_XON_XOFF:
  6832.           case TNC_CTL_IFLOW_RTS_CTS:
  6833.           case TNC_CTL_IFLOW_DTR:
  6834.             TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6835.             tnc_iflow = sb[1];
  6836.             debug(F111,"tnc_tn_sb","iflow",sb[1]);
  6837.             break;
  6838.           default:
  6839.             return(-1);
  6840.         }
  6841.         break;
  6842.  
  6843.       case TNC_C2S_NOTIFY_LINESTATE:
  6844.       case TNC_S2C_SEND_LS:
  6845.         if (len < 2)
  6846.           return(-1);
  6847.         tnc_ls = sb[1];
  6848.         debug(F111,"tnc_tn_sb","linestate",sb[1]);
  6849.         if (tn_deb || debses) {
  6850.             if (tnc_ls & TNC_MS_DATA_READY )
  6851.               tn_debug("  ComPort Linestate Data Ready");
  6852.             if (tnc_ls & TNC_MS_OVERRUN_ERROR )
  6853.               tn_debug("  ComPort Linestate Overrun Error");
  6854.             if (tnc_ls & TNC_MS_PARITY_ERROR )
  6855.               tn_debug("  ComPort Linestate Parity Error");
  6856.             if (tnc_ls & TNC_MS_FRAME_ERROR )
  6857.               tn_debug("  ComPort Linestate Framing Error");
  6858.             if (tnc_ls & TNC_MS_BREAK_ERROR )
  6859.               tn_debug("  ComPort Linestate Break Detect Error");
  6860.             if (tnc_ls & TNC_MS_HR_EMPTY )
  6861.               tn_debug("  ComPort Linestate Holding Register Empty");
  6862.             if (tnc_ls & TNC_MS_SR_EMPTY )
  6863.               tn_debug("  ComPort Linestate Shift Register Empty");
  6864.             if (tnc_ls & TNC_MS_TIMEOUT_ERROR )
  6865.               tn_debug("  ComPort Linestate Timeout Error");
  6866.         }
  6867.         break;
  6868.  
  6869.       case TNC_C2S_NOTIFY_MODEMSTATE:
  6870.       case TNC_S2C_SEND_MS:
  6871.         TELOPT_SB(TELOPT_COMPORT).comport.wait_for_ms = 0;
  6872.         if (len < 2)
  6873.           return(-1);
  6874.         tnc_ms = sb[1];
  6875.         debug(F111,"tnc_tn_sb","modemstate",sb[1]);
  6876.         if (tn_deb || debses) {
  6877.             if (tnc_ms & TNC_MS_CTS_DELTA )
  6878.               tn_debug("  ComPort Modemstate CTS State Change");
  6879.             if (tnc_ms & TNC_MS_DSR_DELTA )
  6880.               tn_debug("  ComPort Modemstate DSR State Change");
  6881.             if (tnc_ms & TNC_MS_EDGE_RING )
  6882.               tn_debug("  ComPort Modemstate Trailing Edge Ring Detector On");
  6883.             else
  6884.               tn_debug("  ComPort Modemstate Trailing Edge Ring Detector Off");
  6885.             if (tnc_ms & TNC_MS_RLSD_DELTA )
  6886.               tn_debug("  ComPort Modemstate RLSD State Change");
  6887.             if (tnc_ms & TNC_MS_CTS_SIG )
  6888.               tn_debug("  ComPort Modemstate CTS Signal On");
  6889.             else
  6890.               tn_debug("  ComPort Modemstate CTS Signal Off");
  6891.             if (tnc_ms & TNC_MS_DSR_SIG )
  6892.               tn_debug("  ComPort Modemstate DSR Signal On");
  6893.             else
  6894.               tn_debug("  ComPort Modemstate DSR Signal Off");
  6895.             if (tnc_ms & TNC_MS_RI_SIG )
  6896.               tn_debug("  ComPort Modemstate Ring Indicator On");
  6897.             else
  6898.               tn_debug("  ComPort Modemstate Ring Indicator Off");
  6899.             if (tnc_ms & TNC_MS_RLSD_SIG )
  6900.               tn_debug("  ComPort Modemstate RLSD Signal On");
  6901.             else
  6902.               tn_debug("  ComPort Modemstate RLSD Signal Off");
  6903.         }
  6904.         break;
  6905.  
  6906.       case TNC_C2S_FLOW_SUSPEND:
  6907.       case TNC_S2C_FLOW_SUSPEND:
  6908.         debug(F110,"tnc_tn_sb","flow suspend",0);
  6909.         tnc_suspend_xmit = 1;
  6910.         break;
  6911.  
  6912.       case TNC_C2S_FLOW_RESUME:
  6913.       case TNC_S2C_FLOW_RESUME:
  6914.         debug(F110,"tnc_tn_sb","flow resume",0);
  6915.         tnc_suspend_xmit = 0;
  6916.         break;
  6917.  
  6918.       case TNC_C2S_SET_LS_MASK:
  6919.       case TNC_S2C_SET_LS_MASK:
  6920.           TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6921.           if (len < 2)
  6922.           return(-1);
  6923.         debug(F111,"tnc_tn_sb","linestate mask",sb[1]);
  6924.         tnc_ls_mask = sb[1];
  6925.         break;
  6926.  
  6927.       case TNC_C2S_SET_MS_MASK:
  6928.       case TNC_S2C_SET_MS_MASK:
  6929.           TELOPT_SB(TELOPT_COMPORT).comport.wait_for_sb = 0;
  6930.           if (len < 2)
  6931.           return(-1);
  6932.         debug(F111,"tnc_tn_sb","modemstate mask",sb[1]);
  6933.         tnc_ls_mask = sb[1];
  6934.         break;
  6935.  
  6936.       case TNC_C2S_PURGE:
  6937.       case TNC_S2C_PURGE:
  6938.         if (len < 2)
  6939.           return(-1);
  6940.         debug(F111,"tnc_tn_sb","purge",sb[1]);
  6941.         switch ( sb[1] ) {
  6942.           case TNC_PURGE_RECEIVE:
  6943.           case TNC_PURGE_TRANSMIT:
  6944.           case TNC_PURGE_BOTH:
  6945.             /* purge local buffers */
  6946.             break;
  6947.           default:
  6948.             return(-1);
  6949.         }
  6950.         break;
  6951.       default:
  6952.         return(-1);
  6953.     }
  6954.     return(0);
  6955. }
  6956.  
  6957. CONST char *
  6958. #ifdef CK_ANSIC
  6959. tnc_get_signature(void)
  6960. #else /* CK_ANSIC */
  6961. tnc_get_signature()
  6962. #endif /* CK_ANSIC */
  6963. /* tnc_get_signature */ {
  6964.     /* send IAC SB COM-PORT SIGNATURE IAC SE */
  6965.     /* wait for response */
  6966.     int i = 0, rc;
  6967.  
  6968.     if (ttnet != NET_TCPB) return(NULL);
  6969.     if (ttnproto != NP_TELNET) return(NULL);
  6970.  
  6971.     if (!TELOPT_ME(TELOPT_COMPORT)) return(NULL);
  6972.  
  6973. #ifdef CK_SSL
  6974.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  6975.         return(NULL);
  6976.     }
  6977. #endif /* CK_SSL */
  6978.  
  6979.     if ( tnc_signature )
  6980.         return(tnc_signature);
  6981.  
  6982.     sb_out[i++] = (CHAR) IAC;           /* I Am a Command */
  6983.     sb_out[i++] = (CHAR) SB;            /* Subnegotiation */
  6984.     sb_out[i++] = TELOPT_COMPORT;               /* ComPort */
  6985.     sb_out[i++] = TNC_C2S_SIGNATURE;    /* Signature */
  6986.     sb_out[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  6987.     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
  6988.  
  6989. #ifdef DEBUG
  6990.     if (deblog || tn_deb || debses) {
  6991.         ckmakmsg(tn_msg_out,TN_MSG_LEN,
  6992.                  "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  6993.                  " SIGNATURE IAC SE", NULL);
  6994.     }
  6995. #endif /* DEBUG */
  6996. #ifdef OS2
  6997.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  6998. #endif
  6999. #ifdef DEBUG
  7000.     debug(F100,tn_msg_out,"",0);
  7001.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7002. #endif /* DEBUG */
  7003.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7004. #ifdef OS2
  7005.     ReleaseTelnetMutex();
  7006. #endif
  7007.     if (rc)
  7008.         return(NULL);
  7009.  
  7010.     if (tnc_wait((CHAR *)"comport signature request",0) < 0) {
  7011.         tn_push();
  7012.         return(NULL);
  7013.     }
  7014.     debug(F110,"tnc_get_signature",tnc_signature,0);
  7015.     return(tnc_signature);
  7016. }
  7017.  
  7018. int
  7019. #ifdef CK_ANSIC
  7020. tnc_send_signature(char * signature)
  7021. #else /* CK_ANSIC */
  7022. tnc_send_signature(signature) char * signature;
  7023. #endif /* CK_ANSIC */
  7024. /* tnc_send_signature */ {
  7025.     /* send IAC SB COM-PORT SIGNATURE <text> IAC SE */
  7026.     int i = 0, j = 0, rc;
  7027.  
  7028.     debug(F110,"tnc_send_signature",signature,0);
  7029.  
  7030.     if (!signature || !signature[0])
  7031.       return(0);
  7032.  
  7033.     if (ttnet != NET_TCPB) return(0);
  7034.     if (ttnproto != NP_TELNET) return(0);
  7035.  
  7036.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7037.  
  7038. #ifdef CK_SSL
  7039.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7040.         return(0);
  7041.     }
  7042. #endif /* CK_SSL */
  7043.  
  7044.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7045.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7046.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7047.     sb_out[i++] = TNC_C2S_SIGNATURE;      /* Signature */
  7048.     for (; signature[j]; i++,j++)
  7049.       sb_out[i] = signature[j];
  7050.     sb_out[i++] = (CHAR) IAC;               /* End of Subnegotiation */
  7051.     sb_out[i++] = (CHAR) SE;                /* marked by IAC SE */
  7052.  
  7053. #ifdef DEBUG
  7054.     if (deblog || tn_deb || debses) {
  7055.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7056.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7057.                   " SIGNATURE ", signature, " IAC SE", NULL,
  7058.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7059.     }
  7060. #endif /* DEBUG */
  7061. #ifdef OS2
  7062.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7063. #endif
  7064. #ifdef DEBUG
  7065.     debug(F100,tn_msg_out,"",0);
  7066.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7067. #endif /* DEBUG */
  7068.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7069. #ifdef OS2
  7070.     ReleaseTelnetMutex();
  7071. #endif
  7072.     if (rc)
  7073.         return(-1);
  7074.     return(0);
  7075. }
  7076.  
  7077. int
  7078. #ifdef CK_ANSIC
  7079. tnc_set_baud( long baud )
  7080. #else /* CK_ANSIC */
  7081. tnc_set_baud(baud) long baud;
  7082. #endif /* CK_ANSIC */
  7083. /* tnc_set_baud */ {
  7084.     /* send IAC SB COM-PORT SET-BAUD <value(4)> IAC SE  */
  7085.     /* wait for response */
  7086.     /* 0 is used to request the current baud rate and */
  7087.     /* may not be sent by this func */
  7088.     /* return new host value */
  7089.  
  7090.     /*
  7091.      *   the above comes from the RFC.  But that is not what I am seeing
  7092.      *   instead I appear to be seeing to following:
  7093.      *
  7094.      *      Value               Baud
  7095.      *          1               ?
  7096.      *          2               ?
  7097.      *          3               300
  7098.      *          4               600
  7099.      *          5               1200
  7100.      *          6               2400
  7101.      *          7               4800      ?
  7102.      *          8               9600
  7103.      *          9                         ?
  7104.      *          10              19200     ?
  7105.      *          11                        ?
  7106.      *          12              38400
  7107.      *          13              57600     ?
  7108.      *          14              115200
  7109.      *          15              230400    ?
  7110.      *          16              460800    ?
  7111.      */
  7112.  
  7113.     int i = 0, rc;
  7114. #ifdef datageneral
  7115.     /* AOS/VS doesn't have htonl() but MV's are big-endian */
  7116.     long net_baud = baud;
  7117. #else
  7118.     long net_baud = htonl(baud);
  7119. #endif /* datageneral */
  7120.     CHAR b;
  7121.  
  7122.     debug(F111,"tnc_set_baud","begin",baud);
  7123.  
  7124.     if (ttnet != NET_TCPB) return(0);
  7125.     if (ttnproto != NP_TELNET) return(0);
  7126.  
  7127.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7128.  
  7129. #ifdef CK_SSL
  7130.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7131.         return(0);
  7132.     }
  7133. #endif /* CK_SSL */
  7134.  
  7135.     if (baud <= 0)
  7136.         return(0);
  7137.  
  7138.     if ( net_baud != 0 && net_baud == tnc_bps)
  7139.         return(tnc_bps);
  7140.  
  7141.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7142.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7143.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7144.     sb_out[i++] = TNC_C2S_SET_BAUDRATE;   /* Set Baud Rate */
  7145.  
  7146.     if (tnc_bps_index) {
  7147.         /* IOS Access Server */
  7148.         if (baud <= 300)
  7149.             b = TNC_BPS_300;
  7150.         else if (baud <= 600)
  7151.             b = TNC_BPS_600;
  7152.         else if (baud <= 1200)
  7153.             b = TNC_BPS_1200;
  7154.         else if (baud <= 2400)
  7155.             b = TNC_BPS_2400;
  7156.         else if (baud <= 4800)
  7157.             b = TNC_BPS_4800;
  7158.         else if (baud <= 9600)
  7159.             b = TNC_BPS_9600;
  7160.         else if (baud <= 14400)
  7161.             b = TNC_BPS_14400;
  7162.         else if (baud <= 19200)
  7163.             b = TNC_BPS_19200;
  7164.         else if (baud <= 28800)
  7165.             b = TNC_BPS_28800;
  7166.         else if (baud <= 38400)
  7167.             b = TNC_BPS_38400;
  7168.         else if (baud <= 57600)
  7169.             b = TNC_BPS_57600;
  7170.         else if (baud <= 115200)
  7171.             b = TNC_BPS_115200;
  7172.         else if (baud <= 230400)
  7173.             b = TNC_BPS_230400;
  7174.         else
  7175.             b = TNC_BPS_460800;
  7176.         sb_out[i++] = b;
  7177.     } else {
  7178.         /* RFC 2217 */
  7179.         sb_out[i++] = ((char *)&net_baud)[0];
  7180.         sb_out[i++] = ((char *)&net_baud)[1];
  7181.         sb_out[i++] = ((char *)&net_baud)[2];
  7182.         sb_out[i++] = ((char *)&net_baud)[3];
  7183.     }
  7184.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7185.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7186.  
  7187. #ifdef DEBUG
  7188.     if (deblog || tn_deb || debses) {
  7189.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7190.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7191.                   " SET-BAUD-RATE ", ckltoa(baud)," IAC SE", NULL,
  7192.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7193.     }
  7194. #endif /* DEBUG */
  7195.  
  7196. #ifdef OS2
  7197.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7198. #endif
  7199. #ifdef DEBUG
  7200.     debug(F100,tn_msg_out,"",0);
  7201.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7202. #endif /* DEBUG */
  7203.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7204. #ifdef OS2
  7205.     ReleaseTelnetMutex();
  7206. #endif
  7207.     if (rc)
  7208.         return(-1);
  7209.  
  7210.     if (tnc_wait((CHAR *)"comport set baud rate",0) < 0) {
  7211.         tn_push();
  7212.         return(-1);
  7213.     }
  7214.     debug(F111,"tnc_set_baud","end",tnc_bps);
  7215.     return(tnc_bps);
  7216. }
  7217.  
  7218. int
  7219. #ifdef CK_ANSIC
  7220. tnc_get_baud(void)
  7221. #else /* CK_ANSIC */
  7222. tnc_get_baud()
  7223. #endif /* CK_ANSIC */
  7224. /* tnc_get_baud */ {
  7225.     /* send IAC SB COM-PORT SET-BAUD <value(4)=0> IAC SE  */
  7226.     /* wait for response */
  7227.     int i = 0, rc;
  7228.  
  7229.     debug(F110,"tnc_get_baud","begin",0);
  7230.  
  7231.     if (ttnet != NET_TCPB) return(0);
  7232.     if (ttnproto != NP_TELNET) return(0);
  7233.  
  7234.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7235.  
  7236. #ifdef CK_SSL
  7237.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7238.         return(0);
  7239.     }
  7240. #endif /* CK_SSL */
  7241.  
  7242.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7243.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7244.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7245.     sb_out[i++] = TNC_C2S_SET_BAUDRATE;   /* Set Baud Rate */
  7246.  
  7247.     if (tnc_bps_index > 0) {
  7248.         /* Access Server */
  7249.         sb_out[i++] = 0;
  7250.     } else {
  7251.         /* RFC 2217 */
  7252.         sb_out[i++] = 0;
  7253.         sb_out[i++] = 0;
  7254.         sb_out[i++] = 0;
  7255.         sb_out[i++] = 0;
  7256.     }
  7257.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7258.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7259.  
  7260. #ifdef DEBUG
  7261.     if (deblog || tn_deb || debses) {
  7262.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7263.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7264.                   " SET-BAUD-RATE ", ckltoa(0)," IAC SE", NULL,
  7265.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7266.     }
  7267. #endif /* DEBUG */
  7268. #ifdef OS2
  7269.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7270. #endif
  7271. #ifdef DEBUG
  7272.     debug(F100,tn_msg_out,"",0);
  7273.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7274. #endif /* DEBUG */
  7275.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7276. #ifdef OS2
  7277.     ReleaseTelnetMutex();
  7278. #endif
  7279.     if (rc)
  7280.         return(-1);
  7281.  
  7282.     if (tnc_wait((CHAR *)"comport get baud rate",0) < 0) {
  7283.         tn_push();
  7284.         return(-1);
  7285.     }
  7286.     debug(F111,"tnc_get_baud","end",tnc_bps);
  7287.     return(tnc_bps);
  7288. }
  7289.  
  7290. int
  7291. #ifdef CK_ANSIC
  7292. tnc_set_datasize(int datasize)
  7293. #else /* CK_ANSIC */
  7294. tnc_set_datasize(datasize) int datasize;
  7295. #endif /* CK_ANSIC */
  7296. /* tnc_set_datasize */ {
  7297.     /* IAC SB COM-PORT SET_DATASIZE <value(1)> IAC SE */
  7298.     /* Valid <value>s are 5 through 8 */
  7299.     /* Wait for response */
  7300.     /* return new host value */
  7301.  
  7302.     int i = 0, rc;
  7303.  
  7304.     debug(F111,"tnc_set_datasize","begin",datasize);
  7305.  
  7306.     if (ttnet != NET_TCPB) return(0);
  7307.     if (ttnproto != NP_TELNET) return(0);
  7308.  
  7309.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7310.  
  7311. #ifdef CK_SSL
  7312.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7313.         return(0);
  7314.     }
  7315. #endif /* CK_SSL */
  7316.  
  7317.     if ( !(datasize >= 5 && datasize <= 8) )
  7318.         return(0);
  7319.  
  7320.     if ( datasize  != 0 &&  datasize == tnc_datasize )
  7321.         return(tnc_datasize);
  7322.  
  7323.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7324.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7325.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7326.     sb_out[i++] = TNC_C2S_SET_DATASIZE;   /* Set DataSize */
  7327.     sb_out[i++] = (unsigned char)(datasize & 0xFF);
  7328.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7329.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7330.  
  7331. #ifdef DEBUG
  7332.     if (deblog || tn_deb || debses) {
  7333.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7334.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7335.                   " SET-DATASIZE ", ckitoa(datasize)," IAC SE", NULL,
  7336.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7337.     }
  7338. #endif /* DEBUG */
  7339. #ifdef OS2
  7340.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7341. #endif
  7342. #ifdef DEBUG
  7343.     debug(F100,tn_msg_out,"",0);
  7344.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7345. #endif /* DEBUG */
  7346.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7347. #ifdef OS2
  7348.     ReleaseTelnetMutex();
  7349. #endif
  7350.     if (rc)
  7351.         return(-1);
  7352.  
  7353.     if (tnc_wait((CHAR *)"comport set datasize",0) < 0) {
  7354.         tn_push();
  7355.         return(-1);
  7356.     }
  7357.     debug(F111,"tnc_set_datasize","end",tnc_datasize);
  7358.     return(tnc_datasize);
  7359. }
  7360.  
  7361. int
  7362. #ifdef CK_ANSIC
  7363. tnc_get_datasize(void)
  7364. #else /* CK_ANSIC */
  7365. tnc_get_datasize()
  7366. #endif /* CK_ANSIC */
  7367. /* tnc_get_datasize */ {
  7368.     /* IAC SB COM-PORT SET_DATASIZE <value(1)=0> IAC SE */
  7369.     /* Wait for response */
  7370.     int i = 0, rc;
  7371.  
  7372.     debug(F110,"tnc_get_datasize","begin",0);
  7373.  
  7374.     if (ttnet != NET_TCPB) return(0);
  7375.     if (ttnproto != NP_TELNET) return(0);
  7376.  
  7377.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7378.  
  7379. #ifdef CK_SSL
  7380.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7381.         return(0);
  7382.     }
  7383. #endif /* CK_SSL */
  7384.  
  7385.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7386.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7387.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7388.     sb_out[i++] = TNC_C2S_SET_DATASIZE;   /* Set DataSize */
  7389.     sb_out[i++] = 0;
  7390.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7391.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7392.  
  7393. #ifdef DEBUG
  7394.     if (deblog || tn_deb || debses) {
  7395.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7396.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7397.                   " SET-DATASIZE ", ckltoa(0)," IAC SE", NULL,
  7398.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7399.     }
  7400. #endif /* DEBUG */
  7401. #ifdef OS2
  7402.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7403. #endif
  7404. #ifdef DEBUG
  7405.     debug(F100,tn_msg_out,"",0);
  7406.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7407. #endif /* DEBUG */
  7408.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7409. #ifdef OS2
  7410.     ReleaseTelnetMutex();
  7411. #endif
  7412.     if (rc)
  7413.         return(-1);
  7414.  
  7415.     if (tnc_wait((CHAR *)"comport get datasize",0) < 0) {
  7416.         tn_push();
  7417.         return(-1);
  7418.     }
  7419.     debug(F111,"tnc_get_datasize","end",tnc_datasize);
  7420.     return(tnc_datasize);
  7421. }
  7422.  
  7423. int
  7424. #ifdef CK_ANSIC
  7425. tnc_set_parity(int parity)
  7426. #else /* CK_ANSIC */
  7427. tnc_set_parity(parity) int parity;
  7428. #endif /* CK_ANSIC */
  7429. /* tnc_set_parity */ {
  7430.     /* IAC SB COM-PORT SET_PARITY <value(1)> IAC SE */
  7431.     /*        Value     Parity
  7432.      *          1       None
  7433.      *          2       Odd
  7434.      *          3       Even
  7435.      *          4       Mark
  7436.      *          5       Space
  7437.      */
  7438.     /* Wait for response.  Return new host value. */
  7439.     int i = 0, rc;
  7440.  
  7441.     debug(F110,"tnc_set_parity","begin",parity);
  7442.  
  7443.     if (ttnet != NET_TCPB) return(0);
  7444.     if (ttnproto != NP_TELNET) return(0);
  7445.  
  7446.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7447.  
  7448. #ifdef CK_SSL
  7449.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7450.         return(0);
  7451.     }
  7452. #endif /* CK_SSL */
  7453.  
  7454.     if ( !(parity >= 1 && parity <= 5) )
  7455.         return(0);
  7456.  
  7457.     if ( parity != 0 && parity == tnc_parity )
  7458.         return(tnc_parity);
  7459.  
  7460.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7461.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7462.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7463.     sb_out[i++] = TNC_C2S_SET_PARITY;     /* Set Parity */
  7464.     sb_out[i++] = (unsigned char)(parity & 0xFF);
  7465.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7466.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7467.  
  7468. #ifdef DEBUG
  7469.     if (deblog || tn_deb || debses) {
  7470.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7471.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7472.                   " SET-PARITY ", ckitoa(parity)," IAC SE", NULL,
  7473.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7474.     }
  7475. #endif /* DEBUG */
  7476. #ifdef OS2
  7477.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7478. #endif
  7479. #ifdef DEBUG
  7480.     debug(F100,tn_msg_out,"",0);
  7481.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7482. #endif /* DEBUG */
  7483.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7484. #ifdef OS2
  7485.     ReleaseTelnetMutex();
  7486. #endif
  7487.     if (rc)
  7488.         return(-1);
  7489.  
  7490.     if (tnc_wait((CHAR *)"comport set parity",0) < 0) {
  7491.         tn_push();
  7492.         return(-1);
  7493.     }
  7494.     debug(F111,"tnc_set_parity","end",tnc_parity);
  7495.     return(tnc_parity);
  7496. }
  7497.  
  7498. int
  7499. #ifdef CK_ANSIC
  7500. tnc_get_parity(void)
  7501. #else /* CK_ANSIC */
  7502. tnc_get_parity()
  7503. #endif /* CK_ANSIC */
  7504. /* tnc_get_parity */ {
  7505.     /* IAC SB COM-PORT SET_PARITY <value(1)=0> IAC SE */
  7506.     /* wait for response */
  7507.     int i = 0, rc;
  7508.  
  7509.     debug(F110,"tnc_get_parity","begin",0);
  7510.     if (ttnet != NET_TCPB) return(0);
  7511.     if (ttnproto != NP_TELNET) return(0);
  7512.  
  7513.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7514.  
  7515. #ifdef CK_SSL
  7516.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7517.         return(0);
  7518.     }
  7519. #endif /* CK_SSL */
  7520.  
  7521.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7522.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7523.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7524.     sb_out[i++] = TNC_C2S_SET_PARITY;     /* Set Parity */
  7525.     sb_out[i++] = 0;
  7526.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7527.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7528.  
  7529. #ifdef DEBUG
  7530.     if (deblog || tn_deb || debses) {
  7531.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7532.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7533.                   " SET-PARITY ", ckitoa(0)," IAC SE", NULL,
  7534.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7535.     }
  7536. #endif /* DEBUG */
  7537. #ifdef OS2
  7538.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7539. #endif
  7540. #ifdef DEBUG
  7541.     debug(F100,tn_msg_out,"",0);
  7542.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7543. #endif /* DEBUG */
  7544.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7545. #ifdef OS2
  7546.     ReleaseTelnetMutex();
  7547. #endif
  7548.     if (rc)
  7549.         return(-1);
  7550.  
  7551.     if (tnc_wait((CHAR *)"comport get parity",0) < 0) {
  7552.         tn_push();
  7553.         return(-1);
  7554.     }
  7555.     debug(F111,"tnc_get_parity","end",tnc_parity);
  7556.     return(tnc_parity);
  7557. }
  7558.  
  7559. int
  7560. #ifdef CK_ANSIC
  7561. tnc_set_stopsize(int stopsize)
  7562. #else /* CK_ANSIC */
  7563. tnc_set_stopsize(stopsize) int stopsize;
  7564. #endif /* CK_ANSIC */
  7565. /* tnc_set_stopsize */ {
  7566.     /* IAC SB COM-PORT SET_STOPSIZE <value(1)> IAC SE */
  7567.     /*        Value     Stop Bit Size
  7568.      *          1       1
  7569.      *          2       2
  7570.      *          3       1.5
  7571.      */
  7572.     /* Wait for response.  Return new host value. */
  7573.     int i = 0, rc;
  7574.  
  7575.     debug(F111,"tnc_set_stopsize","begin",stopsize);
  7576.     if (ttnet != NET_TCPB) return(0);
  7577.     if (ttnproto != NP_TELNET) return(0);
  7578.  
  7579.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7580.  
  7581. #ifdef CK_SSL
  7582.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7583.         return(0);
  7584.     }
  7585. #endif /* CK_SSL */
  7586.  
  7587.     if (!(stopsize >= 1 && stopsize <= 3) )
  7588.       return(0);
  7589.  
  7590.     if ( stopsize != 0 && stopsize == tnc_stopbit )
  7591.         return(tnc_stopbit);
  7592.  
  7593.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7594.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7595.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7596.     sb_out[i++] = TNC_C2S_SET_STOPSIZE;   /* Set Stop Bits */
  7597.     sb_out[i++] = (unsigned char)(stopsize & 0xFF);
  7598.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7599.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7600.  
  7601. #ifdef DEBUG
  7602.     if (deblog || tn_deb || debses) {
  7603.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7604.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7605.                   " SET-STOPSIZE ", ckitoa(stopsize)," IAC SE", NULL,
  7606.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7607.     }
  7608. #endif /* DEBUG */
  7609. #ifdef OS2
  7610.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7611. #endif
  7612. #ifdef DEBUG
  7613.     debug(F100,tn_msg_out,"",0);
  7614.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7615. #endif /* DEBUG */
  7616.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7617. #ifdef OS2
  7618.     ReleaseTelnetMutex();
  7619. #endif
  7620.     if (rc)
  7621.         return(-1);
  7622.  
  7623.     if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
  7624.         tn_push();
  7625.         return(-1);
  7626.     }
  7627.     debug(F111,"tnc_set_stopsize","end",tnc_stopbit);
  7628.     return(tnc_stopbit);
  7629. }
  7630.  
  7631. int
  7632. #ifdef CK_ANSIC
  7633. tnc_get_stopsize(void)
  7634. #else /* CK_ANSIC */
  7635. tnc_get_stopsize()
  7636. #endif /* CK_ANSIC */
  7637. /* tnc_get_stopsize */ {
  7638.     /* IAC SB COM-PORT SET_STOPSIZE <value(1)=0> IAC SE */
  7639.     /* Wait for response */
  7640.     int i = 0, rc;
  7641.  
  7642.     debug(F110,"tnc_get_stopsize","begin",0);
  7643.     if (ttnet != NET_TCPB) return(0);
  7644.     if (ttnproto != NP_TELNET) return(0);
  7645.  
  7646.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7647.  
  7648. #ifdef CK_SSL
  7649.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7650.         return(0);
  7651.     }
  7652. #endif /* CK_SSL */
  7653.  
  7654.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7655.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7656.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7657.     sb_out[i++] = TNC_C2S_SET_STOPSIZE;   /* Set Stop Bits */
  7658.     sb_out[i++] = 0;
  7659.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7660.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7661.  
  7662. #ifdef DEBUG
  7663.     if (deblog || tn_deb || debses) {
  7664.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7665.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7666.                   " SET-STOPSIZE ", ckitoa(0)," IAC SE", NULL,
  7667.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7668.     }
  7669. #endif /* DEBUG */
  7670. #ifdef OS2
  7671.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7672. #endif
  7673. #ifdef DEBUG
  7674.     debug(F100,tn_msg_out,"",0);
  7675.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7676. #endif /* DEBUG */
  7677.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7678. #ifdef OS2
  7679.     ReleaseTelnetMutex();
  7680. #endif
  7681.     if (rc)
  7682.         return(-1);
  7683.  
  7684.     if (tnc_wait((CHAR *)"comport set stopsize",0) < 0) {
  7685.         tn_push();
  7686.         return(-1);
  7687.     }
  7688.     debug(F111,"tnc_get_stopsize","end",tnc_stopbit);
  7689.     return(tnc_stopbit);
  7690. }
  7691.  
  7692. int
  7693. #ifdef CK_ANSIC
  7694. tnc_set_oflow(int control)
  7695. #else /* CK_ANSIC */
  7696. tnc_set_oflow(control) int control;
  7697. #endif /* CK_ANSIC */
  7698. /* tnc_set_oflow */ {
  7699.     /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
  7700.     /*        Value     Flow Control
  7701.      *          1       No Flow Control
  7702.      *          2       Xon/Xoff
  7703.      *          3       Rts/Cts
  7704.      *         17       DCD
  7705.      *         19       DSR
  7706.      */
  7707.     /* wait for response, return new host value. */
  7708.     int i = 0, rc;
  7709.  
  7710.     debug(F111,"tnc_set_oflow","begin",control);
  7711.     if (ttnet != NET_TCPB) return(0);
  7712.     if (ttnproto != NP_TELNET) return(0);
  7713.  
  7714.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7715.  
  7716. #ifdef CK_SSL
  7717.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7718.         return(0);
  7719.     }
  7720. #endif /* CK_SSL */
  7721.  
  7722.     if (control != 1 && control != 2 && control != 3 &&
  7723.         control != 17 && control != 19)
  7724.       return(0);
  7725.  
  7726.     if ( control != 0 && control == tnc_oflow )
  7727.         return(tnc_oflow);
  7728.  
  7729.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7730.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7731.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7732.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  7733.     sb_out[i++] = (unsigned char)(control & 0xFF);
  7734.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7735.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7736.  
  7737. #ifdef DEBUG
  7738.     if (deblog || tn_deb || debses) {
  7739.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7740.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7741.                   " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
  7742.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7743.     }
  7744. #endif /* DEBUG */
  7745. #ifdef OS2
  7746.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7747. #endif
  7748. #ifdef DEBUG
  7749.     debug(F100,tn_msg_out,"",0);
  7750.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7751. #endif /* DEBUG */
  7752.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7753. #ifdef OS2
  7754.     ReleaseTelnetMutex();
  7755. #endif
  7756.     if (rc)
  7757.         return(-1);
  7758.  
  7759.     if (tnc_wait((CHAR *)"comport set outbound flow control",0) < 0) {
  7760.         tn_push();
  7761.         return(-1);
  7762.     }
  7763.     debug(F111,"tnc_set_oflow","end",tnc_oflow);
  7764.     return(tnc_oflow);
  7765. }
  7766.  
  7767. int
  7768. #ifdef CK_ANSIC
  7769. tnc_get_oflow(void)
  7770. #else /* CK_ANSIC */
  7771. tnc_get_oflow()
  7772. #endif /* CK_ANSIC */
  7773. /* tnc_get_oflow */ {
  7774.     /* IAC SB COM_PORT SET_CONTROL <value(1)=0> IAC SE */
  7775.     /* wait for response */
  7776.     int i = 0, rc;
  7777.  
  7778.     debug(F110,"tnc_get_oflow","begin",0);
  7779.     if (ttnet != NET_TCPB) return(0);
  7780.     if (ttnproto != NP_TELNET) return(0);
  7781.  
  7782.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7783.  
  7784. #ifdef CK_SSL
  7785.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7786.         return(0);
  7787.     }
  7788. #endif /* CK_SSL */
  7789.  
  7790.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7791.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7792.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7793.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  7794.     sb_out[i++] = TNC_CTL_OFLOW_REQUEST;
  7795.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7796.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7797.  
  7798. #ifdef DEBUG
  7799.     if (deblog || tn_deb || debses) {
  7800.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7801.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7802.                   " SET-CONTROL ",
  7803.                    ckitoa(TNC_CTL_OFLOW_REQUEST),
  7804.                    " IAC SE", NULL,
  7805.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7806.     }
  7807. #endif /* DEBUG */
  7808. #ifdef OS2
  7809.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7810. #endif
  7811. #ifdef DEBUG
  7812.     debug(F100,tn_msg_out,"",0);
  7813.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7814. #endif /* DEBUG */
  7815.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7816. #ifdef OS2
  7817.     ReleaseTelnetMutex();
  7818. #endif
  7819.     if (rc)
  7820.         return(-1);
  7821.  
  7822.     if (tnc_wait((CHAR *)"comport get outbound flow control",0) < 0) {
  7823.         tn_push();
  7824.         return(-1);
  7825.     }
  7826.     debug(F111,"tnc_get_oflow","end",tnc_oflow);
  7827.     return(tnc_oflow);
  7828. }
  7829.  
  7830. int
  7831. #ifdef CK_ANSIC
  7832. tnc_set_iflow(int control)
  7833. #else /* CK_ANSIC */
  7834. tnc_set_iflow(control) int control;
  7835. #endif /* CK_ANSIC */
  7836. /* tnc_set_iflow */ {
  7837.     /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
  7838.     /*        Value     Flow Control
  7839.      *         14       No Flow Control
  7840.      *         15       Xon/Xoff
  7841.      *         16       Rts/Cts
  7842.      *         18       DTR
  7843.      */
  7844.     /* wait for response, return new host value. */
  7845.     int i = 0, rc;
  7846.  
  7847.     debug(F111,"tnc_set_iflow","begin",control);
  7848.     if (ttnet != NET_TCPB) return(0);
  7849.     if (ttnproto != NP_TELNET) return(0);
  7850.  
  7851.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7852.  
  7853. #ifdef CK_SSL
  7854.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7855.         return(0);
  7856.     }
  7857. #endif /* CK_SSL */
  7858.  
  7859.     if (control != 14 && control != 15 && control != 16 && control != 18)
  7860.       return(0);
  7861.  
  7862.     if ( control != 0 && control == tnc_iflow )
  7863.         return(tnc_iflow);
  7864.  
  7865.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7866.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7867.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7868.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  7869.     sb_out[i++] = (unsigned char)(control & 0xFF);
  7870.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7871.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7872.  
  7873. #ifdef DEBUG
  7874.     if (deblog || tn_deb || debses) {
  7875.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7876.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7877.                   " SET-CONTROL ", ckitoa(control)," IAC SE", NULL,
  7878.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7879.     }
  7880. #endif /* DEBUG */
  7881. #ifdef OS2
  7882.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7883. #endif
  7884. #ifdef DEBUG
  7885.     debug(F100,tn_msg_out,"",0);
  7886.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7887. #endif /* DEBUG */
  7888.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7889. #ifdef OS2
  7890.     ReleaseTelnetMutex();
  7891. #endif
  7892.     if (rc)
  7893.       return(-1);
  7894.  
  7895.     if (tnc_wait((CHAR *)"comport set inbound flow control",0) < 0) {
  7896.         tn_push();
  7897.         return(-1);
  7898.     }
  7899.     debug(F111,"tnc_set_iflow","end",tnc_iflow);
  7900.     return(tnc_iflow);
  7901. }
  7902.  
  7903. int
  7904. #ifdef CK_ANSIC
  7905. tnc_get_iflow(void)
  7906. #else /* CK_ANSIC */
  7907. tnc_get_iflow()
  7908. #endif /* CK_ANSIC */
  7909. /* tnc_get_iflow */ {
  7910.     /* IAC SB COM_PORT SET_CONTROL <value(1)=13> IAC SE */
  7911.     /* wait for response */
  7912.     int i = 0, rc;
  7913.  
  7914.     debug(F110,"tnc_get_iflow","begin",0);
  7915.     if (ttnet != NET_TCPB) return(0);
  7916.     if (ttnproto != NP_TELNET) return(0);
  7917.  
  7918.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7919.  
  7920. #ifdef CK_SSL
  7921.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7922.         return(0);
  7923.     }
  7924. #endif /* CK_SSL */
  7925.  
  7926.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7927.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7928.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7929.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  7930.     sb_out[i++] = TNC_CTL_IFLOW_REQUEST;
  7931.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  7932.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  7933.  
  7934. #ifdef DEBUG
  7935.     if (deblog || tn_deb || debses) {
  7936.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  7937.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  7938.                   " SET-CONTROL ",
  7939.                   ckitoa(TNC_CTL_IFLOW_REQUEST),
  7940.                   " IAC SE", NULL,
  7941.                   NULL,NULL,NULL,NULL,NULL,NULL);
  7942.     }
  7943. #endif /* DEBUG */
  7944. #ifdef OS2
  7945.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  7946. #endif
  7947. #ifdef DEBUG
  7948.     debug(F100,tn_msg_out,"",0);
  7949.     if (tn_deb || debses) tn_debug(tn_msg_out);
  7950. #endif /* DEBUG */
  7951.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  7952. #ifdef OS2
  7953.     ReleaseTelnetMutex();
  7954. #endif
  7955.     if (rc)
  7956.         return(-1);
  7957.  
  7958.     if (tnc_wait((CHAR *)"comport get inbound flow control",0) < 0) {
  7959.         tn_push();
  7960.         return(-1);
  7961.     }
  7962.     debug(F111,"tnc_get_iflow","end",tnc_iflow);
  7963.     return(tnc_iflow);
  7964. }
  7965.  
  7966. int
  7967. #ifdef CK_ANSIC
  7968. tnc_set_break_state(int onoff)
  7969. #else /* CK_ANSIC */
  7970. tnc_set_break_state(onoff) int onoff;
  7971. #endif /* CK_ANSIC */
  7972. /* tnc_set_break_state */ {
  7973.     /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
  7974.     /*        Value     Break State
  7975.      *          5       On
  7976.      *          6       Off
  7977.      */
  7978.     /* wait for response, return new host value. */
  7979.     int i = 0, rc;
  7980.  
  7981.     debug(F111,"tnc_set_break_state","begin",onoff);
  7982.     if (ttnet != NET_TCPB) return(0);
  7983.     if (ttnproto != NP_TELNET) return(0);
  7984.  
  7985.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  7986.  
  7987. #ifdef CK_SSL
  7988.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  7989.         return(0);
  7990.     }
  7991. #endif /* CK_SSL */
  7992.  
  7993.     if ( onoff != 0 && onoff == tnc_break )
  7994.         return(tnc_break);
  7995.  
  7996.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  7997.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  7998.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  7999.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  8000.     sb_out[i++] = onoff ?
  8001.       TNC_CTL_BREAK_ON : TNC_CTL_BREAK_OFF;
  8002.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8003.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8004.  
  8005. #ifdef DEBUG
  8006.     if (deblog || tn_deb || debses) {
  8007.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8008.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8009.                   " SET-CONTROL ",
  8010.                   onoff ? "BREAK-ON" : "BREAK-OFF",
  8011.                   " IAC SE", NULL,
  8012.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8013.     }
  8014. #endif /* DEBUG */
  8015. #ifdef OS2
  8016.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8017. #endif
  8018. #ifdef DEBUG
  8019.     debug(F100,tn_msg_out,"",0);
  8020.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8021. #endif /* DEBUG */
  8022.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8023. #ifdef OS2
  8024.     ReleaseTelnetMutex();
  8025. #endif
  8026.     if (rc)
  8027.         return(-1);
  8028.  
  8029.     if (tnc_wait((CHAR *)"comport set break state",0) < 0) {
  8030.         tn_push();
  8031.         return(-1);
  8032.     }
  8033.     debug(F111,"tnc_set_break_state","end",tnc_break);
  8034.     return(tnc_break);
  8035. }
  8036.  
  8037. int
  8038. #ifdef CK_ANSIC
  8039. tnc_get_break_state(void)
  8040. #else /* CK_ANSIC */
  8041. tnc_get_break_state()
  8042. #endif /* CK_ANSIC */
  8043. /* tnc_get_break_state */ {
  8044.     /* IAC SB COM_PORT SET_CONTROL <value(1)=4> IAC SE */
  8045.     /* wait for response */
  8046.     int i = 0, rc;
  8047.  
  8048.     debug(F110,"tnc_get_break_state","begin",0);
  8049.     if (ttnet != NET_TCPB) return(0);
  8050.     if (ttnproto != NP_TELNET) return(0);
  8051.  
  8052.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8053.  
  8054. #ifdef CK_SSL
  8055.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8056.         return(0);
  8057.     }
  8058. #endif /* CK_SSL */
  8059.  
  8060.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8061.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8062.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8063.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  8064.     sb_out[i++] = TNC_CTL_BREAK_REQUEST;
  8065.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8066.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8067.  
  8068. #ifdef DEBUG
  8069.     if (deblog || tn_deb || debses) {
  8070.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8071.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8072.                   " SET-CONTROL ",
  8073.                   "BREAK-REQUEST",
  8074.                   " IAC SE", NULL,
  8075.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8076.     }
  8077. #endif /* DEBUG */
  8078. #ifdef OS2
  8079.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8080. #endif
  8081. #ifdef DEBUG
  8082.     debug(F100,tn_msg_out,"",0);
  8083.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8084. #endif /* DEBUG */
  8085.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8086. #ifdef OS2
  8087.     ReleaseTelnetMutex();
  8088. #endif
  8089.     if (rc)
  8090.         return(-1);
  8091.  
  8092.     if (tnc_wait((CHAR *)"comport get break state",0) < 0) {
  8093.         tn_push();
  8094.         return(-1);
  8095.     }
  8096.     debug(F111,"tnc_get_break_state","end",tnc_break);
  8097.     return(tnc_break);
  8098. }
  8099.  
  8100. int
  8101. #ifdef CK_ANSIC
  8102. tnc_set_dtr_state(int onoff)
  8103. #else /* CK_ANSIC */
  8104. tnc_set_dtr_state(onoff) int onoff;
  8105. #endif /* CK_ANSIC */
  8106. /* tnc_set_dtr_state */ {
  8107.     /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
  8108.     /*        Value     Dtr State
  8109.      *          8       On
  8110.      *          9       Off
  8111.      */
  8112.     /* wait for response, return new host value. */
  8113.     int i = 0, rc;
  8114.  
  8115.     debug(F111,"tnc_set_dtr_state","begin",onoff);
  8116.     if (ttnet != NET_TCPB) return(0);
  8117.     if (ttnproto != NP_TELNET) return(0);
  8118.  
  8119.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8120.  
  8121. #ifdef CK_SSL
  8122.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8123.         return(0);
  8124.     }
  8125. #endif /* CK_SSL */
  8126.  
  8127.     if ( onoff != 0 && onoff == tnc_dtr )
  8128.         return(tnc_dtr);
  8129.  
  8130.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8131.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8132.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8133.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  8134.     sb_out[i++] = onoff ?
  8135.         TNC_CTL_DTR_ON : TNC_CTL_DTR_OFF;
  8136.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8137.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8138.  
  8139. #ifdef DEBUG
  8140.     if (deblog || tn_deb || debses) {
  8141.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8142.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8143.                   " SET-CONTROL ",
  8144.                   onoff ? "DTR-ON" : "DTR-OFF",
  8145.                   " IAC SE", NULL,
  8146.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8147.     }
  8148. #endif /* DEBUG */
  8149. #ifdef OS2
  8150.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8151. #endif
  8152. #ifdef DEBUG
  8153.     debug(F100,tn_msg_out,"",0);
  8154.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8155. #endif /* DEBUG */
  8156.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8157. #ifdef OS2
  8158.     ReleaseTelnetMutex();
  8159. #endif
  8160.     if (rc)
  8161.       return(-1);
  8162.  
  8163.     if (tnc_wait((CHAR *)"comport set dtr state",0) < 0) {
  8164.         tn_push();
  8165.         return(-1);
  8166.     }
  8167.     debug(F111,"tnc_set_dtr_state","end",tnc_dtr);
  8168.     return(tnc_dtr);
  8169. }
  8170.  
  8171. int
  8172. #ifdef CK_ANSIC
  8173. tnc_get_dtr_state(void)
  8174. #else /* CK_ANSIC */
  8175. tnc_get_dtr_state()
  8176. #endif /* CK_ANSIC */
  8177. /* tnc_get_dtr_state */ {
  8178.     /* IAC SB COM_PORT SET_CONTROL <value(1)=7> IAC SE */
  8179.     /* wait for response */
  8180.     int i = 0, rc;
  8181.  
  8182.     debug(F110,"tnc_get_dtr_state","begin",0);
  8183.     if (ttnet != NET_TCPB) return(0);
  8184.     if (ttnproto != NP_TELNET) return(0);
  8185.  
  8186.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8187.  
  8188. #ifdef CK_SSL
  8189.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8190.         return(0);
  8191.     }
  8192. #endif /* CK_SSL */
  8193.  
  8194.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8195.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8196.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8197.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  8198.     sb_out[i++] = TNC_CTL_DTR_REQUEST;
  8199.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8200.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8201.  
  8202. #ifdef DEBUG
  8203.     if (deblog || tn_deb || debses) {
  8204.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8205.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8206.                   " SET-CONTROL ",
  8207.                   "DTR-REQUEST",
  8208.                   " IAC SE", NULL,
  8209.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8210.     }
  8211. #endif /* DEBUG */
  8212. #ifdef OS2
  8213.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8214. #endif
  8215. #ifdef DEBUG
  8216.     debug(F100,tn_msg_out,"",0);
  8217.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8218. #endif /* DEBUG */
  8219.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8220. #ifdef OS2
  8221.     ReleaseTelnetMutex();
  8222. #endif
  8223.     if (rc)
  8224.       return(-1);
  8225.  
  8226.     if (tnc_wait((CHAR *)"comport get dtr state",0) < 0) {
  8227.         tn_push();
  8228.         return(-1);
  8229.     }
  8230.     debug(F111,"tnc_get_dtr_state","end",tnc_dtr);
  8231.     return(tnc_dtr);
  8232. }
  8233.  
  8234. int
  8235. #ifdef CK_ANSIC
  8236. tnc_set_rts_state(int onoff)
  8237. #else /* CK_ANSIC */
  8238. tnc_set_rts_state(onoff) int onoff;
  8239. #endif /* CK_ANSIC */
  8240. /* tnc_set_rts_state */ {
  8241.     /* IAC SB COM_PORT SET_CONTROL <value(1)> IAC SE */
  8242.     /*        Value     Rts State
  8243.      *          5       On
  8244.      *          6       Off
  8245.      */
  8246.     /* wait for response, return new host value. */
  8247.     int i = 0, rc;
  8248.  
  8249.     debug(F111,"tnc_set_rts_state","begin",onoff);
  8250.     if (ttnet != NET_TCPB) return(0);
  8251.     if (ttnproto != NP_TELNET) return(0);
  8252.  
  8253.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8254.  
  8255. #ifdef CK_SSL
  8256.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8257.         return(0);
  8258.     }
  8259. #endif /* CK_SSL */
  8260.  
  8261.     if ( onoff != 0 && onoff == tnc_rts )
  8262.         return(tnc_rts);
  8263.  
  8264.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8265.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8266.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8267.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  8268.     sb_out[i++] = onoff ?
  8269.       TNC_CTL_RTS_ON : TNC_CTL_RTS_OFF;
  8270.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8271.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8272.  
  8273. #ifdef DEBUG
  8274.     if (deblog || tn_deb || debses) {
  8275.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8276.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8277.                   " SET-CONTROL ",
  8278.                   onoff ? "RTS-ON" : "RTS-OFF",
  8279.                   " IAC SE", NULL,
  8280.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8281.     }
  8282. #endif /* DEBUG */
  8283. #ifdef OS2
  8284.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8285. #endif
  8286. #ifdef DEBUG
  8287.     debug(F100,tn_msg_out,"",0);
  8288.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8289. #endif /* DEBUG */
  8290.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8291. #ifdef OS2
  8292.     ReleaseTelnetMutex();
  8293. #endif
  8294.     if (rc)
  8295.       return(-1);
  8296.  
  8297.     if (tnc_wait((CHAR *)"comport set rts state",0) < 0) {
  8298.         tn_push();
  8299.         return(-1);
  8300.     }
  8301.     debug(F111,"tnc_set_rts_state","end",tnc_rts);
  8302.     return(tnc_rts);
  8303. }
  8304.  
  8305. int
  8306. #ifdef CK_ANSIC
  8307. tnc_get_rts_state(void)
  8308. #else /* CK_ANSIC */
  8309. tnc_get_rts_state()
  8310. #endif /* CK_ANSIC */
  8311. /* tnc_get_rts_state */ {
  8312.     /* IAC SB COM_PORT SET_CONTROL <value(1)=10> IAC SE */
  8313.     /* wait for response */
  8314.     int i = 0, rc;
  8315.  
  8316.     debug(F110,"tnc_get_rts_state","begin",0);
  8317.     if (ttnet != NET_TCPB) return(0);
  8318.     if (ttnproto != NP_TELNET) return(0);
  8319.  
  8320.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8321.  
  8322. #ifdef CK_SSL
  8323.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8324.         return(0);
  8325.     }
  8326. #endif /* CK_SSL */
  8327.  
  8328.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8329.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8330.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8331.     sb_out[i++] = TNC_C2S_SET_CONTROL;    /* Set Control */
  8332.     sb_out[i++] = TNC_CTL_RTS_REQUEST;
  8333.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8334.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8335.  
  8336. #ifdef DEBUG
  8337.     if (deblog || tn_deb || debses) {
  8338.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8339.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8340.                   " SET-CONTROL ",
  8341.                   "RTS-REQUEST",
  8342.                   " IAC SE", NULL,
  8343.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8344.     }
  8345. #endif /* DEBUG */
  8346. #ifdef OS2
  8347.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8348. #endif
  8349. #ifdef DEBUG
  8350.     debug(F100,tn_msg_out,"",0);
  8351.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8352. #endif /* DEBUG */
  8353.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8354. #ifdef OS2
  8355.     ReleaseTelnetMutex();
  8356. #endif
  8357.     if (rc)
  8358.         return(-1);
  8359.  
  8360.     if (tnc_wait((CHAR *)"comport get rts state",0) < 0) {
  8361.         tn_push();
  8362.         return(-1);
  8363.     }
  8364.     debug(F111,"tnc_get_rts_state","end",tnc_rts);
  8365.     return(tnc_rts);
  8366. }
  8367.  
  8368. int
  8369. #ifdef CK_ANSIC
  8370. tnc_set_ls_mask(int mask)
  8371. #else /* CK_ANSIC */
  8372. tnc_set_ls_mask(mask) int mask;
  8373. #endif /* CK_ANSIC */
  8374. /* tnc_set_ls_mask */ {
  8375.     /* IAC SB COM_PORT SET_LINESTATE_MASK <value(1)> IAC SE */
  8376.     /*        Bit       Meaning
  8377.      *          0       Data Ready
  8378.      *          1       Overrun Error
  8379.      *          2       Parity Error
  8380.      *          3       Framing Error
  8381.      *          4       Break Detect Error
  8382.      *          5       Transfer Holding Register Empty
  8383.      *          6       Transfer Shift Register Empty
  8384.      *          7       Timeout Error
  8385.      */
  8386.     int i = 0, rc;
  8387.  
  8388.     debug(F111,"tnc_set_ls_mask","begin",mask);
  8389.     if (ttnet != NET_TCPB) return(0);
  8390.     if (ttnproto != NP_TELNET) return(0);
  8391.  
  8392.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8393.  
  8394. #ifdef CK_SSL
  8395.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8396.         return(0);
  8397.     }
  8398. #endif /* CK_SSL */
  8399.  
  8400.     if ( mask != 0 && mask == tnc_ls_mask )
  8401.         return(tnc_ls_mask);
  8402.  
  8403.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8404.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8405.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8406.     sb_out[i++] = TNC_C2S_SET_LS_MASK;
  8407.     sb_out[i++] = (unsigned char)(mask & 0xFF);
  8408.     if (sb_out[i-1] == IAC )
  8409.       sb_out[i++] = IAC;
  8410.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8411.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8412.  
  8413. #ifdef DEBUG
  8414.     if (deblog || tn_deb || debses) {
  8415.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8416.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8417.                   " SET-LINESTATE-MASK ",
  8418.                   ckitoa(mask & 0xFF),
  8419.                   " IAC SE", NULL,
  8420.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8421.     }
  8422. #endif /* DEBUG */
  8423. #ifdef OS2
  8424.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8425. #endif
  8426. #ifdef DEBUG
  8427.     debug(F100,tn_msg_out,"",0);
  8428.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8429. #endif /* DEBUG */
  8430.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8431. #ifdef OS2
  8432.     ReleaseTelnetMutex();
  8433. #endif
  8434.     if (rc)
  8435.       return(-1);
  8436.  
  8437.     tnc_ls_mask = mask;
  8438.     debug(F111,"tnc_set_ls_mask","end",tnc_ls_mask);
  8439.     return(0);
  8440. }
  8441.  
  8442. int
  8443. #ifdef CK_ANSIC
  8444. tnc_get_ls_mask(void)
  8445. #else /* CK_ANSIC */
  8446. tnc_get_ls_mask()
  8447. #endif /* CK_ANSIC */
  8448. /* tnc_get_ls_mask */ {
  8449.     debug(F101,"tnc_get_ls_mask","",tnc_ls_mask);
  8450.     return(tnc_ls_mask);
  8451. }
  8452.  
  8453. int
  8454. #ifdef CK_ANSIC
  8455. tnc_get_ls(void)
  8456. #else /* CK_ANSIC */
  8457. tnc_get_ls()
  8458. #endif /* CK_ANSIC */
  8459. /* tnc_get_ls */ {
  8460.     int ls = tnc_ls;
  8461.     debug(F101,"tnc_get_ls","",tnc_ls);
  8462.     return(ls);
  8463. }
  8464.  
  8465. int
  8466. #ifdef CK_ANSIC
  8467. tnc_set_ms_mask(int mask)
  8468. #else /* CK_ANSIC */
  8469. tnc_set_ms_mask(mask) int mask;
  8470. #endif /* CK_ANSIC */
  8471. /* tnc_set_ms_mask */ {
  8472.     /* IAC SB COM_PORT SET_MODEMSTATE_MASK <value(1)> IAC SE */
  8473.     /*        Bit       Meaning
  8474.      *          0       Delta Clear To Send
  8475.      *          1       Delta Data Set Ready
  8476.      *          2       Trailing Edge Ring Detector
  8477.      *          3       Delta Receive Line Signal (Carrier) Detect
  8478.      *          4       Clear To Send Signal State
  8479.      *          5       Data-Set-Ready Signal State
  8480.      *          6       Ring Indicator
  8481.      *          7       Receive Line Signal (Carrier) Detect
  8482.      */
  8483.  
  8484.     int i = 0, rc;
  8485.  
  8486.     debug(F111,"tnc_set_ms_mask","begin",mask);
  8487.     if (ttnet != NET_TCPB) return(0);
  8488.     if (ttnproto != NP_TELNET) return(0);
  8489.  
  8490.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8491.  
  8492. #ifdef CK_SSL
  8493.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8494.         return(0);
  8495.     }
  8496. #endif /* CK_SSL */
  8497.  
  8498.     if ( mask != 0 && mask == tnc_ms_mask )
  8499.         return(tnc_ms_mask);
  8500.  
  8501.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8502.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8503.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8504.     sb_out[i++] = TNC_C2S_SET_MS_MASK;
  8505.     sb_out[i++] = (unsigned char)(mask & 0xFF);
  8506.     if (sb_out[i-1] == IAC )
  8507.       sb_out[i++] = IAC;
  8508.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8509.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8510.  
  8511. #ifdef DEBUG
  8512.     if (deblog || tn_deb || debses) {
  8513.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8514.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8515.                   " SET-MODEMSTATE-MASK ",
  8516.                   ckitoa(mask & 0xFF),
  8517.                   " IAC SE", NULL,
  8518.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8519.     }
  8520. #endif /* DEBUG */
  8521. #ifdef OS2
  8522.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8523. #endif
  8524. #ifdef DEBUG
  8525.     debug(F100,tn_msg_out,"",0);
  8526.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8527. #endif /* DEBUG */
  8528.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8529. #ifdef OS2
  8530.     ReleaseTelnetMutex();
  8531. #endif
  8532.     if (rc)
  8533.       return(-1);
  8534.  
  8535.     tnc_ms_mask = mask;
  8536.     debug(F111,"tnc_set_ms_mask","end",tnc_ms_mask);
  8537.     return(0);
  8538. }
  8539.  
  8540. int
  8541. #ifdef CK_ANSIC
  8542. tnc_get_ms_mask(void)
  8543. #else /* CK_ANSIC */
  8544. tnc_get_ms_mask()
  8545. #endif /* CK_ANSIC */
  8546. /* tnc_get_ms_mask */ {
  8547.     debug(F101,"tnc_get_gs_mask","",tnc_ms_mask);
  8548.     return(tnc_ms_mask);
  8549. }
  8550.  
  8551. int
  8552. #ifdef CK_ANSIC
  8553. tnc_get_ms(void)
  8554. #else /* CK_ANSIC */
  8555. tnc_get_ms()
  8556. #endif /* CK_ANSIC */
  8557. /* tnc_get_ms */ {
  8558.     int ms = tnc_ms;
  8559.     debug(F101,"tnc_get_ms","",tnc_ms);
  8560.     return(ms);
  8561. }
  8562.  
  8563. int
  8564. #ifdef CK_ANSIC
  8565. tnc_send_purge_data(int mode)
  8566. #else /* CK_ANSIC */
  8567. tnc_send_purge_data(mode) int mode;
  8568. #endif /* CK_ANSIC */
  8569. /* tnc_send_purge_data */ {
  8570.     /* IAC SB COM_PORT PURGE_DATA <value(1)> IAC SE */
  8571.     /*        Value     Meaning
  8572.      *          1       Purge access server receive data buffer
  8573.      *          2       Purge access server transmit data buffer
  8574.      *          3       Purge access server receive and transmit data buffers
  8575.      */
  8576.     /* No response */
  8577.     int i = 0, rc;
  8578.  
  8579.     debug(F111,"tnc_send_purge_data","begin",mode);
  8580.     if (ttnet != NET_TCPB) return(0);
  8581.     if (ttnproto != NP_TELNET) return(0);
  8582.  
  8583.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8584.  
  8585. #ifdef CK_SSL
  8586.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8587.         return(0);
  8588.     }
  8589. #endif /* CK_SSL */
  8590.  
  8591.     if ( !(mode >= 1 && mode <= 3) )
  8592.         return(0);
  8593.  
  8594.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8595.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8596.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8597.     sb_out[i++] = TNC_C2S_PURGE;
  8598.     sb_out[i++] = (unsigned char)(mode & 0xFF);
  8599.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8600.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8601.  
  8602. #ifdef DEBUG
  8603.     if (deblog || tn_deb || debses) {
  8604.         ckmakxmsg(tn_msg_out,TN_MSG_LEN,
  8605.                   "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8606.                   " PURGE-DATA ",
  8607.                   ckitoa(mode & 0xFF),
  8608.                   " IAC SE", NULL,
  8609.                   NULL,NULL,NULL,NULL,NULL,NULL);
  8610.     }
  8611. #endif /* DEBUG */
  8612. #ifdef OS2
  8613.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8614. #endif
  8615. #ifdef DEBUG
  8616.     debug(F100,tn_msg_out,"",0);
  8617.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8618. #endif /* DEBUG */
  8619.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8620. #ifdef OS2
  8621.     ReleaseTelnetMutex();
  8622. #endif
  8623.     if (rc)
  8624.       return(-1);
  8625.     debug(F110,"tnc_send_purge_data","end",0);
  8626.     return(0);
  8627. }
  8628.  
  8629. int
  8630. #ifdef CK_ANSIC
  8631. tnc_flow_suspended(void)
  8632. #else /* CK_ANSIC */
  8633. tnc_flow_suspended()
  8634. #endif /* CK_ANSIC */
  8635. /* tnc_flow_suspended */ {
  8636.     debug(F111,"tnc_flow_suspended","",tnc_suspend_xmit);
  8637.     return(tnc_suspend_xmit);
  8638. }
  8639.  
  8640. int
  8641. #ifdef CK_ANSIC
  8642. tnc_suspend_flow(void)
  8643. #else /* CK_ANSIC */
  8644. tnc_suspend_flow()
  8645. #endif /* CK_ANSIC */
  8646. /* tnc_suspend_flow */ {
  8647.     /* IAC SB COM_PORT FLOWCONTROL_SUSPEND IAC SE */
  8648.     int i = 0, rc;
  8649.  
  8650.     debug(F110,"tnc_suspend_flow","begin",0);
  8651.     if (ttnet != NET_TCPB) return(0);
  8652.     if (ttnproto != NP_TELNET) return(0);
  8653.  
  8654.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8655.  
  8656. #ifdef CK_SSL
  8657.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8658.         return(0);
  8659.     }
  8660. #endif /* CK_SSL */
  8661.  
  8662.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8663.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8664.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8665.     sb_out[i++] = TNC_C2S_FLOW_SUSPEND;
  8666.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8667.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8668.  
  8669. #ifdef DEBUG
  8670.     if (deblog || tn_deb || debses) {
  8671.         ckmakmsg(tn_msg_out,TN_MSG_LEN,
  8672.                  "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8673.                  " FLOWCONTROL-SUSPEND IAC SE", NULL);
  8674.     }
  8675. #endif /* DEBUG */
  8676. #ifdef OS2
  8677.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8678. #endif
  8679. #ifdef DEBUG
  8680.     debug(F100,tn_msg_out,"",0);
  8681.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8682. #endif /* DEBUG */
  8683.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8684. #ifdef OS2
  8685.     ReleaseTelnetMutex();
  8686. #endif
  8687.     if (rc)
  8688.         return(-1);
  8689.     debug(F110,"tnc_suspend_flow","end",0);
  8690.     return(0);
  8691. }
  8692.  
  8693. int
  8694. #ifdef CK_ANSIC
  8695. tnc_resume_flow(void)
  8696. #else /* CK_ANSIC */
  8697. tnc_resume_flow()
  8698. #endif /* CK_ANSIC */
  8699. /* tnc_resume_flow */ {
  8700.     /* IAC SB COM_PORT FLOWCONTROL_RESUME IAC SE */
  8701.     int i = 0, rc;
  8702.  
  8703.     debug(F110,"tnc_resume_flow","begin",0);
  8704.     if (ttnet != NET_TCPB) return(0);
  8705.     if (ttnproto != NP_TELNET) return(0);
  8706.  
  8707.     if (!TELOPT_ME(TELOPT_COMPORT)) return(0);
  8708.  
  8709. #ifdef CK_SSL
  8710.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  8711.         return(0);
  8712.     }
  8713. #endif /* CK_SSL */
  8714.  
  8715.     sb_out[i++] = (CHAR) IAC;                 /* I Am a Command */
  8716.     sb_out[i++] = (CHAR) SB;                  /* Subnegotiation */
  8717.     sb_out[i++] = TELOPT_COMPORT;             /* ComPort */
  8718.     sb_out[i++] = TNC_C2S_FLOW_RESUME;
  8719.     sb_out[i++] = (CHAR) IAC;                 /* End of Subnegotiation */
  8720.     sb_out[i++] = (CHAR) SE;                  /* marked by IAC SE */
  8721.  
  8722. #ifdef DEBUG
  8723.     if (deblog || tn_deb || debses) {
  8724.         ckmakmsg(tn_msg_out,TN_MSG_LEN,
  8725.                  "TELNET SENT SB ",TELOPT(TELOPT_COMPORT),
  8726.                  " FLOWCONTROL-RESUME IAC SE", NULL);
  8727.     }
  8728. #endif /* DEBUG */
  8729. #ifdef OS2
  8730.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  8731. #endif
  8732. #ifdef DEBUG
  8733.     debug(F100,tn_msg_out,"",0);
  8734.     if (tn_deb || debses) tn_debug(tn_msg_out);
  8735. #endif /* DEBUG */
  8736.     rc = (ttol((CHAR *)sb_out,i) < 0);      /* Send it. */
  8737. #ifdef OS2
  8738.     ReleaseTelnetMutex();
  8739. #endif
  8740.     if (rc)
  8741.         return(-1);
  8742.     debug(F110,"tnc_resume_flow","end",0);
  8743.     return(0);
  8744. }
  8745.  
  8746. int
  8747. #ifdef CK_ANSIC
  8748. tnsetflow(int nflow)
  8749. #else
  8750. tnsetflow(nflow) int nflow;
  8751. #endif /* CK_ANSIC */
  8752. /* tnsetflow */ {
  8753.  
  8754.     int rc = -1;
  8755.  
  8756.     debug(F111,"tnsetflow","begin",nflow);
  8757.     if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
  8758.         return(-1);
  8759.  
  8760.     if (TELOPT_ME(TELOPT_COMPORT)) {
  8761.         switch(nflow) {
  8762.           case FLO_XONX:
  8763.             rc = tnc_set_oflow(
  8764.                  TNC_CTL_OFLOW_XON_XOFF
  8765.                  );
  8766.             if (rc >= 0)
  8767.               rc = tnc_set_iflow(
  8768.                    TNC_CTL_IFLOW_XON_XOFF
  8769.                    );
  8770.             break;
  8771.           case FLO_RTSC:
  8772.             rc = tnc_set_oflow(
  8773.                  TNC_CTL_OFLOW_RTS_CTS
  8774.                  );
  8775.             if (rc >= 0)
  8776.               rc = tnc_set_iflow(
  8777.                    TNC_CTL_IFLOW_RTS_CTS
  8778.                    );
  8779.             break;
  8780.           case FLO_KEEP:
  8781.             /* leave things exactly as they are */
  8782.             rc = 0;
  8783.             break;
  8784.           case FLO_NONE:
  8785.           case FLO_DIAL:  /* dialing hack */
  8786.           case FLO_DIAX:  /* cancel dialing hack */
  8787.             rc = tnc_set_oflow(
  8788.                  TNC_CTL_OFLOW_NONE
  8789.                  );
  8790.             if (rc >= 0)
  8791.               rc = tnc_set_iflow(
  8792.                    TNC_CTL_IFLOW_NONE
  8793.                    );
  8794.             break;
  8795.           case FLO_DTRC:
  8796.           case FLO_ETXA:
  8797.           case FLO_STRG:
  8798.           case FLO_DTRT:
  8799.           default:
  8800.             /* not supported */
  8801.             rc = -1;
  8802.             break;
  8803.         }
  8804.     }
  8805.     debug(F111,"tnsetflow","end",rc);
  8806.     return(rc >= 0 ? 0 : -1);
  8807. }
  8808.  
  8809. int
  8810. #ifdef CK_ANSIC
  8811. tnsettings(int par, int stop)
  8812. #else
  8813. tnsettings(par, stop) int par, stop;
  8814. #endif /* CK_ANSIC */
  8815. /* tnsettings */ {
  8816.     int rc = -1;
  8817.     int datasize = 0;
  8818.     extern int hwparity;
  8819.  
  8820.     debug(F111,"tnsettings begin","par",par);
  8821.     debug(F111,"tnsettings begin","stop",stop);
  8822.     if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
  8823.       return(-1);
  8824.  
  8825.     datasize = par ? TNC_DS_7 : TNC_DS_8;
  8826.     if (!par) par = hwparity;
  8827.  
  8828.     if (TELOPT_ME(TELOPT_COMPORT)) {
  8829.         switch (par) {
  8830.           case 'e':
  8831.             rc = tnc_set_parity(TNC_PAR_EVEN);
  8832.             if (rc >= 0)
  8833.               rc = tnc_set_datasize(datasize);
  8834.             break;
  8835.           case 'o':
  8836.             rc = tnc_set_parity(TNC_PAR_ODD);
  8837.             if (rc >= 0)
  8838.               rc = tnc_set_datasize(datasize);
  8839.             break;
  8840.           case 'm':
  8841.             rc = tnc_set_parity(TNC_PAR_MARK);
  8842.             if (rc >= 0)
  8843.               rc = tnc_set_datasize(datasize);
  8844.             break;
  8845.           case 's':
  8846.             rc = tnc_set_parity(TNC_PAR_SPACE);
  8847.             if (rc >= 0)
  8848.               rc = tnc_set_datasize(datasize);
  8849.             break;
  8850.           case 0:
  8851.           case 'n':
  8852.             rc = tnc_set_parity(TNC_PAR_NONE);
  8853.             if (rc >= 0)
  8854.               rc = tnc_set_datasize(datasize);
  8855.             break;
  8856.           default:
  8857.             /* no change */
  8858.             rc = 0;
  8859.         }
  8860.         switch(stop) {
  8861.           case 2:
  8862.             if (rc >= 0)
  8863.               rc = tnc_set_stopsize(TNC_SB_2);
  8864.             break;
  8865.           case 1:
  8866.             if (rc >= 0)
  8867.               rc = tnc_set_stopsize(TNC_SB_1);
  8868.             break;
  8869.           default:
  8870.             /* no change */
  8871.             if (rc >= 0)
  8872.               rc = 0;
  8873.         }
  8874.     }
  8875.     debug(F111,"tnsettings","end",rc);
  8876.     return((rc >= 0) ? 0 : -1);
  8877. }
  8878.  
  8879. /*  T N G M D M  --  Telnet Get modem signals  */
  8880. /*
  8881.  Looks for the modem signals CTS, DSR, and CTS, and returns those that are
  8882.  on in as its return value, in a bit mask as described for ttwmdm.
  8883.  Returns:
  8884.   -3 Not implemented
  8885.   -2 if the line does not have modem control
  8886.   -1 on error.
  8887.   >= 0 on success, with a bit mask containing the modem signals that are on.
  8888. */
  8889. int
  8890. #ifdef CK_ANSIC
  8891. tngmdm(void)
  8892. #else
  8893. tngmdm()
  8894. #endif /* CK_ANSIC */
  8895. /* tngmdm */ {
  8896.  
  8897.     int rc = -1;
  8898.  
  8899.     debug(F110,"tngmdm","begin",0);
  8900.     if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
  8901.       return(-1);
  8902.  
  8903.     if (TELOPT_ME(TELOPT_COMPORT)) {
  8904.         int modemstate = tnc_get_ms();
  8905.         int modem = 0;
  8906.         if (modemstate & TNC_MS_CTS_SIG)
  8907.           modem |= BM_CTS;
  8908.         if (modemstate & TNC_MS_DSR_SIG)
  8909.           modem |= BM_DSR;
  8910.         if (modemstate & TNC_MS_RI_SIG)
  8911.           modem |= BM_RNG;
  8912.         if (modemstate & TNC_MS_RLSD_SIG)
  8913.           modem |= BM_DCD;
  8914.         debug(F111,"tngmdm","end",modem);
  8915.         return(modem);
  8916.     } else {
  8917.         debug(F111,"tngmdm","end",-2);
  8918.         return(-2);
  8919.     }
  8920. }
  8921.  
  8922. int
  8923. #ifdef CK_ANSIC
  8924. tnsndb(long wait)
  8925. #else
  8926. tnsndb(wait) long wait;
  8927. #endif /* CK_ANSIC */
  8928. /* tnsndb */ {
  8929.     int rc = -1;
  8930.  
  8931.     debug(F111,"tnsndb","begin",wait);
  8932.     if (ttnet != NET_TCPB || ttnproto != NP_TELNET)
  8933.       return(-1);
  8934.  
  8935.     if (TELOPT_ME(TELOPT_COMPORT)) {
  8936.         rc  = tnc_set_break_state(1);
  8937.         if (rc >= 0) {
  8938.             msleep(wait);                         /* ZZZzzz */
  8939.             rc = tnc_set_break_state(0);
  8940.         }
  8941.     }
  8942.     debug(F111,"tnsndb","end",rc);
  8943.     return((rc >= 0) ? 0 : -1);
  8944. }
  8945. #endif /* TN_COMPORT */
  8946. #endif /* TNCODE */
  8947.