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