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