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