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