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