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

unix.superglobalmegacorp.com

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