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

unix.superglobalmegacorp.com

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