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