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