ckctel.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:158k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  1. char *cktelv = "Telnet support, 7.0.191, 30 Dec 1999";
  2. #define CKCTEL_C
  3. int sstelnet = 0;                       /* Do server-side Telnet negotiation */
  4. /*  C K C T E L  --  Telnet support  */
  5. /*
  6.   Authors:
  7.     Telnet protocol by Frank da Cruz and Jeffrey Altman.
  8.     Other contributions as indicated in the code.
  9.   Copyright (C) 1985, 2000,
  10.     Trustees of Columbia University in the City of New York.
  11.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  12.     copyright text in the ckcmai.c module for disclaimer and permissions.
  13. */
  14. /*
  15.   NOTE TO CONTRIBUTORS: This file, and all the other shared (ckc and cku)
  16.   C-Kermit source files, must be compatible with C preprocessors that support
  17.   only #ifdef, #else, #endif, #define, and #undef.  Please do not use #if,
  18.   logical operators, or other preprocessor features in this module.  Also,
  19.   don't use any ANSI C constructs except within #ifdef CK_ANSIC..#endif.
  20. */
  21. #include "ckcsym.h"
  22. #include "ckcdeb.h"
  23. #include "ckcker.h"
  24. #define TELCMDS                         /* to define name array */
  25. #define TELOPTS                         /* to define name array */
  26. #define SLC_NAMES                       /* to define name array */
  27. #define ENCRYPT_NAMES
  28. #define AUTH_NAMES
  29. #define TELOPT_STATES
  30. #define TELOPT_MODES
  31. #include "ckcnet.h"
  32. #include "ckctel.h"
  33. #ifdef CK_SSL
  34. #include "ck_ssl.h"
  35. #endif /* CK_SSL */
  36. #ifdef TNCODE
  37. #ifdef OS2                              /* For terminal type name string */
  38. #include "ckuusr.h"
  39. #ifndef NT
  40. #include <os2.h>
  41. #undef COMMENT
  42. #endif /* NT */
  43. #include "ckocon.h"
  44. extern int tt_type, max_tt;
  45. extern struct tt_info_rec tt_info[];
  46. extern char ttname[];
  47. #endif /* OS2 */
  48. #ifdef OS2
  49. #include <assert.h>
  50. #ifdef NT
  51. #include <setjmpex.h>
  52. #else /* NT */
  53. #include <setjmp.h>
  54. #endif /* NT */
  55. #include <signal.h>
  56. #include "ckcsig.h"
  57. #endif /* OS2 */
  58. #define HEXDISP
  59. #ifdef CK_NAWS                          /* Negotiate About Window Size */
  60. #ifdef RLOGCODE
  61. _PROTOTYP( int rlog_naws, (void) );
  62. #endif /* RLOGCODE */
  63. #endif /* CK_NAWS */
  64. int tn_init = 0;                        /* Telnet protocol initialized flag */
  65. static int tn_first = 1;                /* First time init flag */
  66. extern int tn_exit;                     /* Exit on disconnect */
  67. extern int inserver;                    /* Running as IKSD */
  68. char *tn_term = NULL;                   /* Terminal type override */
  69. #ifdef CK_SNDLOC
  70. char *tn_loc = NULL;                    /* Location override */
  71. #endif /* CK_SNDLOC */
  72. int tn_nlm = TNL_CRLF;                  /* Telnet CR -> CR LF mode */
  73. int tn_b_nlm = TNL_CR;                  /* Telnet Binary CR RAW mode */
  74. int tn_b_meu = 0;                       /* Telnet Binary ME means U too */
  75. int tn_b_ume = 0;                       /* Telnet Binary U means ME too */
  76. int tn_wait_flg = 1;                    /* Telnet Wait for Negotiations */
  77. int tn_infinite = 0;                    /* Telnet Bug Infinite-Loop-Check */
  78. int tn_rem_echo = 1;                    /* We will echo if WILL ECHO */
  79. int tn_b_xfer = 0;                      /* Telnet Binary for Xfers? */
  80. int tn_sb_bug = 1;                      /* Telnet BUG - SB w/o WILL or DO */
  81. int tn_no_encrypt_xfer = 0;             /* Turn off Telnet Encrypt? */
  82. int tn_auth_how = TN_AUTH_HOW_ANY;
  83. int tn_auth_enc = TN_AUTH_ENC_ANY;
  84. int tn_deb = 0;                         /* Telnet Debug mode */
  85. #ifdef OS2
  86. int ttnum = -1;                         /* Last Telnet Terminal Type sent */
  87. int ttnumend = 0;                       /* Has end of list been found */
  88. #endif /* OS2 */
  89. #define TN_MSG_LEN 8196
  90. char tn_msg[TN_MSG_LEN];                /* Telnet data can be rather long */
  91. char hexbuf[TN_MSG_LEN];
  92. /*
  93.   In order to prevent an infinite telnet negotiation loop we maintain a
  94.   count of the number of times the same telnet negotiation message is
  95.   sent. When this count hits MAXTNCNT, we do not send any more of the
  96.   message. The count is stored in the tncnts[][] array.
  97.   The tncnts[][] array is indexed by negotiation option (SUPPRESS GO AHEAD,
  98.   TERMINAL TYPE, NAWS, etc. - see the tnopts[] array) and the four
  99.   negotiation message types (WILL, WONT, DO, DONT).  All telnet negotiations
  100.   are kept track of in this way.
  101.   The count for a message is zeroed when the "opposite" message is sent.
  102.   WILL is the opposite of WONT, and DO is the opposite of DONT.
  103.   For example sending "WILL SGA" increments tncnts[TELOPT_SGA][0]
  104.   and zeroes tncnts[TELOPT_SGA][1].
  105.   The code that does this is in tn_sopt().
  106.   rogersh@fsj.co.jp, 18/3/1995
  107.   8/16/1998 - with the recent rewrite of the telnet state machine I don't
  108.   think this code is necessary anymore.  However, it can't do any harm so
  109.   I am leaving it in.    - Jeff
  110.   12/28/1998 - all references to tncnts[] must be done with TELOPT_INDEX(opt)
  111.   because the Telnet option list is no longer contiguous.  We also must
  112.   allocate NTELOPTS + 1 because the TELOPT_INDEX() macro returns NTELOPTS
  113.   for an invalid option number.
  114. */
  115. #define MAXTNCNT 4      /* Permits 4 intermediate telnet firewalls/gateways */
  116. char tncnts[NTELOPTS+1][4];             /* Counts */
  117. char tnopps[4] = { 1,0,3,2 };           /* Opposites */
  118. #ifdef CK_ENVIRONMENT
  119. #define TSBUFSIZ 1024
  120. char tn_env_acct[64];
  121. char tn_env_disp[64];
  122. char tn_env_job[64];
  123. char tn_env_prnt[64];
  124. char tn_env_sys[64];
  125. int tn_env_flg = 1;
  126. #else /* CK_ENVIRONMENT */
  127. #define TSBUFSIZ 41
  128. int tn_env_flg = 0;
  129. #endif /* CK_ENVIRONMENT */
  130. #ifndef NOSIGWINCH
  131. #ifdef CK_NAWS                          /* Window size business */
  132. #ifdef UNIX
  133. #include <signal.h>
  134. #endif /* UNIX */
  135. #endif /* CK_NAWS */
  136. #endif /* NOSIGWINCH */
  137. unsigned char sb[TSBUFSIZ+8];           /* Buffer for subnegotiations */
  138. int tn_duplex = 1;                      /* Local echo */
  139. extern char uidbuf[];                   /* User ID buffer */
  140. extern int quiet, ttnet, ttnproto, debses, what, duplex;
  141. extern int seslog, sessft, whyclosed;
  142. #ifdef OS2
  143. extern int tt_rows[], tt_cols[];
  144. extern int tt_status;
  145. extern int scrninitialized[];
  146. #else /* OS2 */
  147. extern int tt_rows, tt_cols;            /* Everybody has this */
  148. #endif /* OS2 */
  149. extern int cmd_cols, cmd_rows;
  150. extern char namecopy[];
  151. extern char myipaddr[];             /* Global copy of my IP address */
  152. int sw_armed = 0;                       /* SIGWINCH armed flag */
  153. #ifndef NOSIGWINCH
  154. #ifdef CK_NAWS                          /* Window size business */
  155. #ifdef SIGWINCH
  156. #ifdef UNIX
  157. SIGTYP
  158. winchh(foo) int foo; {
  159.     int x = 0;
  160. #ifdef CK_TTYFD
  161. #ifndef VMS
  162.     extern int ttyfd;
  163. #endif /* VMS */
  164. #endif /* CK_TTYFD */
  165.     debug(F100,"SIGWINCH caught","",0);
  166.     signal(SIGWINCH,winchh);            /* Re-arm the signal */
  167. #ifdef CK_TTYFD
  168.     if
  169. #ifdef VMS
  170.       (vmsttyfd() == -1)
  171. #else
  172.       (ttyfd == -1)
  173. #endif /* VMS */
  174. #else
  175.       (!local)
  176. #endif /* CK_TTYFD */
  177. return;
  178.     x = ttgwsiz();                      /* Get new window size */
  179. /*
  180.   This should be OK.  It might seem that sending this from
  181.   interrupt level could interfere with another TELNET IAC string
  182.   that was in the process of being sent.  But we always send
  183.   TELNET strings with a single write(), which should prevent mixups.
  184. */
  185.     if (x > 0 && tt_rows > 0 && tt_cols > 0) {
  186.         tn_snaws();
  187. #ifdef RLOGCODE
  188.         rlog_naws();
  189. #endif /* RLOGCODE */
  190.     }
  191.     return;
  192. }
  193. #endif /* UNIX */
  194. #endif /* SIGWINCH */
  195. #endif /* CK_NAWS */
  196. #endif /* NOSIGWINCH */
  197. #ifndef TELOPT_MACRO
  198. int
  199. telopt_index(opt) int opt; {
  200.     if (opt >= 0 && opt <= TELOPT_FORWARD_X)
  201.       return(opt);
  202.     else if (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT)
  203.       return(opt-89);
  204.     else if (opt == TELOPT_IBM_SAK)
  205.       return(opt-148);
  206.     else
  207.       return(NTELOPTS);
  208. }
  209. int
  210. telopt_ok(opt) int opt; {
  211.     return((opt >= TELOPT_BINARY && opt <= TELOPT_FORWARD_X) ||
  212.            (opt >= TELOPT_PRAGMA_LOGON && opt <= TELOPT_PRAGMA_HEARTBEAT) ||
  213.            (opt == TELOPT_IBM_SAK));
  214. }
  215. CHAR *
  216. telopt(opt) int opt; {
  217.     if (telopt_ok(opt))
  218.       return((CHAR *)telopts[telopt_index(opt)]);
  219.     else
  220.       return((CHAR *)"UNKNOWN");
  221. }
  222. int
  223. telopt_mode_ok(opt) int opt; {
  224.     return((unsigned int)(opt) <= TN_NG_MU);
  225. }
  226. CHAR *
  227. telopt_mode(opt) int opt; {
  228.     if (telopt_mode_ok(opt))
  229.       return((CHAR *)telopt_modes[opt-TN_NG_RF]);
  230.     else
  231.       return((CHAR *)"UNKNOWN");
  232. }
  233. #endif /* TELOPT_MACRO */
  234. static int
  235. tn_outst(notquiet) int notquiet; {
  236.     int outstanding = 0;
  237.     int x = 0;
  238. #ifdef CK_ENCRYPTION
  239.     int e = 0;
  240.     int d = 0;
  241. #endif /* CK_ENCRYPTION */
  242.     if (tn_wait_flg) {
  243.         for (x = TELOPT_FIRST; x <= TELOPT_LAST; x++) {
  244.             if (TELOPT_OK(x)) {
  245.                 if (TELOPT_UNANSWERED_WILL(x)) {
  246.                     if ( notquiet )
  247.                       printf("?Telnet waiting for response to WILL %srn",
  248.                              TELOPT(x));
  249.                     debug(F111,"tn_outst","unanswered WILL",x);
  250.                     outstanding = 1;
  251.                     if ( !notquiet )
  252.                       break;
  253.                 }
  254.                 if (TELOPT_UNANSWERED_DO(x)) {
  255.                     if ( notquiet )
  256.                       printf("?Telnet waiting for response to DO %srn",
  257.                              TELOPT(x));
  258.                     debug(F111,"tn_outst","unanswered DO",x);
  259.                     outstanding = 1;
  260.                     if ( !notquiet )
  261.                       break;
  262.                 }
  263.                 if (TELOPT_UNANSWERED_WONT(x)) {
  264.                     if ( notquiet )
  265.                       printf("?Telnet waiting for response to WONT %srn",
  266.                              TELOPT(x));
  267.                     debug(F111,"tn_outst","unanswered WONT",x);
  268.                     outstanding = 1;
  269.                     if ( !notquiet )
  270.                       break;
  271.                 }
  272.                 if (TELOPT_UNANSWERED_DONT(x)) {
  273.                     if ( notquiet )
  274.                       printf("?Telnet waiting for response to DONT %srn",
  275.                              TELOPT(x));
  276.                     debug(F111,"tn_outst","unanswered DONT",x);
  277.                     outstanding = 1;
  278.                     if ( !notquiet )
  279.                       break;
  280.                 }
  281.                 if (TELOPT_UNANSWERED_SB(x)) {
  282.                     if ( notquiet )
  283.                       printf("?Telnet waiting for response to SB %srn",
  284.                              TELOPT(x));
  285.                     debug(F111,"tn_outst","unanswered SB",x);
  286.                     outstanding = 1;
  287.                     if ( !notquiet )
  288.                       break;
  289.                 }
  290.             }
  291.         }
  292.         if (!outstanding && !notquiet) {
  293. #ifdef CK_ENCRYPTION
  294.             e = ck_tn_encrypting();
  295.             d = ck_tn_decrypting();
  296.             if (TELOPT_ME(TELOPT_ENCRYPTION)) {
  297.                 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && e ||
  298.                     !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !e
  299.                     ) {
  300.                     if ( notquiet )
  301.                       printf("?Telnet waiting for WILL %s subnegotiationrn",
  302.                              TELOPT(TELOPT_ENCRYPTION));
  303.                     debug(F111,
  304.                           "tn_outst",
  305.                           "encryption mode switch",
  306.                           TELOPT_ENCRYPTION
  307.                           );
  308.                     outstanding = 1;
  309.                 }
  310.             }
  311.             if (TELOPT_U(TELOPT_ENCRYPTION)) {
  312.                 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && d ||
  313.                     !TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && !d
  314.                     ) {
  315.                     if ( notquiet )
  316.                       printf("?Telnet waiting for DO %s subnegotiationrn",
  317.                              TELOPT(TELOPT_ENCRYPTION));
  318.                     debug(F111,
  319.                           "tn_outst",
  320.                           "decryption mode switch",
  321.                            TELOPT_ENCRYPTION
  322.                           );
  323.                     outstanding = 1;
  324.                 }
  325.             }
  326. #endif /* CK_ENCRYPTION */
  327. #ifdef CK_AUTHENTICATION
  328.             if (TELOPT_ME(TELOPT_AUTHENTICATION) &&
  329.                 ck_tn_auth_in_progress()
  330.                 ) {
  331.                 if ( notquiet )
  332.                   printf("?Telnet waiting for WILL %s subnegotiationrn",
  333.                          TELOPT(TELOPT_AUTHENTICATION));
  334.                 debug(F111,
  335.                       "tn_outst",
  336.                       "ME authentication in progress",
  337.                        TELOPT_AUTHENTICATION
  338.                       );
  339.                 outstanding = 1;
  340.             } else if (TELOPT_U(TELOPT_AUTHENTICATION) &&
  341.                        ck_tn_auth_in_progress()
  342.                        ) {
  343.                 if ( notquiet )
  344.                   printf("?Telnet waiting for DO %s subnegotiationrn",
  345.                          TELOPT(TELOPT_AUTHENTICATION));
  346.                 debug(F111,
  347.                       "tn_outst",
  348.                       "U authentication in progress",
  349.                       TELOPT_AUTHENTICATION
  350.                       );
  351.                 outstanding = 1;
  352.             }
  353. #endif /* CK_AUTHENTICATION */
  354.         }
  355.     } /* if (tn_wait_flg) */
  356. #ifdef IKS_OPTION
  357.     /* Even if we are not waiting for Telnet options we must wait for */
  358.     /* Kermit Telnet Subnegotiations if we have sent a request to the */
  359.     /* other guy.  Otherwise we will get out of sync.                 */
  360.     if (!outstanding) {
  361.         if (TELOPT_U(TELOPT_KERMIT) &&
  362.             (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start ||
  363.              TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop ||
  364.              !TELOPT_SB(TELOPT_KERMIT).kermit.sop)
  365.             ) {
  366.             if ( notquiet )
  367.               printf("?Telnet waiting for DO %s subnegotiationrn",
  368.                      TELOPT(TELOPT_KERMIT));
  369.             debug(F111,"tn_outst","U kermit in progress",TELOPT_KERMIT);
  370.             outstanding = 1;
  371.         }
  372.     }
  373. #endif /* IKS_OPTION */
  374.     return(outstanding);
  375. }
  376. /* tn_wait() -- Wait for response to Telnet negotiation. */
  377. /*
  378.   Wait for up to <timeout> seconds for the response to arrive.
  379.   Place all non-telnet data into Telnet Wait Buffer.
  380.   If response does arrive return 1, else return 0.
  381. */
  382. #ifndef TN_WAIT_BUF_SZ
  383. #define TN_WAIT_BUF_SZ 4096
  384. #endif /* TN_WAIT_BUF_SZ */
  385. static char tn_wait_buf[TN_WAIT_BUF_SZ];
  386. static int  tn_wait_idx = 0;
  387. #ifndef TN_TIMEOUT
  388. #define TN_TIMEOUT 120
  389. #endif /* TN_TIMEOUT */
  390. static int tn_wait_tmo = TN_TIMEOUT;
  391. #ifdef CKSPINNER
  392. VOID
  393. prtwait(state) int state; {
  394.     switch (state % 4) {
  395.       case 0:
  396.         printf("/");
  397.         break;
  398.       case 1:
  399.         printf("-");
  400.         break;
  401.       case 2:
  402.         printf("\");
  403.         break;
  404.       case 3:
  405.         printf("|");
  406.         break;
  407.     }
  408. }
  409. #endif /* CKSPINNER */
  410. static int nflag = 0;
  411. int
  412. #ifdef CK_ANSIC
  413. tn_wait(char * where)
  414. #else
  415. tn_wait(where) char * where;
  416. #endif /* CK_ANSIC */
  417. /* tn_wait */ {
  418.     extern int ckxech, local;
  419.     int ch = 0, try = 0, count = 0;
  420.     int outstanding;
  421.     debug(F110,"tn_wait waiting for",where,0);
  422.     tn_wait_tmo = TN_TIMEOUT;
  423.     debug(F111,"tn_wait","timeout",tn_wait_tmo);
  424.     outstanding = tn_outst(0);
  425.     /* The following is meant to be !(||).  We only want to return */
  426.     /* immediately if both the tn_wait_flg && tn_outst() are false */
  427.     if (!(outstanding || tn_wait_flg))  /* If no need to wait */
  428.       return(1);                        /* Don't. */
  429.     if (tn_deb || debses) tn_debug("<wait for outstanding negotiations>");
  430.     if (!sstelnet && !quiet) {
  431. #ifdef CKSPINNER
  432.         prtwait(try);
  433. #endif /* CKSPINNER */
  434.     }
  435.     /* Wait up to TN_TIMEOUT sec for responses to outstanding telnet negs */
  436.     while ((tn_wait_idx < TN_WAIT_BUF_SZ) &&
  437.            (count || ((outstanding || try == 0) && ttchk() >= 0))
  438.            ) {
  439. #ifdef NTSIG
  440.         ck_ih();
  441. #endif /* NTSIG */
  442.         ch = ttinc(1);
  443.         if (ch == -1) {                 /* Timed out */
  444.             try++;
  445.             if (!sstelnet && !quiet) {  /* Let user know... */
  446. #ifdef CKSPINNER
  447.                 printf("b");
  448.                 prtwait(try);
  449. #else
  450.                 if (nflag == 0) {
  451.                     printf(" Negotiations.");
  452.                     nflag++;
  453.                 }
  454.                 if (nflag > 0) {
  455.                     printf(".");
  456.                     nflag++;
  457.                     fflush(stdout);
  458.                 }
  459. #endif /* CKSPINNER */
  460.             }
  461.             if ( try > tn_wait_tmo ) {
  462.                 if (!sstelnet) {
  463.                     printf(
  464.                        "rn?Telnet Protocol Timeout - connection closedrn");
  465.                     if (tn_deb || debses)
  466.                       tn_debug(
  467.                        "<telnet protocol timeout - connection closed>");
  468.                     tn_outst(1);
  469.                 }
  470.                 /* if we do not close the connection, then we will block */
  471.                 /* the next time we hit a wait.  and if we don't we will */
  472.                 /* do the wrong thing if the host sends 0xFF and does    */
  473.                 /* not intend it to be an IAC.                           */
  474.                 ttclos(0);
  475.                 whyclosed = WC_TELOPT;
  476.                 return(-1);
  477.             }
  478.             continue;
  479.         } else if (ch < -1) {
  480.             printf("rn?Connection closed by peer.rn");
  481.             if (tn_deb || debses) tn_debug("<connection closed by peer>");
  482.             return(-1);
  483.         }
  484.         switch (ch) {
  485.           case IAC:
  486. #ifdef CKSPINNER
  487.             if (!sstelnet && !quiet)
  488.               printf("b");
  489. #endif /* CKSPINNER */
  490.             ch = tn_doop((CHAR)(ch & 0xff),inserver?ckxech:duplex,ttinc);
  491. #ifdef CKSPINNER
  492.             if (!sstelnet && !quiet)
  493.               prtwait(try);
  494. #endif /* CKSPINNER */
  495.             debug(F101,"tn_wait tn_doop","",ch);
  496.             switch (ch) {
  497.               case 1:
  498.                 duplex = 1;             /* Turn on echoing */
  499.                 if (inserver)
  500.                   ckxech = 1;
  501.                 break;
  502.               case 2:
  503.                 duplex = 0;             /* Turn off echoing */
  504.                 if (inserver)
  505.                   ckxech = 0;
  506.                 break;
  507.               case 3:
  508.                 tn_wait_buf[tn_wait_idx++] = IAC;
  509.                 break;
  510.               case 4:                   /* IKS event */
  511.               case 6:                   /* Logout */
  512.                 break;
  513.               case -1:
  514.                 printf("?Telnet Option negotiation error.n");
  515.                 if (tn_deb || debses)
  516.                   tn_debug("<Telnet Option negotiation error>");
  517.                 return(-1);
  518.               case -2:
  519.                 printf("?Connection closed by peer.n");
  520.                 if (tn_deb || debses) tn_debug("<Connection closed by peer>");
  521.                 return(-2);
  522.               default:
  523.                 if (ch < 0) {
  524.                   if (tn_deb || debses) tn_debug("<Unknown connection error>");
  525.                   return(ch);
  526.                 }
  527.             } /* switch */
  528.             break;
  529.           default:
  530.             tn_wait_buf[tn_wait_idx++] = (CHAR)(ch & 0xff);
  531.         } /* switch */
  532.         outstanding = tn_outst(0);
  533.         count = ttchk();
  534.         if (!try)
  535.           try++;
  536.     } /* while */
  537.     if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  538.       if (tn_deb || debses) tn_debug("<Telnet Wait Buffer filled>");
  539.       return(0);
  540.     }
  541.     if (!sstelnet && !quiet) {
  542. #ifdef CKSPINNER
  543.         printf("b b");
  544. #else
  545.         if (nflag > 0) {
  546.             printf(" (OK)n");
  547.             nflag = -1;
  548.         }
  549. #endif /* CKSPINNER */
  550.     }
  551.     if (tn_deb || debses) tn_debug("<no outstanding negotiations>");
  552.     return(0);
  553. }
  554. /* Push data from the Telnet Wait Buffer into the I/O Queue */
  555. /* Return 1 on success                                      */
  556. int
  557. tn_push() {
  558. #ifdef NETLEBUF
  559.     extern int tt_push_inited;
  560. #endif /* NETLEBUF */
  561.     if (tn_wait_idx) {
  562.         hexdump((CHAR *)"tn_push",tn_wait_buf,tn_wait_idx);
  563. #ifdef NETLEBUF
  564.         if (!tt_push_inited)            /* Local handling */
  565.           le_init();
  566.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  567. #else                                   /* External handling... */
  568. #ifdef OS2                              /* K95 has its own way */
  569.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  570. #else
  571. #ifdef TTLEBUF                          /* UNIX, etc */
  572.         le_puts((CHAR *)tn_wait_buf,tn_wait_idx);
  573. #else
  574. /*
  575.   If you see this message in AOS/VS, OS-9, VOS, etc, you need to copy
  576.   the #ifdef TTLEBUF..#endif code from ckutio.c to the corresponding
  577.   places in your ck?tio.c module.
  578. */
  579.         printf("tn_push called but not implemented - data lost.n");
  580. #endif /* NETLEBUF */
  581. #endif /* UNIX */
  582. #endif /* OS2 */
  583.         tn_wait_idx = 0;
  584.     }
  585.     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
  586.     return(1);
  587. }
  588. /*  T N _ S O P T  */
  589. /*
  590.    Sends a telnet option, avoids loops.
  591.    Returns 1 if command was sent, 0 if not, -1 on error.
  592. */
  593. int
  594. tn_sopt(cmd,opt) int cmd, opt; {        /* TELNET SEND OPTION */
  595.     CHAR buf[5];
  596.     if (ttnet != NET_TCPB) return(-1);  /* Must be TCP/IP */
  597.     if (ttnproto != NP_TELNET) return(-1); /* Must be telnet protocol */
  598.     if (!TELCMD_OK(cmd)) return(-1);
  599.     if (TELOPT_OK(opt)) {
  600.         if (cmd == DO && TELOPT_UNANSWERED_DO(opt)) return(0);
  601.         if (cmd == WILL && TELOPT_UNANSWERED_WILL(opt)) return(0);
  602.         if (cmd == DONT && TELOPT_UNANSWERED_DONT(opt)) return(0);
  603.         if (cmd == WONT && TELOPT_UNANSWERED_WONT(opt)) return(0);
  604.     }
  605. #ifdef CK_SSL
  606.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  607.         return(0);
  608.     }
  609. #endif /* CK_SSL */
  610.     if (cmd == DO && opt == TELOPT_AUTHENTICATION)
  611.       buf[0] = 0;
  612.     if (tn_infinite && TELOPT_OK(opt)) { /* See comment above about   */
  613.         int index = TELOPT_INDEX(opt);   /* preventing infinite loops */
  614.         int m = cmd - WILL;
  615.         if (tncnts[index][m] > MAXTNCNT) {
  616.             if (tn_deb || debses || deblog) {
  617.                 sprintf(tn_msg,"TELNET negotiation loop %s %s",
  618.                         TELCMD(cmd),
  619.                         TELOPT(opt));
  620.                 debug(F101,tn_msg,"",opt);
  621.                 if (tn_deb || debses) tn_debug(tn_msg);
  622.             }
  623.             return(0);
  624.         }
  625.         tncnts[index][m]++;
  626.         tncnts[index][tnopps[m]] = 0;
  627.     }
  628.     buf[0] = (CHAR) IAC;
  629.     buf[1] = (CHAR) (cmd & 0xff);
  630.     buf[2] = (CHAR) (opt & 0xff);
  631.     buf[3] = (CHAR) 0;
  632.     if ((tn_deb || debses || deblog) && cmd != SB) {
  633.         sprintf(tn_msg,"TELNET SENT %s %s",TELCMD(cmd),
  634.                 TELOPT(opt));
  635.         debug(F101,tn_msg,"",opt);
  636.     }
  637.     if (ttol(buf,3) < 3) {
  638.         return(-1);
  639.     }
  640.     /* Only display the command if it was actually sent. */
  641.     if ((tn_deb || debses) && cmd != SB) tn_debug(tn_msg);
  642.     if (TELOPT_OK(opt)) {
  643.         if (cmd == DONT && TELOPT_UNANSWERED_DO(opt))
  644.           TELOPT_UNANSWERED_DO(opt) = 0;
  645.         if (cmd == WONT && TELOPT_UNANSWERED_WILL(opt))
  646.           TELOPT_UNANSWERED_WILL(opt) = 0;
  647.         if (cmd == DO && TELOPT_UNANSWERED_DONT(opt))
  648.           TELOPT_UNANSWERED_DONT(opt) = 0;
  649.         if (cmd == WILL && TELOPT_UNANSWERED_WONT(opt))
  650.           TELOPT_UNANSWERED_WONT(opt) = 0;
  651.     }
  652.     return(1);
  653. }
  654. /* Send a telnet sub-option */
  655. /* Returns 1 if command was sent, 0 if not, -1 on error */
  656. int
  657. tn_ssbopt(opt,sub,data,len) int opt, sub; CHAR * data; int len; {
  658.     CHAR buf[256];
  659.     int n,m;
  660.     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
  661.     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
  662.     if (!TELOPT_OK(opt)) return(-1);
  663.     if (len < 0 || len > 250) {
  664.         debug(F111,"Unable to Send TELNET SB - data too long","len",len);
  665.         return(-1);                     /* Data too long */
  666.     }
  667. #ifdef CK_SSL
  668.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  669.         if (ttchk() < 0)
  670.           return(-1);
  671.         else
  672.           return(1);
  673.     }
  674. #endif /* CK_SSL */
  675.     if (!data) len = 0;
  676.     buf[0] = (CHAR) IAC;
  677.     buf[1] = (CHAR) (SB & 0xff);
  678.     buf[2] = (CHAR) (opt & 0xff);
  679.     buf[3] = (CHAR) (sub & 0xff);
  680.     if (data && len > 0) {
  681.         memcpy(&buf[4],data,len);
  682.     }
  683.     buf[4+len] = (CHAR) IAC;
  684.     buf[5+len] = (CHAR) SE;
  685.     if (tn_deb || debses || deblog) {
  686.         if (opt == TELOPT_START_TLS && sub == 1)
  687.           sprintf(tn_msg,"TELNET SENT SB %s FOLLOWS IAC SE",
  688.                   TELOPT(opt)
  689.                   );
  690.         else if (opt == TELOPT_TTYPE && sub == 1)
  691.           sprintf(tn_msg,"TELNET SENT SB %s SEND IAC SE", TELOPT(opt));
  692.         else if (opt == TELOPT_TTYPE && sub == 0)
  693.           sprintf(tn_msg,"TELNET SENT SB %s IS %s IAC SE", TELOPT(opt),data);
  694.         else if (opt == TELOPT_NEWENVIRON) {
  695.             int i, quote;
  696.             sprintf(tn_msg,"TELNET SENT SB %s %s",
  697.                     TELOPT(TELOPT_NEWENVIRON),
  698.                     sub == TELQUAL_SEND ? "SEND" :
  699.                     sub == TELQUAL_IS ? "IS" :
  700.                     sub == TELQUAL_INFO ?"INFO" : "UNKNOWN" );
  701.             for (i = 0, quote = 0; i < len; i++) {
  702.                 if (quote) {
  703.                     sprintf(hexbuf,"%02x",data[i]);
  704.                     strcat(tn_msg,hexbuf);
  705.                     quote = 0;
  706.                 } else {
  707.                     switch (data[i]) {
  708.                       case TEL_ENV_USERVAR:
  709.                         strcat(tn_msg," USERVAR ");
  710.                         break;
  711.                       case TEL_ENV_VAR:
  712.                         strcat(tn_msg," VAR ");
  713.                         break;
  714.                       case TEL_ENV_VALUE:
  715.                         strcat(tn_msg," VALUE ");
  716.                         break;
  717.                       case TEL_ENV_ESC:
  718.                         strcat(tn_msg," ESC ");
  719.                         quote = 1;
  720.                         break;
  721.                       case IAC:
  722.                         strcat(tn_msg," IAC ");
  723.                         break;
  724.                       default:
  725.                         sprintf(hexbuf,"%c",data[i]);
  726.                         strcat(tn_msg,hexbuf);
  727.                     }
  728.                 }
  729.             }
  730.             strcat(tn_msg," IAC SE");
  731.         } else
  732.           sprintf(tn_msg,
  733.                   "TELNET SENT SB %s %02x <data> IAC SE",
  734.                   TELOPT(opt),
  735.                   sub
  736.                   );
  737.         debug(F101,tn_msg,"",opt);
  738.         if (tn_deb || debses) tn_debug(tn_msg);
  739.     }
  740.     if (ttol(buf,6+len) < 6+len)
  741.       return(-1);
  742.     return(1);
  743. }
  744. /*
  745.   tn_flui() -- Processes all waiting data for Telnet commands.
  746.   All non-Telnet data is to be stored into the Telnet Wait Buffer.
  747.   Returns 1 on success.
  748. */
  749. int
  750. tn_flui() {
  751.     extern int ckxech;
  752.     int x = 0;
  753.     /* Wait up to 5 sec for responses to outstanding telnet negotiations */
  754.     while (x >= 0 && ttchk() > 0  && tn_wait_idx < TN_WAIT_BUF_SZ) {
  755.         x = ttinc(1);
  756.         switch (x) {
  757.           case IAC:
  758.             x = tn_doop((CHAR)(x & 0xff),inserver?ckxech:duplex,ttinc);
  759.             debug(F101,"tn_flui tn_doop","",x);
  760.             switch (x) {
  761.               case 1:                   /* Turn on echoing */
  762.                 duplex = 1;
  763.                 if (inserver)
  764.                   ckxech = 1;
  765.                 break;
  766.               case 2:                   /* Turn off echoing */
  767.                 duplex = 0;
  768.                 if (inserver)
  769.                   ckxech = 0;
  770.                 break;
  771.               case 3:
  772.                 tn_wait_buf[tn_wait_idx++] = IAC;
  773.                 break;
  774.               case 4:                   /* IKS event */
  775.               case 6:                   /* Logout */
  776.                 break;
  777.             }
  778.             break;
  779.           default:
  780.             if (x >= 0)
  781.               tn_wait_buf[tn_wait_idx++] = x;
  782.         }
  783.     }
  784.     return(1);
  785. }
  786. #ifdef CK_FORWARD_X
  787. int
  788. #ifdef CK_ANSIC
  789. fwdx_tn_sb( unsigned char * sb, int n )
  790. #else
  791. fwdx_tn_sb( sb, n ) unsigned char * sb; int n;
  792. #endif /* CK_ANSIC */
  793. {
  794.     unsigned short hchannel, nchannel;
  795.     unsigned char * p;
  796.     int rc = -1;
  797.     /* as a security precaution should add a test here to check to make sure */
  798.     /* we have negotiated FORWARD_X with the peer.                           */
  799.     switch (sb[0]) {
  800.     case FWDX_SCREEN:
  801.         if (sstelnet && n == 4)
  802.             rc = fwdx_create_listen_socket(sb[1]);
  803.         break;
  804.     case FWDX_OPEN:
  805.         if ( !sstelnet && n == 5 ) {
  806.             p = (unsigned char *) &nchannel;
  807.             p[0] = sb[1];
  808.             p[1] = sb[2];
  809.             hchannel = ntohs(nchannel);
  810.             rc = fwdx_open_client_channel(hchannel);
  811.             if ( rc < 0 ) {
  812.                 /* Failed; Send CLOSE channel */
  813.                 fwdx_send_close(hchannel);
  814.             }
  815. #ifdef NT
  816.             if ( !TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started ) {
  817.                 ckThreadBegin( &fwdx_thread,32655, 0, FALSE, 0 ) ;
  818.                 TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 1;
  819.             }
  820. #endif /* NT */
  821.         }
  822.         break;
  823.     case FWDX_CLOSE:
  824.         p = (unsigned char *) &nchannel;
  825.         p[0] = sb[1];
  826.         p[1] = sb[2];
  827.         hchannel = ntohs(nchannel);
  828.         rc = fwdx_close_channel(hchannel);
  829.         break;
  830.     case FWDX_DATA:
  831.         p = (unsigned char *) &nchannel;
  832.         p[0] = sb[1];
  833.         p[1] = sb[2];
  834.         hchannel = ntohs(nchannel);
  835.         rc = fwdx_write_data_to_channel(hchannel,(char *)&sb[3],n-5);
  836.         break;
  837.     }
  838.     if ( rc < 0 ) {
  839.         if ( sstelnet ) {
  840.             if (tn_sopt(WONT,TELOPT_FORWARD_X) < 0)
  841.                 return(-1);
  842.             TELOPT_UNANSWERED_WONT(TELOPT_FORWARD_X) = 1;
  843.             return(-1);
  844.         } else {
  845.             if (tn_sopt(DONT,TELOPT_FORWARD_X) < 0)
  846.                 return(-1);
  847.             TELOPT_UNANSWERED_DONT(TELOPT_FORWARD_X) = 1;
  848.             return(-1);
  849.         }
  850.     }
  851.     return(0);
  852. }
  853. int
  854. fwdx_send_close(channel) int channel; {
  855.     int nchannel;
  856.     CHAR * p;
  857.     nchannel = htons(channel);
  858.     p = (unsigned char *) &nchannel;
  859.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  860.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  861.     sb[2] = TELOPT_FORWARD_X;           /* Forward X */
  862.     sb[3] = FWDX_CLOSE;                  /* Open */
  863.     sb[4] = p[0];
  864.     sb[5] = p[1];
  865.     sb[6] = (CHAR) IAC;                 /* End of Subnegotiation */
  866.     sb[7] = (CHAR) SE;                  /* marked by IAC SE */
  867.     if (ttol((CHAR *)sb,8) < 0) {       /* Send it. */
  868.         return(-1);
  869.     }
  870. #ifdef DEBUG
  871.     if (deblog || tn_deb || debses) {
  872.         sprintf(tn_msg,"TELNET SENT SB %s CLOSE %02x %02x IAC SE",
  873.         TELOPT(TELOPT_FORWARD_X),p[0],p[1]);
  874.         debug(F100,tn_msg,"",0);
  875.         if (tn_deb || debses) tn_debug(tn_msg);
  876.     }
  877. #endif /* DEBUG */
  878.     return(0);
  879. }
  880. int
  881. fwdx_send_open(channel) int channel; {
  882.     int nchannel;
  883.     CHAR * p;
  884.     nchannel = htons(channel);
  885.     p = (unsigned char *) &nchannel;
  886.     sb[0] = (CHAR) IAC;                 /* I Am a Command */
  887.     sb[1] = (CHAR) SB;                  /* Subnegotiation */
  888.     sb[2] = TELOPT_FORWARD_X;           /* Forward X */
  889.     sb[3] = FWDX_OPEN;                  /* Open */
  890.     sb[4] = p[0];
  891.     sb[5] = p[1];
  892.     sb[6] = (CHAR) IAC;                 /* End of Subnegotiation */
  893.     sb[7] = (CHAR) SE;                  /* marked by IAC SE */
  894.     if (ttol((CHAR *)sb,8) < 0) {       /* Send it. */
  895.         return(-1);
  896.     }
  897. #ifdef DEBUG
  898.     if (deblog || tn_deb || debses) {
  899.         sprintf(tn_msg,"TELNET SENT SB %s OPEN %02x %02x IAC SE",
  900.         TELOPT(TELOPT_FORWARD_X),p[0],p[1]);
  901.         debug(F100,tn_msg,"",0);
  902.         if (tn_deb || debses) tn_debug(tn_msg);
  903.     }
  904. #endif /* DEBUG */
  905.     return(0);
  906. }
  907. #endif /* CK_FORWARD_X */
  908. #ifdef IKS_OPTION
  909. /*
  910.   iks_wait() -- Wait for an IKS subnegotiation response.
  911.   sb - is either KERMIT_REQ_START or KERMIT_REQ_STOP depending on the desired
  912.        state of the peer's Kermit server.
  913.   flushok - specifies whether it is ok to throw away non-Telnet data
  914.        if so, then we call ttflui() instead of tn_flui().
  915.   Returns:
  916.    1 if the desired state is achieved or if it is unknown.
  917.    0 if the desired state is not achieved.
  918. */
  919. int
  920. #ifdef CK_ANSIC
  921. iks_wait(int sb, int flushok)
  922. #else /* CK_ANSIC */
  923. iks_wait(sb,flushok) int sb; int flushok;
  924. #endif /* CK_ANSIC */
  925. {
  926.     int tn_wait_save = tn_wait_flg;
  927.     int x;
  928.     if (TELOPT_U(TELOPT_KERMIT)) {
  929.         switch (sb) {
  930.           case KERMIT_REQ_START:
  931.             debug(F111,
  932.                   "iks_wait KERMIT_REQ_START",
  933.                   "u_start",
  934.                   TELOPT_SB(TELOPT_KERMIT).kermit.u_start
  935.                   );
  936.             tn_siks(KERMIT_REQ_START);
  937.             tn_wait_flg = 1;            /* Kermit Option MUST wait */
  938.             do {
  939.                 if (flushok)
  940.                   tn_wait_idx = 0;
  941.                 x = tn_wait("iks_wait() me_iks_req_start");
  942.             } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
  943.             tn_wait_flg = tn_wait_save;
  944.             if (flushok)
  945.               tn_wait_idx = 0;
  946.     if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  947. /*
  948.  * We are attempting to start a kermit server on the peer
  949.  * the most likely reason is because we want to perform a
  950.  * file transfer.  But there is a huge amount of non telnet
  951.  * negotiation data coming in and so we have not been able
  952.  * to find the response.  So we will lie and assume that
  953.  * response is 'yes'.  The worse that will happen is that
  954.  * a RESP_STOP is received after we enter protocol mode.
  955.  * And the protocol operation will be canceled.
  956.  */
  957. tn_push();
  958. return(1);
  959.     } else {
  960. tn_push();
  961. return(TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
  962.     }
  963.           case KERMIT_REQ_STOP:
  964.             debug(F111,
  965.                   "iks_wait KERMIT_REQ_STOP",
  966.                   "u_start",
  967.                   TELOPT_SB(TELOPT_KERMIT).kermit.u_start
  968.                   );
  969.             tn_siks(KERMIT_REQ_STOP);
  970.             tn_wait_flg = 1;            /* Kermit Option MUST wait */
  971.             do {
  972.                 if (flushok)
  973.                   tn_wait_idx = 0;
  974.                 x = tn_wait("iks_wait() me_iks_req_stop");
  975.             } while (x == 0 && flushok && tn_wait_idx == TN_WAIT_BUF_SZ);
  976.             tn_wait_flg = tn_wait_save;
  977.             if (flushok)
  978.               tn_wait_idx = 0;
  979.     if (tn_wait_idx == TN_WAIT_BUF_SZ) {
  980. /*
  981.  * We are attempting to stop a kermit server on the peer
  982.  * the most likely reason being that we want to enter
  983.  * CONNECT mode.  But there is a huge amount of non telnet
  984.  * negotiation data coming in and so we have not been able
  985.  * to find the response.  So we will lie and assume that
  986.  * the answer is 'yes' and allow the CONNECT command to
  987.  * succeed.  The worst that happens is that CONNECT mode
  988.  * swallows the incoming data displaying it to the user
  989.  * and then it resumes Kermit client mode.
  990.  */
  991. tn_push();
  992. return(1);
  993.     } else {
  994. tn_push();
  995. return(!TELOPT_SB(TELOPT_KERMIT).kermit.u_start);
  996.     }
  997.         }
  998.         tn_push();
  999.     }
  1000.     return(1);
  1001. }
  1002. int
  1003. #ifdef CK_ANSIC
  1004. iks_tn_sb( char * sb, int n )
  1005. #else
  1006. iks_tn_sb( sb, n ) char * sb; int n;
  1007. #endif /* CK_ANSIC */
  1008. {
  1009. #ifndef NOXFER
  1010.     extern int server;
  1011. #ifdef NOICP
  1012.     extern int autodl;
  1013.     int inautodl = 0, cmdadl = 1;
  1014.     extern int local;
  1015. #else
  1016. #ifdef CK_AUTODL
  1017.     extern int autodl, inautodl, cmdadl;
  1018.     extern int local;
  1019. #endif /* CK_AUTODL */
  1020. #endif /* NOICP */
  1021.     switch (sb[0]) {
  1022.       case KERMIT_START:                /* START */
  1023.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
  1024.         return(4);
  1025.       case KERMIT_STOP:                 /* STOP */
  1026.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1027.         return(4);
  1028.       case KERMIT_REQ_START:            /* REQ-START */
  1029.         if (inserver) {
  1030. #ifdef CK_AUTODL
  1031.             cmdadl = 1;                 /* Turn on packet detection */
  1032. #endif /* CK_AUTODL */
  1033.             TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
  1034.             tn_siks(KERMIT_RESP_START);
  1035.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
  1036.             tn_siks(KERMIT_RESP_START);
  1037.         } else {
  1038. #ifdef CK_AUTODL
  1039.             if ((local && what == W_CONNECT && autodl) ||
  1040.                 (local && what != W_CONNECT && inautodl)
  1041.                 )
  1042.               tn_siks(KERMIT_RESP_START); /* STOP */
  1043.             else
  1044. #endif /* CK_AUTODL */
  1045.               tn_siks(KERMIT_RESP_STOP);
  1046.         }
  1047.         return(4);
  1048.       case KERMIT_REQ_STOP:             /* REQ-STOP */
  1049.         /* The protocol requires that the request be responded to */
  1050.         /* either by changing states or by reporting the current  */
  1051.         /* state.  */
  1052.         /* We need to provide the user some way of dictating what */
  1053.         /* the policies should be.  For instance, if we are in    */
  1054.         /* CONNECT mode with autodownload ON and we get a REQ-STOP*/
  1055.         /* what should the proper response be?                    */
  1056.         if (inserver
  1057. #ifdef CK_AUTODL
  1058.             || !local && cmdadl
  1059. #endif /* CK_AUTODL */
  1060.             ) {
  1061. #ifdef CK_AUTODL
  1062.             cmdadl = 0;                 /* Turn off packet detection */
  1063. #endif /* CK_AUTODL */
  1064.             tn_siks(KERMIT_RESP_STOP);
  1065.         } else if (server) {
  1066.             extern int en_fin;
  1067.             if (en_fin) {               /* If the server is allowed to stop */
  1068.                 tn_siks(KERMIT_RESP_STOP);
  1069.             } else {                    /* We are not allowed to stop */
  1070.                 tn_siks(KERMIT_RESP_START);
  1071.             }
  1072. #ifdef CK_AUTODL
  1073.         } else if ((local && what == W_CONNECT && autodl) ||
  1074.                    (local && what != W_CONNECT && inautodl)
  1075.                    ) {
  1076.             /* If we are a pseudo-server and the other side requests */
  1077.             /* that we stop, tell then that we have even though we   */
  1078.             /* have not.  Otherwise, the other side might refuse to  */
  1079.             /* enter SERVER mode.                                    */
  1080.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  1081. #endif /* CK_AUTODL */
  1082.         } else {
  1083.             /* If we are not currently in any mode that accepts */
  1084.             /* Kermit packets then of course report that we are */
  1085.             /* not being a Kermit server.                       */
  1086.             tn_siks(KERMIT_RESP_STOP);  /* STOP */
  1087.         }
  1088.         return(4);
  1089.       case KERMIT_SOP: {                /* SOP */
  1090.           extern CHAR stchr;            /* Incoming SOP character */
  1091.           stchr = sb[1];
  1092.           TELOPT_SB(TELOPT_KERMIT).kermit.sop = 1;
  1093.           return(4);
  1094.       }
  1095.       case KERMIT_RESP_START:           /* START */
  1096.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 1;
  1097.         if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
  1098.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1099.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
  1100.             /* If we have issued a request to stop a Kermit Server */
  1101.             /* and the response is Start, then we must report this */
  1102.             /* to the caller.                                      */
  1103.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1104.         }
  1105.         return(4);
  1106.       case KERMIT_RESP_STOP:            /* STOP */
  1107.         TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1108.         if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start) {
  1109.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1110.             /* If we have issued a request to start a Kermit Server */
  1111.             /* and the response is Stop, then we must report this   */
  1112.             /* to the caller.                                       */
  1113.         } else if (TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop) {
  1114.             TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1115.         }
  1116.         return(4);
  1117.       default:
  1118.         return(0);
  1119.     } /* switch (sb[0]) */
  1120. #else
  1121.     return(0);
  1122. #endif /* NOXFER */
  1123. }
  1124. #endif /* IKS_OPTION */
  1125. /* Initialize telnet settings - set default values for ME and U modes */
  1126. int
  1127. tn_set_modes() {
  1128.     int opt,cmd;
  1129.     /* initialize all options to refuse in both directions */
  1130.     for (opt = 0; opt < NTELOPTS; opt++) {
  1131.         TELOPT_ME(opt) = 0;
  1132.         TELOPT_U(opt)  = 0;
  1133.         TELOPT_UNANSWERED_WILL(opt) = 0;
  1134.         TELOPT_UNANSWERED_DO(opt)   = 0;
  1135.         TELOPT_UNANSWERED_WONT(opt) = 0;
  1136.         TELOPT_UNANSWERED_DONT(opt)   = 0;
  1137.         TELOPT_UNANSWERED_SB(opt)   = 0;
  1138.         TELOPT_ME_MODE(opt) = TN_NG_RF;
  1139.         TELOPT_U_MODE(opt) = TN_NG_RF;
  1140.         TELOPT_DEF_S_ME_MODE(opt) = TN_NG_RF;
  1141.         TELOPT_DEF_S_U_MODE(opt) = TN_NG_RF;
  1142.         TELOPT_DEF_C_ME_MODE(opt) = TN_NG_RF;
  1143.         TELOPT_DEF_C_U_MODE(opt) = TN_NG_RF;
  1144.         for (cmd = 0; cmd < 4; cmd ++)
  1145.           tncnts[TELOPT_INDEX(opt)][cmd] = 0;
  1146.     }
  1147. #ifdef IKS_OPTION
  1148.     TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  1149.     TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1150.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1151.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1152.     TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
  1153. #endif /* IKS_OPTION */
  1154. #ifdef CK_ENCRYPTION
  1155.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1156. #endif /* CK_ENCRYPTION */
  1157. #ifdef  CK_NAWS
  1158.     TELOPT_SB(TELOPT_NAWS).naws.x = 0;
  1159.     TELOPT_SB(TELOPT_NAWS).naws.y = 0;
  1160. #endif /* CK_NAWS */
  1161. #ifdef CK_SSL
  1162.     TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
  1163.     TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
  1164. #endif /* CK_SSL */
  1165.     /* Now set the ones we want to accept to the proper values */
  1166.     TELOPT_DEF_S_ME_MODE(TELOPT_SGA) = TN_NG_RQ;
  1167.     TELOPT_DEF_S_U_MODE(TELOPT_SGA) = TN_NG_RQ;
  1168.     TELOPT_DEF_C_ME_MODE(TELOPT_SGA) = TN_NG_AC;
  1169.     TELOPT_DEF_C_U_MODE(TELOPT_SGA) = TN_NG_AC;
  1170.     TELOPT_DEF_S_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
  1171.     TELOPT_DEF_S_U_MODE(TELOPT_BINARY) = TN_NG_AC;
  1172.     TELOPT_DEF_C_ME_MODE(TELOPT_BINARY) = TN_NG_AC;
  1173.     TELOPT_DEF_C_U_MODE(TELOPT_BINARY) = TN_NG_AC;
  1174.     TELOPT_DEF_S_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1175.     TELOPT_DEF_S_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1176.     TELOPT_DEF_C_ME_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1177.     TELOPT_DEF_C_U_MODE(TELOPT_LOGOUT) = TN_NG_AC;
  1178. #ifdef IKS_OPTION
  1179.     TELOPT_DEF_S_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1180.     TELOPT_DEF_S_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1181.     TELOPT_DEF_C_ME_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1182.     TELOPT_DEF_C_U_MODE(TELOPT_KERMIT) = TN_NG_RQ;
  1183. #endif /* IKS_OPTION */
  1184. #ifdef CK_ENCRYPTION
  1185.     TELOPT_DEF_S_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1186.     TELOPT_DEF_S_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1187.     TELOPT_DEF_C_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1188.     TELOPT_DEF_C_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RQ;
  1189. #endif /* CK_ENCRYPTION */
  1190.     TELOPT_DEF_S_ME_MODE(TELOPT_ECHO) = TN_NG_RQ;
  1191.     TELOPT_DEF_S_U_MODE(TELOPT_TTYPE) = TN_NG_RQ;
  1192. #ifdef CK_ENVIRONMENT
  1193.     TELOPT_DEF_S_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
  1194. #endif /* CK_ENVIRONMENT */
  1195. #ifdef CK_AUTHENTICATION
  1196.     TELOPT_DEF_S_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  1197. #endif /* CK_AUTHENTICATION */
  1198. #ifdef CK_SSL
  1199.     if (ck_ssleay_is_installed()) {
  1200.         TELOPT_DEF_S_U_MODE(TELOPT_START_TLS) = TN_NG_RQ;
  1201.         TELOPT_DEF_C_ME_MODE(TELOPT_START_TLS) = TN_NG_AC;
  1202.     }
  1203. #endif /* CK_SSL */
  1204. #ifdef CK_NAWS
  1205.     TELOPT_DEF_S_U_MODE(TELOPT_NAWS) = TN_NG_RQ;
  1206. #endif /* CK_NAWS */
  1207.     TELOPT_DEF_C_U_MODE(TELOPT_ECHO) = TN_NG_AC;
  1208.     TELOPT_DEF_C_ME_MODE(TELOPT_TTYPE) = TN_NG_RQ;
  1209. #ifdef CK_ENVIRONMENT
  1210.     TELOPT_DEF_C_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RQ;
  1211. #endif /* CK_ENVIRONMENT */
  1212. #ifdef CK_AUTHENTICATION
  1213.     TELOPT_DEF_C_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RQ;
  1214. #endif /* CK_AUTHENTICATION */
  1215. #ifdef CK_NAWS
  1216.     TELOPT_DEF_C_ME_MODE(TELOPT_NAWS) = TN_NG_RQ;
  1217. #endif /* CK_NAWS */
  1218. #ifdef CK_SNDLOC
  1219.     TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RQ;
  1220. #endif /* CK_SNDLOC */
  1221. #ifdef CK_FORWARD_X
  1222.     TELOPT_DEF_C_U_MODE(TELOPT_FORWARD_X) = TN_NG_RQ;
  1223. #endif /* CK_FORWARD_X */
  1224.     /* Set the initial values for currently known mode */
  1225.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  1226.         if (TELOPT_OK(opt)) {
  1227.             TELOPT_ME_MODE(opt) = sstelnet ?
  1228.               TELOPT_DEF_S_ME_MODE(opt) :
  1229.                 TELOPT_DEF_C_ME_MODE(opt);
  1230.             TELOPT_U_MODE(opt) = sstelnet ?
  1231.               TELOPT_DEF_S_U_MODE(opt) :
  1232.                 TELOPT_DEF_C_U_MODE(opt);
  1233.         }
  1234.     }
  1235.     return(1);
  1236. }
  1237. /* Send Delayed Subnegotiations */
  1238. VOID
  1239. tn_sdsb() {
  1240.     if (TELOPT_SB(TELOPT_TTYPE).term.need_to_send) {
  1241.         tn_sttyp();
  1242.         TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
  1243.     }
  1244. #ifdef CK_ENVIRONMENT
  1245.     if (TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send &&
  1246.         TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  1247.         tn_snenv((CHAR *)TELOPT_SB(TELOPT_NEWENVIRON).env.str,
  1248.                  TELOPT_SB(TELOPT_NEWENVIRON).env.len);
  1249.         free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
  1250.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  1251.         TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
  1252.         TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
  1253.     }
  1254. #ifdef CK_XDISPLOC
  1255.     if (TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send) {
  1256.         tn_sxdisploc();
  1257.         TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
  1258.     }
  1259. #endif /* CK_XDISPLOC */
  1260. #endif /* CK_ENVIRONMENT */
  1261. #ifdef CK_NAWS
  1262.     if (TELOPT_SB(TELOPT_NAWS).naws.need_to_send) {
  1263.         tn_snaws();
  1264.         TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
  1265.     }
  1266. #endif /* CK_NAWS */
  1267. #ifdef CK_SNDLOC
  1268.     if (TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send) {
  1269.         tn_sndloc();
  1270.         TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
  1271.     }
  1272. #endif /* CK_SNDLOC */
  1273. #ifdef CK_FORWARD_X
  1274.     if (TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send) {
  1275.         tn_sndfwdx();
  1276.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
  1277.     }
  1278. #endif /* CK_FORWARD_X */
  1279. }
  1280. int
  1281. tn_reset() {
  1282.     int x,opt,cmd;
  1283.     tn_wait_idx = 0;                    /* Clear the tn_push() buffer */
  1284.     tn_wait_tmo = TN_TIMEOUT;           /* Reset wait timer stats */
  1285.     nflag = 0;
  1286.     /* Reset the TELNET OPTIONS counts */
  1287.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  1288.         if (TELOPT_OK(opt)) {
  1289.             TELOPT_ME(opt) = 0;
  1290.             TELOPT_U(opt)  = 0;
  1291.             TELOPT_UNANSWERED_WILL(opt) = 0;
  1292.             TELOPT_UNANSWERED_DO(opt)   = 0;
  1293.             TELOPT_UNANSWERED_WONT(opt) = 0;
  1294.             TELOPT_UNANSWERED_DONT(opt)   = 0;
  1295.             TELOPT_UNANSWERED_SB(opt)   = 0;
  1296.             TELOPT_ME_MODE(opt) = sstelnet ?
  1297.               TELOPT_DEF_S_ME_MODE(opt) :
  1298.                 TELOPT_DEF_C_ME_MODE(opt);
  1299.             TELOPT_U_MODE(opt) = sstelnet ?
  1300.               TELOPT_DEF_S_U_MODE(opt) :
  1301.                 TELOPT_DEF_C_U_MODE(opt);
  1302. #ifdef DEBUG
  1303.             if (deblog) {
  1304.                 switch (TELOPT_ME_MODE(opt)) {
  1305.                   case TN_NG_RF:
  1306.                     debug(F110,"tn_ini ME REFUSE ",TELOPT(opt),0);
  1307.                     break;
  1308.                   case TN_NG_AC:
  1309.                     debug(F110,"tn_ini ME ACCEPT ",TELOPT(opt),0);
  1310.                     break;
  1311.                   case TN_NG_RQ:
  1312.                     debug(F110,"tn_ini ME REQUEST",TELOPT(opt),0);
  1313.                     break;
  1314.                   case TN_NG_MU:
  1315.                     debug(F110,"tn_ini ME REQUIRE",TELOPT(opt),0);
  1316.                     break;
  1317.                 }
  1318.                 switch (TELOPT_U_MODE(opt)) {
  1319.                   case TN_NG_RF:
  1320.                     debug(F110,"tn_ini U  REFUSE ",TELOPT(opt),0);
  1321.                     break;
  1322.                   case TN_NG_AC:
  1323.                     debug(F110,"tn_ini U  ACCEPT ",TELOPT(opt),0);
  1324.                     break;
  1325.                   case TN_NG_RQ:
  1326.                     debug(F110,"tn_ini U  REQUEST",TELOPT(opt),0);
  1327.                     break;
  1328.                   case TN_NG_MU:
  1329.                     debug(F110,"tn_ini U  REQUIRE",TELOPT(opt),0);
  1330.                     break;
  1331.                 }
  1332.             }
  1333. #endif /* DEBUG */
  1334.             for (cmd = 0; cmd < 4; cmd ++)
  1335.               tncnts[TELOPT_INDEX(opt)][cmd] = 0;
  1336.         }
  1337.     }
  1338. #ifdef CK_ENVIRONMENT
  1339.     if (!tn_env_flg) {
  1340.         TELOPT_ME_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
  1341.         TELOPT_U_MODE(TELOPT_NEWENVIRON) = TN_NG_RF;
  1342.     }
  1343. #endif /* CK_ENVIRONMENT */
  1344. #ifdef CK_SNDLOC
  1345.     if (!tn_loc)
  1346.         TELOPT_DEF_C_ME_MODE(TELOPT_SNDLOC) = TN_NG_RF;
  1347. #endif /* CK_SNDLOC */
  1348. #ifdef IKS_OPTION
  1349.     TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  1350.     TELOPT_SB(TELOPT_KERMIT).kermit.u_start = 0;
  1351.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 0;
  1352.     TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 0;
  1353.     TELOPT_SB(TELOPT_KERMIT).kermit.sop = 0;
  1354. #endif /* IKS_OPTION */
  1355. #ifdef CK_ENCRYPTION
  1356.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1357.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.need_to_send = 0;
  1358. #endif /* CK_ENCRYPTION */
  1359. #ifdef  CK_NAWS
  1360.     TELOPT_SB(TELOPT_NAWS).naws.need_to_send = 0;
  1361.     TELOPT_SB(TELOPT_NAWS).naws.x = 0;
  1362.     TELOPT_SB(TELOPT_NAWS).naws.y = 0;
  1363. #endif /* CK_NAWS */
  1364.     TELOPT_SB(TELOPT_TTYPE).term.need_to_send = 0;
  1365.     TELOPT_SB(TELOPT_TTYPE).term.type[0] = '';
  1366. #ifdef CK_ENVIRONMENT
  1367.     TELOPT_SB(TELOPT_NEWENVIRON).env.need_to_send = 0;
  1368.     if (tn_first)
  1369.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  1370.     else if (TELOPT_SB(TELOPT_NEWENVIRON).env.str) {
  1371.         free(TELOPT_SB(TELOPT_NEWENVIRON).env.str);
  1372.         TELOPT_SB(TELOPT_NEWENVIRON).env.str=NULL;
  1373.     }
  1374.     TELOPT_SB(TELOPT_NEWENVIRON).env.len=0;
  1375. #ifdef CK_XDISPLOC
  1376.     TELOPT_SB(TELOPT_XDISPLOC).xdisp.need_to_send = 0;
  1377. #endif /* CK_XDISPLOC */
  1378. #endif /* CK_ENVIRONMENT */
  1379. #ifdef CK_SNDLOC
  1380.     TELOPT_SB(TELOPT_SNDLOC).sndloc.need_to_send = 0;
  1381. #endif /* CK_SNDLOC */
  1382. #ifdef CK_FORWARD_X
  1383.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.need_to_send = 0;
  1384.     if ( TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket != -1 ) {
  1385.     }
  1386.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.listen_socket = -1;
  1387.     for ( x=0 ; x<MAXFWDX ; x++ ) {
  1388.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].fd = -1;
  1389.         TELOPT_SB(TELOPT_FORWARD_X).forward_x.channel[x].id = -1;
  1390.     }
  1391. #ifdef NT
  1392.     TELOPT_SB(TELOPT_FORWARD_X).forward_x.thread_started = 0;
  1393. #endif /* NT */
  1394. #endif /* CK_FORWARD_X */
  1395. #ifdef CK_SSL
  1396.     if (tls_only_flag || ssl_only_flag) {
  1397.         TELOPT_ME_MODE(TELOPT_START_TLS) = TN_NG_RF;
  1398.         TELOPT_U_MODE(TELOPT_START_TLS) = TN_NG_RF;
  1399.     }
  1400.     TELOPT_SB(TELOPT_START_TLS).start_tls.u_follows = 0;
  1401.     TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows = 0;
  1402. #endif /* CK_SSL */
  1403. #ifdef CK_ENCRYPTION
  1404.     if (!ck_crypt_is_installed()
  1405. #ifdef CK_SSL
  1406.         || tls_only_flag || ssl_only_flag
  1407. #endif /* CK_SSL */
  1408.         ) {
  1409.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1410.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1411.     }
  1412. #endif /* CK_ENCRYPTION */
  1413.     tn_first = 0;                       /* No longer the first time init */
  1414. #ifdef OS2
  1415.     ttnum = -1;                         /* Reset TermType negotiation */
  1416.     ttnumend = 0;
  1417. #endif /* OS2 */
  1418.     return(0);
  1419. }
  1420. /* Start a telnet connection. */
  1421. /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
  1422. int
  1423. tn_ini() {
  1424.     int wait, x, opt;
  1425.     debug(F101,"tn_ini ttnproto","",ttnproto);
  1426.     debug(F101,"tn_ini tn_init","",tn_init);
  1427.     if (ttnet != NET_TCPB)              /* Make sure connection is TCP/IP */
  1428.       return(0);
  1429.     if (tn_init)                        /* Have we done this already? */
  1430.       return(0);                        /* Don't do it again. */
  1431.     tn_reset();                         /* Reset telnet parameters */
  1432.     if (ttnproto == NP_RLOGIN) {        /* Reset flags even when RLOGIN */
  1433.         tn_init = 1;
  1434.         return(0);
  1435.     } else if (ttnproto == NP_NONE) {   /* If not talking to a telnet port, */
  1436.         ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
  1437.         tn_init = 1;                    /* but don't send initial options. */
  1438.         debug(F100,"tn_ini skipping telnet negotiations","",0);
  1439.         return(0);
  1440.     } else if (ttnproto == NP_TCPRAW) { /* Raw socket requested. */
  1441.         return(0);
  1442.     } else if (ttnproto == NP_KERMIT) {
  1443.         /* switching to Telnet protocol */
  1444.         debug(F100,"tn_start switching from Kermit to Telnet","",0);
  1445.         ttnproto = NP_TELNET;
  1446.     }
  1447.     debug(F111,"tn_start","sstelnet",sstelnet);
  1448.     wait = 0;
  1449. #ifdef CK_SSL
  1450.     if (!TELOPT_ME(TELOPT_START_TLS) &&
  1451.         TELOPT_ME_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
  1452.         if (tn_sopt(WILL, TELOPT_START_TLS) < 0)
  1453.           return(-1);
  1454.         TELOPT_UNANSWERED_WILL(TELOPT_START_TLS) = 1;
  1455.         wait = 1;
  1456.     }
  1457.     if (!TELOPT_U(TELOPT_START_TLS) &&
  1458.         TELOPT_U_MODE(TELOPT_START_TLS) >= TN_NG_RQ) {
  1459.         if (tn_sopt(DO, TELOPT_START_TLS) < 0)
  1460.           return(-1);
  1461.         TELOPT_UNANSWERED_DO(TELOPT_START_TLS) = 1;
  1462.         wait = 1;
  1463.     }
  1464. #ifdef COMMENT
  1465. /*
  1466.   We can put off waiting for this until after we have requested AUTH.  The
  1467.   next draft will specify how the WILL side is to decide between these
  1468.   conflicting options.
  1469. */
  1470.     if (wait) {
  1471.         if (tn_wait("start_tls") < 0) {
  1472.             tn_push();
  1473.             return(-1);
  1474.         }
  1475.         wait = 0;
  1476.     }
  1477. #endif /* COMMENT */
  1478. #endif /* CK_SSL */
  1479. #ifdef CK_AUTHENTICATION
  1480.     if (tn_init)                /* tn_ini() might be called recursively */
  1481.       return(0);
  1482.     if (!TELOPT_ME(TELOPT_AUTHENTICATION) &&
  1483.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
  1484.         if (tn_sopt(WILL, TELOPT_AUTHENTICATION) < 0)
  1485.           return(-1);
  1486.         TELOPT_UNANSWERED_WILL(TELOPT_AUTHENTICATION) = 1;
  1487.         wait = 1;
  1488.     }
  1489.     if (!TELOPT_U(TELOPT_AUTHENTICATION) &&
  1490.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) >= TN_NG_RQ) {
  1491.         if (tn_sopt(DO, TELOPT_AUTHENTICATION) < 0)
  1492.           return(-1);
  1493.         TELOPT_UNANSWERED_DO(TELOPT_AUTHENTICATION) = 1;
  1494.         wait = 1;
  1495.     }
  1496. #ifdef CK_ENCRYPTION
  1497.     if (TELOPT_U_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF &&
  1498.          TELOPT_ME_MODE(TELOPT_AUTHENTICATION) == TN_NG_RF) {
  1499.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1500.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  1501.     }
  1502. #endif /* CK_ENCRYPTION */
  1503. #endif /* CK_AUTHENTICATION */
  1504. #ifdef CK_NAWS
  1505.     if (!sstelnet) {
  1506.         /* Console terminal screen rows and columns */
  1507. #ifdef OS2
  1508.         debug(F101,
  1509.               "tn_ini tt_rows 1",
  1510.               "",
  1511.               VscrnGetHeight(VTERM)-(tt_status?1:0)
  1512.               );
  1513.         debug(F101,"tn_ini tt_cols 1","",VscrnGetWidth(VTERM));
  1514.         /* Not known yet */
  1515.         if (VscrnGetWidth(VTERM) < 0 ||
  1516.             VscrnGetHeight(VTERM)-(tt_status?1:0) < 0) {
  1517.             ttgwsiz();                  /* Try to find out */
  1518.         }
  1519.         debug(F101,
  1520.               "tn_ini tt_rows 2",
  1521.               "",
  1522.               VscrnGetHeight(VTERM)-(tt_status?1:0)
  1523.               );
  1524.         debug(F101,"tn_ini tt_cols 2","",VscrnGetWidth(VTERM));
  1525.         /* Now do we know? */
  1526.         if (VscrnGetWidth(VTERM) > 0 &&
  1527.             VscrnGetHeight(VTERM)-(tt_status?1:0) > 0) {
  1528.             if (!TELOPT_ME(TELOPT_NAWS) &&
  1529.                 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  1530.                 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
  1531.                   return(-1);
  1532.                 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
  1533.                 wait = 1;
  1534.             }
  1535.         }
  1536. #else /* OS2 */
  1537.         debug(F101,"tn_ini tt_rows 1","",tt_rows);
  1538.         debug(F101,"tn_ini tt_cols 1","",tt_cols);
  1539.         if (tt_rows < 0 || tt_cols < 0) { /* Not known yet */
  1540.             ttgwsiz();                  /* Try to find out */
  1541.         }
  1542.         debug(F101,"tn_ini tt_rows 2","",tt_rows);
  1543.         debug(F101,"tn_ini tt_cols 2","",tt_cols);
  1544.         if (tt_rows > 0 && tt_cols > 0) { /* Now do we know? */
  1545.             if (!TELOPT_ME(TELOPT_NAWS) &&
  1546.                 TELOPT_ME_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  1547.                 if (tn_sopt(WILL, TELOPT_NAWS) < 0)
  1548.                   return(-1);
  1549.                 TELOPT_UNANSWERED_WILL(TELOPT_NAWS) = 1;
  1550.                 wait = 1;
  1551.             }
  1552.         }
  1553. #endif /* OS2 */
  1554.     } else {
  1555.         if (!TELOPT_U(TELOPT_NAWS) &&
  1556.             TELOPT_U_MODE(TELOPT_NAWS) >= TN_NG_RQ) {
  1557.             if (tn_sopt(DO, TELOPT_NAWS) < 0)
  1558.               return(-1);
  1559.             TELOPT_UNANSWERED_DO(TELOPT_NAWS) = 1;
  1560.             wait = 1;
  1561.         }
  1562.     }
  1563. #endif /* CK_NAWS */
  1564.     if (!TELOPT_ME(TELOPT_SGA) &&
  1565.         TELOPT_ME_MODE(TELOPT_SGA) >= TN_NG_RQ) {
  1566.         if (tn_sopt(WILL, TELOPT_SGA) < 0)
  1567.           return(-1);
  1568.         TELOPT_UNANSWERED_WILL(TELOPT_SGA) = 1;
  1569.         wait = 1;
  1570.     }
  1571.     if (!TELOPT_U(TELOPT_SGA) &&
  1572.         TELOPT_U_MODE(TELOPT_SGA) >= TN_NG_RQ) {
  1573.         if (tn_sopt(DO, TELOPT_SGA) < 0)
  1574.           return(-1);
  1575.         TELOPT_UNANSWERED_DO(TELOPT_SGA) = 1;
  1576.         wait = 1;
  1577.     }
  1578.     if (!tn_duplex) {
  1579.         if (!TELOPT_U(TELOPT_ECHO) &&
  1580.             TELOPT_U_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
  1581.             if (tn_sopt(DO, TELOPT_ECHO) < 0)
  1582.               return(-1);
  1583.             TELOPT_UNANSWERED_DO(TELOPT_ECHO) = 1;
  1584.             wait = 1;
  1585.         }
  1586.     }
  1587.     if (!TELOPT_ME(TELOPT_ECHO) &&
  1588.         TELOPT_ME_MODE(TELOPT_ECHO) >= TN_NG_RQ) {
  1589.         if (tn_sopt(WILL, TELOPT_ECHO) < 0)
  1590.           return(-1);
  1591.         TELOPT_UNANSWERED_WILL(TELOPT_ECHO) = 1;
  1592.         wait = 1;
  1593.     }
  1594.     debug(F100,"tn_ini about to send WILL TTYPE if requested","",0);
  1595. /*
  1596.   Talking to TELNET port, so send WILL TERMINAL TYPE and DO SGA.
  1597.   Also send WILL NAWS if we know our screen dimensions.
  1598. */
  1599.     if (!TELOPT_ME(TELOPT_TTYPE) &&
  1600.         TELOPT_ME_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
  1601.         if ((x = tn_sopt(WILL,TELOPT_TTYPE)) < 0) {
  1602.             debug(F101,"tn_ini tn_sopt WILL TTYPE failed","",x);
  1603.             return(-1);
  1604.         }
  1605.         TELOPT_UNANSWERED_WILL(TELOPT_TTYPE) = 1;
  1606.         wait = 1;
  1607.         debug(F100,"tn_ini sent WILL TTYPE ok","",0);
  1608.     }
  1609.     if (!TELOPT_U(TELOPT_TTYPE) &&
  1610.         TELOPT_U_MODE(TELOPT_TTYPE) >= TN_NG_RQ) {
  1611.         if ((x = tn_sopt(DO,TELOPT_TTYPE)) < 0) {
  1612.             debug(F101,"tn_ini tn_sopt DO TTYPE failed","",x);
  1613.             return(-1);
  1614.         }
  1615.         TELOPT_UNANSWERED_DO(TELOPT_TTYPE) = 1;
  1616.         wait = 1;
  1617.         debug(F100,"tn_ini sent DO TTYPE ok","",0);
  1618.     }
  1619.     if (!TELOPT_ME(TELOPT_BINARY) &&
  1620.         TELOPT_ME_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
  1621.         if (tn_sopt(WILL, TELOPT_BINARY) < 0)
  1622.           return(-1);
  1623.         TELOPT_UNANSWERED_WILL(TELOPT_BINARY) = 1;
  1624.         wait = 1;
  1625.     }
  1626.     if (!TELOPT_U(TELOPT_BINARY) &&
  1627.         TELOPT_U_MODE(TELOPT_BINARY) >= TN_NG_RQ) {
  1628.         if (tn_sopt(DO, TELOPT_BINARY) < 0)
  1629.           return(-1);
  1630.         TELOPT_UNANSWERED_DO(TELOPT_BINARY) = 1;
  1631.         wait = 1;
  1632.     }
  1633. #ifdef CK_SNDLOC
  1634.     if (tn_loc) {
  1635.         if (!TELOPT_ME(TELOPT_SNDLOC) &&
  1636.             TELOPT_ME_MODE(TELOPT_SNDLOC) >= TN_NG_RQ) {
  1637.             if (tn_sopt(WILL, TELOPT_SNDLOC) < 0)
  1638.               return(-1);
  1639.             TELOPT_UNANSWERED_WILL(TELOPT_SNDLOC) = 1;
  1640.             wait = 1;
  1641.         }
  1642.     }
  1643. #endif /* CK_SNDLOC */
  1644. #ifdef CK_ENVIRONMENT
  1645. #ifdef CK_XDISPLOC
  1646.     if (!TELOPT_ME(TELOPT_XDISPLOC) &&
  1647.          TELOPT_ME_MODE(TELOPT_XDISPLOC) >= TN_NG_RQ) {
  1648.         if (tn_sopt(WILL, TELOPT_XDISPLOC) < 0)
  1649.             return(-1);
  1650.         TELOPT_UNANSWERED_WILL(TELOPT_XDISPLOC) = 1;
  1651.         wait = 1;
  1652.     }
  1653. #endif /* CK_XDISPLOC */
  1654.     /* Will send terminal environment. */
  1655.     if (!TELOPT_ME(TELOPT_NEWENVIRON) &&
  1656.         TELOPT_ME_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
  1657.         if (tn_sopt(WILL, TELOPT_NEWENVIRON) < 0)
  1658.           return(-1);
  1659.         TELOPT_UNANSWERED_WILL(TELOPT_NEWENVIRON) = 1;
  1660.         wait = 1;
  1661.     }
  1662.     if (!TELOPT_U(TELOPT_NEWENVIRON) &&
  1663.         TELOPT_U_MODE(TELOPT_NEWENVIRON) >= TN_NG_RQ) {
  1664.         if (tn_sopt(DO, TELOPT_NEWENVIRON) < 0)
  1665.           return(-1);
  1666.         TELOPT_UNANSWERED_DO(TELOPT_NEWENVIRON) = 1;
  1667.         wait = 1;
  1668.     }
  1669. #endif /* CK_ENVIRONMENT */
  1670.     /* Take care of any other telnet options that require handling. */
  1671.     for (opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
  1672.         switch (opt) {
  1673.           case TELOPT_AUTHENTICATION:
  1674.           case TELOPT_ENCRYPTION:
  1675.           case TELOPT_TTYPE:
  1676.           case TELOPT_NAWS:
  1677.           case TELOPT_BINARY:
  1678.           case TELOPT_NEWENVIRON:
  1679.           case TELOPT_SNDLOC:
  1680.           case TELOPT_XDISPLOC:
  1681.           case TELOPT_SGA:
  1682.           case TELOPT_ECHO:
  1683.           case TELOPT_KERMIT:
  1684.           case TELOPT_START_TLS:
  1685.             break;
  1686.           default:
  1687.             if (TELOPT_OK(opt)) {
  1688.                 if (!TELOPT_ME(opt) &&
  1689.                     TELOPT_ME_MODE(opt) >= TN_NG_RQ) {
  1690.                     if (tn_sopt(WILL, opt) < 0)
  1691.                       return(-1);
  1692.                     TELOPT_UNANSWERED_WILL(opt) = 1;
  1693.                     wait = 1;
  1694.                 }
  1695.                 if (!TELOPT_U(opt) &&
  1696.                     TELOPT_U_MODE(opt) >= TN_NG_RQ) {
  1697.                     if (tn_sopt(DO, opt) < 0)
  1698.                       return(-1);
  1699.                     TELOPT_UNANSWERED_DO(opt) = 1;
  1700.                     wait = 1;
  1701.                 }
  1702.             }
  1703.         }
  1704.     }
  1705.     if (wait) {
  1706.         if (tn_wait("pre-encrypt") < 0) {
  1707.             tn_push();
  1708.             return(-1);
  1709.         }
  1710.         wait = 0;
  1711.     }
  1712. #ifdef CK_ENCRYPTION
  1713.     if (tn_init)                /* tn_ini() may be called recursively */
  1714.       return(0);
  1715.     if (!TELOPT_ME(TELOPT_ENCRYPTION) &&
  1716.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
  1717.         if (tn_sopt(WILL, TELOPT_ENCRYPTION) < 0)
  1718.           return(-1);
  1719.         TELOPT_UNANSWERED_WILL(TELOPT_ENCRYPTION) = 1;
  1720.         wait = 1;
  1721.     }
  1722.     if (!TELOPT_U(TELOPT_ENCRYPTION) &&
  1723.         TELOPT_U_MODE(TELOPT_ENCRYPTION) >= TN_NG_RQ) {
  1724.         if (tn_sopt(DO, TELOPT_ENCRYPTION) < 0)
  1725.           return(-1);
  1726.         TELOPT_UNANSWERED_DO(TELOPT_ENCRYPTION) = 1;
  1727.         wait = 1;
  1728.     }
  1729.     /* If we are going to encrypt, we want to do it before we send any more */
  1730.     /* data, especially the terminal type and environment variables.        */
  1731.     if (wait) {
  1732.         if (tn_wait("post-encrypt") < 0) {
  1733.             tn_push();
  1734.             return(-1);
  1735.         }
  1736.         wait = 0;
  1737.     }
  1738. #endif /* CK_ENCRYPTION */
  1739.     tn_sdsb();
  1740.     if (tn_init)                   /* tn_ini() may be called recursively */
  1741.         return(0);
  1742. #ifdef IKS_OPTION
  1743.     /* Kermit Server negotiation must go last */
  1744.     /* Send U before ME */
  1745.     if (!TELOPT_U(TELOPT_KERMIT) &&
  1746.         TELOPT_U_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
  1747.         if (tn_sopt(DO, TELOPT_KERMIT) < 0)
  1748.           return(-1);
  1749.         TELOPT_UNANSWERED_DO(TELOPT_KERMIT) = 1;
  1750.         wait = 1;
  1751.     }
  1752.     if (!TELOPT_ME(TELOPT_KERMIT) &&
  1753.         TELOPT_ME_MODE(TELOPT_KERMIT) >= TN_NG_RQ) {
  1754.         if (tn_sopt(WILL, TELOPT_KERMIT) < 0)
  1755.           return(-1);
  1756.         TELOPT_UNANSWERED_WILL(TELOPT_KERMIT) = 1;
  1757.         wait = 1;
  1758.     }
  1759. #endif /* IKS_OPTION */
  1760.     if (wait) {
  1761.         if (tn_wait("end of telnet negotiations") < 0) {
  1762.             tn_push();
  1763.             return(-1);
  1764.         }
  1765.         wait = 0;
  1766.     }
  1767.     tn_sdsb();                          /* Send delayed subnegotiations */
  1768.     tn_push();
  1769.     tn_init = 1;                        /* Remember successful completion. */
  1770.     /* Don't send anything else! */
  1771.     debug(F101,"tn_ini duplex","",duplex);
  1772.     debug(F101,"tn_ini done, tn_init","",tn_init);
  1773.     return(1);
  1774. }
  1775. VOID
  1776. tn_debug(s) char *s; {
  1777. #ifdef OS2
  1778.     void cwrite(unsigned short);
  1779.     char *p = s;
  1780.     _PROTOTYP (void os2bold, (void));
  1781. #endif /* OS2 */
  1782.     if (!(tn_deb || debses))
  1783.       return;
  1784.     debug(F111,"tn_debug",s,what);
  1785. #ifdef OS2
  1786.     if ( what == W_COMMAND ) {
  1787.         extern unsigned char colorcmd;
  1788.         colorcmd ^= 0x8 ;
  1789.         printf("%srn",s);
  1790.         colorcmd ^= 0x8 ;
  1791.     }
  1792.     if (!scrninitialized[VTERM]) {
  1793.         USHORT x,y;
  1794.         checkscreenmode();
  1795.         GetCurPos(&y, &x);
  1796.         SaveCmdMode(x+1,y+1);
  1797.         scrninit();
  1798.         RestoreCmdMode();
  1799.     }
  1800.     os2bold();                          /* Toggle boldness */
  1801.     while (*p)
  1802.       cwrite((CHAR) *p++);              /* Go boldly ... */
  1803.     os2bold();                          /* Toggle boldness back */
  1804.     if (debses) {
  1805.         debses = 0;
  1806.         cwrite((CHAR) '15');
  1807.         cwrite((CHAR) '12');
  1808.         debses = 1;
  1809.     } else {
  1810.         cwrite((CHAR) '15');
  1811.         cwrite((CHAR) '12');
  1812.     }
  1813. #else
  1814.     if (what != W_CONNECT && what != W_COMMAND)
  1815.       return;                           /* CONNECT/command must be active */
  1816.     conoll(s);
  1817. #endif /* OS2 */
  1818. }
  1819. /*
  1820.   Process in-band Telnet negotiation characters from the remote host.
  1821.   Call with the telnet IAC character and the current duplex setting
  1822.   (0 = remote echo, 1 = local echo), and a pointer to a function to call
  1823.   to read more characters.  Returns:
  1824.     6 if DO LOGOUT was received and accepted
  1825.     5 if the Kermit start of packet character has changed
  1826.     4 if state of remote Internet Kermit Service has changed
  1827.     3 if a quoted IAC was received
  1828.     2 if local echo must be changed to remote
  1829.     1 if remote echo must be changed to local
  1830.     0 if nothing happens or no action necessary
  1831.    -1 on failure (= internal or i/o error)
  1832. */
  1833. #ifdef IKS_OPTION
  1834. int
  1835. tn_siks(cmd) int cmd; {         /* TELNET SEND IKS SUB */
  1836. #ifndef NOXFER
  1837.     CHAR buf[8];
  1838.     extern CHAR mystch;                 /* Outgoing Start of Packet Char */
  1839.     int n,m;
  1840.     if (ttnet != NET_TCPB) return(0);   /* Must be TCP/IP */
  1841.     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
  1842.     if (cmd < KERMIT_START || cmd > KERMIT_RESP_STOP) /* Illegal subcommand */
  1843.       return(-1);
  1844. #ifdef CK_SSL
  1845.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1846.         return(0);
  1847.     }
  1848. #endif /* CK_SSL */
  1849.     if (cmd == KERMIT_START || cmd == KERMIT_RESP_START) {
  1850.         TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 1;
  1851.     } else if (cmd == KERMIT_STOP || cmd == KERMIT_RESP_STOP) {
  1852.         TELOPT_SB(TELOPT_KERMIT).kermit.me_start = 0;
  1853.     } else if (cmd == KERMIT_REQ_STOP)
  1854.       TELOPT_SB(TELOPT_KERMIT).kermit.me_req_stop = 1;
  1855.     else if (cmd == KERMIT_REQ_START)
  1856.       TELOPT_SB(TELOPT_KERMIT).kermit.me_req_start = 1;
  1857.     if (cmd == KERMIT_SOP) {
  1858.         buf[0] = (CHAR) IAC;
  1859.         buf[1] = (CHAR) SB;
  1860.         buf[2] = (CHAR) TELOPT_KERMIT;
  1861.         buf[3] = (CHAR) (cmd & 0xff);
  1862.         buf[4] = (CHAR) mystch;
  1863.         buf[5] = (CHAR) IAC;
  1864.         buf[6] = (CHAR) SE;
  1865.         buf[7] = (CHAR) 0;
  1866.         if (tn_deb || debses || deblog) {
  1867.             sprintf(tn_msg,"TELNET SENT SB KERMIT SOP %02X IAC SE",mystch);
  1868.             debug(F101,tn_msg,"",cmd);
  1869.             if (tn_deb || debses) tn_debug(tn_msg);
  1870.         }
  1871.         if (ttol(buf,7) < 7)
  1872.           return(-1);
  1873.     } else {
  1874.         buf[0] = (CHAR) IAC;
  1875.         buf[1] = (CHAR) SB;
  1876.         buf[2] = (CHAR) TELOPT_KERMIT;
  1877.         buf[3] = (CHAR) (cmd & 0xff);
  1878.         buf[4] = (CHAR) IAC;
  1879.         buf[5] = (CHAR) SE;
  1880.         buf[6] = (CHAR) 0;
  1881.         if (tn_deb || debses || deblog) {
  1882.             char * s = 0;
  1883.             switch (cmd) {
  1884.               case KERMIT_START: s = "START"; break;
  1885.               case KERMIT_STOP: s = "STOP"; break;
  1886.               case KERMIT_REQ_START: s = "REQ-START"; break;
  1887.               case KERMIT_REQ_STOP: s = "REQ-STOP"; break;
  1888.               case KERMIT_RESP_START: s = "RESP-START"; break;
  1889.               case KERMIT_RESP_STOP:  s = "RESP-STOP"; break;
  1890.             }
  1891.             sprintf(tn_msg,"TELNET SENT SB kermit %s IAC SE",s);
  1892.             debug(F101,tn_msg,"",cmd);
  1893.             if (tn_deb || debses) tn_debug(tn_msg);
  1894.         }
  1895.         if (ttol(buf,6) < 6)
  1896.           return(-1);
  1897.     }
  1898.     return(1);
  1899. #else
  1900.     return(-1);
  1901. #endif /* NOXFER */
  1902. }
  1903. #endif /* IKS_OPTION */
  1904. /* tn_sb() performs Telnet Subnegotiation Parsing and Debugging */
  1905. /* returns <= 0 on error, 1 on success */
  1906. /* the length returned includes the IAC SE bytes */
  1907. int
  1908. #ifdef CK_ANSIC                         /* TELNET SB */
  1909. tn_sb( int opt, int * len, int (*fn)(int) )
  1910. #else
  1911. tn_sb( opt, len, fn ) int opt; int * len; int (*fn)();
  1912. #endif /* CK_ANSIC */
  1913. /* tn_sb */ {
  1914.     int c, x, y, n, m, flag;
  1915.     debug(F100,"Entering tn_sb()","",0);
  1916.     *len = 0;                   /* Initialize Len to 0 */
  1917.     n = flag = 0;               /* Flag for when done reading SB */
  1918.     while (n < TSBUFSIZ) {      /* Loop looking for IAC SE */
  1919.         if ((y = (*fn)(0)) < 0) /* Read a byte */
  1920.           return(y);
  1921.         y &= 0xff;              /* Make sure it's just 8 bits. */
  1922.         sb[n++] = (char) y;     /* Deposit in buffer. */
  1923.         if (seslog && sessft == XYFT_D) { /* Take care of session log */
  1924.             logchar((char) y);
  1925.         }
  1926.         if (y == IAC) {         /* If this is an IAC                */
  1927.             if (flag) {         /* If previous char was IAC         */
  1928.                 n--;            /* it's quoted, keep one IAC        */
  1929.                 flag = 0;       /* and turn off the flag.           */
  1930.             } else flag = 1;    /* Otherwise set the flag.          */
  1931.         } else if (flag) {      /* Something else following IAC     */
  1932.             if (y == SE)        /* If not SE, it's a protocol error */
  1933.               break;
  1934.             else if (y == DONT) { /* Used DONT instead of SE */
  1935.                 debug(F100,
  1936.                       "TELNET Subnegotiation error - used DONT instead of SE!",
  1937.                       ""
  1938.                       ,0
  1939.                       );
  1940.                 if (tn_deb || debses)
  1941.                   tn_debug(
  1942.                      "TELNET Subnegotiation error - used DONT instead of SE!");
  1943.                 flag = 3;
  1944.                 break;
  1945.             } else {            /* Other protocol error */
  1946.                 flag = 0;
  1947.                 break;
  1948.             }
  1949.         }
  1950. #ifdef COMMENT
  1951.         /* This test is sure to be triggered when we are using encryption */
  1952.         /* Therefore, we must take it out, otherwise, our subnegotiations */
  1953.         /* will be truncated and failure will result.                     */
  1954.         /* This bug was only seen on BeOS DR7 and has been fixed.         */
  1955.         else if (!flag && y == SE) { /* Forgot the IAC ? */
  1956.             flag = 2;
  1957.             debug(F100,
  1958.                    "TELNET Subnegotiation error - forgot the IAC before SE!",
  1959.                    "",
  1960.                   0
  1961.                   );
  1962.             if (tn_deb || debses)
  1963.               tn_debug(
  1964. "TELNET Subnegotiation error - forgot the IAC before SE!");
  1965.             break;
  1966.         }
  1967. #endif /* COMMENT */
  1968. #ifdef CK_FORWARD_X
  1969.         if ( opt == TELOPT_FORWARD_X && sb[0] == FWDX_DATA &&
  1970.              n == (TSBUFSIZ-2) ) {
  1971.             /* do not let the buffer over flow */
  1972.             /* write the data to the channel and continue processing */
  1973.             /* the incoming data until IAC SE is reached. */
  1974.             sb[n++] = IAC;
  1975.             sb[n++] = SE;
  1976.             if ( deblog || tn_deb || debses ) {
  1977.                 int i;
  1978.                 sprintf(tn_msg,"TELNET RCVD SB %s DATA ",TELOPT(opt));
  1979. #ifdef HEXDISP
  1980.                 {
  1981.                     int was_hex = 1;
  1982.                     for (i=1; i < n-2; i++) {
  1983.                         if (sb[i] < 32 || sb[i] >= 127) {
  1984.                             sprintf(hexbuf,"%s%02X ",was_hex?"":"" ",sb[i]);
  1985.                             was_hex = 1;
  1986.                         } else {
  1987.                             sprintf(hexbuf,"%s%c",was_hex?""":"",sb[i]);
  1988.                             was_hex = 0;
  1989.                         }
  1990.                         strcat(tn_msg,hexbuf);
  1991.                     }
  1992.                     if (!was_hex)
  1993.                         strcat(tn_msg,"" ");
  1994.                 }
  1995. #else /* HEXDISP */
  1996.                 memcpy(hexbuf,&sb[i],n-i-2);
  1997.                 hexbuf[n-i-2] = ' ';
  1998.                 hexbuf[n-i-1] = '';
  1999.                 strcat(tn_msg,hexbuf);
  2000. #endif /* HEXDISP */
  2001.                 if (flag == 2)
  2002.                     strcat(tn_msg,"SE");
  2003.                 else if (flag == 3)
  2004.                     strcat(tn_msg," IAC DONT");
  2005.                 else
  2006.                     strcat(tn_msg," IAC SE");
  2007.                 debug(F100,tn_msg,"",0);
  2008.                 if (tn_deb || debses)
  2009.                     tn_debug(tn_msg);
  2010.             }
  2011.             if ( fwdx_tn_sb(sb,n) < 0 )
  2012.                 return(0);
  2013.             /* reset leave the msg type and channel number in place */
  2014.             n = 3;
  2015.         }
  2016. #endif /* CK_FORWARD_X */
  2017.     }
  2018.     debug(F111,"tn_sb end of while loop","flag",flag);
  2019.     if (!flag) {                        /* Make sure we got a valid SB */
  2020.         debug(F111, "TELNET Subnegotiation prematurely broken","opt",opt);
  2021.         if (tn_deb || debses)
  2022.           tn_debug("TELNET Subnegotiation prematurely broken");
  2023.         /* Was -1 but that would be an I/O error, so absorb it and go on. */
  2024.         return(0);
  2025.     }
  2026.     if (deblog || tn_deb || debses) {
  2027.         int i;
  2028.         char * s[16];
  2029.         for (i = 0; i < 16; i++)
  2030.           s[i] = "";
  2031.         if (opt == TELOPT_NAWS) {
  2032.             i = 0;
  2033.         } else {
  2034.             i = 1;
  2035.             s[0] = "UNKNOWN";
  2036.             switch (sb[0]) {
  2037.               case 0:
  2038.                 if (opt == TELOPT_FORWARD_X)
  2039.                   s[0] = "SCREEN";
  2040.                 else if (opt == TELOPT_KERMIT)
  2041.                   s[0] = "START";
  2042.                 else if (opt == TELOPT_LFLOW)
  2043.                   s[0] = "OFF";
  2044.                 else
  2045.                   s[0] = "IS";
  2046.                 if (opt == TELOPT_ENCRYPTION) {
  2047.                     i++;
  2048.                     if (sb[1] < ENCTYPE_CNT) {
  2049.                         s[1] = enctype_names[sb[1]];
  2050.                         i++;
  2051.                         switch(sb[2]) {
  2052.                           case 1:
  2053.                             s[2] = "FB64_IV";
  2054.                             break;
  2055.                           case 2:
  2056.                             s[2] = "FB64_IV_OK";
  2057.                             break;
  2058.                           case 3:
  2059.                             s[2] = "FB64_IV_BAD";
  2060.                             break;
  2061.                           case 4:
  2062.                             s[2] = "FB64_CHALLENGE";
  2063.                             break;
  2064.                           case 5:
  2065.                             s[2] = "FB64_RESPONSE";
  2066.                             break;
  2067.                         }
  2068.                     } else {
  2069.                         s[1] = "UNKNOWN";
  2070.                     }
  2071.                 }
  2072.                 if (opt == TELOPT_AUTHENTICATION) {
  2073.                     i += 2;
  2074.                     s[1] = AUTHTYPE_NAME(sb[1]);
  2075.                     s[2] = AUTHMODE_NAME(sb[2]);
  2076.                     if (sb[1]) {
  2077.                         i++;
  2078.                         switch (sb[3]) {
  2079.                           case 0:
  2080.                             switch (sb[1]) {
  2081.                               case AUTHTYPE_NTLM:
  2082.                                 s[3] = "NTLM_AUTH";
  2083.                                 break;
  2084.                               default:
  2085.                                 s[3] = "AUTH";
  2086.                             }
  2087.                             break;
  2088.                           case 1:
  2089.                             switch (sb[1]) {
  2090.                               case AUTHTYPE_SSL:
  2091.                                 s[3] = "START";
  2092.                                 break;
  2093.                               case AUTHTYPE_NTLM:
  2094.                                 s[3] = "NTLM_CHALLENGE";
  2095.                                 break;
  2096.                               default:
  2097.                                 s[3] = "REJECT";
  2098.                             }
  2099.                             break;
  2100.                           case 2:
  2101.                             switch (sb[1]) {
  2102.                               case AUTHTYPE_NTLM:
  2103.                                 s[3] = "NTLM_RESPONSE";
  2104.                                 break;
  2105.                               default:
  2106.                                 s[3] = "ACCEPT";
  2107.                             }
  2108.                             break;
  2109.                           case 3:
  2110.                             switch (sb[1]) {
  2111.                               case AUTHTYPE_NTLM:
  2112.                                 s[3] = "NTLM_ACCEPT";
  2113.                                 break;
  2114.                               case 1:   /* KERBEROS_v4 */
  2115.                               case 5:   /* SRP */
  2116.                                 s[3] = "CHALLENGE";
  2117.                                 break;
  2118.                               case 2:   /* KERBEROS_v5 */
  2119.                                 s[3] = "RESPONSE";
  2120.                                 break;
  2121.                               case AUTHTYPE_SSL:
  2122.                                 s[3] = "REJECT";
  2123.                                 break;
  2124.                             }
  2125.                             break;
  2126.                           case 4:
  2127.                             switch (sb[1]) {
  2128.                               case AUTHTYPE_NTLM:
  2129.                                 s[3] = "NTLM_REJECT";
  2130.                                 break;
  2131.                               case 1:   /* KERBEROS_V4 */
  2132.                               case 5:   /* SRP */
  2133.                                 s[3] = "RESPONSE";
  2134.                                 break;
  2135.                               case 2:   /* KERBEROS_V5 */
  2136.                                 s[3] = "FORWARD";
  2137.                                 break;
  2138.                             }
  2139.                             break;
  2140.                           case 5: