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