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