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