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[] = "from: @(#)utilities.c 5.3 (Berkeley) 3/22/91";*/ 36 static char rcsid[] = "$Id: utilities.c,v 1.2 1993/08/01 18:07:15 mycroft Exp $"; 37 #endif /* not lint */ 38 39 #define TELOPTS 40 #define TELCMDS 41 #define SLC_NAMES 42 #include <arpa/telnet.h> 43 #include <sys/types.h> 44 #include <sys/time.h> 45 46 #include <ctype.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 FILE *NetTrace = 0; /* Not in bss, since needs to stay */ 59 int prettydump; 60 61 /* 62 * upcase() 63 * 64 * Upcase (in place) the argument. 65 */ 66 67 void 68 upcase(argument) 69 register char *argument; 70 { 71 register int c; 72 73 while ((c = *argument) != 0) { 74 if (islower(c)) { 75 *argument = toupper(c); 76 } 77 argument++; 78 } 79 } 80 81 /* 82 * SetSockOpt() 83 * 84 * Compensate for differences in 4.2 and 4.3 systems. 85 */ 86 87 int 88 SetSockOpt(fd, level, option, yesno) 89 int fd, level, option, yesno; 90 { 91 #ifndef NOT43 92 return setsockopt(fd, level, option, 93 (char *)&yesno, sizeof yesno); 94 #else /* NOT43 */ 95 if (yesno == 0) { /* Can't do that in 4.2! */ 96 fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", 97 option); 98 return -1; 99 } 100 return setsockopt(fd, level, option, 0, 0); 101 #endif /* NOT43 */ 102 } 103 104 /* 105 * The following are routines used to print out debugging information. 106 */ 107 108 unsigned char NetTraceFile[256] = "(standard output)"; 109 110 void 111 SetNetTrace(file) 112 register char *file; 113 { 114 if (NetTrace && NetTrace != stdout) 115 fclose(NetTrace); 116 if (file && (strcmp(file, "-") != 0)) { 117 NetTrace = fopen(file, "w"); 118 if (NetTrace) { 119 strcpy((char *)NetTraceFile, file); 120 return; 121 } 122 fprintf(stderr, "Cannot open %s.\n", file); 123 } 124 NetTrace = stdout; 125 strcpy((char *)NetTraceFile, "(standard output)"); 126 } 127 128 void 129 Dump(direction, buffer, length) 130 char direction; 131 unsigned char *buffer; 132 int length; 133 { 134 # define BYTES_PER_LINE 32 135 # define min(x,y) ((x<y)? x:y) 136 unsigned char *pThis; 137 int offset; 138 extern pettydump; 139 140 offset = 0; 141 142 while (length) { 143 /* print one line */ 144 fprintf(NetTrace, "%c 0x%x\t", direction, offset); 145 pThis = buffer; 146 if (prettydump) { 147 buffer = buffer + min(length, BYTES_PER_LINE/2); 148 while (pThis < buffer) { 149 fprintf(NetTrace, "%c%.2x", 150 (((*pThis)&0xff) == 0xff) ? '*' : ' ', 151 (*pThis)&0xff); 152 pThis++; 153 } 154 length -= BYTES_PER_LINE/2; 155 offset += BYTES_PER_LINE/2; 156 } else { 157 buffer = buffer + min(length, BYTES_PER_LINE); 158 while (pThis < buffer) { 159 fprintf(NetTrace, "%.2x", (*pThis)&0xff); 160 pThis++; 161 } 162 length -= BYTES_PER_LINE; 163 offset += BYTES_PER_LINE; 164 } 165 if (NetTrace == stdout) { 166 fprintf(NetTrace, "\r\n"); 167 } else { 168 fprintf(NetTrace, "\n"); 169 } 170 if (length < 0) { 171 fflush(NetTrace); 172 return; 173 } 174 /* find next unique line */ 175 } 176 fflush(NetTrace); 177 } 178 179 180 void 181 printoption(direction, cmd, option) 182 char *direction; 183 int cmd, option; 184 { 185 if (!showoptions) 186 return; 187 if (cmd == IAC) { 188 if (TELCMD_OK(option)) 189 fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); 190 else 191 fprintf(NetTrace, "%s IAC %d", direction, option); 192 } else { 193 register char *fmt; 194 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : 195 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; 196 if (fmt) { 197 fprintf(NetTrace, "%s %s ", direction, fmt); 198 if (TELOPT_OK(option)) 199 fprintf(NetTrace, "%s", TELOPT(option)); 200 else if (option == TELOPT_EXOPL) 201 fprintf(NetTrace, "EXOPL"); 202 else 203 fprintf(NetTrace, "%d", option); 204 } else 205 fprintf(NetTrace, "%s %d %d", direction, cmd, option); 206 } 207 if (NetTrace == stdout) 208 fprintf(NetTrace, "\r\n"); 209 else 210 fprintf(NetTrace, "\n"); 211 return; 212 } 213 214 void 215 optionstatus() 216 { 217 register int i; 218 extern char will_wont_resp[], do_dont_resp[]; 219 220 for (i = 0; i < 256; i++) { 221 if (do_dont_resp[i]) { 222 if (TELOPT_OK(i)) 223 printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); 224 else if (TELCMD_OK(i)) 225 printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); 226 else 227 printf("resp DO_DONT %d: %d\n", i, 228 do_dont_resp[i]); 229 if (my_want_state_is_do(i)) { 230 if (TELOPT_OK(i)) 231 printf("want DO %s\n", TELOPT(i)); 232 else if (TELCMD_OK(i)) 233 printf("want DO %s\n", TELCMD(i)); 234 else 235 printf("want DO %d\n", i); 236 } else { 237 if (TELOPT_OK(i)) 238 printf("want DONT %s\n", TELOPT(i)); 239 else if (TELCMD_OK(i)) 240 printf("want DONT %s\n", TELCMD(i)); 241 else 242 printf("want DONT %d\n", i); 243 } 244 } else { 245 if (my_state_is_do(i)) { 246 if (TELOPT_OK(i)) 247 printf(" DO %s\n", TELOPT(i)); 248 else if (TELCMD_OK(i)) 249 printf(" DO %s\n", TELCMD(i)); 250 else 251 printf(" DO %d\n", i); 252 } 253 } 254 if (will_wont_resp[i]) { 255 if (TELOPT_OK(i)) 256 printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); 257 else if (TELCMD_OK(i)) 258 printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); 259 else 260 printf("resp WILL_WONT %d: %d\n", 261 i, will_wont_resp[i]); 262 if (my_want_state_is_will(i)) { 263 if (TELOPT_OK(i)) 264 printf("want WILL %s\n", TELOPT(i)); 265 else if (TELCMD_OK(i)) 266 printf("want WILL %s\n", TELCMD(i)); 267 else 268 printf("want WILL %d\n", i); 269 } else { 270 if (TELOPT_OK(i)) 271 printf("want WONT %s\n", TELOPT(i)); 272 else if (TELCMD_OK(i)) 273 printf("want WONT %s\n", TELCMD(i)); 274 else 275 printf("want WONT %d\n", i); 276 } 277 } else { 278 if (my_state_is_will(i)) { 279 if (TELOPT_OK(i)) 280 printf(" WILL %s\n", TELOPT(i)); 281 else if (TELCMD_OK(i)) 282 printf(" WILL %s\n", TELCMD(i)); 283 else 284 printf(" WILL %d\n", i); 285 } 286 } 287 } 288 289 } 290 291 void 292 printsub(direction, pointer, length) 293 char direction; /* '<' or '>' */ 294 unsigned char *pointer; /* where suboption data sits */ 295 int length; /* length of suboption data */ 296 { 297 register int i; 298 char buf[512]; 299 extern int want_status_response; 300 301 if (showoptions || direction == 0 || 302 (want_status_response && (pointer[0] == TELOPT_STATUS))) { 303 if (direction) { 304 fprintf(NetTrace, "%s IAC SB ", 305 (direction == '<')? "RCVD":"SENT"); 306 if (length >= 3) { 307 register int j; 308 309 i = pointer[length-2]; 310 j = pointer[length-1]; 311 312 if (i != IAC || j != SE) { 313 fprintf(NetTrace, "(terminated by "); 314 if (TELOPT_OK(i)) 315 fprintf(NetTrace, "%s ", TELOPT(i)); 316 else if (TELCMD_OK(i)) 317 fprintf(NetTrace, "%s ", TELCMD(i)); 318 else 319 fprintf(NetTrace, "%d ", i); 320 if (TELOPT_OK(j)) 321 fprintf(NetTrace, "%s", TELOPT(j)); 322 else if (TELCMD_OK(j)) 323 fprintf(NetTrace, "%s", TELCMD(j)); 324 else 325 fprintf(NetTrace, "%d", j); 326 fprintf(NetTrace, ", not IAC SE!) "); 327 } 328 } 329 length -= 2; 330 } 331 if (length < 1) { 332 fprintf(NetTrace, "(Empty suboption???)"); 333 return; 334 } 335 switch (pointer[0]) { 336 case TELOPT_TTYPE: 337 fprintf(NetTrace, "TERMINAL-TYPE "); 338 switch (pointer[1]) { 339 case TELQUAL_IS: 340 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 341 break; 342 case TELQUAL_SEND: 343 fprintf(NetTrace, "SEND"); 344 break; 345 default: 346 fprintf(NetTrace, 347 "- unknown qualifier %d (0x%x).", 348 pointer[1], pointer[1]); 349 } 350 break; 351 case TELOPT_TSPEED: 352 fprintf(NetTrace, "TERMINAL-SPEED"); 353 if (length < 2) { 354 fprintf(NetTrace, " (empty suboption???)"); 355 break; 356 } 357 switch (pointer[1]) { 358 case TELQUAL_IS: 359 fprintf(NetTrace, " IS "); 360 fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); 361 break; 362 default: 363 if (pointer[1] == 1) 364 fprintf(NetTrace, " SEND"); 365 else 366 fprintf(NetTrace, " %d (unknown)", pointer[1]); 367 for (i = 2; i < length; i++) 368 fprintf(NetTrace, " ?%d?", pointer[i]); 369 break; 370 } 371 break; 372 373 case TELOPT_LFLOW: 374 fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); 375 if (length < 2) { 376 fprintf(NetTrace, " (empty suboption???)"); 377 break; 378 } 379 switch (pointer[1]) { 380 case 0: 381 fprintf(NetTrace, " OFF"); break; 382 case 1: 383 fprintf(NetTrace, " ON"); 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 #if defined(AUTHENTICATE) 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 #if defined(ENCRYPT) 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 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 register char *cp; 653 register 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_ENVIRON: 748 fprintf(NetTrace, "ENVIRON "); 749 switch (pointer[1]) { 750 case TELQUAL_IS: 751 fprintf(NetTrace, "IS "); 752 goto env_common; 753 case TELQUAL_SEND: 754 fprintf(NetTrace, "SEND "); 755 goto env_common; 756 case TELQUAL_INFO: 757 fprintf(NetTrace, "INFO "); 758 env_common: 759 { 760 register int noquote = 2; 761 for (i = 2; i < length; i++ ) { 762 switch (pointer[i]) { 763 case ENV_VAR: 764 if (pointer[1] == TELQUAL_SEND) 765 goto def_case; 766 fprintf(NetTrace, "\" VAR " + noquote); 767 noquote = 2; 768 break; 769 770 case ENV_VALUE: 771 fprintf(NetTrace, "\" VALUE " + noquote); 772 noquote = 2; 773 break; 774 775 case ENV_ESC: 776 fprintf(NetTrace, "\" ESC " + noquote); 777 noquote = 2; 778 break; 779 780 default: 781 def_case: 782 if (isprint(pointer[i]) && pointer[i] != '"') { 783 if (noquote) { 784 putc('"', NetTrace); 785 noquote = 0; 786 } 787 putc(pointer[i], NetTrace); 788 } else { 789 fprintf(NetTrace, "\" %03o " + noquote, 790 pointer[i]); 791 noquote = 2; 792 } 793 break; 794 } 795 } 796 if (!noquote) 797 putc('"', NetTrace); 798 break; 799 } 800 } 801 break; 802 803 default: 804 if (TELOPT_OK(pointer[0])) 805 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); 806 else 807 fprintf(NetTrace, "%d (unknown)", pointer[i]); 808 for (i = 1; i < length; i++) 809 fprintf(NetTrace, " %d", pointer[i]); 810 break; 811 } 812 if (direction) { 813 if (NetTrace == stdout) 814 fprintf(NetTrace, "\r\n"); 815 else 816 fprintf(NetTrace, "\n"); 817 } 818 } 819 } 820 821 /* EmptyTerminal - called to make sure that the terminal buffer is empty. 822 * Note that we consider the buffer to run all the 823 * way to the kernel (thus the select). 824 */ 825 826 void 827 EmptyTerminal() 828 { 829 #if defined(unix) 830 fd_set o; 831 832 FD_ZERO(&o); 833 #endif /* defined(unix) */ 834 835 if (TTYBYTES() == 0) { 836 #if defined(unix) 837 FD_SET(tout, &o); 838 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 839 (struct timeval *) 0); /* wait for TTLOWAT */ 840 #endif /* defined(unix) */ 841 } else { 842 while (TTYBYTES()) { 843 (void) ttyflush(0); 844 #if defined(unix) 845 FD_SET(tout, &o); 846 (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 847 (struct timeval *) 0); /* wait for TTLOWAT */ 848 #endif /* defined(unix) */ 849 } 850 } 851 } 852 853 void 854 SetForExit() 855 { 856 setconnmode(0); 857 #if defined(TN3270) 858 if (In3270) { 859 Finish3270(); 860 } 861 #else /* defined(TN3270) */ 862 do { 863 (void)telrcv(); /* Process any incoming data */ 864 EmptyTerminal(); 865 } while (ring_full_count(&netiring)); /* While there is any */ 866 #endif /* defined(TN3270) */ 867 setcommandmode(); 868 fflush(stdout); 869 fflush(stderr); 870 #if defined(TN3270) 871 if (In3270) { 872 StopScreen(1); 873 } 874 #endif /* defined(TN3270) */ 875 setconnmode(0); 876 EmptyTerminal(); /* Flush the path to the tty */ 877 setcommandmode(); 878 } 879 880 void 881 Exit(returnCode) 882 int returnCode; 883 { 884 SetForExit(); 885 exit(returnCode); 886 } 887 888 void 889 ExitString(string, returnCode) 890 char *string; 891 int returnCode; 892 { 893 SetForExit(); 894 fwrite(string, 1, strlen(string), stderr); 895 exit(returnCode); 896 } 897