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