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