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