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