Annotation of researchv9/ipc/src/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     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.