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