[BACK]Return to tty.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/tty.c, Revision 1.97

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

CVSweb <webmaster@jp.NetBSD.org>