Annotation of 43BSD/ucb/rlogin.c, revision 1.1.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.