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