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