home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / archives / ckv301.zip / ckctel.c < prev    next >
C/C++ Source or Header  |  2010-03-16  |  305KB  |  9,016 lines

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