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