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