Annotation of 43BSDReno/sys/kern/tty.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1990 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:  *     @(#)tty.c       7.35 (Berkeley) 7/27/90
        !             7:  */
        !             8: 
        !             9: #include "param.h"
        !            10: #include "systm.h"
        !            11: #include "user.h"
        !            12: #include "ioctl.h"
        !            13: #define TTYDEFCHARS
        !            14: #include "tty.h"
        !            15: #undef TTYDEFCHARS
        !            16: #include "proc.h"
        !            17: #include "file.h"
        !            18: #include "conf.h"
        !            19: #include "dkstat.h"
        !            20: #include "uio.h"
        !            21: #include "kernel.h"
        !            22: #include "vnode.h"
        !            23: #include "syslog.h"
        !            24: 
        !            25: #include "machine/reg.h"
        !            26: 
        !            27: /* symbolic sleep message strings */
        !            28: char ttyin[] = "ttyin";
        !            29: char ttyout[] = "ttyout";
        !            30: char ttopen[] = "ttyopn";
        !            31: char ttclos[] = "ttycls";
        !            32: char ttybg[] = "ttybg";
        !            33: char ttybuf[] = "ttybuf";
        !            34: 
        !            35: /*
        !            36:  * Table giving parity for characters and indicating
        !            37:  * character classes to tty driver. The 8th bit
        !            38:  * indicates parity, the 7th bit indicates the character
        !            39:  * is an alphameric or underscore (for ALTWERASE), and the 
        !            40:  * low 6 bits indicate delay type.  If the low 6 bits are 0
        !            41:  * then the character needs no special processing on output.
        !            42:  */
        !            43: 
        !            44: char partab[] = {
        !            45:        0001,0201,0201,0001,0201,0001,0001,0201,        /* nul - bel */
        !            46:        0202,0004,0003,0201,0005,0206,0201,0001,        /* bs - si */
        !            47:        0201,0001,0001,0201,0001,0201,0201,0001,        /* dle - etb */
        !            48:        0001,0201,0201,0001,0201,0001,0001,0201,        /* can - us */
        !            49:        0200,0000,0000,0200,0000,0200,0200,0000,        /* sp - ' */
        !            50:        0000,0200,0200,0000,0200,0000,0000,0200,        /* ( - / */
        !            51:        0100,0300,0300,0100,0300,0100,0100,0300,        /* 0 - 7 */
        !            52:        0300,0100,0000,0200,0000,0200,0200,0000,        /* 8 - ? */
        !            53:        0200,0100,0100,0300,0100,0300,0300,0100,        /* @ - G */
        !            54:        0100,0300,0300,0100,0300,0100,0100,0300,        /* H - O */
        !            55:        0100,0300,0300,0100,0300,0100,0100,0300,        /* P - W */
        !            56:        0300,0100,0100,0200,0000,0200,0200,0300,        /* X - _ */
        !            57:        0000,0300,0300,0100,0300,0100,0100,0300,        /* ` - g */
        !            58:        0300,0100,0100,0300,0100,0300,0300,0100,        /* h - o */
        !            59:        0300,0100,0100,0300,0100,0300,0300,0100,        /* p - w */
        !            60:        0100,0300,0300,0000,0200,0000,0000,0201,        /* x - del */
        !            61:        /*
        !            62:         * meta chars
        !            63:         */
        !            64:        0001,0201,0201,0001,0201,0001,0001,0201,        /* nul - bel */
        !            65:        0202,0004,0003,0201,0005,0206,0201,0001,        /* bs - si */
        !            66:        0201,0001,0001,0201,0001,0201,0201,0001,        /* dle - etb */
        !            67:        0001,0201,0201,0001,0201,0001,0001,0201,        /* can - us */
        !            68:        0200,0000,0000,0200,0000,0200,0200,0000,        /* sp - ' */
        !            69:        0000,0200,0200,0000,0200,0000,0000,0200,        /* ( - / */
        !            70:        0100,0300,0300,0100,0300,0100,0100,0300,        /* 0 - 7 */
        !            71:        0300,0100,0000,0200,0000,0200,0200,0000,        /* 8 - ? */
        !            72:        0200,0100,0100,0300,0100,0300,0300,0100,        /* @ - G */
        !            73:        0100,0300,0300,0100,0300,0100,0100,0300,        /* H - O */
        !            74:        0100,0300,0300,0100,0300,0100,0100,0300,        /* P - W */
        !            75:        0300,0100,0100,0200,0000,0200,0200,0300,        /* X - _ */
        !            76:        0000,0300,0300,0100,0300,0100,0100,0300,        /* ` - g */
        !            77:        0300,0100,0100,0300,0100,0300,0300,0100,        /* h - o */
        !            78:        0300,0100,0100,0300,0100,0300,0300,0100,        /* p - w */
        !            79:        0100,0300,0300,0000,0200,0000,0000,0201,        /* x - del */
        !            80: };
        !            81: 
        !            82: extern struct tty *constty;            /* temporary virtual console */
        !            83: extern char partab[], maptab[];
        !            84: 
        !            85: /*
        !            86:  * Is 'c' a line delimiter ("break" character)?
        !            87:  */
        !            88: #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \
        !            89:        (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)
        !            90: 
        !            91: ttychars(tp)
        !            92:        struct tty *tp;
        !            93: {
        !            94:        bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
        !            95: }
        !            96: 
        !            97: /*
        !            98:  * Wait for output to drain, then flush input waiting.
        !            99:  */
        !           100: ttywflush(tp)
        !           101:        struct tty *tp;
        !           102: {
        !           103:        int error;
        !           104: 
        !           105:        if ((error = ttywait(tp)) == 0)
        !           106:                ttyflush(tp, FREAD);
        !           107:        return (error);
        !           108: }
        !           109: 
        !           110: /*
        !           111:  * Wait for output to drain.
        !           112:  */
        !           113: ttywait(tp)
        !           114:        register struct tty *tp;
        !           115: {
        !           116:        int error = 0, s = spltty();
        !           117: 
        !           118:        while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
        !           119:            (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 
        !           120:            tp->t_oproc) {
        !           121:                (*tp->t_oproc)(tp);
        !           122:                tp->t_state |= TS_ASLEEP;
        !           123:                if (error = ttysleep(tp, (caddr_t)&tp->t_outq, 
        !           124:                    TTOPRI | PCATCH, ttyout, 0))
        !           125:                        break;
        !           126:        }
        !           127:        splx(s);
        !           128:        return (error);
        !           129: }
        !           130: 
        !           131: /*
        !           132:  * Flush all TTY queues
        !           133:  */
        !           134: ttyflush(tp, rw)
        !           135:        register struct tty *tp;
        !           136: {
        !           137:        register s;
        !           138: 
        !           139:        s = spltty();
        !           140:        if (rw & FREAD) {
        !           141:                while (getc(&tp->t_canq) >= 0)
        !           142:                        ;
        !           143:                ttwakeup(tp);
        !           144:        }
        !           145:        if (rw & FWRITE) {
        !           146:                wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */
        !           147:                tp->t_state &= ~TS_TTSTOP;
        !           148:                (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
        !           149:                while (getc(&tp->t_outq) >= 0)
        !           150:                        ;
        !           151:        }
        !           152:        if (rw & FREAD) {
        !           153:                while (getc(&tp->t_rawq) >= 0)
        !           154:                        ;
        !           155:                tp->t_rocount = 0;
        !           156:                tp->t_rocol = 0;
        !           157:                tp->t_state &= ~TS_LOCAL;
        !           158:        }
        !           159:        splx(s);
        !           160: }
        !           161: 
        !           162: /*
        !           163:  * Send stop character on input overflow.
        !           164:  */
        !           165: ttyblock(tp)
        !           166:        register struct tty *tp;
        !           167: {
        !           168:        register x;
        !           169: 
        !           170:        x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
        !           171:        if (tp->t_rawq.c_cc > TTYHOG) {
        !           172:                ttyflush(tp, FREAD|FWRITE);
        !           173:                tp->t_state &= ~TS_TBLOCK;
        !           174:        }
        !           175:        /*
        !           176:         * Block further input iff:
        !           177:         * Current input > threshold AND input is available to user program
        !           178:         */
        !           179:        if (x >= TTYHOG/2 && (tp->t_state & TS_TBLOCK) == 0 &&
        !           180:            ((tp->t_lflag&ICANON) == 0) || (tp->t_canq.c_cc > 0) &&
        !           181:            tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
        !           182:                if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
        !           183:                        tp->t_state |= TS_TBLOCK;
        !           184:                        ttstart(tp);
        !           185:                }
        !           186:        }
        !           187: }
        !           188: 
        !           189: /*
        !           190:  * Restart typewriter output following a delay
        !           191:  * timeout.
        !           192:  * The name of the routine is passed to the timeout
        !           193:  * subroutine and it is called during a clock interrupt.
        !           194:  */
        !           195: ttrstrt(tp)
        !           196:        struct tty *tp;
        !           197: {
        !           198: 
        !           199: #ifdef DIAGNOSTIC
        !           200:        if (tp == 0)
        !           201:                panic("ttrstrt");
        !           202: #endif
        !           203:        tp->t_state &= ~TS_TIMEOUT;
        !           204:        ttstart(tp);
        !           205: }
        !           206: 
        !           207: /*
        !           208:  * Start output on the typewriter. It is used from the top half
        !           209:  * after some characters have been put on the output queue,
        !           210:  * from the interrupt routine to transmit the next
        !           211:  * character, and after a timeout has finished.
        !           212:  */
        !           213: ttstart(tp)
        !           214:        struct tty *tp;
        !           215: {
        !           216: 
        !           217:        if (tp->t_oproc)                /* kludge for pty */
        !           218:                (*tp->t_oproc)(tp);
        !           219: }
        !           220: 
        !           221: /*
        !           222:  * Common code for tty ioctls.
        !           223:  */
        !           224: /*ARGSUSED*/
        !           225: ttioctl(tp, com, data, flag)
        !           226:        register struct tty *tp;
        !           227:        caddr_t data;
        !           228: {
        !           229:        extern int nldisp;
        !           230:        int s, error;
        !           231: 
        !           232:        /*
        !           233:         * If the ioctl involves modification,
        !           234:         * hang if in the background.
        !           235:         */
        !           236:        switch (com) {
        !           237: 
        !           238:        case TIOCSETD: 
        !           239:        case TIOCFLUSH:
        !           240:        /*case TIOCSPGRP:*/
        !           241:        case TIOCSTI:
        !           242:        case TIOCSWINSZ:
        !           243:        case TIOCSETA:
        !           244:        case TIOCSETAW:
        !           245:        case TIOCSETAF:
        !           246: #ifdef COMPAT_43
        !           247:        case TIOCSETP:
        !           248:        case TIOCSETN:
        !           249:        case TIOCSETC:
        !           250:        case TIOCSLTC:
        !           251:        case TIOCLBIS:
        !           252:        case TIOCLBIC:
        !           253:        case TIOCLSET:
        !           254:        case OTIOCSETD:
        !           255: #endif
        !           256:                while (isbackground(u.u_procp, tp) && 
        !           257:                   u.u_procp->p_pgrp->pg_jobc &&
        !           258:                   (u.u_procp->p_flag&SVFORK) == 0 &&
        !           259:                   (u.u_procp->p_sigignore & sigmask(SIGTTOU)) == 0 &&
        !           260:                   (u.u_procp->p_sigmask & sigmask(SIGTTOU)) == 0) {
        !           261:                        pgsignal(u.u_procp->p_pgrp, SIGTTOU, 1);
        !           262:                        if (error = ttysleep(tp, (caddr_t)&lbolt, 
        !           263:                            TTOPRI | PCATCH, ttybg, 0)) 
        !           264:                                return (error);
        !           265:                }
        !           266:                break;
        !           267:        }
        !           268: 
        !           269:        /*
        !           270:         * Process the ioctl.
        !           271:         */
        !           272:        switch (com) {
        !           273: 
        !           274:        /* get discipline number */
        !           275:        case TIOCGETD:
        !           276:                *(int *)data = tp->t_line;
        !           277:                break;
        !           278: 
        !           279:        /* set line discipline */
        !           280:        case TIOCSETD: {
        !           281:                register int t = *(int *)data;
        !           282:                dev_t dev = tp->t_dev;
        !           283: 
        !           284:                if ((unsigned)t >= nldisp)
        !           285:                        return (ENXIO);
        !           286:                if (t != tp->t_line) {
        !           287:                        s = spltty();
        !           288:                        (*linesw[tp->t_line].l_close)(tp);
        !           289:                        error = (*linesw[t].l_open)(dev, tp);
        !           290:                        if (error) {
        !           291:                                (void)(*linesw[tp->t_line].l_open)(dev, tp);
        !           292:                                splx(s);
        !           293:                                return (error);
        !           294:                        }
        !           295:                        tp->t_line = t;
        !           296:                        splx(s);
        !           297:                }
        !           298:                break;
        !           299:        }
        !           300: 
        !           301:        /* prevent more opens on channel */
        !           302:        case TIOCEXCL:
        !           303:                tp->t_state |= TS_XCLUDE;
        !           304:                break;
        !           305: 
        !           306:        case TIOCNXCL:
        !           307:                tp->t_state &= ~TS_XCLUDE;
        !           308:                break;
        !           309: 
        !           310:        case TIOCHPCL:
        !           311:                tp->t_cflag |= HUPCL;
        !           312:                break;
        !           313: 
        !           314:        case TIOCFLUSH: {
        !           315:                register int flags = *(int *)data;
        !           316: 
        !           317:                if (flags == 0)
        !           318:                        flags = FREAD|FWRITE;
        !           319:                else
        !           320:                        flags &= FREAD|FWRITE;
        !           321:                ttyflush(tp, flags);
        !           322:                break;
        !           323:        }
        !           324: 
        !           325:        case FIOASYNC:
        !           326:                if (*(int *)data)
        !           327:                        tp->t_state |= TS_ASYNC;
        !           328:                else
        !           329:                        tp->t_state &= ~TS_ASYNC;
        !           330:                break;
        !           331: 
        !           332:        case FIONBIO:
        !           333:                break;  /* XXX remove */
        !           334: 
        !           335:        /* return number of characters immediately available */
        !           336:        case FIONREAD:
        !           337:                *(off_t *)data = ttnread(tp);
        !           338:                break;
        !           339: 
        !           340:        case TIOCOUTQ:
        !           341:                *(int *)data = tp->t_outq.c_cc;
        !           342:                break;
        !           343: 
        !           344:        case TIOCSTOP:
        !           345:                s = spltty();
        !           346:                if ((tp->t_state&TS_TTSTOP) == 0) {
        !           347:                        tp->t_state |= TS_TTSTOP;
        !           348:                        (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
        !           349:                }
        !           350:                splx(s);
        !           351:                break;
        !           352: 
        !           353:        case TIOCSTART:
        !           354:                s = spltty();
        !           355:                if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) {
        !           356:                        tp->t_state &= ~TS_TTSTOP;
        !           357:                        tp->t_lflag &= ~FLUSHO;
        !           358:                        ttstart(tp);
        !           359:                }
        !           360:                splx(s);
        !           361:                break;
        !           362: 
        !           363:        /*
        !           364:         * Simulate typing of a character at the terminal.
        !           365:         */
        !           366:        case TIOCSTI:
        !           367:                if (u.u_uid && (flag & FREAD) == 0)
        !           368:                        return (EPERM);
        !           369:                if (u.u_uid && !isctty(u.u_procp, tp))
        !           370:                        return (EACCES);
        !           371:                (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
        !           372:                break;
        !           373: 
        !           374:        case TIOCGETA: {
        !           375:                struct termios *t = (struct termios *)data;
        !           376: 
        !           377:                bcopy(&tp->t_termios, t, sizeof(struct termios));
        !           378:                break;
        !           379:        }
        !           380: 
        !           381:        case TIOCSETA:
        !           382:        case TIOCSETAW:
        !           383:        case TIOCSETAF: {
        !           384:                register struct termios *t = (struct termios *)data;
        !           385: 
        !           386:                s = spltty();
        !           387:                if (com == TIOCSETAW || com == TIOCSETAF) {
        !           388:                        if (error = ttywait(tp)) {
        !           389:                                splx(s);
        !           390:                                return (error);
        !           391:                        }
        !           392:                        if (com == TIOCSETAF)
        !           393:                                ttyflush(tp, FREAD);
        !           394:                }
        !           395:                if ((t->c_cflag&CIGNORE) == 0) {
        !           396:                        /*
        !           397:                         * set device hardware
        !           398:                         */
        !           399:                        if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
        !           400:                                splx(s);
        !           401:                                return (error);
        !           402:                        } else {
        !           403:                                if ((tp->t_state&TS_CARR_ON) == 0 &&
        !           404:                                    (tp->t_cflag&CLOCAL) &&
        !           405:                                    (t->c_cflag&CLOCAL) == 0) {
        !           406:                                        tp->t_state &= ~TS_ISOPEN;
        !           407:                                        tp->t_state |= TS_WOPEN;
        !           408:                                        ttwakeup(tp);
        !           409:                                }
        !           410:                                tp->t_cflag = t->c_cflag;
        !           411:                                tp->t_ispeed = t->c_ispeed;
        !           412:                                tp->t_ospeed = t->c_ospeed;
        !           413:                        }
        !           414:                        ttsetwater(tp);
        !           415:                }
        !           416:                if (com != TIOCSETAF) {
        !           417:                        if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON))
        !           418:                                if (t->c_lflag&ICANON) {        
        !           419:                                        tp->t_lflag |= PENDIN;
        !           420:                                        ttwakeup(tp);
        !           421:                                }
        !           422:                                else {
        !           423:                                        struct clist tq;
        !           424: 
        !           425:                                        catq(&tp->t_rawq, &tp->t_canq);
        !           426:                                        tq = tp->t_rawq;
        !           427:                                        tp->t_rawq = tp->t_canq;
        !           428:                                        tp->t_canq = tq;
        !           429:                                }
        !           430:                }
        !           431:                tp->t_iflag = t->c_iflag;
        !           432:                tp->t_oflag = t->c_oflag;
        !           433:                /*
        !           434:                 * Make the EXTPROC bit read only.
        !           435:                 */
        !           436:                if (tp->t_lflag&EXTPROC)
        !           437:                        t->c_lflag |= EXTPROC;
        !           438:                else
        !           439:                        t->c_lflag &= ~EXTPROC;
        !           440:                tp->t_lflag = t->c_lflag;
        !           441:                bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
        !           442:                splx(s);
        !           443:                break;
        !           444:        }
        !           445: 
        !           446:        /*
        !           447:         * Set controlling terminal.
        !           448:         * Session ctty vnode pointer set in vnode layer.
        !           449:         */
        !           450:        case TIOCSCTTY: {
        !           451:                register struct proc *p = u.u_procp;
        !           452: 
        !           453:                if (!SESS_LEADER(p) || 
        !           454:                   (p->p_session->s_ttyvp || tp->t_session) &&
        !           455:                   (tp->t_session != p->p_session))
        !           456:                        return (EPERM);
        !           457:                tp->t_session = p->p_session;
        !           458:                tp->t_pgrp = p->p_pgrp;
        !           459:                p->p_session->s_ttyp = tp;
        !           460:                p->p_flag |= SCTTY;
        !           461:                break;
        !           462:        }
        !           463:                
        !           464:        /*
        !           465:         * Set terminal process group.
        !           466:         */
        !           467:        case TIOCSPGRP: {
        !           468:                register struct proc *p = u.u_procp;
        !           469:                register struct pgrp *pgrp = pgfind(*(int *)data);
        !           470: 
        !           471:                if (!isctty(p, tp))
        !           472:                        return (ENOTTY);
        !           473:                else if (pgrp == NULL || pgrp->pg_session != p->p_session)
        !           474:                        return (EPERM);
        !           475:                tp->t_pgrp = pgrp;
        !           476:                break;
        !           477:        }
        !           478: 
        !           479:        case TIOCGPGRP:
        !           480:                if (!isctty(u.u_procp, tp))
        !           481:                        return (ENOTTY);
        !           482:                *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
        !           483:                break;
        !           484: 
        !           485:        case TIOCSWINSZ:
        !           486:                if (bcmp((caddr_t)&tp->t_winsize, data,
        !           487:                    sizeof (struct winsize))) {
        !           488:                        tp->t_winsize = *(struct winsize *)data;
        !           489:                        pgsignal(tp->t_pgrp, SIGWINCH, 1);
        !           490:                }
        !           491:                break;
        !           492: 
        !           493:        case TIOCGWINSZ:
        !           494:                *(struct winsize *)data = tp->t_winsize;
        !           495:                break;
        !           496: 
        !           497:        case TIOCCONS:
        !           498:                if (*(int *)data) {
        !           499:                        if (constty && constty != tp &&
        !           500:                            (constty->t_state & (TS_CARR_ON|TS_ISOPEN)) ==
        !           501:                            (TS_CARR_ON|TS_ISOPEN))
        !           502:                                return (EBUSY);
        !           503: #ifndef        UCONSOLE
        !           504:                        if (error = suser(u.u_cred, &u.u_acflag))
        !           505:                                return (error);
        !           506: #endif
        !           507:                        constty = tp;
        !           508:                } else if (tp == constty)
        !           509:                        constty = NULL;
        !           510:                break;
        !           511: 
        !           512: #ifdef COMPAT_43
        !           513:        case TIOCGETP:
        !           514:        case TIOCSETP:
        !           515:        case TIOCSETN:
        !           516:        case TIOCGETC:
        !           517:        case TIOCSETC:
        !           518:        case TIOCSLTC:
        !           519:        case TIOCGLTC:
        !           520:        case TIOCLBIS:
        !           521:        case TIOCLBIC:
        !           522:        case TIOCLSET:
        !           523:        case TIOCLGET:
        !           524:        case OTIOCGETD:
        !           525:        case OTIOCSETD:
        !           526:        case OTIOCCONS:
        !           527:                return(ttcompat(tp, com, data, flag));
        !           528: #endif
        !           529: 
        !           530:        default:
        !           531:                return (-1);
        !           532:        }
        !           533:        return (0);
        !           534: }
        !           535: 
        !           536: ttnread(tp)
        !           537:        struct tty *tp;
        !           538: {
        !           539:        int nread = 0;
        !           540: 
        !           541:        if (tp->t_lflag & PENDIN)
        !           542:                ttypend(tp);
        !           543:        nread = tp->t_canq.c_cc;
        !           544:        if ((tp->t_lflag & ICANON) == 0)
        !           545:                nread += tp->t_rawq.c_cc;
        !           546:        return (nread);
        !           547: }
        !           548: 
        !           549: ttselect(dev, rw)
        !           550:        dev_t dev;
        !           551:        int rw;
        !           552: {
        !           553:        register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
        !           554:        int nread;
        !           555:        int s = spltty();
        !           556: 
        !           557:        switch (rw) {
        !           558: 
        !           559:        case FREAD:
        !           560:                nread = ttnread(tp);
        !           561:                if (nread > 0 || 
        !           562:                   ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0))
        !           563:                        goto win;
        !           564:                if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
        !           565:                        tp->t_state |= TS_RCOLL;
        !           566:                else
        !           567:                        tp->t_rsel = u.u_procp;
        !           568:                break;
        !           569: 
        !           570:        case FWRITE:
        !           571:                if (tp->t_outq.c_cc <= tp->t_lowat)
        !           572:                        goto win;
        !           573:                if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
        !           574:                        tp->t_state |= TS_WCOLL;
        !           575:                else
        !           576:                        tp->t_wsel = u.u_procp;
        !           577:                break;
        !           578:        }
        !           579:        splx(s);
        !           580:        return (0);
        !           581: win:
        !           582:        splx(s);
        !           583:        return (1);
        !           584: }
        !           585: 
        !           586: /*
        !           587:  * Initial open of tty, or (re)entry to line discipline.
        !           588:  */
        !           589: ttyopen(dev, tp)
        !           590:        dev_t dev;
        !           591:        register struct tty *tp;
        !           592: {
        !           593: 
        !           594:        tp->t_dev = dev;
        !           595: 
        !           596:        tp->t_state &= ~TS_WOPEN;
        !           597:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           598:                tp->t_state |= TS_ISOPEN;
        !           599:                bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
        !           600:        }
        !           601:        return (0);
        !           602: }
        !           603: 
        !           604: /*
        !           605:  * "close" a line discipline
        !           606:  */
        !           607: ttylclose(tp)
        !           608:        register struct tty *tp;
        !           609: {
        !           610: 
        !           611:        ttywflush(tp);
        !           612: }
        !           613: 
        !           614: /*
        !           615:  * clean tp on last close
        !           616:  */
        !           617: ttyclose(tp)
        !           618:        register struct tty *tp;
        !           619: {
        !           620:        if (constty == tp)
        !           621:                constty = NULL;
        !           622:        ttyflush(tp, FREAD|FWRITE);
        !           623:        tp->t_session = NULL;
        !           624:        tp->t_pgrp = NULL;
        !           625:        tp->t_state = 0;
        !           626:        tp->t_gen++;
        !           627:        return (0);
        !           628: }
        !           629: 
        !           630: /*
        !           631:  * Handle modem control transition on a tty.
        !           632:  * Flag indicates new state of carrier.
        !           633:  * Returns 0 if the line should be turned off, otherwise 1.
        !           634:  */
        !           635: ttymodem(tp, flag)
        !           636:        register struct tty *tp;
        !           637: {
        !           638: 
        !           639:        if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) {
        !           640:                /*
        !           641:                 * MDMBUF: do flow control according to carrier flag
        !           642:                 */
        !           643:                if (flag) {
        !           644:                        tp->t_state &= ~TS_TTSTOP;
        !           645:                        ttstart(tp);
        !           646:                } else if ((tp->t_state&TS_TTSTOP) == 0) {
        !           647:                        tp->t_state |= TS_TTSTOP;
        !           648:                        (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
        !           649:                }
        !           650:        } else if (flag == 0) {
        !           651:                /*
        !           652:                 * Lost carrier.
        !           653:                 */
        !           654:                tp->t_state &= ~TS_CARR_ON;
        !           655:                if (tp->t_state&TS_ISOPEN && (tp->t_cflag&CLOCAL) == 0) {
        !           656:                        if (tp->t_session && tp->t_session->s_leader)
        !           657:                                psignal(tp->t_session->s_leader, SIGHUP);
        !           658:                        ttyflush(tp, FREAD|FWRITE);
        !           659:                        return (0);
        !           660:                }
        !           661:        } else {
        !           662:                /*
        !           663:                 * Carrier now on.
        !           664:                 */
        !           665:                tp->t_state |= TS_CARR_ON;
        !           666:                ttwakeup(tp);
        !           667:        }
        !           668:        return (1);
        !           669: }
        !           670: 
        !           671: /*
        !           672:  * Default modem control routine (for other line disciplines).
        !           673:  * Return argument flag, to turn off device on carrier drop.
        !           674:  */
        !           675: nullmodem(tp, flag)
        !           676:        register struct tty *tp;
        !           677:        int flag;
        !           678: {
        !           679:        
        !           680:        if (flag)
        !           681:                tp->t_state |= TS_CARR_ON;
        !           682:        else {
        !           683:                tp->t_state &= ~TS_CARR_ON;
        !           684:                if ((tp->t_cflag&CLOCAL) == 0) {
        !           685:                        if (tp->t_session && tp->t_session->s_leader)
        !           686:                                psignal(tp->t_session->s_leader, SIGHUP);
        !           687:                        return (0);
        !           688:                }
        !           689:        }
        !           690:        return (1);
        !           691: }
        !           692: 
        !           693: /*
        !           694:  * reinput pending characters after state switch
        !           695:  * call at spltty().
        !           696:  */
        !           697: ttypend(tp)
        !           698:        register struct tty *tp;
        !           699: {
        !           700:        struct clist tq;
        !           701:        register c;
        !           702: 
        !           703:        tp->t_lflag &= ~PENDIN;
        !           704:        tp->t_state |= TS_TYPEN;
        !           705:        tq = tp->t_rawq;
        !           706:        tp->t_rawq.c_cc = 0;
        !           707:        tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
        !           708:        while ((c = getc(&tq)) >= 0)
        !           709:                ttyinput(c, tp);
        !           710:        tp->t_state &= ~TS_TYPEN;
        !           711: }
        !           712: 
        !           713: /*
        !           714:  *
        !           715:  * Place a character on raw TTY input queue,
        !           716:  * putting in delimiters and waking up top
        !           717:  * half as needed.  Also echo if required.
        !           718:  * The arguments are the character and the
        !           719:  * appropriate tty structure.
        !           720:  */
        !           721: ttyinput(c, tp)
        !           722:        register c;
        !           723:        register struct tty *tp;
        !           724: {
        !           725:        register int iflag = tp->t_iflag;
        !           726:        register int lflag = tp->t_lflag;
        !           727:        register u_char *cc = tp->t_cc;
        !           728:        int i, err;
        !           729: 
        !           730:        /*
        !           731:         * If input is pending take it first.
        !           732:         */
        !           733:        if (lflag&PENDIN)
        !           734:                ttypend(tp);
        !           735:        /*
        !           736:         * Gather stats.
        !           737:         */
        !           738:        tk_nin++;
        !           739:        if (lflag&ICANON) {
        !           740:                tk_cancc++;
        !           741:                tp->t_cancc++;
        !           742:        } else {
        !           743:                tk_rawcc++;
        !           744:                tp->t_rawcc++;
        !           745:        }
        !           746:        /*
        !           747:         * Handle exceptional conditions (break, parity, framing).
        !           748:         */
        !           749:        if (err = (c&TTY_ERRORMASK)) {
        !           750:                c &= ~TTY_ERRORMASK;
        !           751:                if (err&TTY_FE && !c) {         /* break */
        !           752:                        if (iflag&IGNBRK)
        !           753:                                goto endcase;
        !           754:                        else if (iflag&BRKINT && lflag&ISIG && 
        !           755:                                (cc[VINTR] != _POSIX_VDISABLE))
        !           756:                                c = cc[VINTR];
        !           757:                        else {
        !           758:                                c = 0;
        !           759:                                if (iflag&PARMRK)
        !           760:                                        goto parmrk;
        !           761:                        }
        !           762:                } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) {
        !           763:                        if (iflag&IGNPAR)
        !           764:                                goto endcase;
        !           765:                        else if (iflag&PARMRK) {
        !           766: parmrk:
        !           767:                                putc(0377|TTY_QUOTE, &tp->t_rawq);
        !           768:                                putc(0|TTY_QUOTE, &tp->t_rawq);
        !           769:                                putc(c|TTY_QUOTE, &tp->t_rawq);
        !           770:                                goto endcase;
        !           771:                        } else
        !           772:                                c = 0;
        !           773:                }
        !           774:        }
        !           775:        /*
        !           776:         * In tandem mode, check high water mark.
        !           777:         */
        !           778:        if (iflag&IXOFF)
        !           779:                ttyblock(tp);
        !           780:        if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP))
        !           781:                c &= 0177;
        !           782:        if ((tp->t_lflag&EXTPROC) == 0) {
        !           783:                /*
        !           784:                 * Check for literal nexting very first
        !           785:                 */
        !           786:                if (tp->t_state&TS_LNCH) {
        !           787:                        c |= TTY_QUOTE;
        !           788:                        tp->t_state &= ~TS_LNCH;
        !           789:                }
        !           790:                /*
        !           791:                 * Scan for special characters.  This code
        !           792:                 * is really just a big case statement with
        !           793:                 * non-constant cases.  The bottom of the
        !           794:                 * case statement is labeled ``endcase'', so goto
        !           795:                 * it after a case match, or similar.
        !           796:                 */
        !           797: 
        !           798:                /*
        !           799:                 * Control chars which aren't controlled
        !           800:                 * by ICANON, ISIG, or IXON.
        !           801:                 */
        !           802:                if (lflag&IEXTEN) {
        !           803:                        if (CCEQ(cc[VLNEXT], c)) {
        !           804:                                if (lflag&ECHO) {
        !           805:                                        if (lflag&ECHOE)
        !           806:                                                ttyoutstr("^\b", tp);
        !           807:                                        else
        !           808:                                                ttyecho(c, tp);
        !           809:                                }
        !           810:                                tp->t_state |= TS_LNCH;
        !           811:                                goto endcase;
        !           812:                        }
        !           813:                        if (CCEQ(cc[VDISCARD], c)) {
        !           814:                                if (lflag&FLUSHO)
        !           815:                                        tp->t_lflag &= ~FLUSHO;
        !           816:                                else {
        !           817:                                        ttyflush(tp, FWRITE);
        !           818:                                        ttyecho(c, tp);
        !           819:                                        if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
        !           820:                                                ttyretype(tp);
        !           821:                                        tp->t_lflag |= FLUSHO;
        !           822:                                }
        !           823:                                goto startoutput;
        !           824:                        }
        !           825:                }
        !           826:                /*
        !           827:                 * Signals.
        !           828:                 */
        !           829:                if (lflag&ISIG) {
        !           830:                        if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
        !           831:                                if ((lflag&NOFLSH) == 0)
        !           832:                                        ttyflush(tp, FREAD|FWRITE);
        !           833:                                ttyecho(c, tp);
        !           834:                                pgsignal(tp->t_pgrp,
        !           835:                                    CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
        !           836:                                goto endcase;
        !           837:                        }
        !           838:                        if (CCEQ(cc[VSUSP], c)) {
        !           839:                                if ((lflag&NOFLSH) == 0)
        !           840:                                        ttyflush(tp, FREAD);
        !           841:                                ttyecho(c, tp);
        !           842:                                pgsignal(tp->t_pgrp, SIGTSTP, 1);
        !           843:                                goto endcase;
        !           844:                        }
        !           845:                }
        !           846:                /*
        !           847:                 * Handle start/stop characters.
        !           848:                 */
        !           849:                if (iflag&IXON) {
        !           850:                        if (CCEQ(cc[VSTOP], c)) {
        !           851:                                if ((tp->t_state&TS_TTSTOP) == 0) {
        !           852:                                        tp->t_state |= TS_TTSTOP;
        !           853:                                        (*cdevsw[major(tp->t_dev)].d_stop)(tp,
        !           854:                                           0);
        !           855:                                        return;
        !           856:                                }
        !           857:                                if (!CCEQ(cc[VSTART], c))
        !           858:                                        return;
        !           859:                                /* 
        !           860:                                 * if VSTART == VSTOP then toggle 
        !           861:                                 */
        !           862:                                goto endcase;
        !           863:                        }
        !           864:                        if (CCEQ(cc[VSTART], c))
        !           865:                                goto restartoutput;
        !           866:                }
        !           867:                /*
        !           868:                 * IGNCR, ICRNL, & INLCR
        !           869:                 */
        !           870:                if (c == '\r') {
        !           871:                        if (iflag&IGNCR)
        !           872:                                goto endcase;
        !           873:                        else if (iflag&ICRNL)
        !           874:                                c = '\n';
        !           875:                } else if (c == '\n' && iflag&INLCR)
        !           876:                        c = '\r';
        !           877:        }
        !           878:        /*
        !           879:         * Non canonical mode; don't process line editing
        !           880:         * characters; check high water mark for wakeup.
        !           881:         * 
        !           882:         */
        !           883:        if ((lflag&ICANON) == 0) {
        !           884:                if (tp->t_rawq.c_cc > TTYHOG) {
        !           885:                        if (iflag&IMAXBEL) {
        !           886:                                if (tp->t_outq.c_cc < tp->t_hiwat)
        !           887:                                        (void) ttyoutput(CTRL('g'), tp);
        !           888:                        } else
        !           889:                                ttyflush(tp, FREAD | FWRITE);
        !           890:                } else {
        !           891:                        if (putc(c, &tp->t_rawq) >= 0) {
        !           892:                                ttwakeup(tp);
        !           893:                                ttyecho(c, tp);
        !           894:                        }
        !           895:                }
        !           896:                goto endcase;
        !           897:        }
        !           898:        if ((tp->t_lflag&EXTPROC) == 0) {
        !           899:                /*
        !           900:                 * From here on down canonical mode character
        !           901:                 * processing takes place.
        !           902:                 */
        !           903:                /*
        !           904:                 * erase (^H / ^?)
        !           905:                 */
        !           906:                if (CCEQ(cc[VERASE], c)) {
        !           907:                        if (tp->t_rawq.c_cc)
        !           908:                                ttyrub(unputc(&tp->t_rawq), tp);
        !           909:                        goto endcase;
        !           910:                }
        !           911:                /*
        !           912:                 * kill (^U)
        !           913:                 */
        !           914:                if (CCEQ(cc[VKILL], c)) {
        !           915:                        if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount &&
        !           916:                            (lflag&ECHOPRT) == 0) {
        !           917:                                while (tp->t_rawq.c_cc)
        !           918:                                        ttyrub(unputc(&tp->t_rawq), tp);
        !           919:                        } else {
        !           920:                                ttyecho(c, tp);
        !           921:                                if (lflag&ECHOK || lflag&ECHOKE)
        !           922:                                        ttyecho('\n', tp);
        !           923:                                while (getc(&tp->t_rawq) > 0)
        !           924:                                        ;
        !           925:                                tp->t_rocount = 0;
        !           926:                        }
        !           927:                        tp->t_state &= ~TS_LOCAL;
        !           928:                        goto endcase;
        !           929:                }
        !           930:                /*
        !           931:                 * word erase (^W)
        !           932:                 */
        !           933:                if (CCEQ(cc[VWERASE], c)) {     
        !           934:                        int ctype;
        !           935: 
        !           936: #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0)
        !           937:                        /* 
        !           938:                         * erase whitespace 
        !           939:                         */
        !           940:                        while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
        !           941:                                ttyrub(c, tp);
        !           942:                        if (c == -1)
        !           943:                                goto endcase;
        !           944:                        /*
        !           945:                         * special case last char of token
        !           946:                         */
        !           947:                        ttyrub(c, tp);
        !           948:                        c = unputc(&tp->t_rawq);
        !           949:                        if (c == -1 || c == ' ' || c == '\t') {
        !           950:                                if (c != -1)
        !           951:                                        (void) putc(c, &tp->t_rawq);
        !           952:                                goto endcase;
        !           953:                        }
        !           954:                        /*
        !           955:                         * erase rest of token
        !           956:                         */
        !           957:                        ctype = CTYPE(c);
        !           958:                        do {
        !           959:                                ttyrub(c, tp);
        !           960:                                c = unputc(&tp->t_rawq);
        !           961:                                if (c == -1)
        !           962:                                        goto endcase;
        !           963:                        } while (c != ' ' && c != '\t' && CTYPE(c) == ctype);
        !           964:                        (void) putc(c, &tp->t_rawq);
        !           965:                        goto endcase;
        !           966: #undef CTYPE
        !           967:                }
        !           968:                /*
        !           969:                 * reprint line (^R)
        !           970:                 */
        !           971:                if (CCEQ(cc[VREPRINT], c)) {
        !           972:                        ttyretype(tp);
        !           973:                        goto endcase;
        !           974:                }
        !           975:                /*
        !           976:                 * ^T - kernel info and generate SIGINFO
        !           977:                 */
        !           978:                if (CCEQ(cc[VSTATUS], c)) {
        !           979:                        pgsignal(tp->t_pgrp, SIGINFO, 1);
        !           980:                        if ((lflag&NOKERNINFO) == 0)
        !           981:                                ttyinfo(tp);
        !           982:                        goto endcase;
        !           983:                }
        !           984:        }
        !           985:        /*
        !           986:         * Check for input buffer overflow
        !           987:         */
        !           988:        if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
        !           989:                if (iflag&IMAXBEL) {
        !           990:                        if (tp->t_outq.c_cc < tp->t_hiwat)
        !           991:                                (void) ttyoutput(CTRL('g'), tp);
        !           992:                } else
        !           993:                        ttyflush(tp, FREAD | FWRITE);
        !           994:                goto endcase;
        !           995:        }
        !           996:        /*
        !           997:         * Put data char in q for user and
        !           998:         * wakeup on seeing a line delimiter.
        !           999:         */
        !          1000:        if (putc(c, &tp->t_rawq) >= 0) {
        !          1001:                if (ttbreakc(c)) {
        !          1002:                        tp->t_rocount = 0;
        !          1003:                        catq(&tp->t_rawq, &tp->t_canq);
        !          1004:                        ttwakeup(tp);
        !          1005:                } else if (tp->t_rocount++ == 0)
        !          1006:                        tp->t_rocol = tp->t_col;
        !          1007:                if (tp->t_state&TS_ERASE) {
        !          1008:                        /*
        !          1009:                         * end of prterase \.../
        !          1010:                         */
        !          1011:                        tp->t_state &= ~TS_ERASE;
        !          1012:                        (void) ttyoutput('/', tp);
        !          1013:                }
        !          1014:                i = tp->t_col;
        !          1015:                ttyecho(c, tp);
        !          1016:                if (CCEQ(cc[VEOF], c) && lflag&ECHO) {
        !          1017:                        /*
        !          1018:                         * Place the cursor over the '^' of the ^D.
        !          1019:                         */
        !          1020:                        i = MIN(2, tp->t_col - i);
        !          1021:                        while (i > 0) {
        !          1022:                                (void) ttyoutput('\b', tp);
        !          1023:                                i--;
        !          1024:                        }
        !          1025:                }
        !          1026:        }
        !          1027: endcase:
        !          1028:        /*
        !          1029:         * IXANY means allow any character to restart output.
        !          1030:         */
        !          1031:        if ((tp->t_state&TS_TTSTOP) && (iflag&IXANY) == 0 && 
        !          1032:            cc[VSTART] != cc[VSTOP])
        !          1033:                return;
        !          1034: restartoutput:
        !          1035:        tp->t_state &= ~TS_TTSTOP;
        !          1036:        tp->t_lflag &= ~FLUSHO;
        !          1037: startoutput:
        !          1038:        ttstart(tp);
        !          1039: }
        !          1040: 
        !          1041: /*
        !          1042:  * Put character on TTY output queue, adding delays,
        !          1043:  * expanding tabs, and handling the CR/NL bit.
        !          1044:  * This is called both from the top half for output,
        !          1045:  * and from interrupt level for echoing.
        !          1046:  * The arguments are the character and the tty structure.
        !          1047:  * Returns < 0 if putc succeeds, otherwise returns char to resend
        !          1048:  * Must be recursive.
        !          1049:  */
        !          1050: ttyoutput(c, tp)
        !          1051:        register c;
        !          1052:        register struct tty *tp;
        !          1053: {
        !          1054:        register short *colp;
        !          1055:        register ctype;
        !          1056:        register long oflag = tp->t_oflag;
        !          1057:        
        !          1058:        if ((oflag&OPOST) == 0) {
        !          1059:                if (tp->t_lflag&FLUSHO) 
        !          1060:                        return (-1);
        !          1061:                if (putc(c, &tp->t_outq))
        !          1062:                        return (c);
        !          1063:                tk_nout++;
        !          1064:                tp->t_outcc++;
        !          1065:                return (-1);
        !          1066:        }
        !          1067:        c &= TTY_CHARMASK;
        !          1068:        /*
        !          1069:         * Turn tabs to spaces as required
        !          1070:         *
        !          1071:         * Special case if we have external processing, we don't
        !          1072:         * do the tab expansion because we'll probably get it
        !          1073:         * wrong.  If tab expansion needs to be done, let it
        !          1074:         * happen externally.
        !          1075:         */
        !          1076:        if ((tp->t_lflag&EXTPROC) == 0 &&
        !          1077:            c == '\t' && oflag&OXTABS ) {
        !          1078:                register int s;
        !          1079: 
        !          1080:                c = 8 - (tp->t_col&7);
        !          1081:                if ((tp->t_lflag&FLUSHO) == 0) {
        !          1082:                        s = spltty();           /* don't interrupt tabs */
        !          1083:                        c -= b_to_q("        ", c, &tp->t_outq);
        !          1084:                        tk_nout += c;
        !          1085:                        tp->t_outcc += c;
        !          1086:                        splx(s);
        !          1087:                }
        !          1088:                tp->t_col += c;
        !          1089:                return (c ? -1 : '\t');
        !          1090:        }
        !          1091:        if (c == CEOT && oflag&ONOEOT)
        !          1092:                return(-1);
        !          1093:        tk_nout++;
        !          1094:        tp->t_outcc++;
        !          1095:        /*
        !          1096:         * turn <nl> to <cr><lf> if desired.
        !          1097:         */
        !          1098:        if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0)
        !          1099:                return (c);
        !          1100:        if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq))
        !          1101:                return (c);
        !          1102:        /*
        !          1103:         * Calculate delays.
        !          1104:         * The numbers here represent clock ticks
        !          1105:         * and are not necessarily optimal for all terminals.
        !          1106:         *
        !          1107:         * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
        !          1108:         *
        !          1109:         * (actually, should THROW AWAY terminals which need delays)
        !          1110:         */
        !          1111:        colp = &tp->t_col;
        !          1112:        ctype = partab[c];
        !          1113:        c = 0;
        !          1114:        switch (ctype&077) {
        !          1115: 
        !          1116:        case ORDINARY:
        !          1117:                (*colp)++;
        !          1118: 
        !          1119:        case CONTROL:
        !          1120:                break;
        !          1121: 
        !          1122:        case BACKSPACE:
        !          1123:                if (*colp)
        !          1124:                        (*colp)--;
        !          1125:                break;
        !          1126: 
        !          1127:        /*
        !          1128:         * This macro is close enough to the correct thing;
        !          1129:         * it should be replaced by real user settable delays
        !          1130:         * in any event...
        !          1131:         */
        !          1132: #define        mstohz(ms)      (((ms) * hz) >> 10)
        !          1133:        case NEWLINE:
        !          1134:                ctype = (tp->t_flags >> 8) & 03;
        !          1135:                if (ctype == 1) { /* tty 37 */
        !          1136:                        if (*colp > 0) {
        !          1137:                                c = (((unsigned)*colp) >> 4) + 3;
        !          1138:                                if ((unsigned)c > 6)
        !          1139:                                        c = 6;
        !          1140:                        }
        !          1141:                } else if (ctype == 2) /* vt05 */
        !          1142:                        c = mstohz(100);
        !          1143:                *colp = 0;
        !          1144:                break;
        !          1145: 
        !          1146:        case TAB:
        !          1147:                ctype = (tp->t_flags >> 10) & 03;
        !          1148:                if (ctype == 1) { /* tty 37 */
        !          1149:                        c = 1 - (*colp | ~07);
        !          1150:                        if (c < 5)
        !          1151:                                c = 0;
        !          1152:                }
        !          1153:                *colp |= 07;
        !          1154:                (*colp)++;
        !          1155:                break;
        !          1156: 
        !          1157:        case VTAB:
        !          1158:                if (tp->t_flags&VTDELAY) /* tty 37 */
        !          1159:                        c = 0177;
        !          1160:                break;
        !          1161: 
        !          1162:        case RETURN:
        !          1163:                ctype = (tp->t_flags >> 12) & 03;
        !          1164:                if (ctype == 1) /* tn 300 */
        !          1165:                        c = mstohz(83);
        !          1166:                else if (ctype == 2) /* ti 700 */
        !          1167:                        c = mstohz(166);
        !          1168:                else if (ctype == 3) { /* concept 100 */
        !          1169:                        int i;
        !          1170: 
        !          1171:                        if ((i = *colp) >= 0)
        !          1172:                                for (; i < 9; i++)
        !          1173:                                        (void) putc(0177, &tp->t_outq);
        !          1174:                }
        !          1175:                *colp = 0;
        !          1176:        }
        !          1177:        if (c && (tp->t_lflag&FLUSHO) == 0)
        !          1178:                (void) putc(c|TTY_QUOTE, &tp->t_outq);
        !          1179:        return (-1);
        !          1180: }
        !          1181: #undef mstohz
        !          1182: 
        !          1183: /*
        !          1184:  * Called from device's read routine after it has
        !          1185:  * calculated the tty-structure given as argument.
        !          1186:  */
        !          1187: ttread(tp, uio, flag)
        !          1188:        register struct tty *tp;
        !          1189:        struct uio *uio;
        !          1190: {
        !          1191:        register struct clist *qp;
        !          1192:        register int c;
        !          1193:        register long lflag;
        !          1194:        register u_char *cc = tp->t_cc;
        !          1195:        int s, first, error = 0;
        !          1196: 
        !          1197: loop:
        !          1198:        lflag = tp->t_lflag;
        !          1199:        s = spltty();
        !          1200:        /*
        !          1201:         * take pending input first 
        !          1202:         */
        !          1203:        if (lflag&PENDIN)
        !          1204:                ttypend(tp);
        !          1205:        splx(s);
        !          1206: 
        !          1207:        /*
        !          1208:         * Hang process if it's in the background.
        !          1209:         */
        !          1210:        if (isbackground(u.u_procp, tp)) {
        !          1211:                if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
        !          1212:                   (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
        !          1213:                    u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0)
        !          1214:                        return (EIO);
        !          1215:                pgsignal(u.u_procp->p_pgrp, SIGTTIN, 1);
        !          1216:                if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 
        !          1217:                    ttybg, 0)) 
        !          1218:                        return (error);
        !          1219:                goto loop;
        !          1220:        }
        !          1221: 
        !          1222:        /*
        !          1223:         * If canonical, use the canonical queue,
        !          1224:         * else use the raw queue.
        !          1225:         *
        !          1226:         * XXX - should get rid of canonical queue.
        !          1227:         * (actually, should get rid of clists...)
        !          1228:         */
        !          1229:        qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq;
        !          1230: 
        !          1231:        /*
        !          1232:         * If there is no input, sleep on rawq
        !          1233:         * awaiting hardware receipt and notification.
        !          1234:         * If we have data, we don't need to check for carrier.
        !          1235:         */
        !          1236:        s = spltty();
        !          1237:        if (qp->c_cc <= 0) {
        !          1238:                int carrier;
        !          1239: 
        !          1240:                carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL);
        !          1241:                if (!carrier && tp->t_state&TS_ISOPEN) {
        !          1242:                        splx(s);
        !          1243:                        return (0);     /* EOF */
        !          1244:                }
        !          1245:                if (flag & IO_NDELAY) {
        !          1246:                        splx(s);
        !          1247:                        return (EWOULDBLOCK);
        !          1248:                }
        !          1249:                error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
        !          1250:                    carrier ? ttyin : ttopen, 0);
        !          1251:                splx(s);
        !          1252:                if (error)
        !          1253:                        return (error);
        !          1254:                goto loop;
        !          1255:        }
        !          1256:        splx(s);
        !          1257: 
        !          1258:        /*
        !          1259:         * Input present, check for input mapping and processing.
        !          1260:         */
        !          1261:        first = 1;
        !          1262:        while ((c = getc(qp)) >= 0) {
        !          1263:                /*
        !          1264:                 * delayed suspend (^Y)
        !          1265:                 */
        !          1266:                if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) {
        !          1267:                        pgsignal(tp->t_pgrp, SIGTSTP, 1);
        !          1268:                        if (first) {
        !          1269:                                if (error = ttysleep(tp, (caddr_t)&lbolt,
        !          1270:                                    TTIPRI | PCATCH, ttybg, 0))
        !          1271:                                        break;
        !          1272:                                goto loop;
        !          1273:                        }
        !          1274:                        break;
        !          1275:                }
        !          1276:                /*
        !          1277:                 * Interpret EOF only in canonical mode.
        !          1278:                 */
        !          1279:                if (CCEQ(cc[VEOF], c) && lflag&ICANON)
        !          1280:                        break;
        !          1281:                /*
        !          1282:                 * Give user character.
        !          1283:                 */
        !          1284:                error = ureadc(c, uio);
        !          1285:                if (error)
        !          1286:                        break;
        !          1287:                if (uio->uio_resid == 0)
        !          1288:                        break;
        !          1289:                /*
        !          1290:                 * In canonical mode check for a "break character"
        !          1291:                 * marking the end of a "line of input".
        !          1292:                 */
        !          1293:                if (lflag&ICANON && ttbreakc(c))
        !          1294:                        break;
        !          1295:                first = 0;
        !          1296:        }
        !          1297:        /*
        !          1298:         * Look to unblock output now that (presumably)
        !          1299:         * the input queue has gone down.
        !          1300:         */
        !          1301:        if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
        !          1302:                if (cc[VSTART] != _POSIX_VDISABLE 
        !          1303:                   && putc(cc[VSTART], &tp->t_outq) == 0) {
        !          1304:                        tp->t_state &= ~TS_TBLOCK;
        !          1305:                        ttstart(tp);
        !          1306:                }
        !          1307:        }
        !          1308:        return (error);
        !          1309: }
        !          1310: 
        !          1311: /*
        !          1312:  * Check the output queue on tp for space for a kernel message
        !          1313:  * (from uprintf/tprintf).  Allow some space over the normal
        !          1314:  * hiwater mark so we don't lose messages due to normal flow
        !          1315:  * control, but don't let the tty run amok.
        !          1316:  * Sleeps here are not interruptible, but we return prematurely
        !          1317:  * if new signals come in.
        !          1318:  */
        !          1319: ttycheckoutq(tp, wait)
        !          1320:        register struct tty *tp;
        !          1321:        int wait;
        !          1322: {
        !          1323:        int hiwat, s, oldsig;
        !          1324: 
        !          1325:        hiwat = tp->t_hiwat;
        !          1326:        s = spltty();
        !          1327:        oldsig = u.u_procp->p_sig;
        !          1328:        if (tp->t_outq.c_cc > hiwat + 200)
        !          1329:                while (tp->t_outq.c_cc > hiwat) {
        !          1330:                        ttstart(tp);
        !          1331:                        if (wait == 0 || u.u_procp->p_sig != oldsig) {
        !          1332:                                splx(s);
        !          1333:                                return (0);
        !          1334:                        }
        !          1335:                        timeout(wakeup, (caddr_t)&tp->t_outq, hz);
        !          1336:                        tp->t_state |= TS_ASLEEP;
        !          1337:                        sleep((caddr_t)&tp->t_outq, PZERO - 1);
        !          1338:                }
        !          1339:        splx(s);
        !          1340:        return (1);
        !          1341: }
        !          1342: 
        !          1343: /*
        !          1344:  * Called from the device's write routine after it has
        !          1345:  * calculated the tty-structure given as argument.
        !          1346:  */
        !          1347: ttwrite(tp, uio, flag)
        !          1348:        register struct tty *tp;
        !          1349:        register struct uio *uio;
        !          1350: {
        !          1351:        register char *cp;
        !          1352:        register int cc = 0, ce;
        !          1353:        int i, hiwat, cnt, error, s;
        !          1354:        char obuf[OBUFSIZ];
        !          1355: 
        !          1356:        hiwat = tp->t_hiwat;
        !          1357:        cnt = uio->uio_resid;
        !          1358:        error = 0;
        !          1359: loop:
        !          1360:        s = spltty();
        !          1361:        if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) {
        !          1362:                if (tp->t_state&TS_ISOPEN) {
        !          1363:                        splx(s);
        !          1364:                        return (EIO);
        !          1365:                } else if (flag & IO_NDELAY) {
        !          1366:                        splx(s);
        !          1367:                        error = EWOULDBLOCK;
        !          1368:                        goto out;
        !          1369:                } else {
        !          1370:                        /*
        !          1371:                         * sleep awaiting carrier
        !          1372:                         */
        !          1373:                        error = ttysleep(tp, (caddr_t)&tp->t_rawq, 
        !          1374:                                        TTIPRI | PCATCH,ttopen, 0);
        !          1375:                        splx(s);
        !          1376:                        if (error)
        !          1377:                                goto out;
        !          1378:                        goto loop;
        !          1379:                }
        !          1380:        }
        !          1381:        splx(s);
        !          1382:        /*
        !          1383:         * Hang the process if it's in the background.
        !          1384:         */
        !          1385:        if (isbackground(u.u_procp, tp) && 
        !          1386:            (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
        !          1387:            (u.u_procp->p_sigignore & sigmask(SIGTTOU)) == 0 &&
        !          1388:            (u.u_procp->p_sigmask & sigmask(SIGTTOU)) == 0 &&
        !          1389:             u.u_procp->p_pgrp->pg_jobc) {
        !          1390:                pgsignal(u.u_procp->p_pgrp, SIGTTOU, 1);
        !          1391:                if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 
        !          1392:                    ttybg, 0))
        !          1393:                        goto out;
        !          1394:                goto loop;
        !          1395:        }
        !          1396:        /*
        !          1397:         * Process the user's data in at most OBUFSIZ
        !          1398:         * chunks.  Perform any output translation.
        !          1399:         * Keep track of high water mark, sleep on overflow
        !          1400:         * awaiting device aid in acquiring new space.
        !          1401:         */
        !          1402:        while (uio->uio_resid > 0 || cc > 0) {
        !          1403:                if (tp->t_lflag&FLUSHO) {
        !          1404:                        uio->uio_resid = 0;
        !          1405:                        return (0);
        !          1406:                }
        !          1407:                if (tp->t_outq.c_cc > hiwat)
        !          1408:                        goto ovhiwat;
        !          1409:                /*
        !          1410:                 * Grab a hunk of data from the user,
        !          1411:                 * unless we have some leftover from last time.
        !          1412:                 */
        !          1413:                if (cc == 0) {
        !          1414:                        cc = min(uio->uio_resid, OBUFSIZ);
        !          1415:                        cp = obuf;
        !          1416:                        error = uiomove(cp, cc, uio);
        !          1417:                        if (error) {
        !          1418:                                cc = 0;
        !          1419:                                break;
        !          1420:                        }
        !          1421:                }
        !          1422:                /*
        !          1423:                 * If nothing fancy need be done, grab those characters we
        !          1424:                 * can handle without any of ttyoutput's processing and
        !          1425:                 * just transfer them to the output q.  For those chars
        !          1426:                 * which require special processing (as indicated by the
        !          1427:                 * bits in partab), call ttyoutput.  After processing
        !          1428:                 * a hunk of data, look for FLUSHO so ^O's will take effect
        !          1429:                 * immediately.
        !          1430:                 */
        !          1431:                while (cc > 0) {
        !          1432:                        if ((tp->t_oflag&OPOST) == 0)
        !          1433:                                ce = cc;
        !          1434:                        else {
        !          1435:                                ce = cc - scanc((unsigned)cc, (u_char *)cp,
        !          1436:                                   (u_char *)partab, 077);
        !          1437:                                /*
        !          1438:                                 * If ce is zero, then we're processing
        !          1439:                                 * a special character through ttyoutput.
        !          1440:                                 */
        !          1441:                                if (ce == 0) {
        !          1442:                                        tp->t_rocount = 0;
        !          1443:                                        if (ttyoutput(*cp, tp) >= 0) {
        !          1444:                                            /* no c-lists, wait a bit */
        !          1445:                                            ttstart(tp);
        !          1446:                                            if (error = ttysleep(tp, 
        !          1447:                                                (caddr_t)&lbolt,
        !          1448:                                                 TTOPRI | PCATCH, ttybuf, 0))
        !          1449:                                                    break;
        !          1450:                                            goto loop;
        !          1451:                                        }
        !          1452:                                        cp++, cc--;
        !          1453:                                        if ((tp->t_lflag&FLUSHO) ||
        !          1454:                                            tp->t_outq.c_cc > hiwat)
        !          1455:                                                goto ovhiwat;
        !          1456:                                        continue;
        !          1457:                                }
        !          1458:                        }
        !          1459:                        /*
        !          1460:                         * A bunch of normal characters have been found,
        !          1461:                         * transfer them en masse to the output queue and
        !          1462:                         * continue processing at the top of the loop.
        !          1463:                         * If there are any further characters in this
        !          1464:                         * <= OBUFSIZ chunk, the first should be a character
        !          1465:                         * requiring special handling by ttyoutput.
        !          1466:                         */
        !          1467:                        tp->t_rocount = 0;
        !          1468:                        i = b_to_q(cp, ce, &tp->t_outq);
        !          1469:                        ce -= i;
        !          1470:                        tp->t_col += ce;
        !          1471:                        cp += ce, cc -= ce, tk_nout += ce;
        !          1472:                        tp->t_outcc += ce;
        !          1473:                        if (i > 0) {
        !          1474:                                /* out of c-lists, wait a bit */
        !          1475:                                ttstart(tp);
        !          1476:                                if (error = ttysleep(tp, (caddr_t)&lbolt,
        !          1477:                                            TTOPRI | PCATCH, ttybuf, 0))
        !          1478:                                        break;
        !          1479:                                goto loop;
        !          1480:                        }
        !          1481:                        if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat)
        !          1482:                                break;
        !          1483:                }
        !          1484:                ttstart(tp);
        !          1485:        }
        !          1486: out:
        !          1487:        /*
        !          1488:         * If cc is nonzero, we leave the uio structure inconsistent,
        !          1489:         * as the offset and iov pointers have moved forward,
        !          1490:         * but it doesn't matter (the call will either return short
        !          1491:         * or restart with a new uio).
        !          1492:         */
        !          1493:        uio->uio_resid += cc;
        !          1494:        return (error);
        !          1495: 
        !          1496: ovhiwat:
        !          1497:        ttstart(tp);
        !          1498:        s = spltty();
        !          1499:        /*
        !          1500:         * This can only occur if FLUSHO is set in t_lflag,
        !          1501:         * or if ttstart/oproc is synchronous (or very fast).
        !          1502:         */
        !          1503:        if (tp->t_outq.c_cc <= hiwat) {
        !          1504:                splx(s);
        !          1505:                goto loop;
        !          1506:        }
        !          1507:        if (flag & IO_NDELAY) {
        !          1508:                splx(s);
        !          1509:                uio->uio_resid += cc;
        !          1510:                if (uio->uio_resid == cnt)
        !          1511:                        return (EWOULDBLOCK);
        !          1512:                return (0);
        !          1513:        }
        !          1514:        tp->t_state |= TS_ASLEEP;
        !          1515:        error = ttysleep(tp, (caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
        !          1516:        splx(s);
        !          1517:        if (error)
        !          1518:                goto out;
        !          1519:        goto loop;
        !          1520: }
        !          1521: 
        !          1522: /*
        !          1523:  * Rubout one character from the rawq of tp
        !          1524:  * as cleanly as possible.
        !          1525:  */
        !          1526: ttyrub(c, tp)
        !          1527:        register c;
        !          1528:        register struct tty *tp;
        !          1529: {
        !          1530:        register char *cp;
        !          1531:        register int savecol;
        !          1532:        int s;
        !          1533:        char *nextc();
        !          1534: 
        !          1535:        if ((tp->t_lflag&ECHO) == 0 || (tp->t_lflag&EXTPROC))
        !          1536:                return;
        !          1537:        tp->t_lflag &= ~FLUSHO; 
        !          1538:        if (tp->t_lflag&ECHOE) {
        !          1539:                if (tp->t_rocount == 0) {
        !          1540:                        /*
        !          1541:                         * Screwed by ttwrite; retype
        !          1542:                         */
        !          1543:                        ttyretype(tp);
        !          1544:                        return;
        !          1545:                }
        !          1546:                if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE))
        !          1547:                        ttyrubo(tp, 2);
        !          1548:                else switch (partab[c&=0377]&077) {
        !          1549: 
        !          1550:                case ORDINARY:
        !          1551:                        ttyrubo(tp, 1);
        !          1552:                        break;
        !          1553: 
        !          1554:                case VTAB:
        !          1555:                case BACKSPACE:
        !          1556:                case CONTROL:
        !          1557:                case RETURN:
        !          1558:                case NEWLINE:   /* XXX can't happen ? */
        !          1559:                        if (tp->t_lflag&ECHOCTL)
        !          1560:                                ttyrubo(tp, 2);
        !          1561:                        break;
        !          1562: 
        !          1563:                case TAB: {
        !          1564:                        int c;
        !          1565: 
        !          1566:                        if (tp->t_rocount < tp->t_rawq.c_cc) {
        !          1567:                                ttyretype(tp);
        !          1568:                                return;
        !          1569:                        }
        !          1570:                        s = spltty();
        !          1571:                        savecol = tp->t_col;
        !          1572:                        tp->t_state |= TS_CNTTB;
        !          1573:                        tp->t_lflag |= FLUSHO;
        !          1574:                        tp->t_col = tp->t_rocol;
        !          1575:                        cp = tp->t_rawq.c_cf;
        !          1576:                        if (cp)
        !          1577:                                c = *cp;        /* XXX FIX NEXTC */
        !          1578:                        for (; cp; cp = nextc(&tp->t_rawq, cp, &c))
        !          1579:                                ttyecho(c, tp);
        !          1580:                        tp->t_lflag &= ~FLUSHO;
        !          1581:                        tp->t_state &= ~TS_CNTTB;
        !          1582:                        splx(s);
        !          1583:                        /*
        !          1584:                         * savecol will now be length of the tab
        !          1585:                         */
        !          1586:                        savecol -= tp->t_col;
        !          1587:                        tp->t_col += savecol;
        !          1588:                        if (savecol > 8)
        !          1589:                                savecol = 8;            /* overflow screw */
        !          1590:                        while (--savecol >= 0)
        !          1591:                                (void) ttyoutput('\b', tp);
        !          1592:                        break;
        !          1593:                }
        !          1594: 
        !          1595:                default:
        !          1596:                        /* XXX */
        !          1597:                        printf("ttyrub: would panic c = %d, val = %d\n",
        !          1598:                                c, partab[c&=0377]&077);
        !          1599:                        /*panic("ttyrub");*/
        !          1600:                }
        !          1601:        } else if (tp->t_lflag&ECHOPRT) {
        !          1602:                if ((tp->t_state&TS_ERASE) == 0) {
        !          1603:                        (void) ttyoutput('\\', tp);
        !          1604:                        tp->t_state |= TS_ERASE;
        !          1605:                }
        !          1606:                ttyecho(c, tp);
        !          1607:        } else
        !          1608:                ttyecho(tp->t_cc[VERASE], tp);
        !          1609:        tp->t_rocount--;
        !          1610: }
        !          1611: 
        !          1612: /*
        !          1613:  * Crt back over cnt chars perhaps
        !          1614:  * erasing them.
        !          1615:  */
        !          1616: ttyrubo(tp, cnt)
        !          1617:        register struct tty *tp;
        !          1618:        int cnt;
        !          1619: {
        !          1620: 
        !          1621:        while (--cnt >= 0)
        !          1622:                ttyoutstr("\b \b", tp);
        !          1623: }
        !          1624: 
        !          1625: /*
        !          1626:  * Reprint the rawq line.
        !          1627:  * We assume c_cc has already been checked.
        !          1628:  */
        !          1629: ttyretype(tp)
        !          1630:        register struct tty *tp;
        !          1631: {
        !          1632:        register char *cp;
        !          1633:        char *nextc();
        !          1634:        int s, c;
        !          1635: 
        !          1636:        if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
        !          1637:                ttyecho(tp->t_cc[VREPRINT], tp);
        !          1638:        (void) ttyoutput('\n', tp);
        !          1639:        s = spltty();
        !          1640:        /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE
        !          1641:          BIT OF FIRST CHAR ****/
        !          1642:        for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) {
        !          1643:                ttyecho(c, tp);
        !          1644:        }
        !          1645:        for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) {
        !          1646:                ttyecho(c, tp);
        !          1647:        }
        !          1648:        tp->t_state &= ~TS_ERASE;
        !          1649:        splx(s);
        !          1650:        tp->t_rocount = tp->t_rawq.c_cc;
        !          1651:        tp->t_rocol = 0;
        !          1652: }
        !          1653: 
        !          1654: /*
        !          1655:  * Echo a typed character to the terminal.
        !          1656:  */
        !          1657: ttyecho(c, tp)
        !          1658:        register c;
        !          1659:        register struct tty *tp;
        !          1660: {
        !          1661:        if ((tp->t_state&TS_CNTTB) == 0)
        !          1662:                tp->t_lflag &= ~FLUSHO;
        !          1663:        if (((tp->t_lflag&ECHO) == 0 && ((tp->t_lflag&ECHONL) == 0 ||
        !          1664:                                          c == '\n')) || (tp->t_lflag&EXTPROC))
        !          1665:                return;
        !          1666:        if (tp->t_lflag&ECHOCTL) {
        !          1667:                if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' ||
        !          1668:                    c == 0177) {
        !          1669:                        (void) ttyoutput('^', tp);
        !          1670:                        c &= TTY_CHARMASK;
        !          1671:                        if (c == 0177)
        !          1672:                                c = '?';
        !          1673:                        else
        !          1674:                                c += 'A' - 1;
        !          1675:                }
        !          1676:        }
        !          1677:        (void) ttyoutput(c, tp);
        !          1678: }
        !          1679: 
        !          1680: /*
        !          1681:  * send string cp to tp
        !          1682:  */
        !          1683: ttyoutstr(cp, tp)
        !          1684:        register char *cp;
        !          1685:        register struct tty *tp;
        !          1686: {
        !          1687:        register char c;
        !          1688: 
        !          1689:        while (c = *cp++)
        !          1690:                (void) ttyoutput(c, tp);
        !          1691: }
        !          1692: 
        !          1693: ttwakeup(tp)
        !          1694:        struct tty *tp;
        !          1695: {
        !          1696: 
        !          1697:        if (tp->t_rsel) {
        !          1698:                selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
        !          1699:                tp->t_state &= ~TS_RCOLL;
        !          1700:                tp->t_rsel = 0;
        !          1701:        }
        !          1702:        if (tp->t_state & TS_ASYNC)
        !          1703:                pgsignal(tp->t_pgrp, SIGIO, 1); 
        !          1704:        wakeup((caddr_t)&tp->t_rawq);
        !          1705: }
        !          1706: 
        !          1707: /*
        !          1708:  * set tty hi and low water marks
        !          1709:  *
        !          1710:  * Try to arrange the dynamics so there's about one second
        !          1711:  * from hi to low water.
        !          1712:  * 
        !          1713:  */
        !          1714: ttsetwater(tp)
        !          1715:        struct tty *tp;
        !          1716: {
        !          1717:        register cps = tp->t_ospeed / 10;
        !          1718:        register x;
        !          1719: 
        !          1720: #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x))
        !          1721:        tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT);
        !          1722:        x += cps;
        !          1723:        x = clamp(x, TTMAXHIWAT, TTMINHIWAT);
        !          1724:        tp->t_hiwat = roundup(x, CBSIZE);
        !          1725: #undef clamp
        !          1726: }
        !          1727: 
        !          1728: ttspeedtab(speed, table)
        !          1729:        struct speedtab table[];
        !          1730: {
        !          1731:        register int i;
        !          1732: 
        !          1733:        for (i = 0; table[i].sp_speed != -1; i++)
        !          1734:                if (table[i].sp_speed == speed)
        !          1735:                        return(table[i].sp_code);
        !          1736:        return(-1);
        !          1737: }
        !          1738: 
        !          1739: int ttyhostname = 0;
        !          1740: /*
        !          1741:  * (^T)
        !          1742:  * Report on state of foreground process group.
        !          1743:  */
        !          1744: ttyinfo(tp)
        !          1745:        struct tty *tp;
        !          1746: {
        !          1747:        register struct proc *p, *pick = NULL;
        !          1748:        register char *cp = hostname;
        !          1749:        int x, s;
        !          1750:        struct timeval utime, stime;
        !          1751: #define        pgtok(a)        (((a)*NBPG)/1024)
        !          1752: 
        !          1753:        if (ttycheckoutq(tp,0) == 0) 
        !          1754:                return;
        !          1755:        /* 
        !          1756:         * hostname 
        !          1757:         */
        !          1758:        if (ttyhostname) {
        !          1759:                if (*cp == '\0')
        !          1760:                        ttyprintf(tp, "amnesia");
        !          1761:                else
        !          1762:                        while (*cp && *cp != '.')
        !          1763:                                tputchar(*cp++, tp);
        !          1764:                tputchar(' ');
        !          1765:        }
        !          1766:        /* 
        !          1767:         * load average 
        !          1768:         */
        !          1769:        x = (averunnable[0] * 100 + FSCALE/2) >> FSHIFT;
        !          1770:        ttyprintf(tp, "load: %d.", x/100);
        !          1771:        ttyoutint(x%100, 10, 2, tp);
        !          1772:        if (tp->t_session == NULL)
        !          1773:                ttyprintf(tp, " not a controlling terminal\n");
        !          1774:        else if (tp->t_pgrp == NULL)
        !          1775:                ttyprintf(tp, " no foreground process group\n");
        !          1776:        else if ((p = tp->t_pgrp->pg_mem) == NULL)
        !          1777:                ttyprintf(tp, " empty foreground process group\n");
        !          1778:        else {
        !          1779:                /* pick interesting process */
        !          1780:                for (; p != NULL; p = p->p_pgrpnxt) {
        !          1781:                        if (proc_compare(pick, p))
        !          1782:                                pick = p;
        !          1783:                }
        !          1784:                ttyprintf(tp, "  cmd: %s %d [%s] ",
        !          1785:                        pick->p_comm, pick->p_pid,
        !          1786:                        pick->p_wmesg ? pick->p_wmesg : "running");
        !          1787:                /* 
        !          1788:                 * cpu time 
        !          1789:                 */
        !          1790:                if (u.u_procp == pick)
        !          1791:                        s = splclock();
        !          1792:                utime = pick->p_utime;
        !          1793:                stime = pick->p_stime;
        !          1794:                if (u.u_procp == pick)
        !          1795:                        splx(s);
        !          1796:                /* user time */
        !          1797:                x = (utime.tv_usec + 5000) / 10000; /* scale to 100's */
        !          1798:                ttyoutint(utime.tv_sec, 10, 1, tp);
        !          1799:                tputchar('.', tp);
        !          1800:                ttyoutint(x, 10, 2, tp);
        !          1801:                tputchar('u', tp);
        !          1802:                tputchar(' ', tp);
        !          1803:                /* system time */
        !          1804:                x = (stime.tv_usec + 5000) / 10000; /* scale to 100's */
        !          1805:                ttyoutint(stime.tv_sec, 10, 1, tp);
        !          1806:                tputchar('.', tp);
        !          1807:                ttyoutint(x, 10, 2, tp);
        !          1808:                tputchar('s', tp);
        !          1809:                tputchar(' ', tp);
        !          1810:                /* 
        !          1811:                 * pctcpu 
        !          1812:                 */
        !          1813:                x = pick->p_pctcpu * 10000 + FSCALE/2 >> FSHIFT;
        !          1814:                ttyoutint(x/100, 10, 1, tp);
        !          1815: #ifdef notdef  /* do we really want this ??? */
        !          1816:                tputchar('.', tp);
        !          1817:                ttyoutint(x%100, 10, 2, tp);
        !          1818: #endif
        !          1819:                ttyprintf(tp, "%% %dk\n", pgtok(pick->p_ssize + pick->p_dsize));
        !          1820:        }
        !          1821:        tp->t_rocount = 0;      /* so pending input will be retyped if BS */
        !          1822: }
        !          1823: 
        !          1824: ttyoutint(n, base, min, tp)
        !          1825:        register int n, base, min;
        !          1826:        register struct tty *tp;
        !          1827: {
        !          1828:        char info[16];
        !          1829:        register char *p = info;
        !          1830: 
        !          1831:        while (--min >= 0 || n) {
        !          1832:                *p++ = "0123456789abcdef"[n%base];
        !          1833:                n /= base;
        !          1834:        }
        !          1835:        while (p > info)
        !          1836:                ttyoutput(*--p, tp);
        !          1837: }
        !          1838: 
        !          1839: /*
        !          1840:  * Returns 1 if p2 is "better" than p1
        !          1841:  *
        !          1842:  * The algorithm for picking the "interesting" process is thus:
        !          1843:  *
        !          1844:  *     1) (Only foreground processes are eligable - implied)
        !          1845:  *     2) Runnable processes are favored over anything
        !          1846:  *        else.  The runner with the highest cpu
        !          1847:  *        utilization is picked (p_cpu).  Ties are
        !          1848:  *        broken by picking the highest pid.
        !          1849:  *     3  Next, the sleeper with the shortest sleep
        !          1850:  *        time is favored.  With ties, we pick out
        !          1851:  *        just "short-term" sleepers (SSINTR == 0).
        !          1852:  *        Further ties are broken by picking the highest
        !          1853:  *        pid.
        !          1854:  *
        !          1855:  */
        !          1856: #define isrun(p)       (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
        !          1857: proc_compare(p1, p2)
        !          1858:        register struct proc *p1, *p2;
        !          1859: {
        !          1860: 
        !          1861:        if (p1 == NULL)
        !          1862:                return (1);
        !          1863:        /*
        !          1864:         * see if at least one of them is runnable
        !          1865:         */
        !          1866:        switch (isrun(p1)<<1 | isrun(p2)) {
        !          1867:        case 0x01:
        !          1868:                return (1);
        !          1869:        case 0x10:
        !          1870:                return (0);
        !          1871:        case 0x11:
        !          1872:                /*
        !          1873:                 * tie - favor one with highest recent cpu utilization
        !          1874:                 */
        !          1875:                if (p2->p_cpu > p1->p_cpu)
        !          1876:                        return (1);
        !          1877:                if (p1->p_cpu > p2->p_cpu)
        !          1878:                        return (0);
        !          1879:                return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
        !          1880:        }
        !          1881:        /* 
        !          1882:         * pick the one with the smallest sleep time
        !          1883:         */
        !          1884:        if (p2->p_slptime > p1->p_slptime)
        !          1885:                return (0);
        !          1886:        if (p1->p_slptime > p2->p_slptime)
        !          1887:                return (1);
        !          1888:        /*
        !          1889:         * favor one sleeping in a non-interruptible sleep
        !          1890:         */
        !          1891:        if (p1->p_flag&SSINTR && (p2->p_flag&SSINTR) == 0)
        !          1892:                return (1);
        !          1893:        if (p2->p_flag&SSINTR && (p1->p_flag&SSINTR) == 0)
        !          1894:                return (0);
        !          1895:        return(p2->p_pid > p1->p_pid);          /* tie - return highest pid */
        !          1896: }
        !          1897: #define TOTTY  0x2     /* XXX should be in header */
        !          1898: /*VARARGS2*/
        !          1899: ttyprintf(tp, fmt, x1)
        !          1900:        struct tty *tp;
        !          1901:        char *fmt;
        !          1902:        unsigned x1;
        !          1903: {
        !          1904:        prf(fmt, &x1, TOTTY, (caddr_t)tp);
        !          1905: }
        !          1906: 
        !          1907: /*
        !          1908:  * Output char to tty; console putchar style.
        !          1909:  */
        !          1910: tputchar(c, tp)
        !          1911:        int c;
        !          1912:        struct tty *tp;
        !          1913: {
        !          1914:        register s = spltty();
        !          1915: 
        !          1916:        if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN)) 
        !          1917:            == (TS_CARR_ON | TS_ISOPEN)) {
        !          1918:                if (c == '\n')
        !          1919:                        (void) ttyoutput('\r', tp);
        !          1920:                (void) ttyoutput(c, tp);
        !          1921:                ttstart(tp);
        !          1922:                splx(s);
        !          1923:                return (0);
        !          1924:        }
        !          1925:        splx(s);
        !          1926:        return (-1);
        !          1927: }
        !          1928: 
        !          1929: /*
        !          1930:  * Sleep on chan.
        !          1931:  *
        !          1932:  * Return ERESTART if tty changed while we napped.
        !          1933:  */
        !          1934: ttysleep(tp, chan, pri, wmesg, timo)
        !          1935:        struct tty *tp;
        !          1936:        caddr_t chan;
        !          1937:        int pri;
        !          1938:        char *wmesg;
        !          1939:        int timo;
        !          1940: {
        !          1941:        int error;
        !          1942:        short gen = tp->t_gen;
        !          1943: 
        !          1944:        if (error = tsleep(chan, pri, wmesg, timo))
        !          1945:                return (error);
        !          1946:        if (tp->t_gen != gen)
        !          1947:                return (ERESTART);
        !          1948:        return (0);
        !          1949: }

unix.superglobalmegacorp.com

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