Annotation of researchv10no/ipc/servers/telnetd.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)telnetd.c  4.26 (Berkeley) 83/08/06";
                      3: #endif
                      4: 
                      5: /*
                      6:  * Stripped-down telnet server.
                      7:  */
                      8: #include <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.