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