Annotation of Net2/kern/tty.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com

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