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