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

unix.superglobalmegacorp.com

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