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