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