Annotation of 43BSDReno/sys/kern/tty.c, revision 1.1.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.