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