Annotation of 43BSD/ucb/rlogin.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1983 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: char copyright[] =
        !             9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
        !            10:  All rights reserved.\n";
        !            11: #endif not lint
        !            12: 
        !            13: #ifndef lint
        !            14: static char sccsid[] = "@(#)rlogin.c   5.10 (Berkeley) 3/30/86";
        !            15: #endif not lint
        !            16: 
        !            17: /*
        !            18:  * rlogin - remote login
        !            19:  */
        !            20: #include <sys/param.h>
        !            21: #include <sys/errno.h>
        !            22: #include <sys/file.h>
        !            23: #include <sys/socket.h>
        !            24: #include <sys/wait.h>
        !            25: 
        !            26: #include <netinet/in.h>
        !            27: 
        !            28: #include <stdio.h>
        !            29: #include <sgtty.h>
        !            30: #include <errno.h>
        !            31: #include <pwd.h>
        !            32: #include <signal.h>
        !            33: #include <setjmp.h>
        !            34: #include <netdb.h>
        !            35: 
        !            36: # ifndef TIOCPKT_WINDOW
        !            37: # define TIOCPKT_WINDOW 0x80
        !            38: # endif TIOCPKT_WINDOW
        !            39: 
        !            40: char   *index(), *rindex(), *malloc(), *getenv();
        !            41: struct passwd *getpwuid();
        !            42: char   *name;
        !            43: int    rem;
        !            44: char   cmdchar = '~';
        !            45: int    eight;
        !            46: int    litout;
        !            47: char   *speeds[] =
        !            48:     { "0", "50", "75", "110", "134", "150", "200", "300",
        !            49:       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
        !            50: char   term[256] = "network";
        !            51: extern int errno;
        !            52: int    lostpeer();
        !            53: int    dosigwinch = 0;
        !            54: #ifndef sigmask
        !            55: #define sigmask(m)     (1 << ((m)-1))
        !            56: #endif
        !            57: #ifdef sun
        !            58: struct ttysize winsize;
        !            59: struct winsize {
        !            60:        unsigned short ws_row, ws_col;
        !            61:        unsigned short ws_xpixel, ws_ypixel;
        !            62: };
        !            63: #else sun
        !            64: struct winsize winsize;
        !            65: #endif sun
        !            66: int    sigwinch(), oob();
        !            67: 
        !            68: main(argc, argv)
        !            69:        int argc;
        !            70:        char **argv;
        !            71: {
        !            72:        char *host, *cp;
        !            73:        struct sgttyb ttyb;
        !            74:        struct passwd *pwd;
        !            75:        struct servent *sp;
        !            76:        int uid, options = 0, oldmask;
        !            77:        int on = 1;
        !            78: 
        !            79:        host = rindex(argv[0], '/');
        !            80:        if (host)
        !            81:                host++;
        !            82:        else
        !            83:                host = argv[0];
        !            84:        argv++, --argc;
        !            85:        if (!strcmp(host, "rlogin"))
        !            86:                host = *argv++, --argc;
        !            87: another:
        !            88:        if (argc > 0 && !strcmp(*argv, "-d")) {
        !            89:                argv++, argc--;
        !            90:                options |= SO_DEBUG;
        !            91:                goto another;
        !            92:        }
        !            93:        if (argc > 0 && !strcmp(*argv, "-l")) {
        !            94:                argv++, argc--;
        !            95:                if (argc == 0)
        !            96:                        goto usage;
        !            97:                name = *argv++; argc--;
        !            98:                goto another;
        !            99:        }
        !           100:        if (argc > 0 && !strncmp(*argv, "-e", 2)) {
        !           101:                cmdchar = argv[0][2];
        !           102:                argv++, argc--;
        !           103:                goto another;
        !           104:        }
        !           105:        if (argc > 0 && !strcmp(*argv, "-8")) {
        !           106:                eight = 1;
        !           107:                argv++, argc--;
        !           108:                goto another;
        !           109:        }
        !           110:        if (argc > 0 && !strcmp(*argv, "-L")) {
        !           111:                litout = 1;
        !           112:                argv++, argc--;
        !           113:                goto another;
        !           114:        }
        !           115:        if (host == 0)
        !           116:                goto usage;
        !           117:        if (argc > 0)
        !           118:                goto usage;
        !           119:        pwd = getpwuid(getuid());
        !           120:        if (pwd == 0) {
        !           121:                fprintf(stderr, "Who are you?\n");
        !           122:                exit(1);
        !           123:        }
        !           124:        sp = getservbyname("login", "tcp");
        !           125:        if (sp == 0) {
        !           126:                fprintf(stderr, "rlogin: login/tcp: unknown service\n");
        !           127:                exit(2);
        !           128:        }
        !           129:        cp = getenv("TERM");
        !           130:        if (cp)
        !           131:                strcpy(term, cp);
        !           132:        if (ioctl(0, TIOCGETP, &ttyb) == 0) {
        !           133:                strcat(term, "/");
        !           134:                strcat(term, speeds[ttyb.sg_ospeed]);
        !           135:        }
        !           136: #ifdef sun
        !           137:        (void) ioctl(0, TIOCGSIZE, &winsize);
        !           138: #else sun
        !           139:        (void) ioctl(0, TIOCGWINSZ, &winsize);
        !           140: #endif sun
        !           141:        signal(SIGPIPE, lostpeer);
        !           142:        signal(SIGURG, oob);
        !           143:        oldmask = sigblock(sigmask(SIGURG));
        !           144:         rem = rcmd(&host, sp->s_port, pwd->pw_name,
        !           145:            name ? name : pwd->pw_name, term, 0);
        !           146:         if (rem < 0)
        !           147:                 exit(1);
        !           148:        if (options & SO_DEBUG &&
        !           149:            setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
        !           150:                perror("rlogin: setsockopt (SO_DEBUG)");
        !           151:        uid = getuid();
        !           152:        if (setuid(uid) < 0) {
        !           153:                perror("rlogin: setuid");
        !           154:                exit(1);
        !           155:        }
        !           156:        doit(oldmask);
        !           157:        /*NOTREACHED*/
        !           158: usage:
        !           159:        fprintf(stderr,
        !           160:            "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n");
        !           161:        exit(1);
        !           162: }
        !           163: 
        !           164: #define CRLF "\r\n"
        !           165: 
        !           166: int    child;
        !           167: int    catchild();
        !           168: int    writeroob();
        !           169: 
        !           170: int    defflags, tabflag;
        !           171: int    deflflags;
        !           172: char   deferase, defkill;
        !           173: struct tchars deftc;
        !           174: struct ltchars defltc;
        !           175: struct tchars notc =   { -1, -1, -1, -1, -1, -1 };
        !           176: struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
        !           177: 
        !           178: doit(oldmask)
        !           179: {
        !           180:        int exit();
        !           181:        struct sgttyb sb;
        !           182: 
        !           183:        ioctl(0, TIOCGETP, (char *)&sb);
        !           184:        defflags = sb.sg_flags;
        !           185:        tabflag = defflags & TBDELAY;
        !           186:        defflags &= ECHO | CRMOD;
        !           187:        deferase = sb.sg_erase;
        !           188:        defkill = sb.sg_kill;
        !           189:        ioctl(0, TIOCLGET, (char *)&deflflags);
        !           190:        ioctl(0, TIOCGETC, (char *)&deftc);
        !           191:        notc.t_startc = deftc.t_startc;
        !           192:        notc.t_stopc = deftc.t_stopc;
        !           193:        ioctl(0, TIOCGLTC, (char *)&defltc);
        !           194:        signal(SIGINT, SIG_IGN);
        !           195:        signal(SIGHUP, exit);
        !           196:        signal(SIGQUIT, exit);
        !           197:        child = fork();
        !           198:        if (child == -1) {
        !           199:                perror("rlogin: fork");
        !           200:                done(1);
        !           201:        }
        !           202:        if (child == 0) {
        !           203:                mode(1);
        !           204:                sigsetmask(oldmask);
        !           205:                if (reader() == 0) {
        !           206:                        prf("Connection closed.");
        !           207:                        exit(0);
        !           208:                }
        !           209:                sleep(1);
        !           210:                prf("\007Connection closed.");
        !           211:                exit(3);
        !           212:        }
        !           213:        signal(SIGURG, writeroob);
        !           214:        sigsetmask(oldmask);
        !           215:        signal(SIGCHLD, catchild);
        !           216:        writer();
        !           217:        prf("Closed connection.");
        !           218:        done(0);
        !           219: }
        !           220: 
        !           221: done(status)
        !           222:        int status;
        !           223: {
        !           224: 
        !           225:        mode(0);
        !           226:        if (child > 0 && kill(child, SIGKILL) >= 0)
        !           227:                wait((int *)0);
        !           228:        exit(status);
        !           229: }
        !           230: 
        !           231: /*
        !           232:  * This is called when the reader process gets the out-of-band (urgent)
        !           233:  * request to turn on the window-changing protocol.
        !           234:  */
        !           235: writeroob()
        !           236: {
        !           237: 
        !           238:        if (dosigwinch == 0) {
        !           239:                sendwindow();
        !           240:                signal(SIGWINCH, sigwinch);
        !           241:        }
        !           242:        dosigwinch = 1;
        !           243: }
        !           244: 
        !           245: catchild()
        !           246: {
        !           247:        union wait status;
        !           248:        int pid;
        !           249: 
        !           250: again:
        !           251:        pid = wait3(&status, WNOHANG|WUNTRACED, 0);
        !           252:        if (pid == 0)
        !           253:                return;
        !           254:        /*
        !           255:         * if the child (reader) dies, just quit
        !           256:         */
        !           257:        if (pid < 0 || pid == child && !WIFSTOPPED(status))
        !           258:                done(status.w_termsig | status.w_retcode);
        !           259:        goto again;
        !           260: }
        !           261: 
        !           262: /*
        !           263:  * writer: write to remote: 0 -> line.
        !           264:  * ~.  terminate
        !           265:  * ~^Z suspend rlogin process.
        !           266:  * ~^Y  suspend rlogin process, but leave reader alone.
        !           267:  */
        !           268: writer()
        !           269: {
        !           270:        char c;
        !           271:        register n;
        !           272:        register bol = 1;               /* beginning of line */
        !           273:        register local = 0;
        !           274: 
        !           275:        for (;;) {
        !           276:                n = read(0, &c, 1);
        !           277:                if (n <= 0) {
        !           278:                        if (n < 0 && errno == EINTR)
        !           279:                                continue;
        !           280:                        break;
        !           281:                }
        !           282:                /*
        !           283:                 * If we're at the beginning of the line
        !           284:                 * and recognize a command character, then
        !           285:                 * we echo locally.  Otherwise, characters
        !           286:                 * are echo'd remotely.  If the command
        !           287:                 * character is doubled, this acts as a 
        !           288:                 * force and local echo is suppressed.
        !           289:                 */
        !           290:                if (bol) {
        !           291:                        bol = 0;
        !           292:                        if (c == cmdchar) {
        !           293:                                bol = 0;
        !           294:                                local = 1;
        !           295:                                continue;
        !           296:                        }
        !           297:                } else if (local) {
        !           298:                        local = 0;
        !           299:                        if (c == '.' || c == deftc.t_eofc) {
        !           300:                                echo(c);
        !           301:                                break;
        !           302:                        }
        !           303:                        if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
        !           304:                                bol = 1;
        !           305:                                echo(c);
        !           306:                                stop(c);
        !           307:                                continue;
        !           308:                        }
        !           309:                        if (c != cmdchar)
        !           310:                                write(rem, &cmdchar, 1);
        !           311:                }
        !           312:                if (write(rem, &c, 1) == 0) {
        !           313:                        prf("line gone");
        !           314:                        break;
        !           315:                }
        !           316:                bol = c == defkill || c == deftc.t_eofc ||
        !           317:                    c == deftc.t_intrc || c == defltc.t_suspc ||
        !           318:                    c == '\r' || c == '\n';
        !           319:        }
        !           320: }
        !           321: 
        !           322: echo(c)
        !           323: register char c;
        !           324: {
        !           325:        char buf[8];
        !           326:        register char *p = buf;
        !           327: 
        !           328:        c &= 0177;
        !           329:        *p++ = cmdchar;
        !           330:        if (c < ' ') {
        !           331:                *p++ = '^';
        !           332:                *p++ = c + '@';
        !           333:        } else if (c == 0177) {
        !           334:                *p++ = '^';
        !           335:                *p++ = '?';
        !           336:        } else
        !           337:                *p++ = c;
        !           338:        *p++ = '\r';
        !           339:        *p++ = '\n';
        !           340:        write(1, buf, p - buf);
        !           341: }
        !           342: 
        !           343: stop(cmdc)
        !           344:        char cmdc;
        !           345: {
        !           346:        mode(0);
        !           347:        signal(SIGCHLD, SIG_IGN);
        !           348:        kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
        !           349:        signal(SIGCHLD, catchild);
        !           350:        mode(1);
        !           351:        sigwinch();                     /* check for size changes */
        !           352: }
        !           353: 
        !           354: #ifdef sun
        !           355: sigwinch()
        !           356: {
        !           357:        struct ttysize ws;
        !           358: 
        !           359:        if (dosigwinch && ioctl(0, TIOCGSIZE, &ws) == 0 &&
        !           360:            bcmp(&ws, &winsize, sizeof (ws))) {
        !           361:                winsize = ws;
        !           362:                sendwindow();
        !           363:        }
        !           364: }
        !           365: 
        !           366: #else sun
        !           367: sigwinch()
        !           368: {
        !           369:        struct winsize ws;
        !           370: 
        !           371:        if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
        !           372:            bcmp(&ws, &winsize, sizeof (ws))) {
        !           373:                winsize = ws;
        !           374:                sendwindow();
        !           375:        }
        !           376: }
        !           377: #endif
        !           378: 
        !           379: /*
        !           380:  * Send the window size to the server via the magic escape
        !           381:  */
        !           382: sendwindow()
        !           383: {
        !           384:        char obuf[4 + sizeof (struct winsize)];
        !           385:        struct winsize *wp = (struct winsize *)(obuf+4);
        !           386: 
        !           387:        obuf[0] = 0377;
        !           388:        obuf[1] = 0377;
        !           389:        obuf[2] = 's';
        !           390:        obuf[3] = 's';
        !           391: #ifdef sun
        !           392:        wp->ws_row = htons(winsize.ts_lines);
        !           393:        wp->ws_col = htons(winsize.ts_cols);
        !           394:        wp->ws_xpixel = 0;
        !           395:        wp->ws_ypixel = 0;
        !           396: #else sun
        !           397:        wp->ws_row = htons(winsize.ws_row);
        !           398:        wp->ws_col = htons(winsize.ws_col);
        !           399:        wp->ws_xpixel = htons(winsize.ws_xpixel);
        !           400:        wp->ws_ypixel = htons(winsize.ws_ypixel);
        !           401: #endif sun
        !           402:        (void) write(rem, obuf, sizeof(obuf));
        !           403: }
        !           404: 
        !           405: /*
        !           406:  * reader: read from remote: line -> 1
        !           407:  */
        !           408: #define        READING 1
        !           409: #define        WRITING 2
        !           410: 
        !           411: char   rcvbuf[8 * 1024];
        !           412: int    rcvcnt;
        !           413: int    rcvstate;
        !           414: int    ppid;
        !           415: jmp_buf        rcvtop;
        !           416: 
        !           417: oob()
        !           418: {
        !           419:        int out = FWRITE, atmark, n;
        !           420:        int rcvd = 0;
        !           421:        char waste[BUFSIZ], mark;
        !           422:        struct sgttyb sb;
        !           423: 
        !           424:        while (recv(rem, &mark, 1, MSG_OOB) < 0)
        !           425:                switch (errno) {
        !           426:                
        !           427:                case EWOULDBLOCK:
        !           428:                        /*
        !           429:                         * Urgent data not here yet.
        !           430:                         * It may not be possible to send it yet
        !           431:                         * if we are blocked for output
        !           432:                         * and our input buffer is full.
        !           433:                         */
        !           434:                        if (rcvcnt < sizeof(rcvbuf)) {
        !           435:                                n = read(rem, rcvbuf + rcvcnt,
        !           436:                                        sizeof(rcvbuf) - rcvcnt);
        !           437:                                if (n <= 0)
        !           438:                                        return;
        !           439:                                rcvd += n;
        !           440:                        } else {
        !           441:                                n = read(rem, waste, sizeof(waste));
        !           442:                                if (n <= 0)
        !           443:                                        return;
        !           444:                        }
        !           445:                        continue;
        !           446:                                
        !           447:                default:
        !           448:                        return;
        !           449:        }
        !           450:        if (mark & TIOCPKT_WINDOW) {
        !           451:                /*
        !           452:                 * Let server know about window size changes
        !           453:                 */
        !           454:                kill(ppid, SIGURG);
        !           455:        }
        !           456:        if (!eight && (mark & TIOCPKT_NOSTOP)) {
        !           457:                ioctl(0, TIOCGETP, (char *)&sb);
        !           458:                sb.sg_flags &= ~CBREAK;
        !           459:                sb.sg_flags |= RAW;
        !           460:                ioctl(0, TIOCSETN, (char *)&sb);
        !           461:                notc.t_stopc = -1;
        !           462:                notc.t_startc = -1;
        !           463:                ioctl(0, TIOCSETC, (char *)&notc);
        !           464:        }
        !           465:        if (!eight && (mark & TIOCPKT_DOSTOP)) {
        !           466:                ioctl(0, TIOCGETP, (char *)&sb);
        !           467:                sb.sg_flags &= ~RAW;
        !           468:                sb.sg_flags |= CBREAK;
        !           469:                ioctl(0, TIOCSETN, (char *)&sb);
        !           470:                notc.t_stopc = deftc.t_stopc;
        !           471:                notc.t_startc = deftc.t_startc;
        !           472:                ioctl(0, TIOCSETC, (char *)&notc);
        !           473:        }
        !           474:        if (mark & TIOCPKT_FLUSHWRITE) {
        !           475:                ioctl(1, TIOCFLUSH, (char *)&out);
        !           476:                for (;;) {
        !           477:                        if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
        !           478:                                perror("ioctl");
        !           479:                                break;
        !           480:                        }
        !           481:                        if (atmark)
        !           482:                                break;
        !           483:                        n = read(rem, waste, sizeof (waste));
        !           484:                        if (n <= 0)
        !           485:                                break;
        !           486:                }
        !           487:                /*
        !           488:                 * Don't want any pending data to be output,
        !           489:                 * so clear the recv buffer.
        !           490:                 * If we were hanging on a write when interrupted,
        !           491:                 * don't want it to restart.  If we were reading,
        !           492:                 * restart anyway.
        !           493:                 */
        !           494:                rcvcnt = 0;
        !           495:                longjmp(rcvtop, 1);
        !           496:        }
        !           497:        /*
        !           498:         * If we filled the receive buffer while a read was pending,
        !           499:         * longjmp to the top to restart appropriately.  Don't abort
        !           500:         * a pending write, however, or we won't know how much was written.
        !           501:         */
        !           502:        if (rcvd && rcvstate == READING)
        !           503:                longjmp(rcvtop, 1);
        !           504: }
        !           505: 
        !           506: /*
        !           507:  * reader: read from remote: line -> 1
        !           508:  */
        !           509: reader()
        !           510: {
        !           511: #if !defined(BSD) || BSD < 43
        !           512:        int pid = -getpid();
        !           513: #else
        !           514:        int pid = getpid();
        !           515: #endif
        !           516:        int n, remaining;
        !           517:        char *bufp = rcvbuf;
        !           518: 
        !           519:        signal(SIGTTOU, SIG_IGN);
        !           520:        fcntl(rem, F_SETOWN, pid);
        !           521:        ppid = getppid();
        !           522:        (void) setjmp(rcvtop);
        !           523:        for (;;) {
        !           524:                while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
        !           525:                        rcvstate = WRITING;
        !           526:                        n = write(1, bufp, remaining);
        !           527:                        if (n < 0) {
        !           528:                                if (errno != EINTR)
        !           529:                                        return (-1);
        !           530:                                continue;
        !           531:                        }
        !           532:                        bufp += n;
        !           533:                }
        !           534:                bufp = rcvbuf;
        !           535:                rcvcnt = 0;
        !           536:                rcvstate = READING;
        !           537:                rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
        !           538:                if (rcvcnt == 0)
        !           539:                        return (0);
        !           540:                if (rcvcnt < 0) {
        !           541:                        if (errno == EINTR)
        !           542:                                continue;
        !           543:                        perror("read");
        !           544:                        return (-1);
        !           545:                }
        !           546:        }
        !           547: }
        !           548: 
        !           549: mode(f)
        !           550: {
        !           551:        struct tchars *tc;
        !           552:        struct ltchars *ltc;
        !           553:        struct sgttyb sb;
        !           554:        int     lflags;
        !           555: 
        !           556:        ioctl(0, TIOCGETP, (char *)&sb);
        !           557:        ioctl(0, TIOCLGET, (char *)&lflags);
        !           558:        switch (f) {
        !           559: 
        !           560:        case 0:
        !           561:                sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
        !           562:                sb.sg_flags |= defflags|tabflag;
        !           563:                tc = &deftc;
        !           564:                ltc = &defltc;
        !           565:                sb.sg_kill = defkill;
        !           566:                sb.sg_erase = deferase;
        !           567:                lflags = deflflags;
        !           568:                break;
        !           569: 
        !           570:        case 1:
        !           571:                sb.sg_flags |= (eight ? RAW : CBREAK);
        !           572:                sb.sg_flags &= ~defflags;
        !           573:                /* preserve tab delays, but turn off XTABS */
        !           574:                if ((sb.sg_flags & TBDELAY) == XTABS)
        !           575:                        sb.sg_flags &= ~TBDELAY;
        !           576:                tc = &notc;
        !           577:                ltc = &noltc;
        !           578:                sb.sg_kill = sb.sg_erase = -1;
        !           579:                if (litout)
        !           580:                        lflags |= LLITOUT;
        !           581:                break;
        !           582: 
        !           583:        default:
        !           584:                return;
        !           585:        }
        !           586:        ioctl(0, TIOCSLTC, (char *)ltc);
        !           587:        ioctl(0, TIOCSETC, (char *)tc);
        !           588:        ioctl(0, TIOCSETN, (char *)&sb);
        !           589:        ioctl(0, TIOCLSET, (char *)&lflags);
        !           590: }
        !           591: 
        !           592: /*VARARGS*/
        !           593: prf(f, a1, a2, a3, a4, a5)
        !           594:        char *f;
        !           595: {
        !           596:        fprintf(stderr, f, a1, a2, a3, a4, a5);
        !           597:        fprintf(stderr, CRLF);
        !           598: }
        !           599: 
        !           600: lostpeer()
        !           601: {
        !           602:        signal(SIGPIPE, SIG_IGN);
        !           603:        prf("\007Connection closed.");
        !           604:        done(1);
        !           605: }
        !           606: 

unix.superglobalmegacorp.com

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