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