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