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