Annotation of cci/usr/src/etc/telnetd.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)telnetd.c  4.26 (Berkeley) 83/08/06";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Stripped-down telnet server.
                      7:  */
                      8: #include <sys/types.h>
                      9: #include <sys/socket.h>
                     10: #include <sys/wait.h>
                     11: 
                     12: #include <netinet/in.h>
                     13: 
                     14: #include <arpa/telnet.h>
                     15: 
                     16: #include <stdio.h>
                     17: #include <signal.h>
                     18: #include <errno.h>
                     19: #include <sgtty.h>
                     20: #include <netdb.h>
                     21: 
                     22: #define        BELL    '\07'
                     23: #define BANNER "\r\n\r\n4.2 BSD UNIX (%s)\r\n\r\r\n\r%s"
                     24: 
                     25: char   hisopts[256];
                     26: char   myopts[256];
                     27: 
                     28: char   doopt[] = { IAC, DO, '%', 'c', 0 };
                     29: char   dont[] = { IAC, DONT, '%', 'c', 0 };
                     30: char   will[] = { IAC, WILL, '%', 'c', 0 };
                     31: char   wont[] = { IAC, WONT, '%', 'c', 0 };
                     32: 
                     33: /*
                     34:  * I/O data buffers, pointers, and counters.
                     35:  */
                     36: char   ptyibuf[BUFSIZ], *ptyip = ptyibuf;
                     37: char   ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
                     38: char   netibuf[BUFSIZ], *netip = netibuf;
                     39: char   netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
                     40: int    pcc, ncc;
                     41: 
                     42: int    pty, net;
                     43: int    inter;
                     44: int    reapchild();
                     45: extern char **environ;
                     46: extern int errno;
                     47: char   line[] = "/dev/ptyp0";
                     48: 
                     49: struct sockaddr_in sin = { AF_INET };
                     50: 
                     51: /*
                     52:  * Changes:
                     53:  *     .       for AYT, write to the network (instead of pseudo-terminal).
                     54:  *     .       telnet(): Add test to see if there are any char in output
                     55:  *             buffers.  If so, continue to flush it.
                     56:  */
                     57: main(argc, argv)
                     58:        char *argv[];
                     59: {
                     60:        int     errcnt = 0;
                     61:        int s, pid, options;
                     62:        struct servent *sp;
                     63: 
                     64:        sp = getservbyname("telnet", "tcp");
                     65:        if (sp == 0) {
                     66:                fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
                     67:                exit(1);
                     68:        }
                     69:        sin.sin_port = sp->s_port;
                     70:        argc--, argv++;
                     71:        if (argc > 0 && !strcmp(*argv, "-d")) {
                     72:                options |= SO_DEBUG;
                     73:                argc--, argv++;
                     74:        }
                     75:        if (argc > 0) {
                     76:                sin.sin_port = atoi(*argv);
                     77:                if (sin.sin_port <= 0) {
                     78:                        fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
                     79:                        exit(1);
                     80:                }
                     81:                sin.sin_port = htons((u_short)sin.sin_port);
                     82:        }
                     83: #ifndef DEBUG
                     84:        if (fork())
                     85:                exit(0);
                     86:        (void) close (0);
                     87:        if ( open("/dev/console", 2) < 0) {
                     88:                fprintf(stderr, "telnetd: cannot open /dev/console\n");
                     89:                exit(1);
                     90:        }
                     91:        (void) dup2(0, 1);
                     92:        (void) dup2(0, 2);
                     93:        for (s = 3; s < 10; s++)
                     94:                (void) close(s);
                     95:        { int tt = open("/dev/tty", 2);
                     96:          if (tt > 0) {
                     97:                ioctl(tt, TIOCNOTTY, 0);
                     98:                close(tt);
                     99:          }
                    100:        }
                    101: #endif
                    102: again:
                    103:        s = socket(AF_INET, SOCK_STREAM, 0, 0);
                    104:        if (s < 0) {
                    105:                perror("telnetd: socket");;
                    106:                sleep(5);
                    107:                goto again;
                    108:        }
                    109:        if (options & SO_DEBUG)
                    110:                if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
                    111:                        perror("telnetd: setsockopt (SO_DEBUG)");
                    112:        if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
                    113:                perror("telnetd: setsockopt (SO_KEEPALIVE)");
                    114:        while (bind(s, (caddr_t)&sin, sizeof (sin), 0) < 0) {
                    115:                perror("telnetd: bind");
                    116:                sleep(5);
                    117:        }
                    118:        signal(SIGCHLD, reapchild);
                    119:        listen(s, 10);
                    120:        for (;errcnt < 20;) {
                    121:                struct sockaddr_in from;
                    122:                int s2, fromlen = sizeof (from);
                    123: 
                    124:                s2 = accept(s, (caddr_t)&from, &fromlen);
                    125:                if (s2 < 0) {
                    126:                        if (errno == EINTR)
                    127:                                continue;
                    128:                        perror("telnetd: accept");
                    129:                        ++errcnt;
                    130:                        sleep(5);
                    131:                        continue;
                    132:                }
                    133:                if ((pid = fork()) < 0) {
                    134:                        perror("telnetd: out of processes");
                    135:                        sleep(5);
                    136:                        continue;
                    137:                }
                    138:                else if (pid == 0) {
                    139:                        errcnt = 0;
                    140:                        signal(SIGCHLD, SIG_DFL);
                    141:                        doit(s2, &from);
                    142:                }
                    143:                errcnt = 0;
                    144:                close(s2);
                    145:        }
                    146:        fprintf(stderr,"telnetd terminates due to too many errors\n");
                    147:        /*NOTREACHED*/
                    148: }
                    149: 
                    150: reapchild()
                    151: {
                    152:        union wait status;
                    153: 
                    154:        while (wait3(&status, WNOHANG, 0) > 0)
                    155:                ;
                    156: }
                    157: 
                    158: char   *envinit[] = { "TERM=network", 0 };
                    159: int    cleanup();
                    160: 
                    161: /*
                    162:  * Get a pty, scan input lines.
                    163:  */
                    164: doit(f, who)
                    165:        int f;
                    166:        struct sockaddr_in *who;
                    167: {
                    168:        char *cp = line, *host, *ntoa();
                    169:        int i, p, cc, t;
                    170:        struct sgttyb b;
                    171:        struct hostent *hp;
                    172: 
                    173:        for (i = 0; i < 16; i++) {
                    174:                cp[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
                    175:                p = open(cp, 2);
                    176:                if (p > 0)
                    177:                        goto gotpty;
                    178:        }
                    179:        fatal(f, "All network ports in use");
                    180:        /*NOTREACHED*/
                    181: gotpty:
                    182:        dup2(f, 0);
                    183:        cp[strlen("/dev/")] = 't';
                    184:        t = open("/dev/tty", 2);
                    185:        if (t >= 0) {
                    186:                ioctl(t, TIOCNOTTY, 0);
                    187:                close(t);
                    188:        }
                    189:        t = open(cp, 2);
                    190:        if (t < 0)
                    191:                fatalperror(f, cp, errno);
                    192:        ioctl(t, TIOCGETP, &b);
                    193:        b.sg_flags = CRMOD|XTABS|ANYP;
                    194:        ioctl(t, TIOCSETP, &b);
                    195:        ioctl(p, TIOCGETP, &b);
                    196:        b.sg_flags &= ~ECHO;
                    197:        ioctl(p, TIOCSETP, &b);
                    198:        hp = gethostbyaddr(&who->sin_addr, sizeof (struct in_addr),
                    199:                who->sin_family);
                    200:        if (hp)
                    201:                host = hp->h_name;
                    202:        else
                    203:                host = ntoa(who->sin_addr);
                    204:        if ((i = fork()) < 0)
                    205:                fatalperror(f, "fork", errno);
                    206:        if (i)
                    207:                telnet(f, p);
                    208:        close(f);
                    209:        close(p);
                    210:        dup2(t, 0);
                    211:        dup2(t, 1);
                    212:        dup2(t, 2);
                    213:        close(t);
                    214:        environ = envinit;
                    215:        execl("/bin/login", "login", "-h", host, 0);
                    216:        fatalperror(f, "/bin/login", errno);
                    217:        /*NOTREACHED*/
                    218: }
                    219: 
                    220: fatal(f, msg)
                    221:        int f;
                    222:        char *msg;
                    223: {
                    224:        char buf[BUFSIZ];
                    225: 
                    226:        (void) sprintf(buf, "telnetd: %s.\n", msg);
                    227:        (void) write(f, buf, strlen(buf));
                    228:        exit(1);
                    229: }
                    230: 
                    231: fatalperror(f, msg, errno)
                    232:        int f;
                    233:        char *msg;
                    234:        int errno;
                    235: {
                    236:        char buf[BUFSIZ];
                    237:        extern char *sys_errlist[];
                    238: 
                    239:        (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
                    240:        fatal(f, buf);
                    241: }
                    242: 
                    243: /*
                    244:  * Main loop.  Select from pty and network, and
                    245:  * hand data to telnet receiver finite state machine.
                    246:  */
                    247: telnet(f, p)
                    248: {
                    249:        int on = 1;
                    250:        char hostname[32];
                    251: 
                    252:        net = f, pty = p;
                    253:        ioctl(f, FIONBIO, &on);
                    254:        ioctl(p, FIONBIO, &on);
                    255:        signal(SIGTSTP, SIG_IGN);
                    256:        signal(SIGCHLD, cleanup);
                    257: 
                    258:        /*
                    259:         * Request to do remote echo.
                    260:         */
                    261:        dooption(TELOPT_ECHO);
                    262:        myopts[TELOPT_ECHO] = 1;
                    263:        /*
                    264:         * Show banner that getty never gave.
                    265:         */
                    266:        gethostname(hostname, sizeof (hostname));
                    267:        sprintf(nfrontp, BANNER, hostname, "");
                    268:        nfrontp += strlen(nfrontp);
                    269:        for (;;) {
                    270:                int ibits = 0, obits = 0;
                    271:                register int c;
                    272: 
                    273:                /*
                    274:                 * Never look for input if there's still
                    275:                 * stuff in the corresponding output buffer
                    276:                 */
                    277:                if (nfrontp - nbackp || pcc > 0)
                    278:                        obits |= (1 << f);
                    279:                else
                    280:                        ibits |= (1 << p);
                    281:                if (pfrontp - pbackp || ncc > 0)
                    282:                        obits |= (1 << p);
                    283:                else
                    284:                        ibits |= (1 << f);
                    285:                if (ncc < 0 && pcc < 0)
                    286:                        break;
                    287:                select(16, &ibits, &obits, 0, 0);
                    288:                if (ibits == 0 && obits == 0) {
                    289:                        sleep(5);
                    290:                        continue;
                    291:                }
                    292: 
                    293:                /*
                    294:                 * Something to read from the network...
                    295:                 */
                    296:                if (ibits & (1 << f)) {
                    297:                        ncc = read(f, netibuf, BUFSIZ);
                    298:                        if (ncc < 0 && errno == EWOULDBLOCK)
                    299:                                ncc = 0;
                    300:                        else {
                    301:                                if (ncc <= 0)
                    302:                                        break;
                    303:                                netip = netibuf;
                    304:                        }
                    305:                }
                    306: 
                    307:                /*
                    308:                 * Something to read from the pty...
                    309:                 */
                    310:                if (ibits & (1 << p)) {
                    311:                        pcc = read(p, ptyibuf, BUFSIZ);
                    312:                        if (pcc < 0 && errno == EWOULDBLOCK)
                    313:                                pcc = 0;
                    314:                        else {
                    315:                                if (pcc <= 0)
                    316:                                        break;
                    317:                                ptyip = ptyibuf;
                    318:                        }
                    319:                }
                    320: 
                    321:                while (pcc > 0) {
                    322:                        if ((&netobuf[BUFSIZ] - nfrontp) < 2)
                    323:                                break;
                    324:                        c = *ptyip++ & 0377, pcc--;
                    325:                        if (c == IAC)
                    326:                                *nfrontp++ = c;
                    327:                        *nfrontp++ = c;
                    328:                }
                    329:                if ((obits & (1 << f)) && (nfrontp - nbackp) > 0)
                    330:                        netflush();
                    331:                if (ncc > 0)
                    332:                        telrcv();
                    333:                if ((obits & (1 << p)) && (pfrontp - pbackp) > 0)
                    334:                        ptyflush();
                    335:        }
                    336:        cleanup();
                    337: }
                    338:        
                    339: /*
                    340:  * State for recv fsm
                    341:  */
                    342: #define        TS_DATA         0       /* base state */
                    343: #define        TS_IAC          1       /* look for double IAC's */
                    344: #define        TS_CR           2       /* CR-LF ->'s CR */
                    345: #define        TS_BEGINNEG     3       /* throw away begin's... */
                    346: #define        TS_ENDNEG       4       /* ...end's (suboption negotiation) */
                    347: #define        TS_WILL         5       /* will option negotiation */
                    348: #define        TS_WONT         6       /* wont " */
                    349: #define        TS_DO           7       /* do " */
                    350: #define        TS_DONT         8       /* dont " */
                    351: 
                    352: telrcv()
                    353: {
                    354:        register int c;
                    355:        static int state = TS_DATA;
                    356:        struct sgttyb b;
                    357: 
                    358:        while (ncc > 0) {
                    359:                if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
                    360:                        return;
                    361:                c = *netip++ & 0377, ncc--;
                    362:                switch (state) {
                    363: 
                    364:                case TS_DATA:
                    365:                        if (c == IAC) {
                    366:                                state = TS_IAC;
                    367:                                break;
                    368:                        }
                    369:                        if (inter > 0)
                    370:                                break;
                    371:                        *pfrontp++ = c;
                    372:                        if (!myopts[TELOPT_BINARY] && c == '\r')
                    373:                                state = TS_CR;
                    374:                        break;
                    375: 
                    376:                case TS_CR:
                    377:                        if (c && c != '\n')
                    378:                                *pfrontp++ = c;
                    379:                        state = TS_DATA;
                    380:                        break;
                    381: 
                    382:                case TS_IAC:
                    383:                        switch (c) {
                    384: 
                    385:                        /*
                    386:                         * Send the process on the pty side an
                    387:                         * interrupt.  Do this with a NULL or
                    388:                         * interrupt char; depending on the tty mode.
                    389:                         */
                    390:                        case BREAK:
                    391:                        case IP:
                    392:                                interrupt();
                    393:                                break;
                    394: 
                    395:                        /*
                    396:                         * Are You There?
                    397:                         */
                    398:                        case AYT:
                    399:                                *nfrontp++ = BELL;
                    400:                                break;
                    401: 
                    402:                        /*
                    403:                         * Erase Character and
                    404:                         * Erase Line
                    405:                         */
                    406:                        case EC:
                    407:                        case EL:
                    408:                                ptyflush();     /* half-hearted */
                    409:                                ioctl(pty, TIOCGETP, &b);
                    410:                                *pfrontp++ = (c == EC) ?
                    411:                                        b.sg_erase : b.sg_kill;
                    412:                                break;
                    413: 
                    414:                        /*
                    415:                         * Check for urgent data...
                    416:                         */
                    417:                        case DM:
                    418:                                break;
                    419: 
                    420:                        /*
                    421:                         * Begin option subnegotiation...
                    422:                         */
                    423:                        case SB:
                    424:                                state = TS_BEGINNEG;
                    425:                                continue;
                    426: 
                    427:                        case WILL:
                    428:                        case WONT:
                    429:                        case DO:
                    430:                        case DONT:
                    431:                                state = TS_WILL + (c - WILL);
                    432:                                continue;
                    433: 
                    434:                        case IAC:
                    435:                                *pfrontp++ = c;
                    436:                                break;
                    437:                        }
                    438:                        state = TS_DATA;
                    439:                        break;
                    440: 
                    441:                case TS_BEGINNEG:
                    442:                        if (c == IAC)
                    443:                                state = TS_ENDNEG;
                    444:                        break;
                    445: 
                    446:                case TS_ENDNEG:
                    447:                        state = c == SE ? TS_DATA : TS_BEGINNEG;
                    448:                        break;
                    449: 
                    450:                case TS_WILL:
                    451:                        if (!hisopts[c])
                    452:                                willoption(c);
                    453:                        state = TS_DATA;
                    454:                        continue;
                    455: 
                    456:                case TS_WONT:
                    457:                        if (hisopts[c])
                    458:                                wontoption(c);
                    459:                        state = TS_DATA;
                    460:                        continue;
                    461: 
                    462:                case TS_DO:
                    463:                        if (!myopts[c])
                    464:                                dooption(c);
                    465:                        state = TS_DATA;
                    466:                        continue;
                    467: 
                    468:                case TS_DONT:
                    469:                        if (myopts[c]) {
                    470:                                myopts[c] = 0;
                    471:                                sprintf(nfrontp, wont, c);
                    472:                                nfrontp += sizeof (wont) - 2;
                    473:                        }
                    474:                        state = TS_DATA;
                    475:                        continue;
                    476: 
                    477:                default:
                    478:                        printf("telnetd: panic state=%d\n", state);
                    479:                        exit(1);
                    480:                }
                    481:        }
                    482: }
                    483: 
                    484: willoption(option)
                    485:        int option;
                    486: {
                    487:        char *fmt;
                    488: 
                    489:        switch (option) {
                    490: 
                    491:        case TELOPT_BINARY:
                    492:                mode(RAW, 0);
                    493:                goto common;
                    494: 
                    495:        case TELOPT_ECHO:
                    496:                mode(0, ECHO|CRMOD);
                    497:                /*FALL THRU*/
                    498: 
                    499:        case TELOPT_SGA:
                    500:        common:
                    501:                hisopts[option] = 1;
                    502:                fmt = doopt;
                    503:                break;
                    504: 
                    505:        case TELOPT_TM:
                    506:                fmt = dont;
                    507:                break;
                    508: 
                    509:        default:
                    510:                fmt = dont;
                    511:                break;
                    512:        }
                    513:        sprintf(nfrontp, fmt, option);
                    514:        nfrontp += sizeof (dont) - 2;
                    515: }
                    516: 
                    517: wontoption(option)
                    518:        int option;
                    519: {
                    520:        char *fmt;
                    521: 
                    522:        switch (option) {
                    523: 
                    524:        case TELOPT_ECHO:
                    525:                mode(ECHO|CRMOD, 0);
                    526:                goto common;
                    527: 
                    528:        case TELOPT_BINARY:
                    529:                mode(0, RAW);
                    530:                /*FALL THRU*/
                    531: 
                    532:        case TELOPT_SGA:
                    533:        common:
                    534:                hisopts[option] = 0;
                    535:                fmt = dont;
                    536:                break;
                    537: 
                    538:        default:
                    539:                fmt = dont;
                    540:        }
                    541:        sprintf(nfrontp, fmt, option);
                    542:        nfrontp += sizeof (doopt) - 2;
                    543: }
                    544: 
                    545: dooption(option)
                    546:        int option;
                    547: {
                    548:        char *fmt;
                    549: 
                    550:        switch (option) {
                    551: 
                    552:        case TELOPT_TM:
                    553:                fmt = wont;
                    554:                break;
                    555: 
                    556:        case TELOPT_ECHO:
                    557:                mode(ECHO|CRMOD, 0);
                    558:                goto common;
                    559: 
                    560:        case TELOPT_BINARY:
                    561:                mode(RAW, 0);
                    562:                /*FALL THRU*/
                    563: 
                    564:        case TELOPT_SGA:
                    565:        common:
                    566:                fmt = will;
                    567:                break;
                    568: 
                    569:        default:
                    570:                fmt = wont;
                    571:                break;
                    572:        }
                    573:        sprintf(nfrontp, fmt, option);
                    574:        nfrontp += sizeof (doopt) - 2;
                    575: }
                    576: 
                    577: mode(on, off)
                    578:        int on, off;
                    579: {
                    580:        struct sgttyb b;
                    581: 
                    582:        ptyflush();
                    583:        ioctl(pty, TIOCGETP, &b);
                    584:        b.sg_flags |= on;
                    585:        b.sg_flags &= ~off;
                    586:        ioctl(pty, TIOCSETP, &b);
                    587: }
                    588: 
                    589: /*
                    590:  * Send interrupt to process on other side of pty.
                    591:  * If it is in raw mode, just write NULL;
                    592:  * otherwise, write intr char.
                    593:  */
                    594: interrupt()
                    595: {
                    596:        struct sgttyb b;
                    597:        struct tchars tchars;
                    598: 
                    599:        ptyflush();     /* half-hearted */
                    600:        ioctl(pty, TIOCGETP, &b);
                    601:        if (b.sg_flags & RAW) {
                    602:                *pfrontp++ = '\0';
                    603:                return;
                    604:        }
                    605:        *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
                    606:                '\177' : tchars.t_intrc;
                    607: }
                    608: 
                    609: ptyflush()
                    610: {
                    611:        int n;
                    612: 
                    613:        if ((n = pfrontp - pbackp) > 0)
                    614:                n = write(pty, pbackp, n);
                    615:        if (n < 0)
                    616:                return;
                    617:        pbackp += n;
                    618:        if (pbackp == pfrontp)
                    619:                pbackp = pfrontp = ptyobuf;
                    620: }
                    621: 
                    622: netflush()
                    623: {
                    624:        int n;
                    625: 
                    626:        if ((n = nfrontp - nbackp) > 0)
                    627:                n = write(net, nbackp, n);
                    628:        if (n < 0) {
                    629:                if (errno == EWOULDBLOCK)
                    630:                        return;
                    631:                /* should blow this guy away... */
                    632:                return;
                    633:        }
                    634:        nbackp += n;
                    635:        if (nbackp == nfrontp)
                    636:                nbackp = nfrontp = netobuf;
                    637: }
                    638: 
                    639: cleanup()
                    640: {
                    641: 
                    642:        rmut();
                    643:        vhangup();      /* XXX */
                    644:        shutdown(net, 2);
                    645:        kill(0, SIGKILL);
                    646:        exit(1);
                    647: }
                    648: 
                    649: #include <utmp.h>
                    650: 
                    651: struct utmp wtmp;
                    652: char   wtmpf[] = "/usr/adm/wtmp";
                    653: char   utmp[] = "/etc/utmp";
                    654: #define SCPYN(a, b)    strncpy(a, b, sizeof (a))
                    655: #define SCMPN(a, b)    strncmp(a, b, sizeof (a))
                    656: 
                    657: rmut()
                    658: {
                    659:        register f;
                    660:        int found = 0;
                    661: 
                    662:        f = open(utmp, 2);
                    663:        if (f >= 0) {
                    664:                while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
                    665:                        if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
                    666:                                continue;
                    667:                        lseek(f, -(long)sizeof (wtmp), 1);
                    668:                        SCPYN(wtmp.ut_name, "");
                    669:                        SCPYN(wtmp.ut_host, "");
                    670:                        time(&wtmp.ut_time);
                    671:                        write(f, (char *)&wtmp, sizeof (wtmp));
                    672:                        found++;
                    673:                }
                    674:                close(f);
                    675:        }
                    676:        if (found) {
                    677:                f = open(wtmpf, 1);
                    678:                if (f >= 0) {
                    679:                        SCPYN(wtmp.ut_line, line+5);
                    680:                        SCPYN(wtmp.ut_name, "");
                    681:                        SCPYN(wtmp.ut_host, "");
                    682:                        time(&wtmp.ut_time);
                    683:                        lseek(f, (long)0, 2);
                    684:                        write(f, (char *)&wtmp, sizeof (wtmp));
                    685:                        close(f);
                    686:                }
                    687:        }
                    688:        chmod(line, 0666);
                    689:        chown(line, 0, 0);
                    690:        line[strlen("/dev/")] = 'p';
                    691:        chmod(line, 0666);
                    692:        chown(line, 0, 0);
                    693: }
                    694: 
                    695: /*
                    696:  * Convert network-format internet address
                    697:  * to base 256 d.d.d.d representation.
                    698:  */
                    699: char *
                    700: ntoa(in)
                    701:        struct in_addr in;
                    702: {
                    703:        static char b[18];
                    704:        register char *p;
                    705: 
                    706:        p = (char *)&in;
                    707: #define        UC(b)   (((int)b)&0xff)
                    708:        sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
                    709:        return (b);
                    710: }

unix.superglobalmegacorp.com

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