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