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