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