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