|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)utility.c 5.4 (Berkeley) 6/28/90"; ! 22: #endif /* not lint */ ! 23: ! 24: #define PRINTOPTIONS ! 25: #include "telnetd.h" ! 26: ! 27: /* ! 28: * utility functions performing io related tasks ! 29: */ ! 30: ! 31: /* ! 32: * ttloop ! 33: * ! 34: * A small subroutine to flush the network output buffer, get some data ! 35: * from the network, and pass it through the telnet state machine. We ! 36: * also flush the pty input buffer (by dropping its data) if it becomes ! 37: * too full. ! 38: */ ! 39: ! 40: void ! 41: ttloop() ! 42: { ! 43: void netflush(); ! 44: ! 45: #ifdef DIAGNOSTICS ! 46: if (diagnostic & TD_REPORT) { ! 47: sprintf(nfrontp, "td: ttloop\r\n"); ! 48: nfrontp += strlen(nfrontp); ! 49: } ! 50: #endif /* DIAGNOSTICS */ ! 51: if (nfrontp-nbackp) { ! 52: netflush(); ! 53: } ! 54: ncc = read(net, netibuf, sizeof netibuf); ! 55: if (ncc < 0) { ! 56: syslog(LOG_INFO, "ttloop: read: %m\n"); ! 57: exit(1); ! 58: } else if (ncc == 0) { ! 59: syslog(LOG_INFO, "ttloop: peer died: %m\n"); ! 60: exit(1); ! 61: } ! 62: #ifdef DIAGNOSTICS ! 63: if (diagnostic & TD_REPORT) { ! 64: sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); ! 65: nfrontp += strlen(nfrontp); ! 66: } ! 67: #endif /* DIAGNOSTICS */ ! 68: netip = netibuf; ! 69: telrcv(); /* state machine */ ! 70: if (ncc > 0) { ! 71: pfrontp = pbackp = ptyobuf; ! 72: telrcv(); ! 73: } ! 74: } /* end of ttloop */ ! 75: ! 76: /* ! 77: * Check a descriptor to see if out of band data exists on it. ! 78: */ ! 79: stilloob(s) ! 80: int s; /* socket number */ ! 81: { ! 82: static struct timeval timeout = { 0 }; ! 83: fd_set excepts; ! 84: int value; ! 85: ! 86: do { ! 87: FD_ZERO(&excepts); ! 88: FD_SET(s, &excepts); ! 89: value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); ! 90: } while ((value == -1) && (errno == EINTR)); ! 91: ! 92: if (value < 0) { ! 93: fatalperror(pty, "select"); ! 94: } ! 95: if (FD_ISSET(s, &excepts)) { ! 96: return 1; ! 97: } else { ! 98: return 0; ! 99: } ! 100: } ! 101: ! 102: ptyflush() ! 103: { ! 104: int n; ! 105: ! 106: if ((n = pfrontp - pbackp) > 0) { ! 107: #ifdef DIAGNOSTICS ! 108: if (diagnostic & (TD_REPORT | TD_PTYDATA)) { ! 109: sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); ! 110: nfrontp += strlen(nfrontp); ! 111: } ! 112: if (diagnostic & TD_PTYDATA) { ! 113: printdata("pd", pbackp, n); ! 114: } ! 115: #endif /* DIAGNOSTICS */ ! 116: n = write(pty, pbackp, n); ! 117: } ! 118: if (n < 0) ! 119: return; ! 120: pbackp += n; ! 121: if (pbackp == pfrontp) ! 122: pbackp = pfrontp = ptyobuf; ! 123: } ! 124: ! 125: /* ! 126: * nextitem() ! 127: * ! 128: * Return the address of the next "item" in the TELNET data ! 129: * stream. This will be the address of the next character if ! 130: * the current address is a user data character, or it will ! 131: * be the address of the character following the TELNET command ! 132: * if the current address is a TELNET IAC ("I Am a Command") ! 133: * character. ! 134: */ ! 135: char * ! 136: nextitem(current) ! 137: char *current; ! 138: { ! 139: if ((*current&0xff) != IAC) { ! 140: return current+1; ! 141: } ! 142: switch (*(current+1)&0xff) { ! 143: case DO: ! 144: case DONT: ! 145: case WILL: ! 146: case WONT: ! 147: return current+3; ! 148: case SB: /* loop forever looking for the SE */ ! 149: { ! 150: register char *look = current+2; ! 151: ! 152: for (;;) { ! 153: if ((*look++&0xff) == IAC) { ! 154: if ((*look++&0xff) == SE) { ! 155: return look; ! 156: } ! 157: } ! 158: } ! 159: } ! 160: default: ! 161: return current+2; ! 162: } ! 163: } /* end of nextitem */ ! 164: ! 165: ! 166: /* ! 167: * netclear() ! 168: * ! 169: * We are about to do a TELNET SYNCH operation. Clear ! 170: * the path to the network. ! 171: * ! 172: * Things are a bit tricky since we may have sent the first ! 173: * byte or so of a previous TELNET command into the network. ! 174: * So, we have to scan the network buffer from the beginning ! 175: * until we are up to where we want to be. ! 176: * ! 177: * A side effect of what we do, just to keep things ! 178: * simple, is to clear the urgent data pointer. The principal ! 179: * caller should be setting the urgent data pointer AFTER calling ! 180: * us in any case. ! 181: */ ! 182: netclear() ! 183: { ! 184: register char *thisitem, *next; ! 185: char *good; ! 186: #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ ! 187: ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) ! 188: ! 189: thisitem = netobuf; ! 190: ! 191: while ((next = nextitem(thisitem)) <= nbackp) { ! 192: thisitem = next; ! 193: } ! 194: ! 195: /* Now, thisitem is first before/at boundary. */ ! 196: ! 197: good = netobuf; /* where the good bytes go */ ! 198: ! 199: while (nfrontp > thisitem) { ! 200: if (wewant(thisitem)) { ! 201: int length; ! 202: ! 203: next = thisitem; ! 204: do { ! 205: next = nextitem(next); ! 206: } while (wewant(next) && (nfrontp > next)); ! 207: length = next-thisitem; ! 208: bcopy(thisitem, good, length); ! 209: good += length; ! 210: thisitem = next; ! 211: } else { ! 212: thisitem = nextitem(thisitem); ! 213: } ! 214: } ! 215: ! 216: nbackp = netobuf; ! 217: nfrontp = good; /* next byte to be sent */ ! 218: neturg = 0; ! 219: } /* end of netclear */ ! 220: ! 221: /* ! 222: * netflush ! 223: * Send as much data as possible to the network, ! 224: * handling requests for urgent data. ! 225: */ ! 226: void ! 227: netflush() ! 228: { ! 229: int n; ! 230: extern int not42; ! 231: ! 232: if ((n = nfrontp - nbackp) > 0) { ! 233: #ifdef DIAGNOSTICS ! 234: if (diagnostic & TD_REPORT) { ! 235: sprintf(nfrontp, "td: netflush %d chars\r\n", n); ! 236: n += strlen(nfrontp); /* get count first */ ! 237: nfrontp += strlen(nfrontp); /* then move pointer */ ! 238: } ! 239: #endif /* DIAGNOSTICS */ ! 240: /* ! 241: * if no urgent data, or if the other side appears to be an ! 242: * old 4.2 client (and thus unable to survive TCP urgent data), ! 243: * write the entire buffer in non-OOB mode. ! 244: */ ! 245: if ((neturg == 0) || (not42 == 0)) { ! 246: n = write(net, nbackp, n); /* normal write */ ! 247: } else { ! 248: n = neturg - nbackp; ! 249: /* ! 250: * In 4.2 (and 4.3) systems, there is some question about ! 251: * what byte in a sendOOB operation is the "OOB" data. ! 252: * To make ourselves compatible, we only send ONE byte ! 253: * out of band, the one WE THINK should be OOB (though ! 254: * we really have more the TCP philosophy of urgent data ! 255: * rather than the Unix philosophy of OOB data). ! 256: */ ! 257: if (n > 1) { ! 258: n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ ! 259: } else { ! 260: n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ ! 261: } ! 262: } ! 263: } ! 264: if (n < 0) { ! 265: if (errno == EWOULDBLOCK || errno == EINTR) ! 266: return; ! 267: cleanup(); ! 268: } ! 269: nbackp += n; ! 270: if (nbackp >= neturg) { ! 271: neturg = 0; ! 272: } ! 273: if (nbackp == nfrontp) { ! 274: nbackp = nfrontp = netobuf; ! 275: } ! 276: return; ! 277: } /* end of netflush */ ! 278: ! 279: ! 280: /* ! 281: * writenet ! 282: * ! 283: * Just a handy little function to write a bit of raw data to the net. ! 284: * It will force a transmit of the buffer if necessary ! 285: * ! 286: * arguments ! 287: * ptr - A pointer to a character string to write ! 288: * len - How many bytes to write ! 289: */ ! 290: writenet(ptr, len) ! 291: register char *ptr; ! 292: register int len; ! 293: { ! 294: /* flush buffer if no room for new data) */ ! 295: if ((&netobuf[BUFSIZ] - nfrontp) < len) { ! 296: /* if this fails, don't worry, buffer is a little big */ ! 297: netflush(); ! 298: } ! 299: ! 300: bcopy(ptr, nfrontp, len); ! 301: nfrontp += len; ! 302: ! 303: } /* end of writenet */ ! 304: ! 305: ! 306: /* ! 307: * miscellaneous functions doing a variety of little jobs follow ... ! 308: */ ! 309: ! 310: ! 311: fatal(f, msg) ! 312: int f; ! 313: char *msg; ! 314: { ! 315: char buf[BUFSIZ]; ! 316: ! 317: (void) sprintf(buf, "telnetd: %s.\r\n", msg); ! 318: (void) write(f, buf, (int)strlen(buf)); ! 319: sleep(1); /*XXX*/ ! 320: exit(1); ! 321: } ! 322: ! 323: fatalperror(f, msg) ! 324: int f; ! 325: char *msg; ! 326: { ! 327: char buf[BUFSIZ], *strerror(); ! 328: ! 329: (void) sprintf(buf, "%s: %s\r\n", msg, strerror(errno)); ! 330: fatal(f, buf); ! 331: } ! 332: ! 333: char editedhost[32]; ! 334: ! 335: edithost(pat, host) ! 336: register char *pat; ! 337: register char *host; ! 338: { ! 339: register char *res = editedhost; ! 340: char *strncpy(); ! 341: ! 342: if (!pat) ! 343: pat = ""; ! 344: while (*pat) { ! 345: switch (*pat) { ! 346: ! 347: case '#': ! 348: if (*host) ! 349: host++; ! 350: break; ! 351: ! 352: case '@': ! 353: if (*host) ! 354: *res++ = *host++; ! 355: break; ! 356: ! 357: default: ! 358: *res++ = *pat; ! 359: break; ! 360: } ! 361: if (res == &editedhost[sizeof editedhost - 1]) { ! 362: *res = '\0'; ! 363: return; ! 364: } ! 365: pat++; ! 366: } ! 367: if (*host) ! 368: (void) strncpy(res, host, ! 369: sizeof editedhost - (res - editedhost) -1); ! 370: else ! 371: *res = '\0'; ! 372: editedhost[sizeof editedhost - 1] = '\0'; ! 373: } ! 374: ! 375: static char *putlocation; ! 376: ! 377: putstr(s) ! 378: register char *s; ! 379: { ! 380: ! 381: while (*s) ! 382: putchr(*s++); ! 383: } ! 384: ! 385: putchr(cc) ! 386: { ! 387: *putlocation++ = cc; ! 388: } ! 389: ! 390: putf(cp, where) ! 391: register char *cp; ! 392: char *where; ! 393: { ! 394: char *slash; ! 395: #ifndef NO_GETTYTAB ! 396: char datebuffer[60]; ! 397: #endif /* NO_GETTYTAB */ ! 398: extern char *rindex(); ! 399: ! 400: putlocation = where; ! 401: ! 402: while (*cp) { ! 403: if (*cp != '%') { ! 404: putchr(*cp++); ! 405: continue; ! 406: } ! 407: switch (*++cp) { ! 408: ! 409: case 't': ! 410: slash = rindex(line, '/'); ! 411: if (slash == (char *) 0) ! 412: putstr(line); ! 413: else ! 414: putstr(&slash[1]); ! 415: break; ! 416: ! 417: case 'h': ! 418: putstr(editedhost); ! 419: break; ! 420: ! 421: #ifndef NO_GETTYTAB ! 422: case 'd': ! 423: get_date(datebuffer); ! 424: putstr(datebuffer); ! 425: break; ! 426: #endif /* NO_GETTYTAB */ ! 427: ! 428: case '%': ! 429: putchr('%'); ! 430: break; ! 431: } ! 432: cp++; ! 433: } ! 434: } ! 435: ! 436: /*ARGSUSED*/ ! 437: #ifdef NO_GETTYTAB ! 438: getent(cp, name) ! 439: char *cp, *name; ! 440: { ! 441: return(0); ! 442: } ! 443: ! 444: /*ARGSUSED*/ ! 445: char * ! 446: getstr(cp, cpp) ! 447: char *cp, **cpp; ! 448: { ! 449: return(0); ! 450: } ! 451: #endif /* NO_GETTYTAB */ ! 452: ! 453: #ifdef DIAGNOSTICS ! 454: /* ! 455: * Print telnet options and commands in plain text, if possible. ! 456: */ ! 457: void ! 458: printoption(fmt, option) ! 459: register char *fmt; ! 460: register int option; ! 461: { ! 462: if (TELOPT_OK(option)) ! 463: sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); ! 464: else if (TELCMD_OK(option)) ! 465: sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option)); ! 466: else ! 467: sprintf(nfrontp, "%s %d\r\n", fmt, option); ! 468: nfrontp += strlen(nfrontp); ! 469: return; ! 470: } ! 471: ! 472: char *slcnames[] = { SLC_NAMES }; ! 473: ! 474: void ! 475: printsub(dirp, pointer, length) ! 476: char *dirp; ! 477: unsigned char *pointer; /* where suboption data sits */ ! 478: int length; /* length of suboption data */ ! 479: { ! 480: register int i; ! 481: ! 482: if (dirp) { ! 483: sprintf(nfrontp, "%s suboption ", dirp); ! 484: nfrontp += strlen(nfrontp); ! 485: if (length >= 3) { ! 486: register int j; ! 487: ! 488: i = pointer[length-2]; ! 489: j = pointer[length-1]; ! 490: ! 491: if (i != IAC || j != SE) { ! 492: sprintf(nfrontp, "(terminated by "); ! 493: nfrontp += strlen(nfrontp); ! 494: if (TELOPT_OK(i)) ! 495: sprintf(nfrontp, "%s ", TELOPT(i)); ! 496: else if (TELCMD_OK(i)) ! 497: sprintf(nfrontp, "%s ", TELCMD(i)); ! 498: else ! 499: sprintf(nfrontp, "%d ", i); ! 500: nfrontp += strlen(nfrontp); ! 501: if (TELOPT_OK(j)) ! 502: sprintf(nfrontp, "%s", TELOPT(j)); ! 503: else if (TELCMD_OK(j)) ! 504: sprintf(nfrontp, "%s", TELCMD(j)); ! 505: else ! 506: sprintf(nfrontp, "%d", j); ! 507: nfrontp += strlen(nfrontp); ! 508: sprintf(nfrontp, ", not IAC SE!) "); ! 509: nfrontp += strlen(nfrontp); ! 510: } ! 511: } ! 512: length -= 2; ! 513: } ! 514: if (length < 1) { ! 515: sprintf(nfrontp, "(Empty suboption???)"); ! 516: nfrontp += strlen(nfrontp); ! 517: return; ! 518: } ! 519: switch (pointer[0]) { ! 520: case TELOPT_TTYPE: ! 521: sprintf(nfrontp, "TERMINAL-TYPE "); ! 522: nfrontp += strlen(nfrontp); ! 523: switch (pointer[1]) { ! 524: case TELQUAL_IS: ! 525: sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); ! 526: break; ! 527: case TELQUAL_SEND: ! 528: sprintf(nfrontp, "SEND"); ! 529: break; ! 530: default: ! 531: sprintf(nfrontp, ! 532: "- unknown qualifier %d (0x%x).", ! 533: pointer[1], pointer[1]); ! 534: } ! 535: nfrontp += strlen(nfrontp); ! 536: break; ! 537: case TELOPT_TSPEED: ! 538: sprintf(nfrontp, "TERMINAL-SPEED"); ! 539: nfrontp += strlen(nfrontp); ! 540: if (length < 2) { ! 541: sprintf(nfrontp, " (empty suboption???)"); ! 542: nfrontp += strlen(nfrontp); ! 543: break; ! 544: } ! 545: switch (pointer[1]) { ! 546: case TELQUAL_IS: ! 547: sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2); ! 548: nfrontp += strlen(nfrontp); ! 549: break; ! 550: default: ! 551: if (pointer[1] == 1) ! 552: sprintf(nfrontp, " SEND"); ! 553: else ! 554: sprintf(nfrontp, " %d (unknown)", pointer[1]); ! 555: nfrontp += strlen(nfrontp); ! 556: for (i = 2; i < length; i++) { ! 557: sprintf(nfrontp, " ?%d?", pointer[i]); ! 558: nfrontp += strlen(nfrontp); ! 559: } ! 560: break; ! 561: } ! 562: break; ! 563: ! 564: case TELOPT_LFLOW: ! 565: sprintf(nfrontp, "TOGGLE-FLOW-CONTROL"); ! 566: nfrontp += strlen(nfrontp); ! 567: if (length < 2) { ! 568: sprintf(nfrontp, " (empty suboption???)"); ! 569: nfrontp += strlen(nfrontp); ! 570: break; ! 571: } ! 572: switch (pointer[1]) { ! 573: case 0: ! 574: sprintf(nfrontp, " OFF"); break; ! 575: case 1: ! 576: sprintf(nfrontp, " ON"); break; ! 577: default: ! 578: sprintf(nfrontp, " %d (unknown)", pointer[1]); ! 579: } ! 580: nfrontp += strlen(nfrontp); ! 581: for (i = 2; i < length; i++) { ! 582: sprintf(nfrontp, " ?%d?", pointer[i]); ! 583: nfrontp += strlen(nfrontp); ! 584: } ! 585: break; ! 586: ! 587: case TELOPT_NAWS: ! 588: sprintf(nfrontp, "NAWS"); ! 589: nfrontp += strlen(nfrontp); ! 590: if (length < 2) { ! 591: sprintf(nfrontp, " (empty suboption???)"); ! 592: nfrontp += strlen(nfrontp); ! 593: break; ! 594: } ! 595: if (length == 2) { ! 596: sprintf(nfrontp, " ?%d?", pointer[1]); ! 597: nfrontp += strlen(nfrontp); ! 598: break; ! 599: } ! 600: sprintf(nfrontp, " %d %d (%d)", ! 601: pointer[1], pointer[2], ! 602: (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); ! 603: nfrontp += strlen(nfrontp); ! 604: if (length == 4) { ! 605: sprintf(nfrontp, " ?%d?", pointer[3]); ! 606: nfrontp += strlen(nfrontp); ! 607: break; ! 608: } ! 609: sprintf(nfrontp, " %d %d (%d)", ! 610: pointer[3], pointer[4], ! 611: (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); ! 612: nfrontp += strlen(nfrontp); ! 613: for (i = 5; i < length; i++) { ! 614: sprintf(nfrontp, " ?%d?", pointer[i]); ! 615: nfrontp += strlen(nfrontp); ! 616: } ! 617: break; ! 618: ! 619: case TELOPT_LINEMODE: ! 620: sprintf(nfrontp, "LINEMODE "); ! 621: nfrontp += strlen(nfrontp); ! 622: if (length < 2) { ! 623: sprintf(nfrontp, " (empty suboption???)"); ! 624: nfrontp += strlen(nfrontp); ! 625: break; ! 626: } ! 627: switch (pointer[1]) { ! 628: case WILL: ! 629: sprintf(nfrontp, "WILL "); ! 630: goto common; ! 631: case WONT: ! 632: sprintf(nfrontp, "WONT "); ! 633: goto common; ! 634: case DO: ! 635: sprintf(nfrontp, "DO "); ! 636: goto common; ! 637: case DONT: ! 638: sprintf(nfrontp, "DONT "); ! 639: common: ! 640: nfrontp += strlen(nfrontp); ! 641: if (length < 3) { ! 642: sprintf(nfrontp, "(no option???)"); ! 643: nfrontp += strlen(nfrontp); ! 644: break; ! 645: } ! 646: switch (pointer[2]) { ! 647: case LM_FORWARDMASK: ! 648: sprintf(nfrontp, "Forward Mask"); ! 649: nfrontp += strlen(nfrontp); ! 650: for (i = 3; i < length; i++) { ! 651: sprintf(nfrontp, " %x", pointer[i]); ! 652: nfrontp += strlen(nfrontp); ! 653: } ! 654: break; ! 655: default: ! 656: sprintf(nfrontp, "%d (unknown)", pointer[2]); ! 657: nfrontp += strlen(nfrontp); ! 658: for (i = 3; i < length; i++) { ! 659: sprintf(nfrontp, " %d", pointer[i]); ! 660: nfrontp += strlen(nfrontp); ! 661: } ! 662: break; ! 663: } ! 664: break; ! 665: ! 666: case LM_SLC: ! 667: sprintf(nfrontp, "SLC"); ! 668: nfrontp += strlen(nfrontp); ! 669: for (i = 2; i < length - 2; i += 3) { ! 670: if (pointer[i+SLC_FUNC] <= NSLC) ! 671: sprintf(nfrontp, " %s", slcnames[pointer[i+SLC_FUNC]]); ! 672: else ! 673: sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]); ! 674: nfrontp += strlen(nfrontp); ! 675: switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { ! 676: case SLC_NOSUPPORT: ! 677: sprintf(nfrontp, " NOSUPPORT"); break; ! 678: case SLC_CANTCHANGE: ! 679: sprintf(nfrontp, " CANTCHANGE"); break; ! 680: case SLC_VARIABLE: ! 681: sprintf(nfrontp, " VARIABLE"); break; ! 682: case SLC_DEFAULT: ! 683: sprintf(nfrontp, " DEFAULT"); break; ! 684: } ! 685: nfrontp += strlen(nfrontp); ! 686: sprintf(nfrontp, "%s%s%s", ! 687: pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", ! 688: pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", ! 689: pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); ! 690: nfrontp += strlen(nfrontp); ! 691: if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| ! 692: SLC_FLUSHOUT| SLC_LEVELBITS)) { ! 693: sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]); ! 694: nfrontp += strlen(nfrontp); ! 695: } ! 696: sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]); ! 697: nfrontp += strlen(nfrontp); ! 698: if ((pointer[i+SLC_VALUE] == IAC) && ! 699: (pointer[i+SLC_VALUE+1] == IAC)) ! 700: i++; ! 701: } ! 702: for (; i < length; i++) { ! 703: sprintf(nfrontp, " ?%d?", pointer[i]); ! 704: nfrontp += strlen(nfrontp); ! 705: } ! 706: break; ! 707: ! 708: case LM_MODE: ! 709: sprintf(nfrontp, "MODE "); ! 710: nfrontp += strlen(nfrontp); ! 711: if (length < 3) { ! 712: sprintf(nfrontp, "(no mode???)"); ! 713: nfrontp += strlen(nfrontp); ! 714: break; ! 715: } ! 716: { ! 717: char tbuf[32]; ! 718: sprintf(tbuf, "%s%s%s%s%s", ! 719: pointer[2]&MODE_EDIT ? "|EDIT" : "", ! 720: pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", ! 721: pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", ! 722: pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", ! 723: pointer[2]&MODE_ACK ? "|ACK" : ""); ! 724: sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0"); ! 725: nfrontp += strlen(nfrontp); ! 726: } ! 727: if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { ! 728: sprintf(nfrontp, " (0x%x)", pointer[2]); ! 729: nfrontp += strlen(nfrontp); ! 730: } ! 731: for (i = 3; i < length; i++) { ! 732: sprintf(nfrontp, " ?0x%x?", pointer[i]); ! 733: nfrontp += strlen(nfrontp); ! 734: } ! 735: break; ! 736: default: ! 737: sprintf(nfrontp, "%d (unknown)", pointer[1]); ! 738: nfrontp += strlen(nfrontp); ! 739: for (i = 2; i < length; i++) { ! 740: sprintf(nfrontp, " %d", pointer[i]); ! 741: nfrontp += strlen(nfrontp); ! 742: } ! 743: } ! 744: break; ! 745: ! 746: case TELOPT_STATUS: { ! 747: register char *cp; ! 748: register int j, k; ! 749: ! 750: sprintf(nfrontp, "STATUS"); ! 751: nfrontp += strlen(nfrontp); ! 752: ! 753: switch (pointer[1]) { ! 754: default: ! 755: if (pointer[1] == TELQUAL_SEND) ! 756: sprintf(nfrontp, " SEND"); ! 757: else ! 758: sprintf(nfrontp, " %d (unknown)", pointer[1]); ! 759: nfrontp += strlen(nfrontp); ! 760: for (i = 2; i < length; i++) { ! 761: sprintf(nfrontp, " ?%d?", pointer[i]); ! 762: nfrontp += strlen(nfrontp); ! 763: } ! 764: break; ! 765: case TELQUAL_IS: ! 766: sprintf(nfrontp, " IS\r\n"); ! 767: nfrontp += strlen(nfrontp); ! 768: ! 769: for (i = 2; i < length; i++) { ! 770: switch(pointer[i]) { ! 771: case DO: cp = "DO"; goto common2; ! 772: case DONT: cp = "DONT"; goto common2; ! 773: case WILL: cp = "WILL"; goto common2; ! 774: case WONT: cp = "WONT"; goto common2; ! 775: common2: ! 776: i++; ! 777: if (TELOPT_OK((int)pointer[i])) ! 778: sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); ! 779: else ! 780: sprintf(nfrontp, " %s %d", cp, pointer[i]); ! 781: nfrontp += strlen(nfrontp); ! 782: ! 783: sprintf(nfrontp, "\r\n"); ! 784: nfrontp += strlen(nfrontp); ! 785: break; ! 786: ! 787: case SB: ! 788: sprintf(nfrontp, " SB "); ! 789: nfrontp += strlen(nfrontp); ! 790: i++; ! 791: j = k = i; ! 792: while (j < length) { ! 793: if (pointer[j] == SE) { ! 794: if (j+1 == length) ! 795: break; ! 796: if (pointer[j+1] == SE) ! 797: j++; ! 798: else ! 799: break; ! 800: } ! 801: pointer[k++] = pointer[j++]; ! 802: } ! 803: printsub(0, &pointer[i], k - i); ! 804: if (i < length) { ! 805: sprintf(nfrontp, " SE"); ! 806: nfrontp += strlen(nfrontp); ! 807: i = j; ! 808: } else ! 809: i = j - 1; ! 810: ! 811: sprintf(nfrontp, "\r\n"); ! 812: nfrontp += strlen(nfrontp); ! 813: ! 814: break; ! 815: ! 816: default: ! 817: sprintf(nfrontp, " %d", pointer[i]); ! 818: nfrontp += strlen(nfrontp); ! 819: break; ! 820: } ! 821: } ! 822: break; ! 823: } ! 824: break; ! 825: } ! 826: ! 827: case TELOPT_XDISPLOC: ! 828: sprintf(nfrontp, "X-DISPLAY-LOCATION "); ! 829: nfrontp += strlen(nfrontp); ! 830: switch (pointer[1]) { ! 831: case TELQUAL_IS: ! 832: sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); ! 833: break; ! 834: case TELQUAL_SEND: ! 835: sprintf(nfrontp, "SEND"); ! 836: break; ! 837: default: ! 838: sprintf(nfrontp, "- unknown qualifier %d (0x%x).", ! 839: pointer[1], pointer[1]); ! 840: } ! 841: nfrontp += strlen(nfrontp); ! 842: break; ! 843: ! 844: case TELOPT_ENVIRON: ! 845: sprintf(nfrontp, "ENVIRON "); ! 846: nfrontp += strlen(nfrontp); ! 847: switch (pointer[1]) { ! 848: case TELQUAL_IS: ! 849: sprintf(nfrontp, "IS "); ! 850: goto env_common; ! 851: case TELQUAL_SEND: ! 852: sprintf(nfrontp, "SEND "); ! 853: goto env_common; ! 854: case TELQUAL_INFO: ! 855: sprintf(nfrontp, "INFO "); ! 856: env_common: ! 857: nfrontp += strlen(nfrontp); ! 858: { ! 859: register int noquote = 2; ! 860: for (i = 2; i < length; i++ ) { ! 861: switch (pointer[i]) { ! 862: case ENV_VAR: ! 863: if (pointer[1] == TELQUAL_SEND) ! 864: goto def_case; ! 865: sprintf(nfrontp, "\" VAR " + noquote); ! 866: nfrontp += strlen(nfrontp); ! 867: noquote = 2; ! 868: break; ! 869: ! 870: case ENV_VALUE: ! 871: sprintf(nfrontp, "\" VALUE " + noquote); ! 872: nfrontp += strlen(nfrontp); ! 873: noquote = 2; ! 874: break; ! 875: ! 876: case ENV_ESC: ! 877: sprintf(nfrontp, "\" ESC " + noquote); ! 878: nfrontp += strlen(nfrontp); ! 879: noquote = 2; ! 880: break; ! 881: ! 882: default: ! 883: def_case: ! 884: if (isprint(pointer[i]) && pointer[i] != '"') { ! 885: if (noquote) { ! 886: *nfrontp++ = '"'; ! 887: noquote = 0; ! 888: } ! 889: *nfrontp++ = pointer[i]; ! 890: } else { ! 891: sprintf(nfrontp, "\" %03o " + noquote, ! 892: pointer[i]); ! 893: nfrontp += strlen(nfrontp); ! 894: noquote = 2; ! 895: } ! 896: break; ! 897: } ! 898: } ! 899: if (!noquote) ! 900: *nfrontp++ = '"'; ! 901: break; ! 902: } ! 903: } ! 904: break; ! 905: ! 906: default: ! 907: sprintf(nfrontp, "Unknown option "); ! 908: nfrontp += strlen(nfrontp); ! 909: for (i = 0; i < length; i++) { ! 910: sprintf(nfrontp, " %d", pointer[i]); ! 911: nfrontp += strlen(nfrontp); ! 912: } ! 913: break; ! 914: } ! 915: sprintf(nfrontp, "\r\n"); ! 916: nfrontp += strlen(nfrontp); ! 917: } ! 918: ! 919: /* ! 920: * Dump a data buffer in hex and ascii to the output data stream. ! 921: */ ! 922: void ! 923: printdata(tag, ptr, cnt) ! 924: register char *tag; ! 925: register char *ptr; ! 926: register int cnt; ! 927: { ! 928: register int i; ! 929: char xbuf[30]; ! 930: ! 931: while (cnt) { ! 932: /* flush net output buffer if no room for new data) */ ! 933: if ((&netobuf[BUFSIZ] - nfrontp) < 80) { ! 934: netflush(); ! 935: } ! 936: ! 937: /* add a line of output */ ! 938: sprintf(nfrontp, "%s: ", tag); ! 939: nfrontp += strlen(nfrontp); ! 940: for (i = 0; i < 20 && cnt; i++) { ! 941: sprintf(nfrontp, "%02x", *ptr); ! 942: nfrontp += strlen(nfrontp); ! 943: if (isprint(*ptr)) { ! 944: xbuf[i] = *ptr; ! 945: } else { ! 946: xbuf[i] = '.'; ! 947: } ! 948: if (i % 2) { ! 949: *nfrontp = ' '; ! 950: nfrontp++; ! 951: } ! 952: cnt--; ! 953: ptr++; ! 954: } ! 955: xbuf[i] = '\0'; ! 956: sprintf(nfrontp, " %s\r\n", xbuf ); ! 957: nfrontp += strlen(nfrontp); ! 958: } ! 959: } ! 960: ! 961: #endif /* DIAGNOSTICS */ ! 962: ! 963: #ifdef NO_STRERROR ! 964: char * ! 965: strerror(errno) ! 966: { ! 967: extern char *sys_errlist[]; ! 968: ! 969: return(sys_errlist[errno]); ! 970: } ! 971: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.