Annotation of 43BSDReno/foreign/src/rlogin/rlogin.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1983, 1990 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted provided
        !             6:  * that: (1) source distributions retain this entire copyright notice and
        !             7:  * comment, and (2) distributions including binaries display the following
        !             8:  * acknowledgement:  ``This product includes software developed by the
        !             9:  * University of California, Berkeley and its contributors'' in the
        !            10:  * documentation or other materials provided with the distribution and in
        !            11:  * all advertising materials mentioning features or use of this software.
        !            12:  * Neither the name of the University nor the names of its contributors may
        !            13:  * be used to endorse or promote products derived from this software without
        !            14:  * specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: char copyright[] =
        !            22: "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
        !            23:  All rights reserved.\n";
        !            24: #endif /* not lint */
        !            25: 
        !            26: #ifndef lint
        !            27: static char sccsid[] = "@(#)rlogin.c   5.32.1.1 (Berkeley) 10/21/90";
        !            28: #endif /* not lint */
        !            29: 
        !            30: /*
        !            31:  * $Source: mit/rlogin/RCS/rlogin.c,v $
        !            32:  * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall
        !            33:  *     Exp Locker: kfall $
        !            34:  */
        !            35: 
        !            36: /*
        !            37:  * rlogin - remote login
        !            38:  */
        !            39: #include <sys/param.h>
        !            40: #include <sys/file.h>
        !            41: #include <sys/socket.h>
        !            42: #include <sys/signal.h>
        !            43: #include <sys/time.h>
        !            44: #include <sys/resource.h>
        !            45: #include <sys/wait.h>
        !            46: 
        !            47: #include <netinet/in.h>
        !            48: #include <netinet/in_systm.h>
        !            49: #include <netinet/ip.h>
        !            50: #include <netdb.h>
        !            51: 
        !            52: #include <sgtty.h>
        !            53: #include <setjmp.h>
        !            54: #include <varargs.h>
        !            55: #include <errno.h>
        !            56: #include <pwd.h>
        !            57: #include <stdio.h>
        !            58: #include <unistd.h>
        !            59: #include <string.h>
        !            60: 
        !            61: #ifdef KERBEROS
        !            62: #include <kerberosIV/des.h>
        !            63: #include <kerberosIV/krb.h>
        !            64: 
        !            65: CREDENTIALS cred;
        !            66: Key_schedule schedule;
        !            67: int use_kerberos = 1, encrypt;
        !            68: char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
        !            69: extern char *krb_realmofhost();
        !            70: #endif
        !            71: 
        !            72: #ifndef TIOCPKT_WINDOW
        !            73: #define        TIOCPKT_WINDOW  0x80
        !            74: #endif
        !            75: 
        !            76: /* concession to Sun */
        !            77: #ifndef SIGUSR1
        !            78: #define        SIGUSR1 30
        !            79: #endif
        !            80: 
        !            81: extern int errno;
        !            82: int eight, litout, rem;
        !            83: 
        !            84: int noescape;
        !            85: u_char escapechar = '~';
        !            86: 
        !            87: char *speeds[] = {
        !            88:        "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200",
        !            89:        "1800", "2400", "4800", "9600", "19200", "38400"
        !            90: };
        !            91: 
        !            92: #ifdef sun
        !            93: struct winsize {
        !            94:        unsigned short ws_row, ws_col;
        !            95:        unsigned short ws_xpixel, ws_ypixel;
        !            96: };
        !            97: #endif
        !            98: struct winsize winsize;
        !            99: 
        !           100: #ifndef sun
        !           101: #define        get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp)
        !           102: #endif
        !           103: 
        !           104: void exit();
        !           105: 
        !           106: main(argc, argv)
        !           107:        int argc;
        !           108:        char **argv;
        !           109: {
        !           110:        extern char *optarg;
        !           111:        extern int optind;
        !           112:        struct passwd *pw;
        !           113:        struct servent *sp;
        !           114:        struct sgttyb ttyb;
        !           115:        long omask;
        !           116:        int argoff, ch, dflag, one, uid;
        !           117:        char *host, *p, *user, term[1024];
        !           118:        void lostpeer();
        !           119:        u_char getescape();
        !           120:        char *getenv();
        !           121: 
        !           122:        argoff = dflag = 0;
        !           123:        one = 1;
        !           124:        host = user = NULL;
        !           125: 
        !           126:        if (p = rindex(argv[0], '/'))
        !           127:                ++p;
        !           128:        else
        !           129:                p = argv[0];
        !           130: 
        !           131:        if (strcmp(p, "rlogin"))
        !           132:                host = p;
        !           133: 
        !           134:        /* handle "rlogin host flags" */
        !           135:        if (!host && argc > 2 && argv[1][0] != '-') {
        !           136:                host = argv[1];
        !           137:                argoff = 1;
        !           138:        }
        !           139: 
        !           140: #ifdef KERBEROS
        !           141: #define        OPTIONS "8EKLde:k:l:x"
        !           142: #else
        !           143: #define        OPTIONS "8EKLde:l:"
        !           144: #endif
        !           145:        while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
        !           146:                switch(ch) {
        !           147:                case '8':
        !           148:                        eight = 1;
        !           149:                        break;
        !           150:                case 'E':
        !           151:                        noescape = 1;
        !           152:                        break;
        !           153:                case 'K':
        !           154: #ifdef KERBEROS
        !           155:                        use_kerberos = 0;
        !           156: #endif
        !           157:                        break;
        !           158:                case 'L':
        !           159:                        litout = 1;
        !           160:                        break;
        !           161:                case 'd':
        !           162:                        dflag = 1;
        !           163:                        break;
        !           164:                case 'e':
        !           165:                        escapechar = getescape(optarg);
        !           166:                        break;
        !           167: #ifdef KERBEROS
        !           168:                case 'k':
        !           169:                        dest_realm = dst_realm_buf;
        !           170:                        (void)strncpy(dest_realm, optarg, REALM_SZ);
        !           171:                        break;
        !           172: #endif
        !           173:                case 'l':
        !           174:                        user = optarg;
        !           175:                        break;
        !           176:                case '?':
        !           177:                default:
        !           178:                        usage();
        !           179:                }
        !           180:        optind += argoff;
        !           181:        argc -= optind;
        !           182:        argv += optind;
        !           183: 
        !           184:        /* if haven't gotten a host yet, do so */
        !           185:        if (!host && !(host = *argv++))
        !           186:                usage();
        !           187: 
        !           188:        if (*argv)
        !           189:                usage();
        !           190: 
        !           191:        if (!(pw = getpwuid(uid = getuid()))) {
        !           192:                (void)fprintf(stderr, "rlogin: unknown user id.\n");
        !           193:                exit(1);
        !           194:        }
        !           195:        if (!user)
        !           196:                user = pw->pw_name;
        !           197: 
        !           198:        sp = NULL;
        !           199: #ifdef KERBEROS
        !           200:        if (use_kerberos) {
        !           201:                sp = getservbyname((encrypt ? "eklogin" : "klogin"), "tcp");
        !           202:                if (sp == NULL) {
        !           203:                        use_kerberos = 0;
        !           204:                        warning("can't get entry for %s/tcp service",
        !           205:                            encrypt ? "eklogin" : "klogin");
        !           206:                }
        !           207:        }
        !           208: #endif
        !           209:        if (sp == NULL)
        !           210:                sp = getservbyname("login", "tcp");
        !           211:        if (sp == NULL) {
        !           212:                (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n");
        !           213:                exit(1);
        !           214:        }
        !           215: 
        !           216:        (void)strcpy(term, (p = getenv("TERM")) ? p : "network");
        !           217:        if (ioctl(0, TIOCGETP, &ttyb) == 0) {
        !           218:                (void)strcat(term, "/");
        !           219:                (void)strcat(term, speeds[ttyb.sg_ospeed]);
        !           220:        }
        !           221: 
        !           222:        (void)get_window_size(0, &winsize);
        !           223: 
        !           224:        (void)signal(SIGPIPE, lostpeer);
        !           225:        /* will use SIGUSR1 for window size hack, so hold it off */
        !           226:        omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
        !           227: 
        !           228: #ifdef KERBEROS
        !           229: try_connect:
        !           230:        if (use_kerberos) {
        !           231:                rem = KSUCCESS;
        !           232:                errno = 0;
        !           233:                if (dest_realm == NULL)
        !           234:                        dest_realm = krb_realmofhost(host);
        !           235: 
        !           236:                        rem = krcmd(&host, sp->s_port, user, term, 0,
        !           237:                            dest_realm);
        !           238:                if (rem < 0) {
        !           239:                        use_kerberos = 0;
        !           240:                        sp = getservbyname("login", "tcp");
        !           241:                        if (sp == NULL) {
        !           242:                                (void)fprintf(stderr,
        !           243:                                    "rlogin: unknown service login/tcp.\n");
        !           244:                                exit(1);
        !           245:                        }
        !           246:                        if (errno == ECONNREFUSED)
        !           247:                                warning("remote host doesn't support Kerberos");
        !           248:                        if (errno == ENOENT)
        !           249:                                warning("can't provide Kerberos auth data");
        !           250:                        goto try_connect;
        !           251:                }
        !           252:        } else {
        !           253:                rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
        !           254:        }
        !           255: #else
        !           256:        rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
        !           257: #endif /* KERBEROS */
        !           258: 
        !           259:        if (rem < 0)
        !           260:                exit(1);
        !           261: 
        !           262:        if (dflag &&
        !           263:            setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0)
        !           264:                (void)fprintf(stderr, "rlogin: setsockopt: %s.\n",
        !           265:                    strerror(errno));
        !           266:        one = IPTOS_LOWDELAY;
        !           267:        if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0)
        !           268:                perror("rlogin: setsockopt TOS (ignored)");
        !           269: 
        !           270:        (void)setuid(uid);
        !           271:        doit(omask);
        !           272:        /*NOTREACHED*/
        !           273: }
        !           274: 
        !           275: int child, defflags, deflflags, tabflag;
        !           276: char deferase, defkill;
        !           277: struct tchars deftc;
        !           278: struct ltchars defltc;
        !           279: struct tchars notc = { -1, -1, -1, -1, -1, -1 };
        !           280: struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
        !           281: 
        !           282: doit(omask)
        !           283:        long omask;
        !           284: {
        !           285:        struct sgttyb sb;
        !           286:        void catch_child(), copytochild(), exit(), writeroob();
        !           287: 
        !           288:        (void)ioctl(0, TIOCGETP, (char *)&sb);
        !           289:        defflags = sb.sg_flags;
        !           290:        tabflag = defflags & TBDELAY;
        !           291:        defflags &= ECHO | CRMOD;
        !           292:        deferase = sb.sg_erase;
        !           293:        defkill = sb.sg_kill;
        !           294:        (void)ioctl(0, TIOCLGET, (char *)&deflflags);
        !           295:        (void)ioctl(0, TIOCGETC, (char *)&deftc);
        !           296:        notc.t_startc = deftc.t_startc;
        !           297:        notc.t_stopc = deftc.t_stopc;
        !           298:        (void)ioctl(0, TIOCGLTC, (char *)&defltc);
        !           299:        (void)signal(SIGINT, SIG_IGN);
        !           300:        setsignal(SIGHUP, exit);
        !           301:        setsignal(SIGQUIT, exit);
        !           302:        child = fork();
        !           303:        if (child == -1) {
        !           304:                (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno));
        !           305:                done(1);
        !           306:        }
        !           307:        if (child == 0) {
        !           308:                mode(1);
        !           309:                if (reader(omask) == 0) {
        !           310:                        msg("connection closed.");
        !           311:                        exit(0);
        !           312:                }
        !           313:                sleep(1);
        !           314:                msg("\007connection closed.");
        !           315:                exit(1);
        !           316:        }
        !           317: 
        !           318:        /*
        !           319:         * We may still own the socket, and may have a pending SIGURG (or might
        !           320:         * receive one soon) that we really want to send to the reader.  Set a
        !           321:         * trap that simply copies such signals to the child.
        !           322:         */
        !           323:        (void)signal(SIGURG, copytochild);
        !           324:        (void)signal(SIGUSR1, writeroob);
        !           325:        (void)sigsetmask(omask);
        !           326:        (void)signal(SIGCHLD, catch_child);
        !           327:        writer();
        !           328:        msg("closed connection.");
        !           329:        done(0);
        !           330: }
        !           331: 
        !           332: /* trap a signal, unless it is being ignored. */
        !           333: setsignal(sig, act)
        !           334:        int sig;
        !           335:        void (*act)();
        !           336: {
        !           337:        int omask = sigblock(sigmask(sig));
        !           338: 
        !           339:        if (signal(sig, act) == SIG_IGN)
        !           340:                (void)signal(sig, SIG_IGN);
        !           341:        (void)sigsetmask(omask);
        !           342: }
        !           343: 
        !           344: done(status)
        !           345:        int status;
        !           346: {
        !           347:        int w;
        !           348: 
        !           349:        mode(0);
        !           350:        if (child > 0) {
        !           351:                /* make sure catch_child does not snap it up */
        !           352:                (void)signal(SIGCHLD, SIG_DFL);
        !           353:                if (kill(child, SIGKILL) >= 0)
        !           354:                        while ((w = wait((union wait *)0)) > 0 && w != child);
        !           355:        }
        !           356:        exit(status);
        !           357: }
        !           358: 
        !           359: int dosigwinch;
        !           360: 
        !           361: /*
        !           362:  * This is called when the reader process gets the out-of-band (urgent)
        !           363:  * request to turn on the window-changing protocol.
        !           364:  */
        !           365: void
        !           366: writeroob()
        !           367: {
        !           368:        void sigwinch();
        !           369: 
        !           370:        if (dosigwinch == 0) {
        !           371:                sendwindow();
        !           372:                (void)signal(SIGWINCH, sigwinch);
        !           373:        }
        !           374:        dosigwinch = 1;
        !           375: }
        !           376: 
        !           377: void
        !           378: catch_child()
        !           379: {
        !           380:        union wait status;
        !           381:        int pid;
        !           382: 
        !           383:        for (;;) {
        !           384:                pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
        !           385:                if (pid == 0)
        !           386:                        return;
        !           387:                /* if the child (reader) dies, just quit */
        !           388:                if (pid < 0 || pid == child && !WIFSTOPPED(status))
        !           389:                        done((int)(status.w_termsig | status.w_retcode));
        !           390:        }
        !           391:        /* NOTREACHED */
        !           392: }
        !           393: 
        !           394: /*
        !           395:  * writer: write to remote: 0 -> line.
        !           396:  * ~.                          terminate
        !           397:  * ~^Z                         suspend rlogin process.
        !           398:  * ~<delayed-suspend char>     suspend rlogin process, but leave reader alone.
        !           399:  */
        !           400: writer()
        !           401: {
        !           402:        register int bol, local, n;
        !           403:        char c;
        !           404: 
        !           405:        bol = 1;                        /* beginning of line */
        !           406:        local = 0;
        !           407:        for (;;) {
        !           408:                n = read(STDIN_FILENO, &c, 1);
        !           409:                if (n <= 0) {
        !           410:                        if (n < 0 && errno == EINTR)
        !           411:                                continue;
        !           412:                        break;
        !           413:                }
        !           414:                /*
        !           415:                 * If we're at the beginning of the line and recognize a
        !           416:                 * command character, then we echo locally.  Otherwise,
        !           417:                 * characters are echo'd remotely.  If the command character
        !           418:                 * is doubled, this acts as a force and local echo is
        !           419:                 * suppressed.
        !           420:                 */
        !           421:                if (bol) {
        !           422:                        bol = 0;
        !           423:                        if (!noescape && c == escapechar) {
        !           424:                                local = 1;
        !           425:                                continue;
        !           426:                        }
        !           427:                } else if (local) {
        !           428:                        local = 0;
        !           429:                        if (c == '.' || c == deftc.t_eofc) {
        !           430:                                echo(c);
        !           431:                                break;
        !           432:                        }
        !           433:                        if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
        !           434:                                bol = 1;
        !           435:                                echo(c);
        !           436:                                stop(c);
        !           437:                                continue;
        !           438:                        }
        !           439:                        if (c != escapechar)
        !           440:                                        (void)write(rem, &escapechar, 1);
        !           441:                }
        !           442: 
        !           443:                        if (write(rem, &c, 1) == 0) {
        !           444:                                msg("line gone");
        !           445:                                break;
        !           446:                        }
        !           447:                bol = c == defkill || c == deftc.t_eofc ||
        !           448:                    c == deftc.t_intrc || c == defltc.t_suspc ||
        !           449:                    c == '\r' || c == '\n';
        !           450:        }
        !           451: }
        !           452: 
        !           453: echo(c)
        !           454: register char c;
        !           455: {
        !           456:        register char *p;
        !           457:        char buf[8];
        !           458: 
        !           459:        p = buf;
        !           460:        c &= 0177;
        !           461:        *p++ = escapechar;
        !           462:        if (c < ' ') {
        !           463:                *p++ = '^';
        !           464:                *p++ = c + '@';
        !           465:        } else if (c == 0177) {
        !           466:                *p++ = '^';
        !           467:                *p++ = '?';
        !           468:        } else
        !           469:                *p++ = c;
        !           470:        *p++ = '\r';
        !           471:        *p++ = '\n';
        !           472:        (void)write(STDOUT_FILENO, buf, p - buf);
        !           473: }
        !           474: 
        !           475: stop(cmdc)
        !           476:        char cmdc;
        !           477: {
        !           478:        mode(0);
        !           479:        (void)signal(SIGCHLD, SIG_IGN);
        !           480:        (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
        !           481:        (void)signal(SIGCHLD, catch_child);
        !           482:        mode(1);
        !           483:        sigwinch();                     /* check for size changes */
        !           484: }
        !           485: 
        !           486: void
        !           487: sigwinch()
        !           488: {
        !           489:        struct winsize ws;
        !           490: 
        !           491:        if (dosigwinch && get_window_size(0, &ws) == 0 &&
        !           492:            bcmp(&ws, &winsize, sizeof(ws))) {
        !           493:                winsize = ws;
        !           494:                sendwindow();
        !           495:        }
        !           496: }
        !           497: 
        !           498: /*
        !           499:  * Send the window size to the server via the magic escape
        !           500:  */
        !           501: sendwindow()
        !           502: {
        !           503:        struct winsize *wp;
        !           504:        char obuf[4 + sizeof (struct winsize)];
        !           505: 
        !           506:        wp = (struct winsize *)(obuf+4);
        !           507:        obuf[0] = 0377;
        !           508:        obuf[1] = 0377;
        !           509:        obuf[2] = 's';
        !           510:        obuf[3] = 's';
        !           511:        wp->ws_row = htons(winsize.ws_row);
        !           512:        wp->ws_col = htons(winsize.ws_col);
        !           513:        wp->ws_xpixel = htons(winsize.ws_xpixel);
        !           514:        wp->ws_ypixel = htons(winsize.ws_ypixel);
        !           515: 
        !           516:                (void)write(rem, obuf, sizeof(obuf));
        !           517: }
        !           518: 
        !           519: /*
        !           520:  * reader: read from remote: line -> 1
        !           521:  */
        !           522: #define        READING 1
        !           523: #define        WRITING 2
        !           524: 
        !           525: jmp_buf rcvtop;
        !           526: int ppid, rcvcnt, rcvstate;
        !           527: char rcvbuf[8 * 1024];
        !           528: 
        !           529: void
        !           530: oob()
        !           531: {
        !           532:        struct sgttyb sb;
        !           533:        int atmark, n, out, rcvd;
        !           534:        char waste[BUFSIZ], mark;
        !           535: 
        !           536:        out = O_RDWR;
        !           537:        rcvd = 0;
        !           538:        while (recv(rem, &mark, 1, MSG_OOB) < 0)
        !           539:                switch (errno) {
        !           540:                case EWOULDBLOCK:
        !           541:                        /*
        !           542:                         * Urgent data not here yet.  It may not be possible
        !           543:                         * to send it yet if we are blocked for output and
        !           544:                         * our input buffer is full.
        !           545:                         */
        !           546:                        if (rcvcnt < sizeof(rcvbuf)) {
        !           547:                                n = read(rem, rcvbuf + rcvcnt,
        !           548:                                    sizeof(rcvbuf) - rcvcnt);
        !           549:                                if (n <= 0)
        !           550:                                        return;
        !           551:                                rcvd += n;
        !           552:                        } else {
        !           553:                                n = read(rem, waste, sizeof(waste));
        !           554:                                if (n <= 0)
        !           555:                                        return;
        !           556:                        }
        !           557:                        continue;
        !           558:                default:
        !           559:                        return;
        !           560:        }
        !           561:        if (mark & TIOCPKT_WINDOW) {
        !           562:                /* Let server know about window size changes */
        !           563:                (void)kill(ppid, SIGUSR1);
        !           564:        }
        !           565:        if (!eight && (mark & TIOCPKT_NOSTOP)) {
        !           566:                (void)ioctl(0, TIOCGETP, (char *)&sb);
        !           567:                sb.sg_flags &= ~CBREAK;
        !           568:                sb.sg_flags |= RAW;
        !           569:                (void)ioctl(0, TIOCSETN, (char *)&sb);
        !           570:                notc.t_stopc = -1;
        !           571:                notc.t_startc = -1;
        !           572:                (void)ioctl(0, TIOCSETC, (char *)&notc);
        !           573:        }
        !           574:        if (!eight && (mark & TIOCPKT_DOSTOP)) {
        !           575:                (void)ioctl(0, TIOCGETP, (char *)&sb);
        !           576:                sb.sg_flags &= ~RAW;
        !           577:                sb.sg_flags |= CBREAK;
        !           578:                (void)ioctl(0, TIOCSETN, (char *)&sb);
        !           579:                notc.t_stopc = deftc.t_stopc;
        !           580:                notc.t_startc = deftc.t_startc;
        !           581:                (void)ioctl(0, TIOCSETC, (char *)&notc);
        !           582:        }
        !           583:        if (mark & TIOCPKT_FLUSHWRITE) {
        !           584:                (void)ioctl(1, TIOCFLUSH, (char *)&out);
        !           585:                for (;;) {
        !           586:                        if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
        !           587:                                (void)fprintf(stderr, "rlogin: ioctl: %s.\n",
        !           588:                                    strerror(errno));
        !           589:                                break;
        !           590:                        }
        !           591:                        if (atmark)
        !           592:                                break;
        !           593:                        n = read(rem, waste, sizeof (waste));
        !           594:                        if (n <= 0)
        !           595:                                break;
        !           596:                }
        !           597:                /*
        !           598:                 * Don't want any pending data to be output, so clear the recv
        !           599:                 * buffer.  If we were hanging on a write when interrupted,
        !           600:                 * don't want it to restart.  If we were reading, restart
        !           601:                 * anyway.
        !           602:                 */
        !           603:                rcvcnt = 0;
        !           604:                longjmp(rcvtop, 1);
        !           605:        }
        !           606: 
        !           607:        /* oob does not do FLUSHREAD (alas!) */
        !           608: 
        !           609:        /*
        !           610:         * If we filled the receive buffer while a read was pending, longjmp
        !           611:         * to the top to restart appropriately.  Don't abort a pending write,
        !           612:         * however, or we won't know how much was written.
        !           613:         */
        !           614:        if (rcvd && rcvstate == READING)
        !           615:                longjmp(rcvtop, 1);
        !           616: }
        !           617: 
        !           618: /* reader: read from remote: line -> 1 */
        !           619: reader(omask)
        !           620:        int omask;
        !           621: {
        !           622:        void oob();
        !           623: 
        !           624: #if !defined(BSD) || BSD < 43
        !           625:        int pid = -getpid();
        !           626: #else
        !           627:        int pid = getpid();
        !           628: #endif
        !           629:        int n, remaining;
        !           630:        char *bufp = rcvbuf;
        !           631: 
        !           632:        (void)signal(SIGTTOU, SIG_IGN);
        !           633:        (void)signal(SIGURG, oob);
        !           634:        ppid = getppid();
        !           635:        (void)fcntl(rem, F_SETOWN, pid);
        !           636:        (void)setjmp(rcvtop);
        !           637:        (void)sigsetmask(omask);
        !           638:        for (;;) {
        !           639:                while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
        !           640:                        rcvstate = WRITING;
        !           641:                        n = write(STDOUT_FILENO, bufp, remaining);
        !           642:                        if (n < 0) {
        !           643:                                if (errno != EINTR)
        !           644:                                        return(-1);
        !           645:                                continue;
        !           646:                        }
        !           647:                        bufp += n;
        !           648:                }
        !           649:                bufp = rcvbuf;
        !           650:                rcvcnt = 0;
        !           651:                rcvstate = READING;
        !           652: 
        !           653:                        rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
        !           654:                if (rcvcnt == 0)
        !           655:                        return (0);
        !           656:                if (rcvcnt < 0) {
        !           657:                        if (errno == EINTR)
        !           658:                                continue;
        !           659:                        (void)fprintf(stderr, "rlogin: read: %s.\n",
        !           660:                            strerror(errno));
        !           661:                        return(-1);
        !           662:                }
        !           663:        }
        !           664: }
        !           665: 
        !           666: mode(f)
        !           667: {
        !           668:        struct ltchars *ltc;
        !           669:        struct sgttyb sb;
        !           670:        struct tchars *tc;
        !           671:        int lflags;
        !           672: 
        !           673:        (void)ioctl(0, TIOCGETP, (char *)&sb);
        !           674:        (void)ioctl(0, TIOCLGET, (char *)&lflags);
        !           675:        switch(f) {
        !           676:        case 0:
        !           677:                sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
        !           678:                sb.sg_flags |= defflags|tabflag;
        !           679:                tc = &deftc;
        !           680:                ltc = &defltc;
        !           681:                sb.sg_kill = defkill;
        !           682:                sb.sg_erase = deferase;
        !           683:                lflags = deflflags;
        !           684:                break;
        !           685:        case 1:
        !           686:                sb.sg_flags |= (eight ? RAW : CBREAK);
        !           687:                sb.sg_flags &= ~defflags;
        !           688:                /* preserve tab delays, but turn off XTABS */
        !           689:                if ((sb.sg_flags & TBDELAY) == XTABS)
        !           690:                        sb.sg_flags &= ~TBDELAY;
        !           691:                tc = &notc;
        !           692:                ltc = &noltc;
        !           693:                sb.sg_kill = sb.sg_erase = -1;
        !           694:                if (litout)
        !           695:                        lflags |= LLITOUT;
        !           696:                break;
        !           697:        default:
        !           698:                return;
        !           699:        }
        !           700:        (void)ioctl(0, TIOCSLTC, (char *)ltc);
        !           701:        (void)ioctl(0, TIOCSETC, (char *)tc);
        !           702:        (void)ioctl(0, TIOCSETN, (char *)&sb);
        !           703:        (void)ioctl(0, TIOCLSET, (char *)&lflags);
        !           704: }
        !           705: 
        !           706: void
        !           707: lostpeer()
        !           708: {
        !           709:        (void)signal(SIGPIPE, SIG_IGN);
        !           710:        msg("\007connection closed.");
        !           711:        done(1);
        !           712: }
        !           713: 
        !           714: /* copy SIGURGs to the child process. */
        !           715: void
        !           716: copytochild()
        !           717: {
        !           718:        (void)kill(child, SIGURG);
        !           719: }
        !           720: 
        !           721: msg(str)
        !           722:        char *str;
        !           723: {
        !           724:        (void)fprintf(stderr, "rlogin: %s\r\n", str);
        !           725: }
        !           726: 
        !           727: #ifdef KERBEROS
        !           728: /* VARARGS */
        !           729: warning(va_alist)
        !           730: va_dcl
        !           731: {
        !           732:        va_list ap;
        !           733:        char *fmt;
        !           734: 
        !           735:        (void)fprintf(stderr, "rlogin: warning, using standard rlogin: ");
        !           736:        va_start(ap);
        !           737:        fmt = va_arg(ap, char *);
        !           738:        vfprintf(stderr, fmt, ap);
        !           739:        va_end(ap);
        !           740:        (void)fprintf(stderr, ".\n");
        !           741: }
        !           742: #endif
        !           743: 
        !           744: usage()
        !           745: {
        !           746:        (void)fprintf(stderr,
        !           747:            "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n",
        !           748: #ifdef KERBEROS
        !           749:            "8EL", " [-k realm] ");
        !           750: #else
        !           751:            "8EL", " ");
        !           752: #endif
        !           753:        exit(1);
        !           754: }
        !           755: 
        !           756: /*
        !           757:  * The following routine provides compatibility (such as it is) between 4.2BSD
        !           758:  * Suns and others.  Suns have only a `ttysize', so we convert it to a winsize.
        !           759:  */
        !           760: #ifdef sun
        !           761: get_window_size(fd, wp)
        !           762:        int fd;
        !           763:        struct winsize *wp;
        !           764: {
        !           765:        struct ttysize ts;
        !           766:        int error;
        !           767: 
        !           768:        if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
        !           769:                return(error);
        !           770:        wp->ws_row = ts.ts_lines;
        !           771:        wp->ws_col = ts.ts_cols;
        !           772:        wp->ws_xpixel = 0;
        !           773:        wp->ws_ypixel = 0;
        !           774:        return(0);
        !           775: }
        !           776: #endif
        !           777: 
        !           778: u_char
        !           779: getescape(p)
        !           780:        register char *p;
        !           781: {
        !           782:        long val;
        !           783:        int len;
        !           784: 
        !           785:        if ((len = strlen(p)) == 1)     /* use any single char, including '\' */
        !           786:                return((u_char)*p);
        !           787:                                        /* otherwise, \nnn */
        !           788:        if (*p == '\\' && len >= 2 && len <= 4) {
        !           789:                val = strtol(++p, (char **)NULL, 8);
        !           790:                for (;;) {
        !           791:                        if (!*++p)
        !           792:                                return((u_char)val);
        !           793:                        if (*p < '0' || *p > '8')
        !           794:                                break;
        !           795:                }
        !           796:        }
        !           797:        msg("illegal option value -- e");
        !           798:        usage();
        !           799:        /* NOTREACHED */
        !           800: }

unix.superglobalmegacorp.com

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