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