1 /* 2 * Copyright (c) 1988, 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. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #if 0 31 #ifndef lint 32 static const char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; 33 #endif 34 #endif 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 #define TELOPTS 39 #define TELCMDS 40 #define SLC_NAMES 41 #include <arpa/telnet.h> 42 #include <sys/types.h> 43 #include <sys/socket.h> 44 #include <sys/time.h> 45 #include <ctype.h> 46 #include <stdlib.h> 47 #include <unistd.h> 48 49 #include "general.h" 50 51 #include "fdset.h" 52 53 #include "ring.h" 54 55 #include "defines.h" 56 57 #include "externs.h" 58 59 #ifdef AUTHENTICATION 60 #include <libtelnet/auth.h> 61 #endif 62 #ifdef ENCRYPTION 63 #include <libtelnet/encrypt.h> 64 #endif 65 66 FILE *NetTrace = 0; /* Not in bss, since needs to stay */ 67 int prettydump; 68 69 /* 70 * upcase() 71 * 72 * Upcase (in place) the argument. 73 */ 74 75 void 76 upcase(char *argument) 77 { 78 int c; 79 80 while ((c = *argument) != 0) { 81 if (islower(c)) { 82 *argument = toupper(c); 83 } 84 argument++; 85 } 86 } 87 88 /* 89 * SetSockOpt() 90 * 91 * Compensate for differences in 4.2 and 4.3 systems. 92 */ 93 94 int 95 SetSockOpt(int fd, int level, int option, int yesno) 96 { 97 return setsockopt(fd, level, option, 98 (char *)&yesno, sizeof yesno); 99 } 100 101 /* 102 * The following are routines used to print out debugging information. 103 */ 104 105 unsigned char NetTraceFile[256] = "(standard output)"; 106 107 void 108 SetNetTrace(char *file) 109 { 110 if (NetTrace && NetTrace != stdout) 111 fclose(NetTrace); 112 if (file && (strcmp(file, "-") != 0)) { 113 NetTrace = fopen(file, "w"); 114 if (NetTrace) { 115 strcpy((char *)NetTraceFile, file); 116 return; 117 } 118 fprintf(stderr, "Cannot open %s.\n", file); 119 } 120 NetTrace = stdout; 121 strcpy((char *)NetTraceFile, "(standard output)"); 122 } 123 124 void 125 Dump(char direction, unsigned char *buffer, int length) 126 { 127 # define BYTES_PER_LINE 32 128 # define min(x,y) ((x<y)? x:y) 129 unsigned char *pThis; 130 int offset; 131 132 offset = 0; 133 134 while (length) { 135 /* print one line */ 136 fprintf(NetTrace, "%c 0x%x\t", direction, offset); 137 pThis = buffer; 138 if (prettydump) { 139 buffer = buffer + min(length, BYTES_PER_LINE/2); 140 while (pThis < buffer) { 141 fprintf(NetTrace, "%c%.2x", 142 (((*pThis)&0xff) == 0xff) ? '*' : ' ', 143 (*pThis)&0xff); 144 pThis++; 145 } 146 length -= BYTES_PER_LINE/2; 147 offset += BYTES_PER_LINE/2; 148 } else { 149 buffer = buffer + min(length, BYTES_PER_LINE); 150 while (pThis < buffer) { 151 fprintf(NetTrace, "%.2x", (*pThis)&0xff); 152 pThis++; 153 } 154 length -= BYTES_PER_LINE; 155 offset += BYTES_PER_LINE; 156 } 157 if (NetTrace == stdout) { 158 fprintf(NetTrace, "\r\n"); 159 } else { 160 fprintf(NetTrace, "\n"); 161 } 162 if (length < 0) { 163 fflush(NetTrace); 164 return; 165 } 166 /* find next unique line */ 167 } 168 fflush(NetTrace); 169 } 170 171 172 void 173 printoption(const char *direction, int cmd, int option) 174 { 175 if (!showoptions) 176 return; 177 if (cmd == IAC) { 178 if (TELCMD_OK(option)) 179 fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); 180 else 181 fprintf(NetTrace, "%s IAC %d", direction, option); 182 } else { 183 const char *fmt; 184 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : 185 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; 186 if (fmt) { 187 fprintf(NetTrace, "%s %s ", direction, fmt); 188 if (TELOPT_OK(option)) 189 fprintf(NetTrace, "%s", TELOPT(option)); 190 else if (option == TELOPT_EXOPL) 191 fprintf(NetTrace, "EXOPL"); 192 else 193 fprintf(NetTrace, "%d", option); 194 } else 195 fprintf(NetTrace, "%s %d %d", direction, cmd, option); 196 } 197 if (NetTrace == stdout) { 198 fprintf(NetTrace, "\r\n"); 199 fflush(NetTrace); 200 } else { 201 fprintf(NetTrace, "\n"); 202 } 203 return; 204 } 205 206 void 207 optionstatus(void) 208 { 209 int i; 210 extern char will_wont_resp[], do_dont_resp[]; 211 212 for (i = 0; i < 256; i++) { 213 if (do_dont_resp[i]) { 214 if (TELOPT_OK(i)) 215 printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); 216 else if (TELCMD_OK(i)) 217 printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); 218 else 219 printf("resp DO_DONT %d: %d\n", i, 220 do_dont_resp[i]); 221 if (my_want_state_is_do(i)) { 222 if (TELOPT_OK(i)) 223 printf("want DO %s\n", TELOPT(i)); 224 else if (TELCMD_OK(i)) 225 printf("want DO %s\n", TELCMD(i)); 226 else 227 printf("want DO %d\n", i); 228 } else { 229 if (TELOPT_OK(i)) 230 printf("want DONT %s\n", TELOPT(i)); 231 else if (TELCMD_OK(i)) 232 printf("want DONT %s\n", TELCMD(i)); 233 else 234 printf("want DONT %d\n", i); 235 } 236 } else { 237 if (my_state_is_do(i)) { 238 if (TELOPT_OK(i)) 239 printf(" DO %s\n", TELOPT(i)); 240 else if (TELCMD_OK(i)) 241 printf(" DO %s\n", TELCMD(i)); 242 else 243 printf(" DO %d\n", i); 244 } 245 } 246 if (will_wont_resp[i]) { 247 if (TELOPT_OK(i)) 248 printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); 249 else if (TELCMD_OK(i)) 250 printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); 251 else 252 printf("resp WILL_WONT %d: %d\n", 253 i, will_wont_resp[i]); 254 if (my_want_state_is_will(i)) { 255 if (TELOPT_OK(i)) 256 printf("want WILL %s\n", TELOPT(i)); 257 else if (TELCMD_OK(i)) 258 printf("want WILL %s\n", TELCMD(i)); 259 else 260 printf("want WILL %d\n", i); 261 } else { 262 if (TELOPT_OK(i)) 263 printf("want WONT %s\n", TELOPT(i)); 264 else if (TELCMD_OK(i)) 265 printf("want WONT %s\n", TELCMD(i)); 266 else 267 printf("want WONT %d\n", i); 268 } 269 } else { 270 if (my_state_is_will(i)) { 271 if (TELOPT_OK(i)) 272 printf(" WILL %s\n", TELOPT(i)); 273 else if (TELCMD_OK(i)) 274 printf(" WILL %s\n", TELCMD(i)); 275 else 276 printf(" WILL %d\n", i); 277 } 278 } 279 } 280 281 } 282 283 void 284 printsub(char direction, unsigned char *pointer, int length) 285 { 286 int i; 287 #ifdef AUTHENTICATION 288 char buf[512]; 289 #endif 290 extern int want_status_response; 291 292 if (showoptions || direction == 0 || 293 (want_status_response && (pointer[0] == TELOPT_STATUS))) { 294 if (direction) { 295 fprintf(NetTrace, "%s IAC SB ", 296 (direction == '<')? "RCVD":"SENT"); 297 if (length >= 3) { 298 int j; 299 300 i = pointer[length-2]; 301 j = pointer[length-1]; 302 303 if (i != IAC || j != SE) { 304 fprintf(NetTrace, "(terminated by "); 305 if (TELOPT_OK(i)) 306 fprintf(NetTrace, "%s ", TELOPT(i)); 307 else if (TELCMD_OK(i)) 308 fprintf(NetTrace, "%s ", TELCMD(i)); 309 else 310 fprintf(NetTrace, "%d ", i); 311 if (TELOPT_OK(j)) 312 fprintf(NetTrace, "%s", TELOPT(j)); 313 else if (TELCMD_OK(j)) 314 fprintf(NetTrace, "%s", TELCMD(j)); 315 else 316 fprintf(NetTrace, "%d", j); 317 fprintf(NetTrace, ", not IAC SE!) "); 318 } 319 } 320 length -= 2; 321 } 322 if (length < 1) { 323 fprintf(NetTrace, "(Empty suboption??\?)"); 324 if (NetTrace == stdout) 325 fflush(NetTrace); 326 return; 327 } 328 switch (pointer[0]) { 329 case TELOPT_TTYPE: 330 fprintf(NetTrace, "TERMINAL-TYPE "); 331 switch (pointer[1]) { 332 case TELQUAL_IS: 333 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 334 break; 335 case TELQUAL_SEND: 336 fprintf(NetTrace, "SEND"); 337 break; 338 default: 339 fprintf(NetTrace, 340 "- unknown qualifier %d (0x%x).", 341 pointer[1], pointer[1]); 342 } 343 break; 344 case TELOPT_TSPEED: 345 fprintf(NetTrace, "TERMINAL-SPEED"); 346 if (length < 2) { 347 fprintf(NetTrace, " (empty suboption??\?)"); 348 break; 349 } 350 switch (pointer[1]) { 351 case TELQUAL_IS: 352 fprintf(NetTrace, " IS "); 353 fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); 354 break; 355 default: 356 if (pointer[1] == 1) 357 fprintf(NetTrace, " SEND"); 358 else 359 fprintf(NetTrace, " %d (unknown)", pointer[1]); 360 for (i = 2; i < length; i++) 361 fprintf(NetTrace, " ?%d?", pointer[i]); 362 break; 363 } 364 break; 365 366 case TELOPT_LFLOW: 367 fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); 368 if (length < 2) { 369 fprintf(NetTrace, " (empty suboption??\?)"); 370 break; 371 } 372 switch (pointer[1]) { 373 case LFLOW_OFF: 374 fprintf(NetTrace, " OFF"); break; 375 case LFLOW_ON: 376 fprintf(NetTrace, " ON"); break; 377 case LFLOW_RESTART_ANY: 378 fprintf(NetTrace, " RESTART-ANY"); break; 379 case LFLOW_RESTART_XON: 380 fprintf(NetTrace, " RESTART-XON"); break; 381 default: 382 fprintf(NetTrace, " %d (unknown)", pointer[1]); 383 } 384 for (i = 2; i < length; i++) 385 fprintf(NetTrace, " ?%d?", pointer[i]); 386 break; 387 388 case TELOPT_NAWS: 389 fprintf(NetTrace, "NAWS"); 390 if (length < 2) { 391 fprintf(NetTrace, " (empty suboption??\?)"); 392 break; 393 } 394 if (length == 2) { 395 fprintf(NetTrace, " ?%d?", pointer[1]); 396 break; 397 } 398 fprintf(NetTrace, " %d %d (%d)", 399 pointer[1], pointer[2], 400 (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 401 if (length == 4) { 402 fprintf(NetTrace, " ?%d?", pointer[3]); 403 break; 404 } 405 fprintf(NetTrace, " %d %d (%d)", 406 pointer[3], pointer[4], 407 (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 408 for (i = 5; i < length; i++) 409 fprintf(NetTrace, " ?%d?", pointer[i]); 410 break; 411 412 #ifdef AUTHENTICATION 413 case TELOPT_AUTHENTICATION: 414 fprintf(NetTrace, "AUTHENTICATION"); 415 if (length < 2) { 416 fprintf(NetTrace, " (empty suboption??\?)"); 417 break; 418 } 419 switch (pointer[1]) { 420 case TELQUAL_REPLY: 421 case TELQUAL_IS: 422 fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? 423 "IS" : "REPLY"); 424 if (AUTHTYPE_NAME_OK(pointer[2])) 425 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); 426 else 427 fprintf(NetTrace, "%d ", pointer[2]); 428 if (length < 3) { 429 fprintf(NetTrace, "(partial suboption??\?)"); 430 break; 431 } 432 fprintf(NetTrace, "%s|%s", 433 ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 434 "CLIENT" : "SERVER", 435 ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 436 "MUTUAL" : "ONE-WAY"); 437 438 auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 439 fprintf(NetTrace, "%s", buf); 440 break; 441 442 case TELQUAL_SEND: 443 i = 2; 444 fprintf(NetTrace, " SEND "); 445 while (i < length) { 446 if (AUTHTYPE_NAME_OK(pointer[i])) 447 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); 448 else 449 fprintf(NetTrace, "%d ", pointer[i]); 450 if (++i >= length) { 451 fprintf(NetTrace, "(partial suboption??\?)"); 452 break; 453 } 454 fprintf(NetTrace, "%s|%s ", 455 ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 456 "CLIENT" : "SERVER", 457 ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 458 "MUTUAL" : "ONE-WAY"); 459 ++i; 460 } 461 break; 462 463 case TELQUAL_NAME: 464 i = 2; 465 fprintf(NetTrace, " NAME \""); 466 while (i < length) 467 putc(pointer[i++], NetTrace); 468 putc('"', NetTrace); 469 break; 470 471 default: 472 for (i = 2; i < length; i++) 473 fprintf(NetTrace, " ?%d?", pointer[i]); 474 break; 475 } 476 break; 477 #endif 478 479 #ifdef ENCRYPTION 480 case TELOPT_ENCRYPT: 481 fprintf(NetTrace, "ENCRYPT"); 482 if (length < 2) { 483 fprintf(NetTrace, " (empty suboption??\?)"); 484 break; 485 } 486 switch (pointer[1]) { 487 case ENCRYPT_START: 488 fprintf(NetTrace, " START"); 489 break; 490 491 case ENCRYPT_END: 492 fprintf(NetTrace, " END"); 493 break; 494 495 case ENCRYPT_REQSTART: 496 fprintf(NetTrace, " REQUEST-START"); 497 break; 498 499 case ENCRYPT_REQEND: 500 fprintf(NetTrace, " REQUEST-END"); 501 break; 502 503 case ENCRYPT_IS: 504 case ENCRYPT_REPLY: 505 fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? 506 "IS" : "REPLY"); 507 if (length < 3) { 508 fprintf(NetTrace, " (partial suboption??\?)"); 509 break; 510 } 511 if (ENCTYPE_NAME_OK(pointer[2])) 512 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); 513 else 514 fprintf(NetTrace, " %d (unknown)", pointer[2]); 515 516 encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 517 fprintf(NetTrace, "%s", buf); 518 break; 519 520 case ENCRYPT_SUPPORT: 521 i = 2; 522 fprintf(NetTrace, " SUPPORT "); 523 while (i < length) { 524 if (ENCTYPE_NAME_OK(pointer[i])) 525 fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); 526 else 527 fprintf(NetTrace, "%d ", pointer[i]); 528 i++; 529 } 530 break; 531 532 case ENCRYPT_ENC_KEYID: 533 fprintf(NetTrace, " ENC_KEYID "); 534 goto encommon; 535 536 case ENCRYPT_DEC_KEYID: 537 fprintf(NetTrace, " DEC_KEYID "); 538 goto encommon; 539 540 default: 541 fprintf(NetTrace, " %d (unknown)", pointer[1]); 542 encommon: 543 for (i = 2; i < length; i++) 544 fprintf(NetTrace, " %d", pointer[i]); 545 break; 546 } 547 break; 548 #endif /* ENCRYPTION */ 549 550 case TELOPT_LINEMODE: 551 fprintf(NetTrace, "LINEMODE "); 552 if (length < 2) { 553 fprintf(NetTrace, " (empty suboption??\?)"); 554 break; 555 } 556 switch (pointer[1]) { 557 case WILL: 558 fprintf(NetTrace, "WILL "); 559 goto common; 560 case WONT: 561 fprintf(NetTrace, "WONT "); 562 goto common; 563 case DO: 564 fprintf(NetTrace, "DO "); 565 goto common; 566 case DONT: 567 fprintf(NetTrace, "DONT "); 568 common: 569 if (length < 3) { 570 fprintf(NetTrace, "(no option??\?)"); 571 break; 572 } 573 switch (pointer[2]) { 574 case LM_FORWARDMASK: 575 fprintf(NetTrace, "Forward Mask"); 576 for (i = 3; i < length; i++) 577 fprintf(NetTrace, " %x", pointer[i]); 578 break; 579 default: 580 fprintf(NetTrace, "%d (unknown)", pointer[2]); 581 for (i = 3; i < length; i++) 582 fprintf(NetTrace, " %d", pointer[i]); 583 break; 584 } 585 break; 586 587 case LM_SLC: 588 fprintf(NetTrace, "SLC"); 589 for (i = 2; i < length - 2; i += 3) { 590 if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 591 fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 592 else 593 fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); 594 switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 595 case SLC_NOSUPPORT: 596 fprintf(NetTrace, " NOSUPPORT"); break; 597 case SLC_CANTCHANGE: 598 fprintf(NetTrace, " CANTCHANGE"); break; 599 case SLC_VARIABLE: 600 fprintf(NetTrace, " VARIABLE"); break; 601 case SLC_DEFAULT: 602 fprintf(NetTrace, " DEFAULT"); break; 603 } 604 fprintf(NetTrace, "%s%s%s", 605 pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 606 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 607 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 608 if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 609 SLC_FLUSHOUT| SLC_LEVELBITS)) 610 fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); 611 fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); 612 if ((pointer[i+SLC_VALUE] == IAC) && 613 (pointer[i+SLC_VALUE+1] == IAC)) 614 i++; 615 } 616 for (; i < length; i++) 617 fprintf(NetTrace, " ?%d?", pointer[i]); 618 break; 619 620 case LM_MODE: 621 fprintf(NetTrace, "MODE "); 622 if (length < 3) { 623 fprintf(NetTrace, "(no mode??\?)"); 624 break; 625 } 626 { 627 char tbuf[64]; 628 snprintf(tbuf, sizeof(tbuf), "%s%s%s%s%s", 629 pointer[2]&MODE_EDIT ? "|EDIT" : "", 630 pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 631 pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 632 pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 633 pointer[2]&MODE_ACK ? "|ACK" : ""); 634 fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); 635 } 636 if (pointer[2]&~(MODE_MASK)) 637 fprintf(NetTrace, " (0x%x)", pointer[2]); 638 for (i = 3; i < length; i++) 639 fprintf(NetTrace, " ?0x%x?", pointer[i]); 640 break; 641 default: 642 fprintf(NetTrace, "%d (unknown)", pointer[1]); 643 for (i = 2; i < length; i++) 644 fprintf(NetTrace, " %d", pointer[i]); 645 } 646 break; 647 648 case TELOPT_STATUS: { 649 const char *cp; 650 int j, k; 651 652 fprintf(NetTrace, "STATUS"); 653 654 switch (pointer[1]) { 655 default: 656 if (pointer[1] == TELQUAL_SEND) 657 fprintf(NetTrace, " SEND"); 658 else 659 fprintf(NetTrace, " %d (unknown)", pointer[1]); 660 for (i = 2; i < length; i++) 661 fprintf(NetTrace, " ?%d?", pointer[i]); 662 break; 663 case TELQUAL_IS: 664 if (--want_status_response < 0) 665 want_status_response = 0; 666 if (NetTrace == stdout) 667 fprintf(NetTrace, " IS\r\n"); 668 else 669 fprintf(NetTrace, " IS\n"); 670 671 for (i = 2; i < length; i++) { 672 switch(pointer[i]) { 673 case DO: cp = "DO"; goto common2; 674 case DONT: cp = "DONT"; goto common2; 675 case WILL: cp = "WILL"; goto common2; 676 case WONT: cp = "WONT"; goto common2; 677 common2: 678 i++; 679 if (TELOPT_OK((int)pointer[i])) 680 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); 681 else 682 fprintf(NetTrace, " %s %d", cp, pointer[i]); 683 684 if (NetTrace == stdout) 685 fprintf(NetTrace, "\r\n"); 686 else 687 fprintf(NetTrace, "\n"); 688 break; 689 690 case SB: 691 fprintf(NetTrace, " SB "); 692 i++; 693 j = k = i; 694 while (j < length) { 695 if (pointer[j] == SE) { 696 if (j+1 == length) 697 break; 698 if (pointer[j+1] == SE) 699 j++; 700 else 701 break; 702 } 703 pointer[k++] = pointer[j++]; 704 } 705 printsub(0, &pointer[i], k - i); 706 if (i < length) { 707 fprintf(NetTrace, " SE"); 708 i = j; 709 } else 710 i = j - 1; 711 712 if (NetTrace == stdout) 713 fprintf(NetTrace, "\r\n"); 714 else 715 fprintf(NetTrace, "\n"); 716 717 break; 718 719 default: 720 fprintf(NetTrace, " %d", pointer[i]); 721 break; 722 } 723 } 724 break; 725 } 726 break; 727 } 728 729 case TELOPT_XDISPLOC: 730 fprintf(NetTrace, "X-DISPLAY-LOCATION "); 731 switch (pointer[1]) { 732 case TELQUAL_IS: 733 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 734 break; 735 case TELQUAL_SEND: 736 fprintf(NetTrace, "SEND"); 737 break; 738 default: 739 fprintf(NetTrace, "- unknown qualifier %d (0x%x).", 740 pointer[1], pointer[1]); 741 } 742 break; 743 744 case TELOPT_NEW_ENVIRON: 745 fprintf(NetTrace, "NEW-ENVIRON "); 746 #ifdef OLD_ENVIRON 747 goto env_common1; 748 case TELOPT_OLD_ENVIRON: 749 fprintf(NetTrace, "OLD-ENVIRON"); 750 env_common1: 751 #endif 752 switch (pointer[1]) { 753 case TELQUAL_IS: 754 fprintf(NetTrace, "IS "); 755 goto env_common; 756 case TELQUAL_SEND: 757 fprintf(NetTrace, "SEND "); 758 goto env_common; 759 case TELQUAL_INFO: 760 fprintf(NetTrace, "INFO "); 761 env_common: 762 { 763 int noquote = 2; 764 #if defined(ENV_HACK) && defined(OLD_ENVIRON) 765 extern int old_env_var, old_env_value; 766 #endif 767 for (i = 2; i < length; i++ ) { 768 switch (pointer[i]) { 769 case NEW_ENV_VALUE: 770 #ifdef OLD_ENVIRON 771 /* case NEW_ENV_OVAR: */ 772 if (pointer[0] == TELOPT_OLD_ENVIRON) { 773 # ifdef ENV_HACK 774 if (old_env_var == OLD_ENV_VALUE) 775 fprintf(NetTrace, "\" (VALUE) " + noquote); 776 else 777 # endif 778 fprintf(NetTrace, "\" VAR " + noquote); 779 } else 780 #endif /* OLD_ENVIRON */ 781 fprintf(NetTrace, "%s", "\" VALUE " + noquote); 782 noquote = 2; 783 break; 784 785 case NEW_ENV_VAR: 786 #ifdef OLD_ENVIRON 787 /* case OLD_ENV_VALUE: */ 788 if (pointer[0] == TELOPT_OLD_ENVIRON) { 789 # ifdef ENV_HACK 790 if (old_env_value == OLD_ENV_VAR) 791 fprintf(NetTrace, "\" (VAR) " + noquote); 792 else 793 # endif 794 fprintf(NetTrace, "\" VALUE " + noquote); 795 } else 796 #endif /* OLD_ENVIRON */ 797 fprintf(NetTrace, "%s", "\" VAR " + noquote); 798 noquote = 2; 799 break; 800 801 case ENV_ESC: 802 fprintf(NetTrace, "%s", "\" ESC " + noquote); 803 noquote = 2; 804 break; 805 806 case ENV_USERVAR: 807 fprintf(NetTrace, "%s", "\" USERVAR " + noquote); 808 noquote = 2; 809 break; 810 811 default: 812 if (isprint(pointer[i]) && pointer[i] != '"') { 813 if (noquote) { 814 putc('"', NetTrace); 815 noquote = 0; 816 } 817 putc(pointer[i], NetTrace); 818 } else { 819 fprintf(NetTrace, "\" %03o " + noquote, 820 pointer[i]); 821 noquote = 2; 822 } 823 break; 824 } 825 } 826 if (!noquote) 827 putc('"', NetTrace); 828 break; 829 } 830 } 831 break; 832 833 default: 834 if (TELOPT_OK(pointer[0])) 835 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); 836 else 837 fprintf(NetTrace, "%d (unknown)", pointer[0]); 838 for (i = 1; i < length; i++) 839 fprintf(NetTrace, " %d", pointer[i]); 840 break; 841 } 842 if (direction) { 843 if (NetTrace == stdout) 844 fprintf(NetTrace, "\r\n"); 845 else 846 fprintf(NetTrace, "\n"); 847 } 848 if (NetTrace == stdout) 849 fflush(NetTrace); 850 } 851 } 852 853 /* EmptyTerminal - called to make sure that the terminal buffer is empty. 854 * Note that we consider the buffer to run all the 855 * way to the kernel (thus the select). 856 */ 857 858 static void 859 EmptyTerminal(void) 860 { 861 fd_set o; 862 863 FD_ZERO(&o); 864 865 if (TTYBYTES() == 0) { 866 FD_SET(tout, &o); 867 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 868 (struct timeval *) 0); /* wait for TTLOWAT */ 869 } else { 870 while (TTYBYTES()) { 871 (void) ttyflush(0); 872 FD_SET(tout, &o); 873 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 874 (struct timeval *) 0); /* wait for TTLOWAT */ 875 } 876 } 877 } 878 879 static void 880 SetForExit(void) 881 { 882 setconnmode(0); 883 do { 884 (void)telrcv(); /* Process any incoming data */ 885 EmptyTerminal(); 886 } while (ring_full_count(&netiring)); /* While there is any */ 887 setcommandmode(); 888 fflush(stdout); 889 fflush(stderr); 890 setconnmode(0); 891 EmptyTerminal(); /* Flush the path to the tty */ 892 setcommandmode(); 893 } 894 895 void 896 Exit(int returnCode) 897 { 898 SetForExit(); 899 exit(returnCode); 900 } 901 902 void 903 ExitString(const char *string, int returnCode) 904 { 905 SetForExit(); 906 fwrite(string, 1, strlen(string), stderr); 907 exit(returnCode); 908 } 909