Annotation of 43BSDReno/libexec/telnetd/utility.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.