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