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