1 /* 2 * Copyright (c) 1988, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #if 0 35 #ifndef lint 36 static const char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; 37 #endif 38 #endif 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD: src/contrib/telnet/telnet/telnet.c,v 1.16 2005/03/28 14:45:12 nectar Exp $"); 41 42 #include <sys/types.h> 43 44 /* By the way, we need to include curses.h before telnet.h since, 45 * among other things, telnet.h #defines 'DO', which is a variable 46 * declared in curses.h. 47 */ 48 49 #include <ctype.h> 50 #include <curses.h> 51 #include <signal.h> 52 #include <stdlib.h> 53 #include <term.h> 54 #include <unistd.h> 55 #include <arpa/telnet.h> 56 57 #include "ring.h" 58 59 #include "defines.h" 60 #include "externs.h" 61 #include "types.h" 62 #include "general.h" 63 64 #ifdef AUTHENTICATION 65 #include <libtelnet/auth.h> 66 #endif 67 #ifdef ENCRYPTION 68 #include <libtelnet/encrypt.h> 69 #endif 70 #include <libtelnet/misc.h> 71 72 #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) 73 74 static unsigned char subbuffer[SUBBUFSIZE], 75 *subpointer, *subend; /* buffer for sub-options */ 76 #define SB_CLEAR() subpointer = subbuffer; 77 #define SB_TERM() { subend = subpointer; SB_CLEAR(); } 78 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ 79 *subpointer++ = (c); \ 80 } 81 82 #define SB_GET() ((*subpointer++)&0xff) 83 #define SB_PEEK() ((*subpointer)&0xff) 84 #define SB_EOF() (subpointer >= subend) 85 #define SB_LEN() (subend - subpointer) 86 87 char options[256]; /* The combined options */ 88 char do_dont_resp[256]; 89 char will_wont_resp[256]; 90 91 int 92 eight = 0, 93 autologin = 0, /* Autologin anyone? */ 94 skiprc = 0, 95 connected, 96 showoptions, 97 ISend, /* trying to send network data in */ 98 telnet_debug = 0, 99 crmod, 100 netdata, /* Print out network data flow */ 101 crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ 102 telnetport, 103 SYNCHing, /* we are in TELNET SYNCH mode */ 104 flushout, /* flush output */ 105 autoflush = 0, /* flush output when interrupting? */ 106 autosynch, /* send interrupt characters with SYNCH? */ 107 localflow, /* we handle flow control locally */ 108 restartany, /* if flow control enabled, restart on any character */ 109 localchars, /* we recognize interrupt/quit */ 110 donelclchars, /* the user has set "localchars" */ 111 donebinarytoggle, /* the user has put us in binary */ 112 dontlecho, /* do we suppress local echoing right now? */ 113 globalmode, 114 doaddrlookup = 1, /* do a reverse address lookup? */ 115 clienteof = 0; 116 117 char *prompt = 0; 118 #ifdef ENCRYPTION 119 char *line; /* hack around breakage in sra.c :-( !! */ 120 #endif 121 122 cc_t escape; 123 cc_t rlogin; 124 #ifdef KLUDGELINEMODE 125 cc_t echoc; 126 #endif 127 128 /* 129 * Telnet receiver states for fsm 130 */ 131 #define TS_DATA 0 132 #define TS_IAC 1 133 #define TS_WILL 2 134 #define TS_WONT 3 135 #define TS_DO 4 136 #define TS_DONT 5 137 #define TS_CR 6 138 #define TS_SB 7 /* sub-option collection */ 139 #define TS_SE 8 /* looking for sub-option end */ 140 141 static int telrcv_state; 142 #ifdef OLD_ENVIRON 143 unsigned char telopt_environ = TELOPT_NEW_ENVIRON; 144 #else 145 # define telopt_environ TELOPT_NEW_ENVIRON 146 #endif 147 148 jmp_buf toplevel; 149 jmp_buf peerdied; 150 151 int flushline; 152 int linemode; 153 154 #ifdef KLUDGELINEMODE 155 int kludgelinemode = 1; 156 #endif 157 158 static int is_unique(char *, char **, char **); 159 160 /* 161 * The following are some clocks used to decide how to interpret 162 * the relationship between various variables. 163 */ 164 165 Clocks clocks; 166 167 /* 168 * Initialize telnet environment. 169 */ 170 171 void 172 init_telnet(void) 173 { 174 env_init(); 175 176 SB_CLEAR(); 177 ClearArray(options); 178 179 connected = ISend = localflow = donebinarytoggle = 0; 180 #ifdef AUTHENTICATION 181 #ifdef ENCRYPTION 182 auth_encrypt_connect(connected); 183 #endif 184 #endif 185 restartany = -1; 186 187 SYNCHing = 0; 188 189 /* Don't change NetTrace */ 190 191 escape = CONTROL(']'); 192 rlogin = _POSIX_VDISABLE; 193 #ifdef KLUDGELINEMODE 194 echoc = CONTROL('E'); 195 #endif 196 197 flushline = 1; 198 telrcv_state = TS_DATA; 199 } 200 201 202 /* 203 * These routines are in charge of sending option negotiations 204 * to the other side. 205 * 206 * The basic idea is that we send the negotiation if either side 207 * is in disagreement as to what the current state should be. 208 */ 209 210 void 211 send_do(int c, int init) 212 { 213 if (init) { 214 if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || 215 my_want_state_is_do(c)) 216 return; 217 set_my_want_state_do(c); 218 do_dont_resp[c]++; 219 } 220 if (telnetport < 0) 221 return; 222 NET2ADD(IAC, DO); 223 NETADD(c); 224 printoption("SENT", DO, c); 225 } 226 227 void 228 send_dont(int c, int init) 229 { 230 if (init) { 231 if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || 232 my_want_state_is_dont(c)) 233 return; 234 set_my_want_state_dont(c); 235 do_dont_resp[c]++; 236 } 237 if (telnetport < 0) 238 return; 239 NET2ADD(IAC, DONT); 240 NETADD(c); 241 printoption("SENT", DONT, c); 242 } 243 244 void 245 send_will(int c, int init) 246 { 247 if (init) { 248 if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || 249 my_want_state_is_will(c)) 250 return; 251 set_my_want_state_will(c); 252 will_wont_resp[c]++; 253 } 254 if (telnetport < 0) 255 return; 256 NET2ADD(IAC, WILL); 257 NETADD(c); 258 printoption("SENT", WILL, c); 259 } 260 261 void 262 send_wont(int c, int init) 263 { 264 if (init) { 265 if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || 266 my_want_state_is_wont(c)) 267 return; 268 set_my_want_state_wont(c); 269 will_wont_resp[c]++; 270 } 271 if (telnetport < 0) 272 return; 273 NET2ADD(IAC, WONT); 274 NETADD(c); 275 printoption("SENT", WONT, c); 276 } 277 278 void 279 willoption(int option) 280 { 281 int new_state_ok = 0; 282 283 if (do_dont_resp[option]) { 284 --do_dont_resp[option]; 285 if (do_dont_resp[option] && my_state_is_do(option)) 286 --do_dont_resp[option]; 287 } 288 289 if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { 290 291 switch (option) { 292 293 case TELOPT_ECHO: 294 case TELOPT_BINARY: 295 case TELOPT_SGA: 296 settimer(modenegotiated); 297 /* FALLTHROUGH */ 298 case TELOPT_STATUS: 299 #ifdef AUTHENTICATION 300 case TELOPT_AUTHENTICATION: 301 #endif 302 #ifdef ENCRYPTION 303 case TELOPT_ENCRYPT: 304 #endif /* ENCRYPTION */ 305 new_state_ok = 1; 306 break; 307 308 case TELOPT_TM: 309 if (flushout) 310 flushout = 0; 311 /* 312 * Special case for TM. If we get back a WILL, 313 * pretend we got back a WONT. 314 */ 315 set_my_want_state_dont(option); 316 set_my_state_dont(option); 317 return; /* Never reply to TM will's/wont's */ 318 319 case TELOPT_LINEMODE: 320 default: 321 break; 322 } 323 324 if (new_state_ok) { 325 set_my_want_state_do(option); 326 send_do(option, 0); 327 setconnmode(0); /* possibly set new tty mode */ 328 } else { 329 do_dont_resp[option]++; 330 send_dont(option, 0); 331 } 332 } 333 set_my_state_do(option); 334 #ifdef ENCRYPTION 335 if (option == TELOPT_ENCRYPT) 336 encrypt_send_support(); 337 #endif /* ENCRYPTION */ 338 } 339 340 void 341 wontoption(int option) 342 { 343 if (do_dont_resp[option]) { 344 --do_dont_resp[option]; 345 if (do_dont_resp[option] && my_state_is_dont(option)) 346 --do_dont_resp[option]; 347 } 348 349 if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { 350 351 switch (option) { 352 353 #ifdef KLUDGELINEMODE 354 case TELOPT_SGA: 355 if (!kludgelinemode) 356 break; 357 /* FALLTHROUGH */ 358 #endif 359 case TELOPT_ECHO: 360 settimer(modenegotiated); 361 break; 362 363 case TELOPT_TM: 364 if (flushout) 365 flushout = 0; 366 set_my_want_state_dont(option); 367 set_my_state_dont(option); 368 return; /* Never reply to TM will's/wont's */ 369 370 default: 371 break; 372 } 373 set_my_want_state_dont(option); 374 if (my_state_is_do(option)) 375 send_dont(option, 0); 376 setconnmode(0); /* Set new tty mode */ 377 } else if (option == TELOPT_TM) { 378 /* 379 * Special case for TM. 380 */ 381 if (flushout) 382 flushout = 0; 383 set_my_want_state_dont(option); 384 } 385 set_my_state_dont(option); 386 } 387 388 static void 389 dooption(int option) 390 { 391 int new_state_ok = 0; 392 393 if (will_wont_resp[option]) { 394 --will_wont_resp[option]; 395 if (will_wont_resp[option] && my_state_is_will(option)) 396 --will_wont_resp[option]; 397 } 398 399 if (will_wont_resp[option] == 0) { 400 if (my_want_state_is_wont(option)) { 401 402 switch (option) { 403 404 case TELOPT_TM: 405 /* 406 * Special case for TM. We send a WILL, but pretend 407 * we sent WONT. 408 */ 409 send_will(option, 0); 410 set_my_want_state_wont(TELOPT_TM); 411 set_my_state_wont(TELOPT_TM); 412 return; 413 414 case TELOPT_BINARY: /* binary mode */ 415 case TELOPT_NAWS: /* window size */ 416 case TELOPT_TSPEED: /* terminal speed */ 417 case TELOPT_LFLOW: /* local flow control */ 418 case TELOPT_TTYPE: /* terminal type option */ 419 case TELOPT_SGA: /* no big deal */ 420 #ifdef ENCRYPTION 421 case TELOPT_ENCRYPT: /* encryption variable option */ 422 #endif /* ENCRYPTION */ 423 new_state_ok = 1; 424 break; 425 426 case TELOPT_NEW_ENVIRON: /* New environment variable option */ 427 #ifdef OLD_ENVIRON 428 if (my_state_is_will(TELOPT_OLD_ENVIRON)) 429 send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ 430 goto env_common; 431 case TELOPT_OLD_ENVIRON: /* Old environment variable option */ 432 if (my_state_is_will(TELOPT_NEW_ENVIRON)) 433 break; /* Don't enable if new one is in use! */ 434 env_common: 435 telopt_environ = option; 436 #endif 437 new_state_ok = 1; 438 break; 439 440 #ifdef AUTHENTICATION 441 case TELOPT_AUTHENTICATION: 442 if (autologin) 443 new_state_ok = 1; 444 break; 445 #endif 446 447 case TELOPT_XDISPLOC: /* X Display location */ 448 if (env_getvalue("DISPLAY")) 449 new_state_ok = 1; 450 break; 451 452 case TELOPT_LINEMODE: 453 #ifdef KLUDGELINEMODE 454 kludgelinemode = 0; 455 send_do(TELOPT_SGA, 1); 456 #endif 457 set_my_want_state_will(TELOPT_LINEMODE); 458 send_will(option, 0); 459 set_my_state_will(TELOPT_LINEMODE); 460 slc_init(); 461 return; 462 463 case TELOPT_ECHO: /* We're never going to echo... */ 464 default: 465 break; 466 } 467 468 if (new_state_ok) { 469 set_my_want_state_will(option); 470 send_will(option, 0); 471 setconnmode(0); /* Set new tty mode */ 472 } else { 473 will_wont_resp[option]++; 474 send_wont(option, 0); 475 } 476 } else { 477 /* 478 * Handle options that need more things done after the 479 * other side has acknowledged the option. 480 */ 481 switch (option) { 482 case TELOPT_LINEMODE: 483 #ifdef KLUDGELINEMODE 484 kludgelinemode = 0; 485 send_do(TELOPT_SGA, 1); 486 #endif 487 set_my_state_will(option); 488 slc_init(); 489 send_do(TELOPT_SGA, 0); 490 return; 491 } 492 } 493 } 494 set_my_state_will(option); 495 } 496 497 static void 498 dontoption(int option) 499 { 500 501 if (will_wont_resp[option]) { 502 --will_wont_resp[option]; 503 if (will_wont_resp[option] && my_state_is_wont(option)) 504 --will_wont_resp[option]; 505 } 506 507 if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { 508 switch (option) { 509 case TELOPT_LINEMODE: 510 linemode = 0; /* put us back to the default state */ 511 break; 512 #ifdef OLD_ENVIRON 513 case TELOPT_NEW_ENVIRON: 514 /* 515 * The new environ option wasn't recognized, try 516 * the old one. 517 */ 518 send_will(TELOPT_OLD_ENVIRON, 1); 519 telopt_environ = TELOPT_OLD_ENVIRON; 520 break; 521 #endif 522 } 523 /* we always accept a DONT */ 524 set_my_want_state_wont(option); 525 if (my_state_is_will(option)) 526 send_wont(option, 0); 527 setconnmode(0); /* Set new tty mode */ 528 } 529 set_my_state_wont(option); 530 } 531 532 /* 533 * Given a buffer returned by tgetent(), this routine will turn 534 * the pipe separated list of names in the buffer into an array 535 * of pointers to null terminated names. We toss out any bad, 536 * duplicate, or verbose names (names with spaces). 537 */ 538 539 static const char *name_unknown = "UNKNOWN"; 540 static const char *unknown[] = { NULL, NULL }; 541 542 static const char ** 543 mklist(char *buf, char *name) 544 { 545 int n; 546 char c, *cp, **argvp, *cp2, **argv, **avt; 547 548 if (name) { 549 if (strlen(name) > 40) { 550 name = 0; 551 unknown[0] = name_unknown; 552 } else { 553 unknown[0] = name; 554 upcase(name); 555 } 556 } else 557 unknown[0] = name_unknown; 558 /* 559 * Count up the number of names. 560 */ 561 for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { 562 if (*cp == '|') 563 n++; 564 } 565 /* 566 * Allocate an array to put the name pointers into 567 */ 568 argv = (char **)malloc((n+3)*sizeof(char *)); 569 if (argv == 0) 570 return(unknown); 571 572 /* 573 * Fill up the array of pointers to names. 574 */ 575 *argv = 0; 576 argvp = argv+1; 577 n = 0; 578 for (cp = cp2 = buf; (c = *cp); cp++) { 579 if (c == '|' || c == ':') { 580 *cp++ = '\0'; 581 /* 582 * Skip entries that have spaces or are over 40 583 * characters long. If this is our environment 584 * name, then put it up front. Otherwise, as 585 * long as this is not a duplicate name (case 586 * insensitive) add it to the list. 587 */ 588 if (n || (cp - cp2 > 41)) 589 ; 590 else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) 591 *argv = cp2; 592 else if (is_unique(cp2, argv+1, argvp)) 593 *argvp++ = cp2; 594 if (c == ':') 595 break; 596 /* 597 * Skip multiple delimiters. Reset cp2 to 598 * the beginning of the next name. Reset n, 599 * the flag for names with spaces. 600 */ 601 while ((c = *cp) == '|') 602 cp++; 603 cp2 = cp; 604 n = 0; 605 } 606 /* 607 * Skip entries with spaces or non-ascii values. 608 * Convert lower case letters to upper case. 609 */ 610 if ((c == ' ') || !isascii(c)) 611 n = 1; 612 else if (islower(c)) 613 *cp = toupper(c); 614 } 615 616 /* 617 * Check for an old V6 2 character name. If the second 618 * name points to the beginning of the buffer, and is 619 * only 2 characters long, move it to the end of the array. 620 */ 621 if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { 622 --argvp; 623 for (avt = &argv[1]; avt < argvp; avt++) 624 *avt = *(avt+1); 625 *argvp++ = buf; 626 } 627 628 /* 629 * Duplicate last name, for TTYPE option, and null 630 * terminate the array. If we didn't find a match on 631 * our terminal name, put that name at the beginning. 632 */ 633 cp = *(argvp-1); 634 *argvp++ = cp; 635 *argvp = 0; 636 637 if (*argv == 0) { 638 if (name) 639 *argv = name; 640 else { 641 --argvp; 642 for (avt = argv; avt < argvp; avt++) 643 *avt = *(avt+1); 644 } 645 } 646 if (*argv) 647 return((const char **)argv); 648 else 649 return(unknown); 650 } 651 652 static int 653 is_unique(char *name, char **as, char **ae) 654 { 655 char **ap; 656 int n; 657 658 n = strlen(name) + 1; 659 for (ap = as; ap < ae; ap++) 660 if (strncasecmp(*ap, name, n) == 0) 661 return(0); 662 return (1); 663 } 664 665 #ifdef TERMCAP 666 char termbuf[1024]; 667 668 /*ARGSUSED*/ 669 static int 670 setupterm(char *tname, int fd, int *errp) 671 { 672 if (tgetent(termbuf, tname) == 1) { 673 termbuf[1023] = '\0'; 674 if (errp) 675 *errp = 1; 676 return(0); 677 } 678 if (errp) 679 *errp = 0; 680 return(-1); 681 } 682 #else 683 #define termbuf ttytype 684 extern char ttytype[]; 685 #endif 686 687 int resettermname = 1; 688 689 static const char * 690 gettermname(void) 691 { 692 char *tname; 693 static const char **tnamep = 0; 694 static const char **next; 695 int err; 696 697 if (resettermname) { 698 resettermname = 0; 699 if (tnamep && tnamep != unknown) 700 free(tnamep); 701 if ((tname = env_getvalue("TERM")) && 702 (setupterm(tname, 1, &err) == 0)) { 703 tnamep = mklist(termbuf, tname); 704 } else { 705 if (tname && (strlen(tname) <= 40)) { 706 unknown[0] = tname; 707 upcase(tname); 708 } else 709 unknown[0] = name_unknown; 710 tnamep = unknown; 711 } 712 next = tnamep; 713 } 714 if (*next == 0) 715 next = tnamep; 716 return(*next++); 717 } 718 /* 719 * suboption() 720 * 721 * Look at the sub-option buffer, and try to be helpful to the other 722 * side. 723 * 724 * Currently we recognize: 725 * 726 * Terminal type, send request. 727 * Terminal speed (send request). 728 * Local flow control (is request). 729 * Linemode 730 */ 731 732 static void 733 suboption(void) 734 { 735 unsigned char subchar; 736 737 printsub('<', subbuffer, SB_LEN()+2); 738 switch (subchar = SB_GET()) { 739 case TELOPT_TTYPE: 740 if (my_want_state_is_wont(TELOPT_TTYPE)) 741 return; 742 if (SB_EOF() || SB_GET() != TELQUAL_SEND) { 743 return; 744 } else { 745 const char *name; 746 unsigned char temp[50]; 747 int len; 748 749 name = gettermname(); 750 len = strlen(name) + 4 + 2; 751 if (len < NETROOM()) { 752 sprintf(temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 753 TELQUAL_IS, name, IAC, SE); 754 ring_supply_data(&netoring, temp, len); 755 printsub('>', &temp[2], len-2); 756 } else { 757 ExitString("No room in buffer for terminal type.\n", 1); 758 /*NOTREACHED*/ 759 } 760 } 761 break; 762 case TELOPT_TSPEED: 763 if (my_want_state_is_wont(TELOPT_TSPEED)) 764 return; 765 if (SB_EOF()) 766 return; 767 if (SB_GET() == TELQUAL_SEND) { 768 long ospeed, ispeed; 769 unsigned char temp[50]; 770 int len; 771 772 TerminalSpeeds(&ispeed, &ospeed); 773 774 sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, 775 TELQUAL_IS, ospeed, ispeed, IAC, SE); 776 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 777 778 if (len < NETROOM()) { 779 ring_supply_data(&netoring, temp, len); 780 printsub('>', temp+2, len - 2); 781 } 782 /*@*/ else printf("lm_will: not enough room in buffer\n"); 783 } 784 break; 785 case TELOPT_LFLOW: 786 if (my_want_state_is_wont(TELOPT_LFLOW)) 787 return; 788 if (SB_EOF()) 789 return; 790 switch(SB_GET()) { 791 case LFLOW_RESTART_ANY: 792 restartany = 1; 793 break; 794 case LFLOW_RESTART_XON: 795 restartany = 0; 796 break; 797 case LFLOW_ON: 798 localflow = 1; 799 break; 800 case LFLOW_OFF: 801 localflow = 0; 802 break; 803 default: 804 return; 805 } 806 setcommandmode(); 807 setconnmode(0); 808 break; 809 810 case TELOPT_LINEMODE: 811 if (my_want_state_is_wont(TELOPT_LINEMODE)) 812 return; 813 if (SB_EOF()) 814 return; 815 switch (SB_GET()) { 816 case WILL: 817 lm_will(subpointer, SB_LEN()); 818 break; 819 case WONT: 820 lm_wont(subpointer, SB_LEN()); 821 break; 822 case DO: 823 lm_do(subpointer, SB_LEN()); 824 break; 825 case DONT: 826 lm_dont(subpointer, SB_LEN()); 827 break; 828 case LM_SLC: 829 slc(subpointer, SB_LEN()); 830 break; 831 case LM_MODE: 832 lm_mode(subpointer, SB_LEN(), 0); 833 break; 834 default: 835 break; 836 } 837 break; 838 839 #ifdef OLD_ENVIRON 840 case TELOPT_OLD_ENVIRON: 841 #endif 842 case TELOPT_NEW_ENVIRON: 843 if (SB_EOF()) 844 return; 845 switch(SB_PEEK()) { 846 case TELQUAL_IS: 847 case TELQUAL_INFO: 848 if (my_want_state_is_dont(subchar)) 849 return; 850 break; 851 case TELQUAL_SEND: 852 if (my_want_state_is_wont(subchar)) { 853 return; 854 } 855 break; 856 default: 857 return; 858 } 859 env_opt(subpointer, SB_LEN()); 860 break; 861 862 case TELOPT_XDISPLOC: 863 if (my_want_state_is_wont(TELOPT_XDISPLOC)) 864 return; 865 if (SB_EOF()) 866 return; 867 if (SB_GET() == TELQUAL_SEND) { 868 unsigned char temp[50], *dp; 869 int len; 870 871 if ((dp = env_getvalue("DISPLAY")) == NULL || 872 strlen(dp) > sizeof(temp) - 7) { 873 /* 874 * Something happened, we no longer have a DISPLAY 875 * variable. Or it is too long. So, turn off the option. 876 */ 877 send_wont(TELOPT_XDISPLOC, 1); 878 break; 879 } 880 snprintf(temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB, 881 TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); 882 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 883 884 if (len < NETROOM()) { 885 ring_supply_data(&netoring, temp, len); 886 printsub('>', temp+2, len - 2); 887 } 888 /*@*/ else printf("lm_will: not enough room in buffer\n"); 889 } 890 break; 891 892 #ifdef AUTHENTICATION 893 case TELOPT_AUTHENTICATION: { 894 if (!autologin) 895 break; 896 if (SB_EOF()) 897 return; 898 switch(SB_GET()) { 899 case TELQUAL_IS: 900 if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) 901 return; 902 auth_is(subpointer, SB_LEN()); 903 break; 904 case TELQUAL_SEND: 905 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 906 return; 907 auth_send(subpointer, SB_LEN()); 908 break; 909 case TELQUAL_REPLY: 910 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 911 return; 912 auth_reply(subpointer, SB_LEN()); 913 break; 914 case TELQUAL_NAME: 915 if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) 916 return; 917 auth_name(subpointer, SB_LEN()); 918 break; 919 } 920 } 921 break; 922 #endif 923 #ifdef ENCRYPTION 924 case TELOPT_ENCRYPT: 925 if (SB_EOF()) 926 return; 927 switch(SB_GET()) { 928 case ENCRYPT_START: 929 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 930 return; 931 encrypt_start(subpointer, SB_LEN()); 932 break; 933 case ENCRYPT_END: 934 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 935 return; 936 encrypt_end(); 937 break; 938 case ENCRYPT_SUPPORT: 939 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 940 return; 941 encrypt_support(subpointer, SB_LEN()); 942 break; 943 case ENCRYPT_REQSTART: 944 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 945 return; 946 encrypt_request_start(subpointer, SB_LEN()); 947 break; 948 case ENCRYPT_REQEND: 949 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 950 return; 951 /* 952 * We can always send an REQEND so that we cannot 953 * get stuck encrypting. We should only get this 954 * if we have been able to get in the correct mode 955 * anyhow. 956 */ 957 encrypt_request_end(); 958 break; 959 case ENCRYPT_IS: 960 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 961 return; 962 encrypt_is(subpointer, SB_LEN()); 963 break; 964 case ENCRYPT_REPLY: 965 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 966 return; 967 encrypt_reply(subpointer, SB_LEN()); 968 break; 969 case ENCRYPT_ENC_KEYID: 970 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 971 return; 972 encrypt_enc_keyid(subpointer, SB_LEN()); 973 break; 974 case ENCRYPT_DEC_KEYID: 975 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 976 return; 977 encrypt_dec_keyid(subpointer, SB_LEN()); 978 break; 979 default: 980 break; 981 } 982 break; 983 #endif /* ENCRYPTION */ 984 default: 985 break; 986 } 987 } 988 989 static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; 990 991 void 992 lm_will(unsigned char *cmd, int len) 993 { 994 if (len < 1) { 995 /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ 996 return; 997 } 998 switch(cmd[0]) { 999 case LM_FORWARDMASK: /* We shouldn't ever get this... */ 1000 default: 1001 str_lm[3] = DONT; 1002 str_lm[4] = cmd[0]; 1003 if (NETROOM() > (int)sizeof(str_lm)) { 1004 ring_supply_data(&netoring, str_lm, sizeof(str_lm)); 1005 printsub('>', &str_lm[2], sizeof(str_lm)-2); 1006 } 1007 /*@*/ else printf("lm_will: not enough room in buffer\n"); 1008 break; 1009 } 1010 } 1011 1012 void 1013 lm_wont(unsigned char *cmd, int len) 1014 { 1015 if (len < 1) { 1016 /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ 1017 return; 1018 } 1019 switch(cmd[0]) { 1020 case LM_FORWARDMASK: /* We shouldn't ever get this... */ 1021 default: 1022 /* We are always DONT, so don't respond */ 1023 return; 1024 } 1025 } 1026 1027 void 1028 lm_do(unsigned char *cmd, int len) 1029 { 1030 if (len < 1) { 1031 /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ 1032 return; 1033 } 1034 switch(cmd[0]) { 1035 case LM_FORWARDMASK: 1036 default: 1037 str_lm[3] = WONT; 1038 str_lm[4] = cmd[0]; 1039 if (NETROOM() > (int)sizeof(str_lm)) { 1040 ring_supply_data(&netoring, str_lm, sizeof(str_lm)); 1041 printsub('>', &str_lm[2], sizeof(str_lm)-2); 1042 } 1043 /*@*/ else printf("lm_do: not enough room in buffer\n"); 1044 break; 1045 } 1046 } 1047 1048 void 1049 lm_dont(unsigned char *cmd, int len) 1050 { 1051 if (len < 1) { 1052 /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ 1053 return; 1054 } 1055 switch(cmd[0]) { 1056 case LM_FORWARDMASK: 1057 default: 1058 /* we are always WONT, so don't respond */ 1059 break; 1060 } 1061 } 1062 1063 static unsigned char str_lm_mode[] = { 1064 IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE 1065 }; 1066 1067 void 1068 lm_mode(unsigned char *cmd, int len, int init) 1069 { 1070 if (len != 1) 1071 return; 1072 if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) 1073 return; 1074 if (*cmd&MODE_ACK) 1075 return; 1076 linemode = *cmd&(MODE_MASK&~MODE_ACK); 1077 str_lm_mode[4] = linemode; 1078 if (!init) 1079 str_lm_mode[4] |= MODE_ACK; 1080 if (NETROOM() > (int)sizeof(str_lm_mode)) { 1081 ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); 1082 printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); 1083 } 1084 /*@*/ else printf("lm_mode: not enough room in buffer\n"); 1085 setconnmode(0); /* set changed mode */ 1086 } 1087 1088 1089 1090 /* 1091 * slc() 1092 * Handle special character suboption of LINEMODE. 1093 */ 1094 1095 struct spc { 1096 cc_t val; 1097 cc_t *valp; 1098 char flags; /* Current flags & level */ 1099 char mylevel; /* Maximum level & flags */ 1100 } spc_data[NSLC+1]; 1101 1102 #define SLC_IMPORT 0 1103 #define SLC_EXPORT 1 1104 #define SLC_RVALUE 2 1105 static int slc_mode = SLC_EXPORT; 1106 1107 void 1108 slc_init(void) 1109 { 1110 struct spc *spcp; 1111 1112 localchars = 1; 1113 for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { 1114 spcp->val = 0; 1115 spcp->valp = 0; 1116 spcp->flags = spcp->mylevel = SLC_NOSUPPORT; 1117 } 1118 1119 #define initfunc(func, flags) { \ 1120 spcp = &spc_data[func]; \ 1121 if ((spcp->valp = tcval(func))) { \ 1122 spcp->val = *spcp->valp; \ 1123 spcp->mylevel = SLC_VARIABLE|flags; \ 1124 } else { \ 1125 spcp->val = 0; \ 1126 spcp->mylevel = SLC_DEFAULT; \ 1127 } \ 1128 } 1129 1130 initfunc(SLC_SYNCH, 0); 1131 /* No BRK */ 1132 initfunc(SLC_AO, 0); 1133 initfunc(SLC_AYT, 0); 1134 /* No EOR */ 1135 initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); 1136 initfunc(SLC_EOF, 0); 1137 #ifndef SYSV_TERMIO 1138 initfunc(SLC_SUSP, SLC_FLUSHIN); 1139 #endif 1140 initfunc(SLC_EC, 0); 1141 initfunc(SLC_EL, 0); 1142 #ifndef SYSV_TERMIO 1143 initfunc(SLC_EW, 0); 1144 initfunc(SLC_RP, 0); 1145 initfunc(SLC_LNEXT, 0); 1146 #endif 1147 initfunc(SLC_XON, 0); 1148 initfunc(SLC_XOFF, 0); 1149 #ifdef SYSV_TERMIO 1150 spc_data[SLC_XON].mylevel = SLC_CANTCHANGE; 1151 spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE; 1152 #endif 1153 initfunc(SLC_FORW1, 0); 1154 #ifdef USE_TERMIO 1155 initfunc(SLC_FORW2, 0); 1156 /* No FORW2 */ 1157 #endif 1158 1159 initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); 1160 #undef initfunc 1161 1162 if (slc_mode == SLC_EXPORT) 1163 slc_export(); 1164 else 1165 slc_import(1); 1166 1167 } 1168 1169 void 1170 slcstate(void) 1171 { 1172 printf("Special characters are %s values\n", 1173 slc_mode == SLC_IMPORT ? "remote default" : 1174 slc_mode == SLC_EXPORT ? "local" : 1175 "remote"); 1176 } 1177 1178 void 1179 slc_mode_export(void) 1180 { 1181 slc_mode = SLC_EXPORT; 1182 if (my_state_is_will(TELOPT_LINEMODE)) 1183 slc_export(); 1184 } 1185 1186 void 1187 slc_mode_import(int def) 1188 { 1189 slc_mode = def ? SLC_IMPORT : SLC_RVALUE; 1190 if (my_state_is_will(TELOPT_LINEMODE)) 1191 slc_import(def); 1192 } 1193 1194 unsigned char slc_import_val[] = { 1195 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE 1196 }; 1197 unsigned char slc_import_def[] = { 1198 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE 1199 }; 1200 1201 void 1202 slc_import(int def) 1203 { 1204 if (NETROOM() > (int)sizeof(slc_import_val)) { 1205 if (def) { 1206 ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); 1207 printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); 1208 } else { 1209 ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); 1210 printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); 1211 } 1212 } 1213 /*@*/ else printf("slc_import: not enough room\n"); 1214 } 1215 1216 void 1217 slc_export(void) 1218 { 1219 struct spc *spcp; 1220 1221 TerminalDefaultChars(); 1222 1223 slc_start_reply(); 1224 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1225 if (spcp->mylevel != SLC_NOSUPPORT) { 1226 if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 1227 spcp->flags = SLC_NOSUPPORT; 1228 else 1229 spcp->flags = spcp->mylevel; 1230 if (spcp->valp) 1231 spcp->val = *spcp->valp; 1232 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 1233 } 1234 } 1235 slc_end_reply(); 1236 (void)slc_update(); 1237 setconnmode(1); /* Make sure the character values are set */ 1238 } 1239 1240 void 1241 slc(unsigned char *cp, int len) 1242 { 1243 struct spc *spcp; 1244 int func,level; 1245 1246 slc_start_reply(); 1247 1248 for (; len >= 3; len -=3, cp +=3) { 1249 1250 func = cp[SLC_FUNC]; 1251 1252 if (func == 0) { 1253 /* 1254 * Client side: always ignore 0 function. 1255 */ 1256 continue; 1257 } 1258 if (func > NSLC) { 1259 if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) 1260 slc_add_reply(func, SLC_NOSUPPORT, 0); 1261 continue; 1262 } 1263 1264 spcp = &spc_data[func]; 1265 1266 level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); 1267 1268 if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && 1269 ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { 1270 continue; 1271 } 1272 1273 if (level == (SLC_DEFAULT|SLC_ACK)) { 1274 /* 1275 * This is an error condition, the SLC_ACK 1276 * bit should never be set for the SLC_DEFAULT 1277 * level. Our best guess to recover is to 1278 * ignore the SLC_ACK bit. 1279 */ 1280 cp[SLC_FLAGS] &= ~SLC_ACK; 1281 } 1282 1283 if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { 1284 spcp->val = (cc_t)cp[SLC_VALUE]; 1285 spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ 1286 continue; 1287 } 1288 1289 level &= ~SLC_ACK; 1290 1291 if (level <= (spcp->mylevel&SLC_LEVELBITS)) { 1292 spcp->flags = cp[SLC_FLAGS]|SLC_ACK; 1293 spcp->val = (cc_t)cp[SLC_VALUE]; 1294 } 1295 if (level == SLC_DEFAULT) { 1296 if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) 1297 spcp->flags = spcp->mylevel; 1298 else 1299 spcp->flags = SLC_NOSUPPORT; 1300 } 1301 slc_add_reply(func, spcp->flags, spcp->val); 1302 } 1303 slc_end_reply(); 1304 if (slc_update()) 1305 setconnmode(1); /* set the new character values */ 1306 } 1307 1308 void 1309 slc_check(void) 1310 { 1311 struct spc *spcp; 1312 1313 slc_start_reply(); 1314 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1315 if (spcp->valp && spcp->val != *spcp->valp) { 1316 spcp->val = *spcp->valp; 1317 if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 1318 spcp->flags = SLC_NOSUPPORT; 1319 else 1320 spcp->flags = spcp->mylevel; 1321 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 1322 } 1323 } 1324 slc_end_reply(); 1325 setconnmode(1); 1326 } 1327 1328 unsigned char slc_reply[128]; 1329 unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)]; 1330 unsigned char *slc_replyp; 1331 1332 void 1333 slc_start_reply(void) 1334 { 1335 slc_replyp = slc_reply; 1336 *slc_replyp++ = IAC; 1337 *slc_replyp++ = SB; 1338 *slc_replyp++ = TELOPT_LINEMODE; 1339 *slc_replyp++ = LM_SLC; 1340 } 1341 1342 void 1343 slc_add_reply(unsigned char func, unsigned char flags, cc_t value) 1344 { 1345 /* A sequence of up to 6 bytes my be written for this member of the SLC 1346 * suboption list by this function. The end of negotiation command, 1347 * which is written by slc_end_reply(), will require 2 additional 1348 * bytes. Do not proceed unless there is sufficient space for these 1349 * items. 1350 */ 1351 if (&slc_replyp[6+2] > slc_reply_eom) 1352 return; 1353 if ((*slc_replyp++ = func) == IAC) 1354 *slc_replyp++ = IAC; 1355 if ((*slc_replyp++ = flags) == IAC) 1356 *slc_replyp++ = IAC; 1357 if ((*slc_replyp++ = (unsigned char)value) == IAC) 1358 *slc_replyp++ = IAC; 1359 } 1360 1361 void 1362 slc_end_reply(void) 1363 { 1364 int len; 1365 1366 /* The end of negotiation command requires 2 bytes. */ 1367 if (&slc_replyp[2] > slc_reply_eom) 1368 return; 1369 *slc_replyp++ = IAC; 1370 *slc_replyp++ = SE; 1371 len = slc_replyp - slc_reply; 1372 if (len <= 6) 1373 return; 1374 if (NETROOM() > len) { 1375 ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); 1376 printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); 1377 } 1378 /*@*/else printf("slc_end_reply: not enough room\n"); 1379 } 1380 1381 int 1382 slc_update(void) 1383 { 1384 struct spc *spcp; 1385 int need_update = 0; 1386 1387 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1388 if (!(spcp->flags&SLC_ACK)) 1389 continue; 1390 spcp->flags &= ~SLC_ACK; 1391 if (spcp->valp && (*spcp->valp != spcp->val)) { 1392 *spcp->valp = spcp->val; 1393 need_update = 1; 1394 } 1395 } 1396 return(need_update); 1397 } 1398 1399 #ifdef OLD_ENVIRON 1400 # ifdef ENV_HACK 1401 /* 1402 * Earlier version of telnet/telnetd from the BSD code had 1403 * the definitions of VALUE and VAR reversed. To ensure 1404 * maximum interoperability, we assume that the server is 1405 * an older BSD server, until proven otherwise. The newer 1406 * BSD servers should be able to handle either definition, 1407 * so it is better to use the wrong values if we don't 1408 * know what type of server it is. 1409 */ 1410 int env_auto = 1; 1411 int old_env_var = OLD_ENV_VAR; 1412 int old_env_value = OLD_ENV_VALUE; 1413 # else 1414 # define old_env_var OLD_ENV_VAR 1415 # define old_env_value OLD_ENV_VALUE 1416 # endif 1417 #endif 1418 1419 void 1420 env_opt(unsigned char *buf, int len) 1421 { 1422 unsigned char *ep = 0, *epc = 0; 1423 int i; 1424 1425 switch(buf[0]&0xff) { 1426 case TELQUAL_SEND: 1427 env_opt_start(); 1428 if (len == 1) { 1429 env_opt_add(NULL); 1430 } else for (i = 1; i < len; i++) { 1431 switch (buf[i]&0xff) { 1432 #ifdef OLD_ENVIRON 1433 case OLD_ENV_VAR: 1434 # ifdef ENV_HACK 1435 if (telopt_environ == TELOPT_OLD_ENVIRON 1436 && env_auto) { 1437 /* Server has the same definitions */ 1438 old_env_var = OLD_ENV_VAR; 1439 old_env_value = OLD_ENV_VALUE; 1440 } 1441 /* FALLTHROUGH */ 1442 # endif 1443 case OLD_ENV_VALUE: 1444 /* 1445 * Although OLD_ENV_VALUE is not legal, we will 1446 * still recognize it, just in case it is an 1447 * old server that has VAR & VALUE mixed up... 1448 */ 1449 /* FALLTHROUGH */ 1450 #else 1451 case NEW_ENV_VAR: 1452 #endif 1453 case ENV_USERVAR: 1454 if (ep) { 1455 *epc = 0; 1456 env_opt_add(ep); 1457 } 1458 ep = epc = &buf[i+1]; 1459 break; 1460 case ENV_ESC: 1461 i++; 1462 /*FALLTHROUGH*/ 1463 default: 1464 if (epc) 1465 *epc++ = buf[i]; 1466 break; 1467 } 1468 } 1469 if (ep) { 1470 *epc = 0; 1471 env_opt_add(ep); 1472 } 1473 env_opt_end(1); 1474 break; 1475 1476 case TELQUAL_IS: 1477 case TELQUAL_INFO: 1478 /* Ignore for now. We shouldn't get it anyway. */ 1479 break; 1480 1481 default: 1482 break; 1483 } 1484 } 1485 1486 #define OPT_REPLY_SIZE (2 * SUBBUFSIZE) 1487 unsigned char *opt_reply = NULL; 1488 unsigned char *opt_replyp; 1489 unsigned char *opt_replyend; 1490 1491 void 1492 env_opt_start(void) 1493 { 1494 if (opt_reply) 1495 opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); 1496 else 1497 opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE); 1498 if (opt_reply == NULL) { 1499 /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); 1500 opt_reply = opt_replyp = opt_replyend = NULL; 1501 return; 1502 } 1503 opt_replyp = opt_reply; 1504 opt_replyend = opt_reply + OPT_REPLY_SIZE; 1505 *opt_replyp++ = IAC; 1506 *opt_replyp++ = SB; 1507 *opt_replyp++ = telopt_environ; 1508 *opt_replyp++ = TELQUAL_IS; 1509 } 1510 1511 void 1512 env_opt_start_info(void) 1513 { 1514 env_opt_start(); 1515 if (opt_replyp) 1516 opt_replyp[-1] = TELQUAL_INFO; 1517 } 1518 1519 void 1520 env_opt_add(unsigned char *ep) 1521 { 1522 unsigned char *vp, c; 1523 1524 if (opt_reply == NULL) /*XXX*/ 1525 return; /*XXX*/ 1526 1527 if (ep == NULL || *ep == '\0') { 1528 /* Send user defined variables first. */ 1529 env_default(1, 0); 1530 while ((ep = env_default(0, 0))) 1531 env_opt_add(ep); 1532 1533 /* Now add the list of well know variables. */ 1534 env_default(1, 1); 1535 while ((ep = env_default(0, 1))) 1536 env_opt_add(ep); 1537 return; 1538 } 1539 vp = env_getvalue(ep); 1540 if (opt_replyp + (vp ? 2 * strlen((char *)vp) : 0) + 1541 2 * strlen((char *)ep) + 6 > opt_replyend) 1542 { 1543 int len; 1544 opt_replyend += OPT_REPLY_SIZE; 1545 len = opt_replyend - opt_reply; 1546 opt_reply = (unsigned char *)realloc(opt_reply, len); 1547 if (opt_reply == NULL) { 1548 /*@*/ printf("env_opt_add: realloc() failed!!!\n"); 1549 opt_reply = opt_replyp = opt_replyend = NULL; 1550 return; 1551 } 1552 opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); 1553 opt_replyend = opt_reply + len; 1554 } 1555 if (opt_welldefined(ep)) 1556 #ifdef OLD_ENVIRON 1557 if (telopt_environ == TELOPT_OLD_ENVIRON) 1558 *opt_replyp++ = old_env_var; 1559 else 1560 #endif 1561 *opt_replyp++ = NEW_ENV_VAR; 1562 else 1563 *opt_replyp++ = ENV_USERVAR; 1564 for (;;) { 1565 while ((c = *ep++)) { 1566 if (opt_replyp + (2 + 2) > opt_replyend) 1567 return; 1568 switch(c&0xff) { 1569 case IAC: 1570 *opt_replyp++ = IAC; 1571 break; 1572 case NEW_ENV_VAR: 1573 case NEW_ENV_VALUE: 1574 case ENV_ESC: 1575 case ENV_USERVAR: 1576 *opt_replyp++ = ENV_ESC; 1577 break; 1578 } 1579 *opt_replyp++ = c; 1580 } 1581 if ((ep = vp)) { 1582 if (opt_replyp + (1 + 2 + 2) > opt_replyend) 1583 return; 1584 #ifdef OLD_ENVIRON 1585 if (telopt_environ == TELOPT_OLD_ENVIRON) 1586 *opt_replyp++ = old_env_value; 1587 else 1588 #endif 1589 *opt_replyp++ = NEW_ENV_VALUE; 1590 vp = NULL; 1591 } else 1592 break; 1593 } 1594 } 1595 1596 int 1597 opt_welldefined(const char *ep) 1598 { 1599 if ((strcmp(ep, "USER") == 0) || 1600 (strcmp(ep, "DISPLAY") == 0) || 1601 (strcmp(ep, "PRINTER") == 0) || 1602 (strcmp(ep, "SYSTEMTYPE") == 0) || 1603 (strcmp(ep, "JOB") == 0) || 1604 (strcmp(ep, "ACCT") == 0)) 1605 return(1); 1606 return(0); 1607 } 1608 1609 void 1610 env_opt_end(int emptyok) 1611 { 1612 int len; 1613 1614 if (opt_replyp + 2 > opt_replyend) 1615 return; 1616 len = opt_replyp + 2 - opt_reply; 1617 if (emptyok || len > 6) { 1618 *opt_replyp++ = IAC; 1619 *opt_replyp++ = SE; 1620 if (NETROOM() > len) { 1621 ring_supply_data(&netoring, opt_reply, len); 1622 printsub('>', &opt_reply[2], len - 2); 1623 } 1624 /*@*/ else printf("slc_end_reply: not enough room\n"); 1625 } 1626 if (opt_reply) { 1627 free(opt_reply); 1628 opt_reply = opt_replyp = opt_replyend = NULL; 1629 } 1630 } 1631 1632 1633 1634 int 1635 telrcv(void) 1636 { 1637 int c; 1638 int scc; 1639 unsigned char *sbp; 1640 int count; 1641 int returnValue = 0; 1642 1643 scc = 0; 1644 count = 0; 1645 while (TTYROOM() > 2) { 1646 if (scc == 0) { 1647 if (count) { 1648 ring_consumed(&netiring, count); 1649 returnValue = 1; 1650 count = 0; 1651 } 1652 sbp = netiring.consume; 1653 scc = ring_full_consecutive(&netiring); 1654 if (scc == 0) { 1655 /* No more data coming in */ 1656 break; 1657 } 1658 } 1659 1660 c = *sbp++ & 0xff, scc--; count++; 1661 #ifdef ENCRYPTION 1662 if (decrypt_input) 1663 c = (*decrypt_input)(c); 1664 #endif /* ENCRYPTION */ 1665 1666 switch (telrcv_state) { 1667 1668 case TS_CR: 1669 telrcv_state = TS_DATA; 1670 if (c == '\0') { 1671 break; /* Ignore \0 after CR */ 1672 } 1673 else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { 1674 TTYADD(c); 1675 break; 1676 } 1677 /* FALLTHROUGH */ 1678 1679 case TS_DATA: 1680 if (c == IAC && telnetport >= 0) { 1681 telrcv_state = TS_IAC; 1682 break; 1683 } 1684 /* 1685 * The 'crmod' hack (see following) is needed 1686 * since we can't * set CRMOD on output only. 1687 * Machines like MULTICS like to send \r without 1688 * \n; since we must turn off CRMOD to get proper 1689 * input, the mapping is done here (sigh). 1690 */ 1691 if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { 1692 if (scc > 0) { 1693 c = *sbp&0xff; 1694 #ifdef ENCRYPTION 1695 if (decrypt_input) 1696 c = (*decrypt_input)(c); 1697 #endif /* ENCRYPTION */ 1698 if (c == 0) { 1699 sbp++, scc--; count++; 1700 /* a "true" CR */ 1701 TTYADD('\r'); 1702 } else if (my_want_state_is_dont(TELOPT_ECHO) && 1703 (c == '\n')) { 1704 sbp++, scc--; count++; 1705 TTYADD('\n'); 1706 } else { 1707 #ifdef ENCRYPTION 1708 if (decrypt_input) 1709 (*decrypt_input)(-1); 1710 #endif /* ENCRYPTION */ 1711 1712 TTYADD('\r'); 1713 if (crmod) { 1714 TTYADD('\n'); 1715 } 1716 } 1717 } else { 1718 telrcv_state = TS_CR; 1719 TTYADD('\r'); 1720 if (crmod) { 1721 TTYADD('\n'); 1722 } 1723 } 1724 } else { 1725 TTYADD(c); 1726 } 1727 continue; 1728 1729 case TS_IAC: 1730 process_iac: 1731 switch (c) { 1732 1733 case WILL: 1734 telrcv_state = TS_WILL; 1735 continue; 1736 1737 case WONT: 1738 telrcv_state = TS_WONT; 1739 continue; 1740 1741 case DO: 1742 telrcv_state = TS_DO; 1743 continue; 1744 1745 case DONT: 1746 telrcv_state = TS_DONT; 1747 continue; 1748 1749 case DM: 1750 /* 1751 * We may have missed an urgent notification, 1752 * so make sure we flush whatever is in the 1753 * buffer currently. 1754 */ 1755 printoption("RCVD", IAC, DM); 1756 SYNCHing = 1; 1757 (void) ttyflush(1); 1758 SYNCHing = stilloob(); 1759 settimer(gotDM); 1760 break; 1761 1762 case SB: 1763 SB_CLEAR(); 1764 telrcv_state = TS_SB; 1765 continue; 1766 1767 case IAC: 1768 TTYADD(IAC); 1769 break; 1770 1771 case NOP: 1772 case GA: 1773 default: 1774 printoption("RCVD", IAC, c); 1775 break; 1776 } 1777 telrcv_state = TS_DATA; 1778 continue; 1779 1780 case TS_WILL: 1781 printoption("RCVD", WILL, c); 1782 willoption(c); 1783 telrcv_state = TS_DATA; 1784 continue; 1785 1786 case TS_WONT: 1787 printoption("RCVD", WONT, c); 1788 wontoption(c); 1789 telrcv_state = TS_DATA; 1790 continue; 1791 1792 case TS_DO: 1793 printoption("RCVD", DO, c); 1794 dooption(c); 1795 if (c == TELOPT_NAWS) { 1796 sendnaws(); 1797 } else if (c == TELOPT_LFLOW) { 1798 localflow = 1; 1799 setcommandmode(); 1800 setconnmode(0); 1801 } 1802 telrcv_state = TS_DATA; 1803 continue; 1804 1805 case TS_DONT: 1806 printoption("RCVD", DONT, c); 1807 dontoption(c); 1808 flushline = 1; 1809 setconnmode(0); /* set new tty mode (maybe) */ 1810 telrcv_state = TS_DATA; 1811 continue; 1812 1813 case TS_SB: 1814 if (c == IAC) { 1815 telrcv_state = TS_SE; 1816 } else { 1817 SB_ACCUM(c); 1818 } 1819 continue; 1820 1821 case TS_SE: 1822 if (c != SE) { 1823 if (c != IAC) { 1824 /* 1825 * This is an error. We only expect to get 1826 * "IAC IAC" or "IAC SE". Several things may 1827 * have happend. An IAC was not doubled, the 1828 * IAC SE was left off, or another option got 1829 * inserted into the suboption are all possibilities. 1830 * If we assume that the IAC was not doubled, 1831 * and really the IAC SE was left off, we could 1832 * get into an infinate loop here. So, instead, 1833 * we terminate the suboption, and process the 1834 * partial suboption if we can. 1835 */ 1836 SB_ACCUM(IAC); 1837 SB_ACCUM(c); 1838 subpointer -= 2; 1839 SB_TERM(); 1840 1841 printoption("In SUBOPTION processing, RCVD", IAC, c); 1842 suboption(); /* handle sub-option */ 1843 telrcv_state = TS_IAC; 1844 goto process_iac; 1845 } 1846 SB_ACCUM(c); 1847 telrcv_state = TS_SB; 1848 } else { 1849 SB_ACCUM(IAC); 1850 SB_ACCUM(SE); 1851 subpointer -= 2; 1852 SB_TERM(); 1853 suboption(); /* handle sub-option */ 1854 telrcv_state = TS_DATA; 1855 } 1856 } 1857 } 1858 if (count) 1859 ring_consumed(&netiring, count); 1860 return returnValue||count; 1861 } 1862 1863 static int bol = 1, local = 0; 1864 1865 int 1866 rlogin_susp(void) 1867 { 1868 if (local) { 1869 local = 0; 1870 bol = 1; 1871 command(0, "z\n", 2); 1872 return(1); 1873 } 1874 return(0); 1875 } 1876 1877 static int 1878 telsnd(void) 1879 { 1880 int tcc; 1881 int count; 1882 int returnValue = 0; 1883 unsigned char *tbp; 1884 1885 tcc = 0; 1886 count = 0; 1887 while (NETROOM() > 2) { 1888 int sc; 1889 int c; 1890 1891 if (tcc == 0) { 1892 if (count) { 1893 ring_consumed(&ttyiring, count); 1894 returnValue = 1; 1895 count = 0; 1896 } 1897 tbp = ttyiring.consume; 1898 tcc = ring_full_consecutive(&ttyiring); 1899 if (tcc == 0) { 1900 break; 1901 } 1902 } 1903 c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; 1904 if (rlogin != _POSIX_VDISABLE) { 1905 if (bol) { 1906 bol = 0; 1907 if (sc == rlogin) { 1908 local = 1; 1909 continue; 1910 } 1911 } else if (local) { 1912 local = 0; 1913 if (sc == '.' || c == termEofChar) { 1914 bol = 1; 1915 command(0, "close\n", 6); 1916 continue; 1917 } 1918 if (sc == termSuspChar) { 1919 bol = 1; 1920 command(0, "z\n", 2); 1921 continue; 1922 } 1923 if (sc == escape) { 1924 command(0, tbp, tcc); 1925 bol = 1; 1926 count += tcc; 1927 tcc = 0; 1928 flushline = 1; 1929 break; 1930 } 1931 if (sc != rlogin) { 1932 ++tcc; 1933 --tbp; 1934 --count; 1935 c = sc = rlogin; 1936 } 1937 } 1938 if ((sc == '\n') || (sc == '\r')) 1939 bol = 1; 1940 } else if (escape != _POSIX_VDISABLE && sc == escape) { 1941 /* 1942 * Double escape is a pass through of a single escape character. 1943 */ 1944 if (tcc && strip(*tbp) == escape) { 1945 tbp++; 1946 tcc--; 1947 count++; 1948 bol = 0; 1949 } else { 1950 command(0, (char *)tbp, tcc); 1951 bol = 1; 1952 count += tcc; 1953 tcc = 0; 1954 flushline = 1; 1955 break; 1956 } 1957 } else 1958 bol = 0; 1959 #ifdef KLUDGELINEMODE 1960 if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { 1961 if (tcc > 0 && strip(*tbp) == echoc) { 1962 tcc--; tbp++; count++; 1963 } else { 1964 dontlecho = !dontlecho; 1965 settimer(echotoggle); 1966 setconnmode(0); 1967 flushline = 1; 1968 break; 1969 } 1970 } 1971 #endif 1972 if (MODE_LOCAL_CHARS(globalmode)) { 1973 if (TerminalSpecialChars(sc) == 0) { 1974 bol = 1; 1975 break; 1976 } 1977 } 1978 if (my_want_state_is_wont(TELOPT_BINARY)) { 1979 switch (c) { 1980 case '\n': 1981 /* 1982 * If we are in CRMOD mode (\r ==> \n) 1983 * on our local machine, then probably 1984 * a newline (unix) is CRLF (TELNET). 1985 */ 1986 if (MODE_LOCAL_CHARS(globalmode)) { 1987 NETADD('\r'); 1988 } 1989 NETADD('\n'); 1990 bol = flushline = 1; 1991 break; 1992 case '\r': 1993 if (!crlf) { 1994 NET2ADD('\r', '\0'); 1995 } else { 1996 NET2ADD('\r', '\n'); 1997 } 1998 bol = flushline = 1; 1999 break; 2000 case IAC: 2001 NET2ADD(IAC, IAC); 2002 break; 2003 default: 2004 NETADD(c); 2005 break; 2006 } 2007 } else if (c == IAC) { 2008 NET2ADD(IAC, IAC); 2009 } else { 2010 NETADD(c); 2011 } 2012 } 2013 if (count) 2014 ring_consumed(&ttyiring, count); 2015 return returnValue||count; /* Non-zero if we did anything */ 2016 } 2017 2018 /* 2019 * Scheduler() 2020 * 2021 * Try to do something. 2022 * 2023 * If we do something useful, return 1; else return 0. 2024 * 2025 */ 2026 2027 static int 2028 Scheduler(int block) 2029 { 2030 /* One wants to be a bit careful about setting returnValue 2031 * to one, since a one implies we did some useful work, 2032 * and therefore probably won't be called to block next 2033 */ 2034 int returnValue; 2035 int netin, netout, netex, ttyin, ttyout; 2036 2037 /* Decide which rings should be processed */ 2038 2039 netout = ring_full_count(&netoring) && 2040 (flushline || 2041 (my_want_state_is_wont(TELOPT_LINEMODE) 2042 #ifdef KLUDGELINEMODE 2043 && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) 2044 #endif 2045 ) || 2046 my_want_state_is_will(TELOPT_BINARY)); 2047 ttyout = ring_full_count(&ttyoring); 2048 2049 ttyin = ring_empty_count(&ttyiring) && (clienteof == 0); 2050 2051 netin = !ISend && ring_empty_count(&netiring); 2052 2053 netex = !SYNCHing; 2054 2055 /* Call to system code to process rings */ 2056 2057 returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); 2058 2059 /* Now, look at the input rings, looking for work to do. */ 2060 2061 if (ring_full_count(&ttyiring)) { 2062 returnValue |= telsnd(); 2063 } 2064 2065 if (ring_full_count(&netiring)) { 2066 returnValue |= telrcv(); 2067 } 2068 return returnValue; 2069 } 2070 2071 #ifdef AUTHENTICATION 2072 #define __unusedhere 2073 #else 2074 #define __unusedhere __unused 2075 #endif 2076 /* 2077 * Select from tty and network... 2078 */ 2079 void 2080 telnet(char *user __unusedhere) 2081 { 2082 sys_telnet_init(); 2083 2084 #ifdef AUTHENTICATION 2085 #ifdef ENCRYPTION 2086 { 2087 static char local_host[256] = { 0 }; 2088 2089 if (!local_host[0]) { 2090 gethostname(local_host, sizeof(local_host)); 2091 local_host[sizeof(local_host)-1] = 0; 2092 } 2093 auth_encrypt_init(local_host, hostname, "TELNET", 0); 2094 auth_encrypt_user(user); 2095 } 2096 #endif 2097 #endif 2098 if (telnetport > 0) { 2099 #ifdef AUTHENTICATION 2100 if (autologin) 2101 send_will(TELOPT_AUTHENTICATION, 1); 2102 #endif 2103 #ifdef ENCRYPTION 2104 send_do(TELOPT_ENCRYPT, 1); 2105 send_will(TELOPT_ENCRYPT, 1); 2106 #endif /* ENCRYPTION */ 2107 send_do(TELOPT_SGA, 1); 2108 send_will(TELOPT_TTYPE, 1); 2109 send_will(TELOPT_NAWS, 1); 2110 send_will(TELOPT_TSPEED, 1); 2111 send_will(TELOPT_LFLOW, 1); 2112 send_will(TELOPT_LINEMODE, 1); 2113 send_will(TELOPT_NEW_ENVIRON, 1); 2114 send_do(TELOPT_STATUS, 1); 2115 if (env_getvalue("DISPLAY")) 2116 send_will(TELOPT_XDISPLOC, 1); 2117 if (eight) 2118 tel_enter_binary(eight); 2119 } 2120 2121 for (;;) { 2122 int schedValue; 2123 2124 while ((schedValue = Scheduler(0)) != 0) { 2125 if (schedValue == -1) { 2126 setcommandmode(); 2127 return; 2128 } 2129 } 2130 2131 if (Scheduler(1) == -1) { 2132 setcommandmode(); 2133 return; 2134 } 2135 } 2136 } 2137 2138 #if 0 /* XXX - this not being in is a bug */ 2139 /* 2140 * nextitem() 2141 * 2142 * Return the address of the next "item" in the TELNET data 2143 * stream. This will be the address of the next character if 2144 * the current address is a user data character, or it will 2145 * be the address of the character following the TELNET command 2146 * if the current address is a TELNET IAC ("I Am a Command") 2147 * character. 2148 */ 2149 2150 static char * 2151 nextitem(char *current) 2152 { 2153 if ((*current&0xff) != IAC) { 2154 return current+1; 2155 } 2156 switch (*(current+1)&0xff) { 2157 case DO: 2158 case DONT: 2159 case WILL: 2160 case WONT: 2161 return current+3; 2162 case SB: /* loop forever looking for the SE */ 2163 { 2164 char *look = current+2; 2165 2166 for (;;) { 2167 if ((*look++&0xff) == IAC) { 2168 if ((*look++&0xff) == SE) { 2169 return look; 2170 } 2171 } 2172 } 2173 } 2174 default: 2175 return current+2; 2176 } 2177 } 2178 #endif /* 0 */ 2179 2180 /* 2181 * netclear() 2182 * 2183 * We are about to do a TELNET SYNCH operation. Clear 2184 * the path to the network. 2185 * 2186 * Things are a bit tricky since we may have sent the first 2187 * byte or so of a previous TELNET command into the network. 2188 * So, we have to scan the network buffer from the beginning 2189 * until we are up to where we want to be. 2190 * 2191 * A side effect of what we do, just to keep things 2192 * simple, is to clear the urgent data pointer. The principal 2193 * caller should be setting the urgent data pointer AFTER calling 2194 * us in any case. 2195 */ 2196 2197 static void 2198 netclear(void) 2199 { 2200 /* Deleted */ 2201 } 2202 2203 /* 2204 * These routines add various telnet commands to the data stream. 2205 */ 2206 2207 static void 2208 doflush(void) 2209 { 2210 NET2ADD(IAC, DO); 2211 NETADD(TELOPT_TM); 2212 flushline = 1; 2213 flushout = 1; 2214 (void) ttyflush(1); /* Flush/drop output */ 2215 /* do printoption AFTER flush, otherwise the output gets tossed... */ 2216 printoption("SENT", DO, TELOPT_TM); 2217 } 2218 2219 void 2220 xmitAO(void) 2221 { 2222 NET2ADD(IAC, AO); 2223 printoption("SENT", IAC, AO); 2224 if (autoflush) { 2225 doflush(); 2226 } 2227 } 2228 2229 void 2230 xmitEL(void) 2231 { 2232 NET2ADD(IAC, EL); 2233 printoption("SENT", IAC, EL); 2234 } 2235 2236 void 2237 xmitEC(void) 2238 { 2239 NET2ADD(IAC, EC); 2240 printoption("SENT", IAC, EC); 2241 } 2242 2243 int 2244 dosynch(char *ch __unused) 2245 { 2246 netclear(); /* clear the path to the network */ 2247 NETADD(IAC); 2248 setneturg(); 2249 NETADD(DM); 2250 printoption("SENT", IAC, DM); 2251 return 1; 2252 } 2253 2254 int want_status_response = 0; 2255 2256 int 2257 get_status(char *ch __unused) 2258 { 2259 unsigned char tmp[16]; 2260 unsigned char *cp; 2261 2262 if (my_want_state_is_dont(TELOPT_STATUS)) { 2263 printf("Remote side does not support STATUS option\n"); 2264 return 0; 2265 } 2266 cp = tmp; 2267 2268 *cp++ = IAC; 2269 *cp++ = SB; 2270 *cp++ = TELOPT_STATUS; 2271 *cp++ = TELQUAL_SEND; 2272 *cp++ = IAC; 2273 *cp++ = SE; 2274 if (NETROOM() >= cp - tmp) { 2275 ring_supply_data(&netoring, tmp, cp-tmp); 2276 printsub('>', tmp+2, cp - tmp - 2); 2277 } 2278 ++want_status_response; 2279 return 1; 2280 } 2281 2282 void 2283 intp(void) 2284 { 2285 NET2ADD(IAC, IP); 2286 printoption("SENT", IAC, IP); 2287 flushline = 1; 2288 if (autoflush) { 2289 doflush(); 2290 } 2291 if (autosynch) { 2292 dosynch(NULL); 2293 } 2294 } 2295 2296 void 2297 sendbrk(void) 2298 { 2299 NET2ADD(IAC, BREAK); 2300 printoption("SENT", IAC, BREAK); 2301 flushline = 1; 2302 if (autoflush) { 2303 doflush(); 2304 } 2305 if (autosynch) { 2306 dosynch(NULL); 2307 } 2308 } 2309 2310 void 2311 sendabort(void) 2312 { 2313 NET2ADD(IAC, ABORT); 2314 printoption("SENT", IAC, ABORT); 2315 flushline = 1; 2316 if (autoflush) { 2317 doflush(); 2318 } 2319 if (autosynch) { 2320 dosynch(NULL); 2321 } 2322 } 2323 2324 void 2325 sendsusp(void) 2326 { 2327 NET2ADD(IAC, SUSP); 2328 printoption("SENT", IAC, SUSP); 2329 flushline = 1; 2330 if (autoflush) { 2331 doflush(); 2332 } 2333 if (autosynch) { 2334 dosynch(NULL); 2335 } 2336 } 2337 2338 void 2339 sendeof(void) 2340 { 2341 NET2ADD(IAC, xEOF); 2342 printoption("SENT", IAC, xEOF); 2343 } 2344 2345 void 2346 sendayt(void) 2347 { 2348 NET2ADD(IAC, AYT); 2349 printoption("SENT", IAC, AYT); 2350 } 2351 2352 /* 2353 * Send a window size update to the remote system. 2354 */ 2355 2356 void 2357 sendnaws(void) 2358 { 2359 long rows, cols; 2360 unsigned char tmp[16]; 2361 unsigned char *cp; 2362 2363 if (my_state_is_wont(TELOPT_NAWS)) 2364 return; 2365 2366 #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ 2367 if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } 2368 2369 if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ 2370 return; 2371 } 2372 2373 cp = tmp; 2374 2375 *cp++ = IAC; 2376 *cp++ = SB; 2377 *cp++ = TELOPT_NAWS; 2378 PUTSHORT(cp, cols); 2379 PUTSHORT(cp, rows); 2380 *cp++ = IAC; 2381 *cp++ = SE; 2382 if (NETROOM() >= cp - tmp) { 2383 ring_supply_data(&netoring, tmp, cp-tmp); 2384 printsub('>', tmp+2, cp - tmp - 2); 2385 } 2386 } 2387 2388 void 2389 tel_enter_binary(int rw) 2390 { 2391 if (rw&1) 2392 send_do(TELOPT_BINARY, 1); 2393 if (rw&2) 2394 send_will(TELOPT_BINARY, 1); 2395 } 2396 2397 void 2398 tel_leave_binary(int rw) 2399 { 2400 if (rw&1) 2401 send_dont(TELOPT_BINARY, 1); 2402 if (rw&2) 2403 send_wont(TELOPT_BINARY, 1); 2404 } 2405