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