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