Annotation of researchv8dc/cmd/inet/etc/telnetd.c, revision 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 <stdio.h>
        !             9: #include <sys/param.h>
        !            10: #include <sys/types.h>
        !            11: #include <sys/stat.h>
        !            12: 
        !            13: #include <errno.h>
        !            14: #include <pwd.h>
        !            15: #include <signal.h>
        !            16: #include <sgtty.h>
        !            17: #include <stdio.h>
        !            18: #include <wait.h>
        !            19: #include <sys/inet/in.h>
        !            20: #include <sys/ttyld.h>
        !            21: #include <sys/stream.h>
        !            22: #include "config.h"
        !            23: #include "telnet.h"
        !            24: 
        !            25: #define        BELL    '\07'
        !            26: #define DEBUG if (debug)
        !            27: 
        !            28: /* option settings (remote and local) */
        !            29: static char    hisopts[256];
        !            30: static char    myopts[256];
        !            31: 
        !            32: /* formats for option messages */
        !            33: static char    doopt[] = { IAC, DO, '%', 'c', 0 };
        !            34: static char    dont[] = { IAC, DONT, '%', 'c', 0 };
        !            35: static char    will[] = { IAC, WILL, '%', 'c', 0 };
        !            36: static char    wont[] = { IAC, WONT, '%', 'c', 0 };
        !            37: 
        !            38: static int     ptno;           /* number of the pt */
        !            39: static int     ptfd, netfd;    /* fd's to pt and tcp */
        !            40: static int     done;           /* true if session is to be ended */
        !            41: static int     debug;          /* true if debugging is to be output */
        !            42: static struct sgttyb ptb;      /* result of an IOCGETP on the pt */
        !            43: static struct tchars ptt;      /* result of an IOCGETC on the pt */
        !            44: 
        !            45: /* predefined */
        !            46: static         reapchild();
        !            47: static catchint();     
        !            48: 
        !            49: /* imported */
        !            50: extern char **environ;
        !            51: extern int errno;
        !            52: extern char *strrchr(), *strchr();
        !            53:  
        !            54: 
        !            55: /*
        !            56:  *     The following macros and routines are used to
        !            57:  *     manage the I/O buffers.  They're a cross between
        !            58:  *     stream buffers and standard I/O.
        !            59:  */
        !            60: struct buffer {
        !            61:        char *b_rp;             /* read pointer */
        !            62:        char *b_wp;             /* write pointer */
        !            63:        char b_buf[BUFSIZ];     /* the buffer */
        !            64: };
        !            65: struct buffer ptibuf, *ptin = &ptibuf;
        !            66: struct buffer ptobuf, *ptout = &ptobuf;
        !            67: struct buffer netibuf, *netin = &netibuf;
        !            68: struct buffer netobuf, *netout = &netobuf;
        !            69: 
        !            70: #define binit(bp) (bp->b_rp = bp->b_wp = bp->b_buf)
        !            71: #define bytes_filled(bp) (bp->b_wp - bp->b_rp)
        !            72: #define space_left(bp) (bp->b_buf+sizeof(bp->b_buf) - bp->b_wp)
        !            73: #define bput(bp, c) (*(bp->b_wp++) = c)
        !            74: #define bget(bp) (*(bp->b_rp++) & 0377)
        !            75: 
        !            76: /* read whatever the buffer can take */
        !            77: static int
        !            78: bread(bp, fd)
        !            79:        struct buffer *bp;
        !            80:        int fd;
        !            81: {
        !            82:        int cc;
        !            83: 
        !            84:        /* normalize the buffer */
        !            85:        if (bytes_filled(bp) == 0)
        !            86:                bp->b_rp = bp->b_wp = bp->b_buf;
        !            87: 
        !            88:        /* fill it */
        !            89:        cc = read(fd, bp->b_wp, space_left(bp));
        !            90:        if (cc > 0)
        !            91:                bp->b_wp += cc;
        !            92:        return cc;
        !            93: }
        !            94: 
        !            95: /* read at most n bytes */
        !            96: static int
        !            97: breadn(bp, fd, n)
        !            98:        struct buffer *bp;
        !            99:        int fd, n;
        !           100: {
        !           101:        int cc;
        !           102: 
        !           103:        /* normalize the buffer */
        !           104:        if (bytes_filled(bp) == 0)
        !           105:                bp->b_rp = bp->b_wp = bp->b_buf;
        !           106:        if (n > space_left(bp))
        !           107:                n = space_left(bp);
        !           108: 
        !           109:        /* fill it */
        !           110:        cc = read(fd, bp->b_wp, n);
        !           111:        if (cc > 0)
        !           112:                bp->b_wp += cc;
        !           113:        return cc;
        !           114: }
        !           115: 
        !           116: /* empty the buffer */
        !           117: static int
        !           118: bwrite(bp, fd)
        !           119:        struct buffer *bp;
        !           120:        int fd;
        !           121: {
        !           122:        int cc;
        !           123: 
        !           124:        
        !           125:        cc = write(fd, bp->b_rp, bytes_filled(bp));
        !           126: 
        !           127:        /* normalize the buffer */
        !           128:        if (cc == bytes_filled(bp))
        !           129:                binit(bp);
        !           130:        return cc;
        !           131: }
        !           132: static int
        !           133: bputs(bp, s)
        !           134:        struct buffer *bp;
        !           135:        char *s;
        !           136: {
        !           137:        while (*s)
        !           138:                bput(bp, *s++);
        !           139: }
        !           140: 
        !           141: /*
        !           142:  *     Establish a tcp socket and fork off a process for each connection.
        !           143:  */
        !           144: main(argc, argv)
        !           145:        char *argv[];
        !           146: {
        !           147:        int pid;
        !           148:        int f, dev;
        !           149:        unsigned long faddr;
        !           150:        int myport, fport;
        !           151:        struct in_service *sp;
        !           152: 
        !           153:        sp = in_service("telnet", "tcp", 0);
        !           154:        if (sp == 0) {
        !           155:                fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
        !           156:                exit(1);
        !           157:        }
        !           158:        myport = sp->port;
        !           159:        argc--, argv++;
        !           160:        if (argc > 0 && !strcmp(*argv, "-d")) {
        !           161:                debug++;
        !           162:                argc--, argv++;
        !           163:        }
        !           164:        signal(SIGPIPE, SIG_IGN);
        !           165:        signal(SIGHUP, SIG_IGN);
        !           166: 
        !           167:        do {
        !           168:                f = tcp_sock();
        !           169:                if (f < 0) {
        !           170:                        perror("telnetd: socket");;
        !           171:                        sleep(5);
        !           172:                        continue;
        !           173:                }
        !           174:                if (tcp_listen(f, myport, 0, 0) < 0) {
        !           175:                        close(f);
        !           176:                        f = -1;
        !           177:                        sleep(30);
        !           178:                        continue;
        !           179:                }
        !           180:        } while (f < 0);
        !           181: 
        !           182:        signal(SIGCHLD, reapchild);
        !           183:        for (;;) {
        !           184:                int s;
        !           185: 
        !           186:                s = tcp_accept(f, &faddr, &fport, &dev);
        !           187:                if (s < 0) {
        !           188:                        if (errno == EINTR)
        !           189:                                continue;
        !           190:                        perror("telnetd: accept");
        !           191:                        sleep(1);
        !           192:                        continue;
        !           193:                }
        !           194:                switch(fork()) {
        !           195:                case -1:
        !           196:                        printf("Out of processes\n");
        !           197:                        break;
        !           198:                case 0:
        !           199:                        doit(s, faddr, fport, dev);
        !           200:                        exit(0);
        !           201:                }
        !           202:                close(s);
        !           203:        }
        !           204:        /*NOTREACHED*/
        !           205: }
        !           206: 
        !           207: static
        !           208: reapchild()
        !           209: {
        !           210:        union wait status;
        !           211: 
        !           212:        while (wait3(&status, WNOHANG, 0) > 0)
        !           213:                ;
        !           214: }
        !           215: 
        !           216: char   *envinit[] = { "TERM=network", 0 };
        !           217: 
        !           218: /*
        !           219:  *     Get a pt.  Put a login on one side and a telnet receiver on
        !           220:  *     the other.
        !           221:  */
        !           222: static
        !           223: doit(f, faddr, fport, dev)
        !           224:        int f;
        !           225:        unsigned long faddr;
        !           226: {
        !           227:        char *host, *in_ntoa(), *ptname();
        !           228:        int pfd[2];
        !           229: #      define TERMEND pfd[0]
        !           230: #      define PROCEND pfd[1]
        !           231:        extern int tty_ld, mesg_ld;
        !           232: 
        !           233:        /* get a pt pair */
        !           234:        if ((ptno = ptpipe(pfd)) < 0)
        !           235:                fatalperror(f, "out of pts", errno);
        !           236: 
        !           237:        host = (char *)in_host(faddr);
        !           238:        if (host == 0)
        !           239:                host = in_ntoa(faddr);
        !           240:        DEBUG fprintf(stderr, "telnet from %s: login on %s\n", host, ptname(ptno));
        !           241:        DEBUG fprintf(stderr, "telnetd pid = %d\n", getpid());
        !           242: 
        !           243: 
        !           244:        /* get the pt's characteristics */
        !           245:        ioctl(PROCEND, TIOCGETC, &ptt);
        !           246:        ioctl(PROCEND, TIOCGETP, &ptb);
        !           247: 
        !           248:        /* make it really look like a terminal */
        !           249:        ioctl(TERMEND, FIOPUSHLD, (struct sgttyb *)&mesg_ld);
        !           250:        ioctl(PROCEND, FIOPUSHLD, (struct sgttyb *)&tty_ld);
        !           251: 
        !           252:        /* prepare for the death of a child */
        !           253:        signal(SIGCHLD, catchint);
        !           254:        switch (fork()) {
        !           255:        case -1:
        !           256:                fatalperror(f, "fork", errno);
        !           257:        case 0:
        !           258:                /* a process which is the remote login */
        !           259:                getty(PROCEND);
        !           260:        default:
        !           261:                /* the protocol process */
        !           262:                close(PROCEND);
        !           263:                netfd = f;
        !           264:                ptfd = TERMEND;
        !           265:                telnet();
        !           266:        }
        !           267: 
        !           268:        /*NOTREACHED*/
        !           269: }
        !           270: 
        !           271: static
        !           272: fatal(f, msg)
        !           273:        int f;
        !           274:        char *msg;
        !           275: {
        !           276:        char buf[BUFSIZ];
        !           277: 
        !           278:        (void) sprintf(buf, "telnetd: %s.\n", msg);
        !           279:        (void) write(f, buf, strlen(buf));
        !           280:        exit(1);
        !           281: }
        !           282: 
        !           283: static
        !           284: fatalperror(f, msg, errno)
        !           285:        int f;
        !           286:        char *msg;
        !           287:        int errno;
        !           288: {
        !           289:        char buf[BUFSIZ];
        !           290:        extern char *sys_errlist[];
        !           291: 
        !           292:        (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
        !           293:        fatal(f, buf);
        !           294: }
        !           295: 
        !           296: static
        !           297: terminate(s)
        !           298:        char *s;
        !           299: {
        !           300:        DEBUG fprintf(stderr, "session on %s terminated because of %s\n",
        !           301:                        ptname(ptno), s);
        !           302:        done = 1;
        !           303: }
        !           304: 
        !           305: /* loop on input from the pt and the network */
        !           306: static
        !           307: telnet()
        !           308: {
        !           309:        register int c;
        !           310:        int n;
        !           311:        fd_set ibits, obits;
        !           312: 
        !           313:        binit(ptin);
        !           314:        binit(ptout);
        !           315:        binit(netin);
        !           316:        binit(netout);
        !           317: 
        !           318:        /* Request to do remote echo. */
        !           319:        dooption(TELOPT_ECHO);
        !           320:        myopts[TELOPT_ECHO] = 1;
        !           321: 
        !           322:        while(!done) {
        !           323:                FD_ZERO(ibits);
        !           324:                FD_ZERO(obits);
        !           325: 
        !           326:                /* process anything sitting in the input buffers */
        !           327:                if (bytes_filled(ptin) > 0)
        !           328:                        ptprocess();
        !           329:                if (bytes_filled(netin) > 0)
        !           330:                        netprocess();
        !           331: 
        !           332:                /* select for read only if there's room to read into */
        !           333:                if (space_left(netin) > 0)
        !           334:                        FD_SET(netfd, ibits);
        !           335:                if (space_left(ptin) > 0)
        !           336:                        FD_SET(ptfd, ibits);
        !           337: 
        !           338:                /* select for write only if there's something to write */
        !           339:                if (bytes_filled(ptout) > 0)
        !           340:                        FD_SET(ptfd, obits);
        !           341:                if (bytes_filled(netout) > 0)
        !           342:                        FD_SET(netfd, obits);
        !           343: 
        !           344:                n = select(NOFILE, &ibits, &obits, 100000);
        !           345:                if (n < 0)
        !           346:                        break;
        !           347:                else if (n == 0)
        !           348:                        continue;
        !           349: 
        !           350:                /* fill input buffers */
        !           351:                if (FD_ISSET(netfd, ibits))
        !           352:                        netrcv();
        !           353:                if (FD_ISSET(ptfd, ibits))
        !           354:                        ptrcv();
        !           355: 
        !           356:                /* flush output buffers */
        !           357:                if (FD_ISSET(netfd, obits) && bytes_filled(netout) > 0)
        !           358:                        netflush();
        !           359:                if (FD_ISSET(ptfd, obits) && bytes_filled(ptout) > 0)
        !           360:                        ptflush();
        !           361:        }
        !           362:        rmut();
        !           363:        close(netfd);
        !           364:        close(ptfd);
        !           365:        exit(0);
        !           366: }
        !           367: 
        !           368: struct mesg {
        !           369:        short type;
        !           370:        short size;
        !           371: };
        !           372: static struct mesg m;
        !           373: 
        !           374: /* read from the pt */
        !           375: static
        !           376: ptrcv()
        !           377: {
        !           378:        /* get the header if we don't already have one */
        !           379:        if (m.size <= 0)
        !           380:                if (read(ptfd, &m, sizeof(m)) != sizeof(m)) {
        !           381:                        terminate("pt read");
        !           382:                        return;
        !           383:                }
        !           384:        switch(m.type) {
        !           385:        case M_HANGUP:
        !           386:                terminate("pt hangup");
        !           387:                break;
        !           388:        case M_DATA:
        !           389:                datamesg();
        !           390:                break;
        !           391:        case M_IOCTL:
        !           392:                ioctlmesg();
        !           393:                break;
        !           394:        case M_IOCACK:
        !           395:                fprintf(stderr, "IOCACK\n");
        !           396:                flushmesg();
        !           397:                break;
        !           398:        case M_IOCNAK:
        !           399:                fprintf(stderr, "IOCNAK\n");
        !           400:                flushmesg();
        !           401:                break;
        !           402:        default:
        !           403:                othermesg();
        !           404:                break;
        !           405:        }
        !           406: }
        !           407: 
        !           408: /* flush a message from the pt */
        !           409: static
        !           410: flushmesg()
        !           411: {
        !           412:        union stmsg s;
        !           413:        int cc;
        !           414: 
        !           415:        /* flush it */
        !           416:        while (m.size > 0) {
        !           417:                fprintf(stderr, "flush\n");
        !           418:                cc = read(ptfd, &s, sizeof(s));
        !           419:                if (cc < 0) {
        !           420:                        terminate("pt read");
        !           421:                        return;
        !           422:                }
        !           423:                m.size -= cc;
        !           424:        }
        !           425: }
        !           426: 
        !           427: /* handle an ioctl message from the pt */
        !           428: static
        !           429: ioctlmesg()
        !           430: {
        !           431:        struct mesg rm;
        !           432:        union stmsg s;
        !           433:        int cc;
        !           434: 
        !           435:        rm.size = m.size;
        !           436:        if (m.size > 0) {
        !           437:                cc = read(ptfd, &s, sizeof(s));
        !           438:                if (cc < 0) {
        !           439:                        terminate("pt read");
        !           440:                        return;
        !           441:                }
        !           442:                m.size -= cc;
        !           443:        }
        !           444:        rm.type = M_IOCACK;
        !           445:        switch (s.ioc0.com) {
        !           446: 
        !           447:        case TIOCSETN:
        !           448:        case TIOCSETP:
        !           449:                ptb = s.ioc1.sb;
        !           450:                rm.size = 0;
        !           451:                break;
        !           452: 
        !           453:        case TIOCGETP:
        !           454:                s.ioc1.sb.sg_ispeed = B9600;
        !           455:                s.ioc1.sb.sg_ospeed = B9600;
        !           456:                ptb = s.ioc1.sb;
        !           457:                break;
        !           458: 
        !           459:        default:
        !           460:                rm.type = M_IOCNAK;
        !           461:                rm.size = 0;
        !           462:                break;
        !           463:        }
        !           464:        if (write(ptfd, &rm, sizeof(rm)) != sizeof(rm)) {
        !           465:                terminate("pt write");
        !           466:                return;
        !           467:        }
        !           468:        if (rm.size > 0)
        !           469:                if (write(ptfd, &s, rm.size) != rm.size) {
        !           470:                        terminate("pt write");
        !           471:                        return;
        !           472:                }
        !           473: 
        !           474:        flushmesg();
        !           475: }
        !           476: 
        !           477: /* read bytes from the pt and write to the network connection */
        !           478: static
        !           479: datamesg()
        !           480: {
        !           481:        int cc;
        !           482: 
        !           483:        cc = breadn(ptin, ptfd, m.size);
        !           484:        if (cc < 0)
        !           485:                terminate("pt read");
        !           486:        else
        !           487:                m.size -= cc;
        !           488: }
        !           489: 
        !           490: /* handle an unrecognized type of message */
        !           491: static
        !           492: othermesg()
        !           493: {
        !           494:        struct mesg rm;
        !           495:        char buf[132];
        !           496:        int rcc, wcc;
        !           497: 
        !           498:        wcc = write(ptfd, &m, sizeof(m));
        !           499:        if (wcc != sizeof(m)) {
        !           500:                terminate("pt write");
        !           501:                return;
        !           502:        }
        !           503:        while (m.size > 0) {
        !           504:                rcc = read(ptfd, buf, sizeof(buf));
        !           505:                if (rcc < 0) {
        !           506:                        terminate("pt read");
        !           507:                        return;
        !           508:                }
        !           509:                wcc = write(ptfd, buf, rcc);
        !           510:                if (wcc != rcc) {
        !           511:                        terminate("pt write");
        !           512:                        return;
        !           513:                }
        !           514:                m.size -= rcc;
        !           515:        }
        !           516: }
        !           517: 
        !           518: /* set pt mode */
        !           519: static
        !           520: mode(on, off)
        !           521:        int on, off;
        !           522: {
        !           523:        ptflush();
        !           524:        ptb.sg_flags |= on;
        !           525:        ptb.sg_flags &= ~off;
        !           526:        if(ioctl(ptfd, TIOCSETP, &ptb)<0)
        !           527:                terminate("setting mode of pt");
        !           528: }
        !           529: 
        !           530: /* flush the pt's output buffer */
        !           531: ptflush()
        !           532: {
        !           533:        struct mesg rm;
        !           534: 
        !           535:        rm.type = M_DATA;
        !           536:        rm.size = bytes_filled(ptout);
        !           537:        if (rm.size > 0) {
        !           538:                if (write(ptfd, &rm, sizeof(rm)) < sizeof(rm))
        !           539:                        terminate("pt write");
        !           540:                else if (bwrite(ptout, ptfd) <= 0)
        !           541:                        terminate("pt write");
        !           542:        }
        !           543: }
        !           544: 
        !           545: /* process bytes from the pt */
        !           546: static
        !           547: ptprocess()
        !           548: {
        !           549:        register int c;
        !           550: 
        !           551:        while(bytes_filled(ptin) && space_left(netout) > 1) {
        !           552:                c = bget(ptin);
        !           553:                if (c == IAC)
        !           554:                        bput(netout, c);
        !           555:                bput(netout, c);
        !           556:        }
        !           557: }
        !           558: 
        !           559: /* read bytes from the net */
        !           560: static
        !           561: netrcv()
        !           562: {
        !           563:        if (bread(netin, netfd) < 0)
        !           564:                terminate("net read");
        !           565: }
        !           566: 
        !           567: /* flush the netwrk's output buffer */
        !           568: netflush()
        !           569: {
        !           570:        if (bwrite(netout, netfd) < 0)  
        !           571:                terminate("net write");
        !           572: }
        !           573:        
        !           574: /*
        !           575:  * State for recv fsm
        !           576:  */
        !           577: #define        TS_DATA         0       /* base state */
        !           578: #define        TS_IAC          1       /* look for double IAC's */
        !           579: #define        TS_CR           2       /* CR-LF ->'s CR */
        !           580: #define        TS_BEGINNEG     3       /* throw away begin's... */
        !           581: #define        TS_ENDNEG       4       /* ...end's (suboption negotiation) */
        !           582: #define        TS_WILL         5       /* will option negotiation */
        !           583: #define        TS_WONT         6       /* wont " */
        !           584: #define        TS_DO           7       /* do " */
        !           585: #define        TS_DONT         8       /* dont " */
        !           586: 
        !           587: static
        !           588: netprocess()
        !           589: {
        !           590:        static int state = TS_DATA;
        !           591:        register int c;
        !           592:        char buf[10];
        !           593: 
        !           594:        while (bytes_filled(netin)) {
        !           595:                c = bget(netin);
        !           596:                switch (state) {
        !           597: 
        !           598:                case TS_DATA:
        !           599:                        if (c == IAC) {
        !           600:                                state = TS_IAC;
        !           601:                                break;
        !           602:                        }
        !           603:                        bput(ptout, c);
        !           604:                        if (!myopts[TELOPT_BINARY] && c == '\r')
        !           605:                                state = TS_CR;
        !           606:                        break;
        !           607: 
        !           608:                case TS_CR:
        !           609:                        if (c && c != '\n')
        !           610:                                bput(ptout, c);
        !           611:                        state = TS_DATA;
        !           612:                        break;
        !           613: 
        !           614:                case TS_IAC:
        !           615:                        switch (c) {
        !           616: 
        !           617:                        /*
        !           618:                         * Send the process on the pty side an
        !           619:                         * interrupt.  Do this with a NULL or
        !           620:                         * interrupt char; depending on the tty mode.
        !           621:                         */
        !           622:                        case BREAK:
        !           623:                        case IP:
        !           624:                                interrupt();
        !           625:                                break;
        !           626: 
        !           627:                        /*
        !           628:                         * Are You There?
        !           629:                         */
        !           630:                        case AYT:
        !           631:                                bput(ptout, BELL);
        !           632:                                break;
        !           633: 
        !           634:                        /*
        !           635:                         * Erase Character and
        !           636:                         * Erase Line
        !           637:                         */
        !           638:                        case EC:
        !           639:                        case EL:
        !           640:                                ptflush();
        !           641:                                bput(ptout, (c == EC) ? ptb.sg_erase : ptb.sg_kill);
        !           642:                                break;
        !           643: 
        !           644:                        /*
        !           645:                         * Check for urgent data...
        !           646:                         */
        !           647:                        case DM:
        !           648:                                break;
        !           649: 
        !           650:                        /*
        !           651:                         * Begin option subnegotiation...
        !           652:                         */
        !           653:                        case SB:
        !           654:                                state = TS_BEGINNEG;
        !           655:                                continue;
        !           656: 
        !           657:                        case WILL:
        !           658:                        case WONT:
        !           659:                        case DO:
        !           660:                        case DONT:
        !           661:                                state = TS_WILL + (c - WILL);
        !           662:                                continue;
        !           663: 
        !           664:                        case IAC:
        !           665:                                bput(ptout, c);
        !           666:                                break;
        !           667:                        }
        !           668:                        state = TS_DATA;
        !           669:                        break;
        !           670: 
        !           671:                case TS_BEGINNEG:
        !           672:                        if (c == IAC)
        !           673:                                state = TS_ENDNEG;
        !           674:                        break;
        !           675: 
        !           676:                case TS_ENDNEG:
        !           677:                        state = c == SE ? TS_DATA : TS_BEGINNEG;
        !           678:                        break;
        !           679: 
        !           680:                case TS_WILL:
        !           681:                        if (!hisopts[c])
        !           682:                                willoption(c);
        !           683:                        state = TS_DATA;
        !           684:                        continue;
        !           685: 
        !           686:                case TS_WONT:
        !           687:                        if (hisopts[c])
        !           688:                                wontoption(c);
        !           689:                        state = TS_DATA;
        !           690:                        continue;
        !           691: 
        !           692:                case TS_DO:
        !           693:                        if (!myopts[c])
        !           694:                                dooption(c);
        !           695:                        state = TS_DATA;
        !           696:                        continue;
        !           697: 
        !           698:                case TS_DONT:
        !           699:                        if (myopts[c]) {
        !           700:                                myopts[c] = 0;
        !           701:                                sprintf(buf, wont, c);
        !           702:                                bputs(netout, buf);
        !           703:                        }
        !           704:                        state = TS_DATA;
        !           705:                        continue;
        !           706: 
        !           707:                default:
        !           708:                        printf("telnetd: panic state=%d\n", state);
        !           709:                        exit(1);
        !           710:                }
        !           711:        }
        !           712: }
        !           713: 
        !           714: static
        !           715: willoption(option)
        !           716:        int option;
        !           717: {
        !           718:        char *fmt;
        !           719:        char buf[10];
        !           720: 
        !           721:        switch (option) {
        !           722: 
        !           723:        case TELOPT_BINARY:
        !           724:                mode(RAW, 0);
        !           725:                goto common;
        !           726: 
        !           727:        case TELOPT_ECHO:
        !           728:                mode(0, ECHO|CRMOD);
        !           729:                /*FALL THRU*/
        !           730: 
        !           731:        case TELOPT_SGA:
        !           732:        common:
        !           733:                hisopts[option] = 1;
        !           734:                fmt = doopt;
        !           735:                break;
        !           736: 
        !           737:        case TELOPT_TM:
        !           738:                fmt = dont;
        !           739:                break;
        !           740: 
        !           741:        default:
        !           742:                fmt = dont;
        !           743:                break;
        !           744:        }
        !           745:        sprintf(buf, fmt, option);
        !           746:        bputs(netout, buf);
        !           747: }
        !           748: 
        !           749: static
        !           750: wontoption(option)
        !           751:        int option;
        !           752: {
        !           753:        char *fmt;
        !           754:        char buf[10];
        !           755: 
        !           756:        switch (option) {
        !           757: 
        !           758:        case TELOPT_ECHO:
        !           759:                mode(ECHO|CRMOD, 0);
        !           760:                goto common;
        !           761: 
        !           762:        case TELOPT_BINARY:
        !           763:                mode(0, RAW);
        !           764:                /*FALL THRU*/
        !           765: 
        !           766:        case TELOPT_SGA:
        !           767:        common:
        !           768:                hisopts[option] = 0;
        !           769:                fmt = dont;
        !           770:                break;
        !           771: 
        !           772:        default:
        !           773:                fmt = dont;
        !           774:        }
        !           775:        sprintf(buf, fmt, option);
        !           776:        bputs(netout, buf);
        !           777: }
        !           778: 
        !           779: static
        !           780: dooption(option)
        !           781:        int option;
        !           782: {
        !           783:        char *fmt;
        !           784:        char buf[10];
        !           785: 
        !           786:        switch (option) {
        !           787: 
        !           788:        case TELOPT_TM:
        !           789:                fmt = wont;
        !           790:                break;
        !           791: 
        !           792:        case TELOPT_ECHO:
        !           793:                mode(ECHO|CRMOD, 0);
        !           794:                goto common;
        !           795: 
        !           796:        case TELOPT_BINARY:
        !           797:                mode(RAW, 0);
        !           798:                /*FALL THRU*/
        !           799: 
        !           800:        case TELOPT_SGA:
        !           801:        common:
        !           802:                fmt = will;
        !           803:                break;
        !           804: 
        !           805:        default:
        !           806:                fmt = wont;
        !           807:                break;
        !           808:        }
        !           809:        sprintf(buf, fmt, option);
        !           810:        bputs(netout, buf);
        !           811: }
        !           812: 
        !           813: /*
        !           814:  * Send interrupt to process on other side of pty.
        !           815:  * If it is in raw mode, just write NULL;
        !           816:  * otherwise, write intr char.
        !           817:  */
        !           818: static
        !           819: interrupt()
        !           820: {
        !           821:        ptflush();
        !           822:        ioctl(ptfd, TIOCGETC, &ptt);
        !           823:        bput(ptout, ptb.sg_flags & RAW ? '\0' : ptt.t_intrc);
        !           824: }
        !           825: 
        !           826: static
        !           827: catchint()
        !           828: {
        !           829:        terminate("child death");
        !           830: }
        !           831: 
        !           832: #include <utmp.h>
        !           833: 
        !           834: struct utmp wtmp;
        !           835: char   wtmpf[] = "/usr/adm/wtmp";
        !           836: char   utmp[] = "/etc/utmp";
        !           837: #define SCPYN(a, b)    strncpy(a, b, sizeof (a))
        !           838: #define SCMPN(a, b)    strncmp(a, b, sizeof (a))
        !           839: 
        !           840: static
        !           841: rmut()
        !           842: {
        !           843:        register f;
        !           844:        int found = 0;
        !           845:        char *line, *dev;
        !           846: 
        !           847:        dev = ptname(ptno);
        !           848:        line = dev + 5;
        !           849: 
        !           850:        DEBUG fprintf(stderr, "closing connection on %s\n", line);
        !           851: 
        !           852:        f = open(utmp, 2);
        !           853:        if (f >= 0) {
        !           854:                while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
        !           855:                        if (SCMPN(wtmp.ut_line, line) || wtmp.ut_name[0]==0)
        !           856:                                continue;
        !           857:                        lseek(f, -(long)sizeof (wtmp), 1);
        !           858:                        SCPYN(wtmp.ut_name, "");
        !           859:                        time(&wtmp.ut_time);
        !           860:                        write(f, (char *)&wtmp, sizeof (wtmp));
        !           861:                        found++;
        !           862:                }
        !           863:                close(f);
        !           864:        }
        !           865:        if (found) {
        !           866:                f = open(wtmpf, 1);
        !           867:                if (f >= 0) {
        !           868:                        SCPYN(wtmp.ut_line, line);
        !           869:                        SCPYN(wtmp.ut_name, "");
        !           870:                        time(&wtmp.ut_time);
        !           871:                        lseek(f, (long)0, 2);
        !           872:                        write(f, (char *)&wtmp, sizeof (wtmp));
        !           873:                        close(f);
        !           874:                }
        !           875:        }
        !           876:        chown(dev, 0, 0);
        !           877:        chmod(dev, 0666);
        !           878: }
        !           879: 
        !           880: static
        !           881: getty(f)
        !           882: {
        !           883:        int i;
        !           884:        struct sgttyb b;
        !           885:        char banner[128];
        !           886: 
        !           887:        ioctl(f, TIOCSPGRP, 0);
        !           888:        signal(SIGTERM, SIG_DFL) ;
        !           889:        signal(SIGPIPE, SIG_DFL) ;
        !           890:        signal(SIGQUIT, SIG_DFL) ;
        !           891:        signal(SIGINT, SIG_DFL) ;
        !           892:        signal(SIGALRM, SIG_DFL) ;
        !           893:        signal(SIGHUP, SIG_DFL) ;
        !           894:        signal(SIGCHLD, SIG_DFL) ;
        !           895:        close(0) ;
        !           896:        close(1) ;
        !           897:        close(2) ;
        !           898:        close(3) ;
        !           899:        dup(f) ;
        !           900:        dup(f) ;
        !           901:        dup(f) ;
        !           902:        dup(f);         /* for /dev/tty */
        !           903:        for (i=4; i<NOFILE; i++)
        !           904:                close(i) ;
        !           905:        ioctl(0, TIOCGETP, &b);
        !           906:        b.sg_flags |= CRMOD|XTABS|ANYP|ECHO;
        !           907:        b.sg_erase = '#';
        !           908:        b.sg_kill = '@';
        !           909:        ioctl(0, TIOCSETP, &b);
        !           910:        sprintf(banner, "%s (%s) ", whoami(), strrchr(ptname(ptno), '/')+1);
        !           911:        write (netfd, banner, strlen(banner));
        !           912:        execl(LOGIN, "login", 0);
        !           913:        fatalperror(2, LOGIN, errno);
        !           914:        exit(1);
        !           915: 
        !           916: }

unix.superglobalmegacorp.com

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