[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.221.2.4

1.221.2.4! yamt        1: /*     $NetBSD: tty.c,v 1.221.2.3 2009/08/19 18:48:17 yamt Exp $       */
1.215     ad          2:
                      3: /*-
                      4:  * Copyright (c) 2008 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     17:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
1.49      cgd        28:
                     29: /*-
                     30:  * Copyright (c) 1982, 1986, 1990, 1991, 1993
                     31:  *     The Regents of the University of California.  All rights reserved.
                     32:  * (c) UNIX System Laboratories, Inc.
                     33:  * All or some portions of this file are derived from material licensed
                     34:  * to the University of California by American Telephone and Telegraph
                     35:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     36:  * the permission of UNIX System Laboratories, Inc.
                     37:  *
                     38:  * Redistribution and use in source and binary forms, with or without
                     39:  * modification, are permitted provided that the following conditions
                     40:  * are met:
                     41:  * 1. Redistributions of source code must retain the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer.
                     43:  * 2. Redistributions in binary form must reproduce the above copyright
                     44:  *    notice, this list of conditions and the following disclaimer in the
                     45:  *    documentation and/or other materials provided with the distribution.
1.155     agc        46:  * 3. Neither the name of the University nor the names of its contributors
1.49      cgd        47:  *    may be used to endorse or promote products derived from this software
                     48:  *    without specific prior written permission.
                     49:  *
                     50:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     51:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     52:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     53:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     54:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     55:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     56:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     57:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     58:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     59:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     60:  * SUCH DAMAGE.
                     61:  *
1.105     fvdl       62:  *     @(#)tty.c       8.13 (Berkeley) 1/9/95
1.49      cgd        63:  */
1.129     lukem      64:
                     65: #include <sys/cdefs.h>
1.221.2.4! yamt       66: __KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.221.2.3 2009/08/19 18:48:17 yamt Exp $");
1.49      cgd        67:
                     68: #include <sys/param.h>
                     69: #include <sys/systm.h>
                     70: #include <sys/ioctl.h>
                     71: #include <sys/proc.h>
                     72: #define        TTYDEFCHARS
                     73: #include <sys/tty.h>
                     74: #undef TTYDEFCHARS
                     75: #include <sys/file.h>
                     76: #include <sys/conf.h>
                     77: #include <sys/dkstat.h>
                     78: #include <sys/uio.h>
                     79: #include <sys/kernel.h>
                     80: #include <sys/vnode.h>
                     81: #include <sys/syslog.h>
1.216     ad         82: #include <sys/kmem.h>
1.65      christos   83: #include <sys/signalvar.h>
                     84: #include <sys/resourcevar.h>
1.74      mycroft    85: #include <sys/poll.h>
1.149     christos   86: #include <sys/kprintf.h>
1.151     christos   87: #include <sys/namei.h>
1.159     atatat     88: #include <sys/sysctl.h>
1.182     elad       89: #include <sys/kauth.h>
1.201     ad         90: #include <sys/intr.h>
1.221.2.2  yamt       91: #include <sys/ioctl_compat.h>
                     92: #include <sys/module.h>
1.149     christos   93:
                     94: #include <machine/stdarg.h>
1.49      cgd        95:
1.126     lukem      96: static int     ttnread(struct tty *);
                     97: static void    ttyblock(struct tty *);
                     98: static void    ttyecho(int, struct tty *);
                     99: static void    ttyrubo(struct tty *, int);
1.149     christos  100: static void    ttyprintf_nolock(struct tty *, const char *fmt, ...)
                    101:     __attribute__((__format__(__printf__,2,3)));
1.126     lukem     102: static int     proc_compare(struct proc *, struct proc *);
1.201     ad        103: static void    ttysigintr(void *);
1.49      cgd       104:
                    105: /* Symbolic sleep message strings. */
1.98      mycroft   106: const char     ttclos[] = "ttycls";
                    107: const char     ttopen[] = "ttyopn";
                    108: const char     ttybg[] = "ttybg";
                    109: const char     ttyin[] = "ttyin";
                    110: const char     ttyout[] = "ttyout";
1.49      cgd       111:
                    112: /*
1.83      mycroft   113:  * Used to determine whether we still have a connection.  This is true in
                    114:  * one of 3 cases:
                    115:  * 1) We have carrier.
                    116:  * 2) It's a locally attached terminal, and we are therefore ignoring carrier.
                    117:  * 3) We're using a flow control mechanism that overloads the carrier signal.
                    118:  */
                    119: #define        CONNECTED(tp)   (ISSET(tp->t_state, TS_CARR_ON) ||      \
                    120:                         ISSET(tp->t_cflag, CLOCAL | MDMBUF))
                    121:
                    122: /*
1.49      cgd       123:  * Table with character classes and parity. The 8th bit indicates parity,
                    124:  * the 7th bit indicates the character is an alphameric or underscore (for
                    125:  * ALTWERASE), and the low 6 bits indicate delay type.  If the low 6 bits
                    126:  * are 0 then the character needs no special processing on output; classes
                    127:  * other than 0 might be translated or (not currently) require delays.
                    128:  */
                    129: #define        E       0x00    /* Even parity. */
                    130: #define        O       0x80    /* Odd parity. */
                    131: #define        PARITY(c)       (char_type[c] & O)
                    132:
                    133: #define        ALPHA   0x40    /* Alpha or underscore. */
                    134: #define        ISALPHA(c)      (char_type[(c) & TTY_CHARMASK] & ALPHA)
                    135:
                    136: #define        CCLASSMASK      0x3f
                    137: #define        CCLASS(c)       (char_type[c] & CCLASSMASK)
                    138:
                    139: #define        BS      BACKSPACE
                    140: #define        CC      CONTROL
                    141: #define        CR      RETURN
                    142: #define        NA      ORDINARY | ALPHA
                    143: #define        NL      NEWLINE
                    144: #define        NO      ORDINARY
                    145: #define        TB      TAB
                    146: #define        VT      VTAB
                    147:
1.146     simonb    148: unsigned char const char_type[] = {
1.49      cgd       149:        E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
1.137     simonb    150:        O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
1.138     enami     151:        O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
                    152:        E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
                    153:        O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
                    154:        E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
                    155:        E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
                    156:        O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
                    157:        O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
                    158:        E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
                    159:        E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
                    160:        O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
                    161:        E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
                    162:        O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
                    163:        O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
                    164:        E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
1.49      cgd       165:        /*
                    166:         * Meta chars; should be settable per character set;
                    167:         * for now, treat them all as normal characters.
                    168:         */
                    169:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    170:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    171:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    172:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    173:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    174:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    175:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    176:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    177:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    178:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    179:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    180:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    181:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    182:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    183:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    184:        NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
                    185: };
                    186: #undef BS
                    187: #undef CC
                    188: #undef CR
                    189: #undef NA
                    190: #undef NL
                    191: #undef NO
                    192: #undef TB
                    193: #undef VT
                    194:
1.201     ad        195: static struct ttylist_head tty_sigqueue = TAILQ_HEAD_INITIALIZER(tty_sigqueue);
                    196: static void *tty_sigsih;
                    197:
1.169     thorpej   198: struct ttylist_head ttylist = TAILQ_HEAD_INITIALIZER(ttylist);
1.69      mrg       199: int tty_count;
1.201     ad        200: kmutex_t tty_lock;
1.221.2.2  yamt      201: krwlock_t ttcompat_lock;
                    202: int (*ttcompatvec)(struct tty *, u_long, void *, int, struct lwp *);
1.69      mrg       203:
1.179     perry     204: uint64_t tk_cancc;
                    205: uint64_t tk_nin;
                    206: uint64_t tk_nout;
                    207: uint64_t tk_rawcc;
1.159     atatat    208:
1.221.2.4! yamt      209: static kauth_listener_t tty_listener;
        !           210:
1.159     atatat    211: SYSCTL_SETUP(sysctl_kern_tkstat_setup, "sysctl kern.tkstat subtree setup")
                    212: {
                    213:
1.165     atatat    214:        sysctl_createv(clog, 0, NULL, NULL,
                    215:                       CTLFLAG_PERMANENT,
1.159     atatat    216:                       CTLTYPE_NODE, "kern", NULL,
                    217:                       NULL, 0, NULL, 0,
                    218:                       CTL_KERN, CTL_EOL);
1.165     atatat    219:        sysctl_createv(clog, 0, NULL, NULL,
                    220:                       CTLFLAG_PERMANENT,
1.168     atatat    221:                       CTLTYPE_NODE, "tkstat",
                    222:                       SYSCTL_DESCR("Number of characters sent and and "
                    223:                                    "received on ttys"),
1.159     atatat    224:                       NULL, 0, NULL, 0,
                    225:                       CTL_KERN, KERN_TKSTAT, CTL_EOL);
                    226:
1.165     atatat    227:        sysctl_createv(clog, 0, NULL, NULL,
                    228:                       CTLFLAG_PERMANENT,
1.168     atatat    229:                       CTLTYPE_QUAD, "nin",
                    230:                       SYSCTL_DESCR("Total number of tty input characters"),
1.159     atatat    231:                       NULL, 0, &tk_nin, 0,
                    232:                       CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NIN, CTL_EOL);
1.165     atatat    233:        sysctl_createv(clog, 0, NULL, NULL,
                    234:                       CTLFLAG_PERMANENT,
1.168     atatat    235:                       CTLTYPE_QUAD, "nout",
                    236:                       SYSCTL_DESCR("Total number of tty output characters"),
1.159     atatat    237:                       NULL, 0, &tk_nout, 0,
                    238:                       CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_NOUT, CTL_EOL);
1.165     atatat    239:        sysctl_createv(clog, 0, NULL, NULL,
                    240:                       CTLFLAG_PERMANENT,
1.168     atatat    241:                       CTLTYPE_QUAD, "cancc",
                    242:                       SYSCTL_DESCR("Number of canonical tty input characters"),
1.159     atatat    243:                       NULL, 0, &tk_cancc, 0,
                    244:                       CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_CANCC, CTL_EOL);
1.165     atatat    245:        sysctl_createv(clog, 0, NULL, NULL,
                    246:                       CTLFLAG_PERMANENT,
1.168     atatat    247:                       CTLTYPE_QUAD, "rawcc",
                    248:                       SYSCTL_DESCR("Number of raw tty input characters"),
1.159     atatat    249:                       NULL, 0, &tk_rawcc, 0,
                    250:                       CTL_KERN, KERN_TKSTAT, KERN_TKSTAT_RAWCC, CTL_EOL);
                    251: }
1.111     thorpej   252:
1.107     mycroft   253: int
1.126     lukem     254: ttyopen(struct tty *tp, int dialout, int nonblock)
1.107     mycroft   255: {
1.201     ad        256:        int     error;
1.107     mycroft   257:
1.147     pk        258:        error = 0;
                    259:
1.201     ad        260:        mutex_spin_enter(&tty_lock);
1.107     mycroft   261:
                    262:        if (dialout) {
                    263:                /*
                    264:                 * If the device is already open for non-dialout, fail.
                    265:                 * Otherwise, set TS_DIALOUT to block any pending non-dialout
                    266:                 * opens.
                    267:                 */
                    268:                if (ISSET(tp->t_state, TS_ISOPEN) &&
                    269:                    !ISSET(tp->t_state, TS_DIALOUT)) {
1.147     pk        270:                        error = EBUSY;
                    271:                        goto out;
1.107     mycroft   272:                }
                    273:                SET(tp->t_state, TS_DIALOUT);
                    274:        } else {
                    275:                if (!nonblock) {
                    276:                        /*
                    277:                         * Wait for carrier.  Also wait for any dialout
                    278:                         * processes to close the tty first.
                    279:                         */
                    280:                        while (ISSET(tp->t_state, TS_DIALOUT) ||
1.147     pk        281:                               !CONNECTED(tp)) {
1.107     mycroft   282:                                tp->t_wopen++;
1.221.2.2  yamt      283:                                error = ttysleep(tp, &tp->t_rawcv, true, 0);
1.107     mycroft   284:                                tp->t_wopen--;
1.147     pk        285:                                if (error)
                    286:                                        goto out;
1.107     mycroft   287:                        }
                    288:                } else {
                    289:                        /*
                    290:                         * Don't allow a non-blocking non-dialout open if the
                    291:                         * device is already open for dialout.
                    292:                         */
1.138     enami     293:                        if (ISSET(tp->t_state, TS_DIALOUT)) {
1.147     pk        294:                                error = EBUSY;
                    295:                                goto out;
1.107     mycroft   296:                        }
                    297:                }
                    298:        }
                    299:
1.147     pk        300: out:
1.201     ad        301:        mutex_spin_exit(&tty_lock);
1.147     pk        302:        return (error);
1.107     mycroft   303: }
                    304:
1.49      cgd       305: /*
                    306:  * Initial open of tty, or (re)entry to standard tty line discipline.
                    307:  */
                    308: int
1.126     lukem     309: ttylopen(dev_t device, struct tty *tp)
1.49      cgd       310: {
                    311:
1.201     ad        312:        mutex_spin_enter(&tty_lock);
1.49      cgd       313:        tp->t_dev = device;
                    314:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                    315:                SET(tp->t_state, TS_ISOPEN);
1.109     perry     316:                memset(&tp->t_winsize, 0, sizeof(tp->t_winsize));
1.50      mycroft   317:                tp->t_flags = 0;
1.49      cgd       318:        }
1.201     ad        319:        mutex_spin_exit(&tty_lock);
1.49      cgd       320:        return (0);
                    321: }
                    322:
                    323: /*
                    324:  * Handle close() on a tty line: flush and set to initial state,
                    325:  * bumping generation number so that pending read/write calls
                    326:  * can detect recycling of the tty.
                    327:  */
                    328: int
1.126     lukem     329: ttyclose(struct tty *tp)
1.49      cgd       330: {
                    331:        extern struct tty *constty;     /* Temporary virtual console. */
1.201     ad        332:        struct session *sess;
1.147     pk        333:
1.201     ad        334:        mutex_spin_enter(&tty_lock);
1.49      cgd       335:
                    336:        if (constty == tp)
                    337:                constty = NULL;
                    338:
                    339:        ttyflush(tp, FREAD | FWRITE);
                    340:
                    341:        tp->t_gen++;
                    342:        tp->t_pgrp = NULL;
1.190     ad        343:        tp->t_state = 0;
1.209     ad        344:        sess = tp->t_session;
                    345:        tp->t_session = NULL;
1.190     ad        346:
1.201     ad        347:        mutex_spin_exit(&tty_lock);
1.190     ad        348:
1.221.2.2  yamt      349:        if (sess != NULL) {
                    350:                mutex_enter(proc_lock);
                    351:                /* Releases proc_lock. */
                    352:                proc_sessrele(sess);
                    353:        }
1.49      cgd       354:        return (0);
                    355: }
                    356:
                    357: #define        FLUSHQ(q) {                                                     \
                    358:        if ((q)->c_cc)                                                  \
                    359:                ndflush(q, (q)->c_cc);                                  \
                    360: }
                    361:
1.88      kleink    362: /*
                    363:  * This macro is used in canonical mode input processing, where a read
                    364:  * request shall not return unless a 'line delimiter' ('\n') or 'break'
                    365:  * (EOF, EOL, EOL2) character (or a signal) has been received. As EOL2
                    366:  * is an extension to the POSIX.1 defined set of special characters,
                    367:  * recognize it only if IEXTEN is set in the set of local flags.
                    368:  */
1.85      kleink    369: #define        TTBREAKC(c, lflg)                                               \
1.87      cgd       370:        ((c) == '\n' || (((c) == cc[VEOF] || (c) == cc[VEOL] ||         \
1.85      kleink    371:        ((c) == cc[VEOL2] && ISSET(lflg, IEXTEN))) && (c) != _POSIX_VDISABLE))
1.49      cgd       372:
                    373:
1.147     pk        374:
1.49      cgd       375: /*
1.147     pk        376:  * ttyinput() helper.
1.201     ad        377:  * Call with the tty lock held.
1.49      cgd       378:  */
1.221.2.2  yamt      379: /* XXX static */ int
1.147     pk        380: ttyinput_wlock(int c, struct tty *tp)
1.49      cgd       381: {
1.126     lukem     382:        int     iflag, lflag, i, error;
                    383:        u_char  *cc;
1.78      christos  384:
1.201     ad        385:        KASSERT(mutex_owned(&tty_lock));
                    386:
1.78      christos  387:        /*
1.49      cgd       388:         * If input is pending take it first.
                    389:         */
                    390:        lflag = tp->t_lflag;
                    391:        if (ISSET(lflag, PENDIN))
                    392:                ttypend(tp);
                    393:        /*
                    394:         * Gather stats.
                    395:         */
                    396:        if (ISSET(lflag, ICANON)) {
                    397:                ++tk_cancc;
                    398:                ++tp->t_cancc;
                    399:        } else {
                    400:                ++tk_rawcc;
                    401:                ++tp->t_rawcc;
                    402:        }
                    403:        ++tk_nin;
                    404:
                    405:        cc = tp->t_cc;
1.94      kleink    406:
                    407:        /*
                    408:         * Handle exceptional conditions (break, parity, framing).
                    409:         */
1.49      cgd       410:        iflag = tp->t_iflag;
1.65      christos  411:        if ((error = (ISSET(c, TTY_ERRORMASK))) != 0) {
1.49      cgd       412:                CLR(c, TTY_ERRORMASK);
1.94      kleink    413:                if (ISSET(error, TTY_FE) && c == 0) {           /* Break. */
1.49      cgd       414:                        if (ISSET(iflag, IGNBRK))
1.94      kleink    415:                                return (0);
                    416:                        else if (ISSET(iflag, BRKINT)) {
                    417:                                ttyflush(tp, FREAD | FWRITE);
1.201     ad        418:                                ttysig(tp, TTYSIG_PG1, SIGINT);
1.94      kleink    419:                                return (0);
1.138     enami     420:                        } else if (ISSET(iflag, PARMRK))
1.49      cgd       421:                                goto parmrk;
1.138     enami     422:                } else if ((ISSET(error, TTY_PE) && ISSET(iflag, INPCK)) ||
1.94      kleink    423:                    ISSET(error, TTY_FE)) {
1.49      cgd       424:                        if (ISSET(iflag, IGNPAR))
1.94      kleink    425:                                return (0);
1.49      cgd       426:                        else if (ISSET(iflag, PARMRK)) {
1.126     lukem     427:  parmrk:                       (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
1.94      kleink    428:                                (void)putc(0    | TTY_QUOTE, &tp->t_rawq);
                    429:                                (void)putc(c    | TTY_QUOTE, &tp->t_rawq);
                    430:                                return (0);
1.138     enami     431:                        } else
1.49      cgd       432:                                c = 0;
                    433:                }
1.138     enami     434:        } else if (c == 0377 &&
1.94      kleink    435:            ISSET(iflag, ISTRIP|IGNPAR|INPCK|PARMRK) == (INPCK|PARMRK)) {
                    436:                /* "Escape" a valid character of '\377'. */
                    437:                (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
                    438:                (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
                    439:                goto endcase;
                    440:        }
                    441:
1.49      cgd       442:        /*
                    443:         * In tandem mode, check high water mark.
                    444:         */
                    445:        if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CHWFLOW))
                    446:                ttyblock(tp);
                    447:        if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
                    448:                CLR(c, 0x80);
                    449:        if (!ISSET(lflag, EXTPROC)) {
                    450:                /*
                    451:                 * Check for literal nexting very first
                    452:                 */
                    453:                if (ISSET(tp->t_state, TS_LNCH)) {
                    454:                        SET(c, TTY_QUOTE);
                    455:                        CLR(tp->t_state, TS_LNCH);
                    456:                }
                    457:                /*
                    458:                 * Scan for special characters.  This code
                    459:                 * is really just a big case statement with
                    460:                 * non-constant cases.  The bottom of the
                    461:                 * case statement is labeled ``endcase'', so goto
                    462:                 * it after a case match, or similar.
                    463:                 */
                    464:
                    465:                /*
                    466:                 * Control chars which aren't controlled
                    467:                 * by ICANON, ISIG, or IXON.
                    468:                 */
                    469:                if (ISSET(lflag, IEXTEN)) {
                    470:                        if (CCEQ(cc[VLNEXT], c)) {
                    471:                                if (ISSET(lflag, ECHO)) {
                    472:                                        if (ISSET(lflag, ECHOE)) {
                    473:                                                (void)ttyoutput('^', tp);
                    474:                                                (void)ttyoutput('\b', tp);
                    475:                                        } else
                    476:                                                ttyecho(c, tp);
                    477:                                }
                    478:                                SET(tp->t_state, TS_LNCH);
                    479:                                goto endcase;
                    480:                        }
                    481:                        if (CCEQ(cc[VDISCARD], c)) {
                    482:                                if (ISSET(lflag, FLUSHO))
                    483:                                        CLR(tp->t_lflag, FLUSHO);
                    484:                                else {
                    485:                                        ttyflush(tp, FWRITE);
                    486:                                        ttyecho(c, tp);
                    487:                                        if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
                    488:                                                ttyretype(tp);
                    489:                                        SET(tp->t_lflag, FLUSHO);
                    490:                                }
                    491:                                goto startoutput;
                    492:                        }
                    493:                }
                    494:                /*
                    495:                 * Signals.
                    496:                 */
                    497:                if (ISSET(lflag, ISIG)) {
                    498:                        if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
                    499:                                if (!ISSET(lflag, NOFLSH))
                    500:                                        ttyflush(tp, FREAD | FWRITE);
                    501:                                ttyecho(c, tp);
1.201     ad        502:                                ttysig(tp, TTYSIG_PG1, CCEQ(cc[VINTR], c) ?
                    503:                                    SIGINT : SIGQUIT);
1.49      cgd       504:                                goto endcase;
                    505:                        }
                    506:                        if (CCEQ(cc[VSUSP], c)) {
                    507:                                if (!ISSET(lflag, NOFLSH))
                    508:                                        ttyflush(tp, FREAD);
                    509:                                ttyecho(c, tp);
1.201     ad        510:                                ttysig(tp, TTYSIG_PG1, SIGTSTP);
1.49      cgd       511:                                goto endcase;
                    512:                        }
                    513:                }
                    514:                /*
                    515:                 * Handle start/stop characters.
                    516:                 */
                    517:                if (ISSET(iflag, IXON)) {
                    518:                        if (CCEQ(cc[VSTOP], c)) {
                    519:                                if (!ISSET(tp->t_state, TS_TTSTOP)) {
                    520:                                        SET(tp->t_state, TS_TTSTOP);
1.201     ad        521:                                        cdev_stop(tp, 0);
1.49      cgd       522:                                        return (0);
                    523:                                }
                    524:                                if (!CCEQ(cc[VSTART], c))
                    525:                                        return (0);
                    526:                                /*
                    527:                                 * if VSTART == VSTOP then toggle
                    528:                                 */
                    529:                                goto endcase;
                    530:                        }
                    531:                        if (CCEQ(cc[VSTART], c))
                    532:                                goto restartoutput;
                    533:                }
                    534:                /*
                    535:                 * IGNCR, ICRNL, & INLCR
                    536:                 */
                    537:                if (c == '\r') {
                    538:                        if (ISSET(iflag, IGNCR))
                    539:                                goto endcase;
                    540:                        else if (ISSET(iflag, ICRNL))
                    541:                                c = '\n';
                    542:                } else if (c == '\n' && ISSET(iflag, INLCR))
                    543:                        c = '\r';
                    544:        }
1.147     pk        545:        if (!ISSET(lflag, EXTPROC) && ISSET(lflag, ICANON)) {
1.49      cgd       546:                /*
                    547:                 * From here on down canonical mode character
                    548:                 * processing takes place.
                    549:                 */
                    550:                /*
                    551:                 * erase (^H / ^?)
                    552:                 */
                    553:                if (CCEQ(cc[VERASE], c)) {
                    554:                        if (tp->t_rawq.c_cc)
                    555:                                ttyrub(unputc(&tp->t_rawq), tp);
                    556:                        goto endcase;
                    557:                }
                    558:                /*
                    559:                 * kill (^U)
                    560:                 */
                    561:                if (CCEQ(cc[VKILL], c)) {
                    562:                        if (ISSET(lflag, ECHOKE) &&
                    563:                            tp->t_rawq.c_cc == tp->t_rocount &&
                    564:                            !ISSET(lflag, ECHOPRT))
                    565:                                while (tp->t_rawq.c_cc)
                    566:                                        ttyrub(unputc(&tp->t_rawq), tp);
                    567:                        else {
                    568:                                ttyecho(c, tp);
                    569:                                if (ISSET(lflag, ECHOK) ||
                    570:                                    ISSET(lflag, ECHOKE))
                    571:                                        ttyecho('\n', tp);
                    572:                                FLUSHQ(&tp->t_rawq);
                    573:                                tp->t_rocount = 0;
                    574:                        }
                    575:                        CLR(tp->t_state, TS_LOCAL);
                    576:                        goto endcase;
                    577:                }
                    578:                /*
1.81      kleink    579:                 * Extensions to the POSIX.1 GTI set of functions.
1.49      cgd       580:                 */
1.81      kleink    581:                if (ISSET(lflag, IEXTEN)) {
1.49      cgd       582:                        /*
1.81      kleink    583:                         * word erase (^W)
1.49      cgd       584:                         */
1.81      kleink    585:                        if (CCEQ(cc[VWERASE], c)) {
                    586:                                int alt = ISSET(lflag, ALTWERASE);
                    587:                                int ctype;
                    588:
                    589:                                /*
                    590:                                 * erase whitespace
                    591:                                 */
                    592:                                while ((c = unputc(&tp->t_rawq)) == ' ' ||
1.138     enami     593:                                    c == '\t')
1.81      kleink    594:                                        ttyrub(c, tp);
                    595:                                if (c == -1)
                    596:                                        goto endcase;
                    597:                                /*
                    598:                                 * erase last char of word and remember the
                    599:                                 * next chars type (for ALTWERASE)
                    600:                                 */
1.49      cgd       601:                                ttyrub(c, tp);
1.81      kleink    602:                                c = unputc(&tp->t_rawq);
                    603:                                if (c == -1)
                    604:                                        goto endcase;
                    605:                                if (c == ' ' || c == '\t') {
                    606:                                        (void)putc(c, &tp->t_rawq);
                    607:                                        goto endcase;
                    608:                                }
                    609:                                ctype = ISALPHA(c);
                    610:                                /*
                    611:                                 * erase rest of word
                    612:                                 */
                    613:                                do {
                    614:                                        ttyrub(c, tp);
                    615:                                        c = unputc(&tp->t_rawq);
                    616:                                        if (c == -1)
                    617:                                                goto endcase;
                    618:                                } while (c != ' ' && c != '\t' &&
1.138     enami     619:                                    (alt == 0 || ISALPHA(c) == ctype));
1.81      kleink    620:                                (void)putc(c, &tp->t_rawq);
1.49      cgd       621:                                goto endcase;
1.81      kleink    622:                        }
1.49      cgd       623:                        /*
1.81      kleink    624:                         * reprint line (^R)
1.49      cgd       625:                         */
1.81      kleink    626:                        if (CCEQ(cc[VREPRINT], c)) {
                    627:                                ttyretype(tp);
1.49      cgd       628:                                goto endcase;
                    629:                        }
                    630:                        /*
1.81      kleink    631:                         * ^T - kernel info and generate SIGINFO
1.49      cgd       632:                         */
1.81      kleink    633:                        if (CCEQ(cc[VSTATUS], c)) {
1.215     ad        634:                                ttysig(tp, TTYSIG_PG1, SIGINFO);
1.81      kleink    635:                                goto endcase;
                    636:                        }
1.49      cgd       637:                }
                    638:        }
                    639:        /*
                    640:         * Check for input buffer overflow
                    641:         */
                    642:        if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
                    643:                if (ISSET(iflag, IMAXBEL)) {
                    644:                        if (tp->t_outq.c_cc < tp->t_hiwat)
                    645:                                (void)ttyoutput(CTRL('g'), tp);
                    646:                } else
                    647:                        ttyflush(tp, FREAD | FWRITE);
                    648:                goto endcase;
                    649:        }
                    650:        /*
                    651:         * Put data char in q for user and
                    652:         * wakeup on seeing a line delimiter.
                    653:         */
                    654:        if (putc(c, &tp->t_rawq) >= 0) {
                    655:                if (!ISSET(lflag, ICANON)) {
                    656:                        ttwakeup(tp);
                    657:                        ttyecho(c, tp);
                    658:                        goto endcase;
                    659:                }
1.85      kleink    660:                if (TTBREAKC(c, lflag)) {
1.49      cgd       661:                        tp->t_rocount = 0;
                    662:                        catq(&tp->t_rawq, &tp->t_canq);
                    663:                        ttwakeup(tp);
                    664:                } else if (tp->t_rocount++ == 0)
                    665:                        tp->t_rocol = tp->t_column;
                    666:                if (ISSET(tp->t_state, TS_ERASE)) {
                    667:                        /*
                    668:                         * end of prterase \.../
                    669:                         */
                    670:                        CLR(tp->t_state, TS_ERASE);
                    671:                        (void)ttyoutput('/', tp);
                    672:                }
                    673:                i = tp->t_column;
                    674:                ttyecho(c, tp);
                    675:                if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
                    676:                        /*
                    677:                         * Place the cursor over the '^' of the ^D.
                    678:                         */
                    679:                        i = min(2, tp->t_column - i);
                    680:                        while (i > 0) {
                    681:                                (void)ttyoutput('\b', tp);
                    682:                                i--;
                    683:                        }
                    684:                }
                    685:        }
1.126     lukem     686:  endcase:
1.49      cgd       687:        /*
                    688:         * IXANY means allow any character to restart output.
                    689:         */
                    690:        if (ISSET(tp->t_state, TS_TTSTOP) &&
1.147     pk        691:            !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
1.49      cgd       692:                return (0);
1.147     pk        693:        }
1.126     lukem     694:  restartoutput:
1.49      cgd       695:        CLR(tp->t_lflag, FLUSHO);
                    696:        CLR(tp->t_state, TS_TTSTOP);
1.126     lukem     697:  startoutput:
1.49      cgd       698:        return (ttstart(tp));
                    699: }
                    700:
                    701: /*
1.147     pk        702:  * Process input of a single character received on a tty.
                    703:  *
                    704:  * XXX - this is a hack, all drivers must changed to acquire the
                    705:  *      lock before calling linesw->l_rint()
                    706:  */
                    707: int
                    708: ttyinput(int c, struct tty *tp)
                    709: {
                    710:        int error;
                    711:
                    712:        /*
                    713:         * Unless the receiver is enabled, drop incoming data.
                    714:         */
                    715:        if (!ISSET(tp->t_cflag, CREAD))
                    716:                return (0);
                    717:
1.201     ad        718:        mutex_spin_enter(&tty_lock);
1.147     pk        719:        error = ttyinput_wlock(c, tp);
1.201     ad        720:        mutex_spin_exit(&tty_lock);
                    721:
1.147     pk        722:        return (error);
                    723: }
                    724:
                    725: /*
1.49      cgd       726:  * Output a single character on a tty, doing output processing
                    727:  * as needed (expanding tabs, newline processing, etc.).
                    728:  * Returns < 0 if succeeds, otherwise returns char to resend.
                    729:  * Must be recursive.
1.201     ad        730:  *
                    731:  * Call with tty lock held.
1.49      cgd       732:  */
                    733: int
1.126     lukem     734: ttyoutput(int c, struct tty *tp)
1.49      cgd       735: {
1.126     lukem     736:        long    oflag;
1.201     ad        737:        int     col, notout;
                    738:
                    739:        KASSERT(mutex_owned(&tty_lock));
1.49      cgd       740:
                    741:        oflag = tp->t_oflag;
                    742:        if (!ISSET(oflag, OPOST)) {
                    743:                tk_nout++;
                    744:                tp->t_outcc++;
1.99      mycroft   745:                if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
                    746:                        return (c);
1.49      cgd       747:                return (-1);
                    748:        }
                    749:        /*
1.103     kleink    750:         * Do tab expansion if OXTABS is set.  Special case if we do external
1.49      cgd       751:         * processing, we don't do the tab expansion because we'll probably
                    752:         * get it wrong.  If tab expansion needs to be done, let it happen
                    753:         * externally.
                    754:         */
                    755:        CLR(c, ~TTY_CHARMASK);
                    756:        if (c == '\t' &&
                    757:            ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
                    758:                c = 8 - (tp->t_column & 7);
                    759:                if (ISSET(tp->t_lflag, FLUSHO)) {
                    760:                        notout = 0;
                    761:                } else {
                    762:                        notout = b_to_q("        ", c, &tp->t_outq);
                    763:                        c -= notout;
                    764:                        tk_nout += c;
                    765:                        tp->t_outcc += c;
                    766:                }
                    767:                tp->t_column += c;
                    768:                return (notout ? '\t' : -1);
                    769:        }
                    770:        if (c == CEOT && ISSET(oflag, ONOEOT))
                    771:                return (-1);
                    772:
                    773:        /*
                    774:         * Newline translation: if ONLCR is set,
                    775:         * translate newline into "\r\n".
                    776:         */
                    777:        if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
                    778:                tk_nout++;
                    779:                tp->t_outcc++;
1.99      mycroft   780:                if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq))
1.49      cgd       781:                        return (c);
                    782:        }
1.103     kleink    783:        /* If OCRNL is set, translate "\r" into "\n". */
1.79      kleink    784:        else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
                    785:                c = '\n';
1.103     kleink    786:        /* If ONOCR is set, don't transmit CRs when on column 0. */
                    787:        else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0)
                    788:                return (-1);
1.79      kleink    789:
1.49      cgd       790:        tk_nout++;
                    791:        tp->t_outcc++;
                    792:        if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
                    793:                return (c);
                    794:
                    795:        col = tp->t_column;
                    796:        switch (CCLASS(c)) {
                    797:        case BACKSPACE:
                    798:                if (col > 0)
                    799:                        --col;
                    800:                break;
                    801:        case CONTROL:
                    802:                break;
                    803:        case NEWLINE:
1.103     kleink    804:                if (ISSET(tp->t_oflag, ONLCR | ONLRET))
1.79      kleink    805:                        col = 0;
                    806:                break;
1.49      cgd       807:        case RETURN:
                    808:                col = 0;
                    809:                break;
                    810:        case ORDINARY:
                    811:                ++col;
                    812:                break;
                    813:        case TAB:
                    814:                col = (col + 8) & ~7;
                    815:                break;
                    816:        }
                    817:        tp->t_column = col;
                    818:        return (-1);
                    819: }
                    820:
                    821: /*
                    822:  * Ioctls for all tty devices.  Called after line-discipline specific ioctl
                    823:  * has been called to do discipline-specific functions and/or reject any
                    824:  * of these ioctl commands.
                    825:  */
                    826: /* ARGSUSED */
                    827: int
1.192     christos  828: ttioctl(struct tty *tp, u_long cmd, void *data, int flag, struct lwp *l)
1.49      cgd       829: {
                    830:        extern struct tty *constty;     /* Temporary virtual console. */
1.188     martin    831:        struct proc *p = l ? l->l_proc : NULL;
1.126     lukem     832:        struct linesw   *lp;
                    833:        int             s, error;
1.151     christos  834:        struct nameidata nd;
1.215     ad        835:        char            infobuf[200];
1.49      cgd       836:
                    837:        /* If the ioctl involves modification, hang if in the background. */
                    838:        switch (cmd) {
                    839:        case  TIOCFLUSH:
1.92      kleink    840:        case  TIOCDRAIN:
1.95      kleink    841:        case  TIOCSBRK:
                    842:        case  TIOCCBRK:
                    843:        case  TIOCSTART:
1.49      cgd       844:        case  TIOCSETA:
                    845:        case  TIOCSETD:
1.121     eeh       846:        case  TIOCSLINED:
1.49      cgd       847:        case  TIOCSETAF:
                    848:        case  TIOCSETAW:
                    849: #ifdef notdef
                    850:        case  TIOCSPGRP:
1.158     jdolecek  851:        case  FIOSETOWN:
1.49      cgd       852: #endif
                    853:        case  TIOCSTAT:
                    854:        case  TIOCSTI:
                    855:        case  TIOCSWINSZ:
                    856:        case  TIOCLBIC:
                    857:        case  TIOCLBIS:
                    858:        case  TIOCLSET:
                    859:        case  TIOCSETC:
                    860:        case OTIOCSETD:
                    861:        case  TIOCSETN:
                    862:        case  TIOCSETP:
                    863:        case  TIOCSLTC:
1.209     ad        864:                mutex_spin_enter(&tty_lock);
1.49      cgd       865:                while (isbackground(curproc, tp) &&
1.221.2.2  yamt      866:                    p->p_pgrp->pg_jobc && (p->p_lflag & PL_PPWAIT) == 0 &&
1.190     ad        867:                    !sigismasked(l, SIGTTOU)) {
1.210     ad        868:                        mutex_spin_exit(&tty_lock);
                    869:
1.220     ad        870:                        mutex_enter(proc_lock);
1.210     ad        871:                        pgsignal(p->p_pgrp, SIGTTOU, 1);
1.220     ad        872:                        mutex_exit(proc_lock);
1.210     ad        873:
                    874:                        mutex_spin_enter(&tty_lock);
1.201     ad        875:                        error = ttysleep(tp, &lbolt, true, 0);
1.147     pk        876:                        if (error) {
1.209     ad        877:                                mutex_spin_exit(&tty_lock);
1.49      cgd       878:                                return (error);
1.147     pk        879:                        }
1.49      cgd       880:                }
1.209     ad        881:                mutex_spin_exit(&tty_lock);
1.49      cgd       882:                break;
                    883:        }
                    884:
                    885:        switch (cmd) {                  /* Process the ioctl. */
                    886:        case FIOASYNC:                  /* set/clear async i/o */
1.201     ad        887:                mutex_spin_enter(&tty_lock);
1.49      cgd       888:                if (*(int *)data)
                    889:                        SET(tp->t_state, TS_ASYNC);
                    890:                else
                    891:                        CLR(tp->t_state, TS_ASYNC);
1.201     ad        892:                mutex_spin_exit(&tty_lock);
1.49      cgd       893:                break;
                    894:        case FIONBIO:                   /* set/clear non-blocking i/o */
                    895:                break;                  /* XXX: delete. */
                    896:        case FIONREAD:                  /* get # bytes to read */
1.201     ad        897:                mutex_spin_enter(&tty_lock);
1.49      cgd       898:                *(int *)data = ttnread(tp);
1.201     ad        899:                mutex_spin_exit(&tty_lock);
1.49      cgd       900:                break;
1.170     wrstuden  901:        case FIONWRITE:                 /* get # bytes to written & unsent */
1.201     ad        902:                mutex_spin_enter(&tty_lock);
1.170     wrstuden  903:                *(int *)data = tp->t_outq.c_cc;
1.201     ad        904:                mutex_spin_exit(&tty_lock);
1.170     wrstuden  905:                break;
                    906:        case FIONSPACE:                 /* get # bytes to written & unsent */
1.201     ad        907:                mutex_spin_enter(&tty_lock);
1.170     wrstuden  908:                *(int *)data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1.201     ad        909:                mutex_spin_exit(&tty_lock);
1.170     wrstuden  910:                break;
1.49      cgd       911:        case TIOCEXCL:                  /* set exclusive use of tty */
1.201     ad        912:                mutex_spin_enter(&tty_lock);
1.49      cgd       913:                SET(tp->t_state, TS_XCLUDE);
1.201     ad        914:                mutex_spin_exit(&tty_lock);
1.49      cgd       915:                break;
                    916:        case TIOCFLUSH: {               /* flush buffers */
1.118     augustss  917:                int flags = *(int *)data;
1.49      cgd       918:
                    919:                if (flags == 0)
                    920:                        flags = FREAD | FWRITE;
                    921:                else
                    922:                        flags &= FREAD | FWRITE;
1.201     ad        923:                mutex_spin_enter(&tty_lock);
1.49      cgd       924:                ttyflush(tp, flags);
1.201     ad        925:                mutex_spin_exit(&tty_lock);
1.49      cgd       926:                break;
                    927:        }
                    928:        case TIOCCONS:                  /* become virtual console */
                    929:                if (*(int *)data) {
                    930:                        if (constty && constty != tp &&
                    931:                            ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
                    932:                            (TS_CARR_ON | TS_ISOPEN))
1.151     christos  933:                                return EBUSY;
                    934:
                    935:                        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
1.208     pooka     936:                            "/dev/console");
1.151     christos  937:                        if ((error = namei(&nd)) != 0)
                    938:                                return error;
1.206     pooka     939:                        error = VOP_ACCESS(nd.ni_vp, VREAD, l->l_cred);
1.151     christos  940:                        vput(nd.ni_vp);
                    941:                        if (error)
                    942:                                return error;
                    943:
1.49      cgd       944:                        constty = tp;
                    945:                } else if (tp == constty)
                    946:                        constty = NULL;
                    947:                break;
                    948:        case TIOCDRAIN:                 /* wait till output drained */
1.65      christos  949:                if ((error = ttywait(tp)) != 0)
1.49      cgd       950:                        return (error);
                    951:                break;
                    952:        case TIOCGETA: {                /* get termios struct */
                    953:                struct termios *t = (struct termios *)data;
                    954:
1.109     perry     955:                memcpy(t, &tp->t_termios, sizeof(struct termios));
1.49      cgd       956:                break;
                    957:        }
1.177     thorpej   958:        case TIOCGETD:                  /* get line discipline (old) */
1.127     enami     959:                *(int *)data = tp->t_linesw->l_no;
1.121     eeh       960:                break;
1.177     thorpej   961:        case TIOCGLINED:                /* get line discipline (new) */
1.138     enami     962:                (void)strncpy((char *)data, tp->t_linesw->l_name,
1.131     christos  963:                    TTLINEDNAMELEN - 1);
1.49      cgd       964:                break;
                    965:        case TIOCGWINSZ:                /* get window size */
                    966:                *(struct winsize *)data = tp->t_winsize;
                    967:                break;
1.158     jdolecek  968:        case FIOGETOWN:
1.220     ad        969:                mutex_enter(proc_lock);
                    970:                if (tp->t_session != NULL && !isctty(p, tp)) {
                    971:                        mutex_exit(proc_lock);
1.158     jdolecek  972:                        return (ENOTTY);
1.220     ad        973:                }
1.158     jdolecek  974:                *(int *)data = tp->t_pgrp ? -tp->t_pgrp->pg_id : 0;
1.220     ad        975:                mutex_exit(proc_lock);
1.158     jdolecek  976:                break;
1.49      cgd       977:        case TIOCGPGRP:                 /* get pgrp of tty */
1.220     ad        978:                mutex_enter(proc_lock);
                    979:                if (!isctty(p, tp)) {
                    980:                        mutex_exit(proc_lock);
1.49      cgd       981:                        return (ENOTTY);
1.220     ad        982:                }
1.150     dsl       983:                *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
1.220     ad        984:                mutex_exit(proc_lock);
1.104     thorpej   985:                break;
                    986:        case TIOCGSID:                  /* get sid of tty */
1.220     ad        987:                mutex_enter(proc_lock);
                    988:                if (!isctty(p, tp)) {
                    989:                        mutex_exit(proc_lock);
1.104     thorpej   990:                        return (ENOTTY);
1.220     ad        991:                }
1.104     thorpej   992:                *(int *)data = tp->t_session->s_sid;
1.220     ad        993:                mutex_exit(proc_lock);
1.49      cgd       994:                break;
                    995: #ifdef TIOCHPCL
                    996:        case TIOCHPCL:                  /* hang up on last close */
1.201     ad        997:                mutex_spin_enter(&tty_lock);
1.49      cgd       998:                SET(tp->t_cflag, HUPCL);
1.201     ad        999:                mutex_spin_exit(&tty_lock);
1.49      cgd      1000:                break;
                   1001: #endif
                   1002:        case TIOCNXCL:                  /* reset exclusive use of tty */
1.201     ad       1003:                mutex_spin_enter(&tty_lock);
1.49      cgd      1004:                CLR(tp->t_state, TS_XCLUDE);
1.201     ad       1005:                mutex_spin_exit(&tty_lock);
1.49      cgd      1006:                break;
                   1007:        case TIOCOUTQ:                  /* output queue size */
                   1008:                *(int *)data = tp->t_outq.c_cc;
                   1009:                break;
                   1010:        case TIOCSETA:                  /* set termios struct */
                   1011:        case TIOCSETAW:                 /* drain output, set */
                   1012:        case TIOCSETAF: {               /* drn out, fls in, set */
1.118     augustss 1013:                struct termios *t = (struct termios *)data;
1.49      cgd      1014:
                   1015:                if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1.147     pk       1016:                        if ((error = ttywait(tp)) != 0)
                   1017:                                return (error);
                   1018:
                   1019:                        if (cmd == TIOCSETAF) {
1.201     ad       1020:                                mutex_spin_enter(&tty_lock);
1.147     pk       1021:                                ttyflush(tp, FREAD);
1.201     ad       1022:                                mutex_spin_exit(&tty_lock);
1.49      cgd      1023:                        }
                   1024:                }
1.147     pk       1025:
                   1026:                s = spltty();
1.148     pk       1027:                /*
                   1028:                 * XXXSMP - some drivers call back on us from t_param(), so
                   1029:                 *          don't take the tty spin lock here.
                   1030:                 *          require t_param() to unlock upon callback?
                   1031:                 */
1.201     ad       1032:                /* wanted here: mutex_spin_enter(&tty_lock); */
1.49      cgd      1033:                if (!ISSET(t->c_cflag, CIGNORE)) {
                   1034:                        /*
                   1035:                         * Set device hardware.
                   1036:                         */
                   1037:                        if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1.201     ad       1038:                                /* wanted here: mutex_spin_exit(&tty_lock); */
1.49      cgd      1039:                                splx(s);
                   1040:                                return (error);
                   1041:                        } else {
                   1042:                                tp->t_cflag = t->c_cflag;
                   1043:                                tp->t_ispeed = t->c_ispeed;
                   1044:                                tp->t_ospeed = t->c_ospeed;
1.201     ad       1045:                                if (t->c_ospeed == 0)
                   1046:                                        ttysig(tp, TTYSIG_LEADER, SIGHUP);
1.49      cgd      1047:                        }
                   1048:                        ttsetwater(tp);
                   1049:                }
1.148     pk       1050:
1.201     ad       1051:                /* delayed lock acquiring */
                   1052:                mutex_spin_enter(&tty_lock);
1.49      cgd      1053:                if (cmd != TIOCSETAF) {
                   1054:                        if (ISSET(t->c_lflag, ICANON) !=
1.110     thorpej  1055:                            ISSET(tp->t_lflag, ICANON)) {
1.49      cgd      1056:                                if (ISSET(t->c_lflag, ICANON)) {
                   1057:                                        SET(tp->t_lflag, PENDIN);
                   1058:                                        ttwakeup(tp);
                   1059:                                } else {
                   1060:                                        struct clist tq;
                   1061:
                   1062:                                        catq(&tp->t_rawq, &tp->t_canq);
                   1063:                                        tq = tp->t_rawq;
                   1064:                                        tp->t_rawq = tp->t_canq;
                   1065:                                        tp->t_canq = tq;
                   1066:                                        CLR(tp->t_lflag, PENDIN);
                   1067:                                }
1.110     thorpej  1068:                        }
1.49      cgd      1069:                }
                   1070:                tp->t_iflag = t->c_iflag;
                   1071:                tp->t_oflag = t->c_oflag;
                   1072:                /*
                   1073:                 * Make the EXTPROC bit read only.
                   1074:                 */
                   1075:                if (ISSET(tp->t_lflag, EXTPROC))
                   1076:                        SET(t->c_lflag, EXTPROC);
                   1077:                else
                   1078:                        CLR(t->c_lflag, EXTPROC);
                   1079:                tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1.109     perry    1080:                memcpy(tp->t_cc, t->c_cc, sizeof(t->c_cc));
1.201     ad       1081:                mutex_spin_exit(&tty_lock);
1.49      cgd      1082:                splx(s);
                   1083:                break;
                   1084:        }
1.177     thorpej  1085:        case TIOCSETD:                  /* set line discipline (old) */
                   1086:                lp = ttyldisc_lookup_bynum(*(int *)data);
                   1087:                goto setldisc;
1.49      cgd      1088:
1.177     thorpej  1089:        case TIOCSLINED: {              /* set line discipline (new) */
1.121     eeh      1090:                char *name = (char *)data;
1.124     enami    1091:                dev_t device;
1.121     eeh      1092:
                   1093:                /* Null terminate to prevent buffer overflow */
1.138     enami    1094:                name[TTLINEDNAMELEN - 1] = '\0';
1.121     eeh      1095:                lp = ttyldisc_lookup(name);
1.126     lukem    1096:  setldisc:
1.124     enami    1097:                if (lp == NULL)
1.121     eeh      1098:                        return (ENXIO);
                   1099:
                   1100:                if (lp != tp->t_linesw) {
1.124     enami    1101:                        device = tp->t_dev;
1.49      cgd      1102:                        s = spltty();
1.124     enami    1103:                        (*tp->t_linesw->l_close)(tp, flag);
1.121     eeh      1104:                        error = (*lp->l_open)(device, tp);
1.49      cgd      1105:                        if (error) {
1.121     eeh      1106:                                (void)(*tp->t_linesw->l_open)(device, tp);
1.49      cgd      1107:                                splx(s);
1.177     thorpej  1108:                                ttyldisc_release(lp);
1.49      cgd      1109:                                return (error);
                   1110:                        }
1.177     thorpej  1111:                        ttyldisc_release(tp->t_linesw);
1.121     eeh      1112:                        tp->t_linesw = lp;
1.49      cgd      1113:                        splx(s);
1.177     thorpej  1114:                } else {
                   1115:                        /* Drop extra reference. */
                   1116:                        ttyldisc_release(lp);
1.49      cgd      1117:                }
                   1118:                break;
                   1119:        }
                   1120:        case TIOCSTART:                 /* start output, like ^Q */
1.201     ad       1121:                mutex_spin_enter(&tty_lock);
1.49      cgd      1122:                if (ISSET(tp->t_state, TS_TTSTOP) ||
                   1123:                    ISSET(tp->t_lflag, FLUSHO)) {
                   1124:                        CLR(tp->t_lflag, FLUSHO);
                   1125:                        CLR(tp->t_state, TS_TTSTOP);
                   1126:                        ttstart(tp);
                   1127:                }
1.201     ad       1128:                mutex_spin_exit(&tty_lock);
1.49      cgd      1129:                break;
                   1130:        case TIOCSTI:                   /* simulate terminal input */
1.212     elad     1131:                if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_STI,
                   1132:                    tp) != 0) {
1.189     elad     1133:                        if (!ISSET(flag, FREAD))
                   1134:                                return (EPERM);
                   1135:                        if (!isctty(p, tp))
                   1136:                                return (EACCES);
                   1137:                }
1.121     eeh      1138:                (*tp->t_linesw->l_rint)(*(u_char *)data, tp);
1.49      cgd      1139:                break;
                   1140:        case TIOCSTOP:                  /* stop output, like ^S */
1.142     gehenna  1141:        {
1.201     ad       1142:                mutex_spin_enter(&tty_lock);
1.49      cgd      1143:                if (!ISSET(tp->t_state, TS_TTSTOP)) {
                   1144:                        SET(tp->t_state, TS_TTSTOP);
1.201     ad       1145:                        cdev_stop(tp, 0);
1.49      cgd      1146:                }
1.201     ad       1147:                mutex_spin_exit(&tty_lock);
1.49      cgd      1148:                break;
1.142     gehenna  1149:        }
1.49      cgd      1150:        case TIOCSCTTY:                 /* become controlling tty */
1.220     ad       1151:                mutex_enter(proc_lock);
1.209     ad       1152:                mutex_spin_enter(&tty_lock);
1.190     ad       1153:
1.49      cgd      1154:                /* Session ctty vnode pointer set in vnode layer. */
                   1155:                if (!SESS_LEADER(p) ||
1.65      christos 1156:                    ((p->p_session->s_ttyvp || tp->t_session) &&
1.190     ad       1157:                    (tp->t_session != p->p_session))) {
1.209     ad       1158:                        mutex_spin_exit(&tty_lock);
1.220     ad       1159:                        mutex_exit(proc_lock);
1.49      cgd      1160:                        return (EPERM);
1.190     ad       1161:                }
1.139     jdolecek 1162:
1.160     pk       1163:                /*
                   1164:                 * `p_session' acquires a reference.
                   1165:                 * But note that if `t_session' is set at this point,
                   1166:                 * it must equal `p_session', in which case the session
                   1167:                 * already has the correct reference count.
                   1168:                 */
1.221.2.2  yamt     1169:                if (tp->t_session == NULL) {
                   1170:                        proc_sesshold(p->p_session);
                   1171:                }
1.49      cgd      1172:                tp->t_session = p->p_session;
                   1173:                tp->t_pgrp = p->p_pgrp;
                   1174:                p->p_session->s_ttyp = tp;
1.190     ad       1175:                p->p_lflag |= PL_CONTROLT;
1.209     ad       1176:                mutex_spin_exit(&tty_lock);
1.220     ad       1177:                mutex_exit(proc_lock);
1.49      cgd      1178:                break;
1.158     jdolecek 1179:        case FIOSETOWN: {               /* set pgrp of tty */
                   1180:                pid_t pgid = *(int *)data;
                   1181:                struct pgrp *pgrp;
                   1182:
1.220     ad       1183:                mutex_enter(proc_lock);
1.209     ad       1184:                if (tp->t_session != NULL && !isctty(p, tp)) {
1.220     ad       1185:                        mutex_exit(proc_lock);
1.158     jdolecek 1186:                        return (ENOTTY);
1.209     ad       1187:                }
1.191     dsl      1188:
                   1189:                if (pgid < 0) {
                   1190:                        pgrp = pg_find(-pgid, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
                   1191:                        if (pgrp == NULL)
                   1192:                                return (EINVAL);
                   1193:                } else {
                   1194:                        struct proc *p1;
                   1195:                        p1 = p_find(pgid, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
1.158     jdolecek 1196:                        if (!p1)
                   1197:                                return (ESRCH);
                   1198:                        pgrp = p1->p_pgrp;
                   1199:                }
                   1200:
1.191     dsl      1201:                if (pgrp->pg_session != p->p_session) {
1.220     ad       1202:                        mutex_exit(proc_lock);
1.158     jdolecek 1203:                        return (EPERM);
1.191     dsl      1204:                }
1.209     ad       1205:                mutex_spin_enter(&tty_lock);
1.158     jdolecek 1206:                tp->t_pgrp = pgrp;
1.209     ad       1207:                mutex_spin_exit(&tty_lock);
1.220     ad       1208:                mutex_exit(proc_lock);
1.158     jdolecek 1209:                break;
                   1210:        }
1.49      cgd      1211:        case TIOCSPGRP: {               /* set pgrp of tty */
1.191     dsl      1212:                struct pgrp *pgrp;
1.49      cgd      1213:
1.220     ad       1214:                mutex_enter(proc_lock);
1.209     ad       1215:                if (!isctty(p, tp)) {
1.220     ad       1216:                        mutex_exit(proc_lock);
1.49      cgd      1217:                        return (ENOTTY);
1.209     ad       1218:                }
1.191     dsl      1219:                pgrp = pg_find(*(int *)data, PFIND_LOCKED | PFIND_UNLOCK_FAIL);
                   1220:                if (pgrp == NULL)
1.93      kleink   1221:                        return (EINVAL);
1.191     dsl      1222:                if (pgrp->pg_session != p->p_session) {
1.220     ad       1223:                        mutex_exit(proc_lock);
1.49      cgd      1224:                        return (EPERM);
1.191     dsl      1225:                }
1.209     ad       1226:                mutex_spin_enter(&tty_lock);
1.49      cgd      1227:                tp->t_pgrp = pgrp;
1.209     ad       1228:                mutex_spin_exit(&tty_lock);
1.220     ad       1229:                mutex_exit(proc_lock);
1.49      cgd      1230:                break;
                   1231:        }
                   1232:        case TIOCSTAT:                  /* get load avg stats */
1.220     ad       1233:                mutex_enter(proc_lock);
1.215     ad       1234:                ttygetinfo(tp, 0, infobuf, sizeof(infobuf));
1.220     ad       1235:                mutex_exit(proc_lock);
1.215     ad       1236:
1.201     ad       1237:                mutex_spin_enter(&tty_lock);
1.215     ad       1238:                ttyputinfo(tp, infobuf);
1.201     ad       1239:                mutex_spin_exit(&tty_lock);
1.49      cgd      1240:                break;
                   1241:        case TIOCSWINSZ:                /* set window size */
1.201     ad       1242:                mutex_spin_enter(&tty_lock);
1.192     christos 1243:                if (memcmp((void *)&tp->t_winsize, data,
1.108     perry    1244:                    sizeof(struct winsize))) {
1.49      cgd      1245:                        tp->t_winsize = *(struct winsize *)data;
1.201     ad       1246:                        ttysig(tp, TTYSIG_PG1, SIGWINCH);
1.49      cgd      1247:                }
1.201     ad       1248:                mutex_spin_exit(&tty_lock);
1.49      cgd      1249:                break;
                   1250:        default:
1.221.2.2  yamt     1251:                /* We may have to load the compat module for this. */
                   1252:                for (;;) {
                   1253:                        rw_enter(&ttcompat_lock, RW_READER);
                   1254:                        if (ttcompatvec != NULL) {
                   1255:                                break;
                   1256:                        }
                   1257:                        rw_exit(&ttcompat_lock);
                   1258:                        mutex_enter(&module_lock);
                   1259:                        (void)module_autoload("compat", MODULE_CLASS_ANY);
                   1260:                        if (ttcompatvec == NULL) {
                   1261:                                mutex_exit(&module_lock);
                   1262:                                return EPASSTHROUGH;
                   1263:                        }
                   1264:                        mutex_exit(&module_lock);
                   1265:                }
                   1266:                error = (*ttcompatvec)(tp, cmd, data, flag, l);
                   1267:                rw_exit(&ttcompat_lock);
                   1268:                return error;
1.49      cgd      1269:        }
                   1270:        return (0);
                   1271: }
                   1272:
                   1273: int
1.178     christos 1274: ttpoll(struct tty *tp, int events, struct lwp *l)
1.126     lukem    1275: {
1.201     ad       1276:        int     revents;
1.74      mycroft  1277:
1.126     lukem    1278:        revents = 0;
1.201     ad       1279:        mutex_spin_enter(&tty_lock);
1.74      mycroft  1280:        if (events & (POLLIN | POLLRDNORM))
                   1281:                if (ttnread(tp) > 0)
                   1282:                        revents |= events & (POLLIN | POLLRDNORM);
                   1283:
                   1284:        if (events & (POLLOUT | POLLWRNORM))
                   1285:                if (tp->t_outq.c_cc <= tp->t_lowat)
                   1286:                        revents |= events & (POLLOUT | POLLWRNORM);
                   1287:
                   1288:        if (events & POLLHUP)
1.83      mycroft  1289:                if (!CONNECTED(tp))
1.74      mycroft  1290:                        revents |= POLLHUP;
                   1291:
                   1292:        if (revents == 0) {
                   1293:                if (events & (POLLIN | POLLHUP | POLLRDNORM))
1.178     christos 1294:                        selrecord(l, &tp->t_rsel);
1.49      cgd      1295:
1.74      mycroft  1296:                if (events & (POLLOUT | POLLWRNORM))
1.178     christos 1297:                        selrecord(l, &tp->t_wsel);
1.74      mycroft  1298:        }
1.49      cgd      1299:
1.201     ad       1300:        mutex_spin_exit(&tty_lock);
                   1301:
1.74      mycroft  1302:        return (revents);
1.49      cgd      1303: }
                   1304:
1.143     jdolecek 1305: static void
                   1306: filt_ttyrdetach(struct knote *kn)
                   1307: {
                   1308:        struct tty      *tp;
                   1309:
                   1310:        tp = kn->kn_hook;
1.201     ad       1311:        mutex_spin_enter(&tty_lock);
1.144     christos 1312:        SLIST_REMOVE(&tp->t_rsel.sel_klist, kn, knote, kn_selnext);
1.201     ad       1313:        mutex_spin_exit(&tty_lock);
1.143     jdolecek 1314: }
                   1315:
                   1316: static int
                   1317: filt_ttyread(struct knote *kn, long hint)
                   1318: {
                   1319:        struct tty      *tp;
                   1320:
                   1321:        tp = kn->kn_hook;
1.162     jdolecek 1322:        if ((hint & NOTE_SUBMIT) == 0)
1.201     ad       1323:                mutex_spin_enter(&tty_lock);
1.143     jdolecek 1324:        kn->kn_data = ttnread(tp);
1.162     jdolecek 1325:        if ((hint & NOTE_SUBMIT) == 0)
1.201     ad       1326:                mutex_spin_exit(&tty_lock);
1.143     jdolecek 1327:        return (kn->kn_data > 0);
                   1328: }
                   1329:
                   1330: static void
                   1331: filt_ttywdetach(struct knote *kn)
                   1332: {
                   1333:        struct tty      *tp;
                   1334:
                   1335:        tp = kn->kn_hook;
1.201     ad       1336:        mutex_spin_enter(&tty_lock);
1.144     christos 1337:        SLIST_REMOVE(&tp->t_wsel.sel_klist, kn, knote, kn_selnext);
1.201     ad       1338:        mutex_spin_exit(&tty_lock);
1.143     jdolecek 1339: }
                   1340:
                   1341: static int
                   1342: filt_ttywrite(struct knote *kn, long hint)
                   1343: {
                   1344:        struct tty      *tp;
1.201     ad       1345:        int             canwrite;
1.143     jdolecek 1346:
                   1347:        tp = kn->kn_hook;
1.162     jdolecek 1348:        if ((hint & NOTE_SUBMIT) == 0)
1.201     ad       1349:                mutex_spin_enter(&tty_lock);
1.143     jdolecek 1350:        kn->kn_data = tp->t_outq.c_cn - tp->t_outq.c_cc;
1.147     pk       1351:        canwrite = (tp->t_outq.c_cc <= tp->t_lowat) && CONNECTED(tp);
1.162     jdolecek 1352:        if ((hint & NOTE_SUBMIT) == 0)
1.201     ad       1353:                mutex_spin_exit(&tty_lock);
1.147     pk       1354:        return (canwrite);
1.143     jdolecek 1355: }
                   1356:
                   1357: static const struct filterops ttyread_filtops =
                   1358:        { 1, NULL, filt_ttyrdetach, filt_ttyread };
                   1359: static const struct filterops ttywrite_filtops =
                   1360:        { 1, NULL, filt_ttywdetach, filt_ttywrite };
                   1361:
                   1362: int
                   1363: ttykqfilter(dev_t dev, struct knote *kn)
                   1364: {
                   1365:        struct tty      *tp;
                   1366:        struct klist    *klist;
                   1367:
1.201     ad       1368:        if ((tp = cdev_tty(dev)) == NULL)
1.143     jdolecek 1369:                return (ENXIO);
1.157     manu     1370:
1.143     jdolecek 1371:        switch (kn->kn_filter) {
                   1372:        case EVFILT_READ:
1.144     christos 1373:                klist = &tp->t_rsel.sel_klist;
1.143     jdolecek 1374:                kn->kn_fop = &ttyread_filtops;
                   1375:                break;
                   1376:        case EVFILT_WRITE:
1.144     christos 1377:                klist = &tp->t_wsel.sel_klist;
1.143     jdolecek 1378:                kn->kn_fop = &ttywrite_filtops;
                   1379:                break;
                   1380:        default:
1.176     christos 1381:                return EINVAL;
1.143     jdolecek 1382:        }
                   1383:
                   1384:        kn->kn_hook = tp;
                   1385:
1.201     ad       1386:        mutex_spin_enter(&tty_lock);
1.143     jdolecek 1387:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1.201     ad       1388:        mutex_spin_exit(&tty_lock);
1.143     jdolecek 1389:
                   1390:        return (0);
                   1391: }
                   1392:
1.147     pk       1393: /*
                   1394:  * Find the number of chars ready to be read from this tty.
1.201     ad       1395:  * Call with the tty lock held.
1.147     pk       1396:  */
1.49      cgd      1397: static int
1.126     lukem    1398: ttnread(struct tty *tp)
1.49      cgd      1399: {
1.126     lukem    1400:        int     nread;
1.49      cgd      1401:
1.201     ad       1402:        KASSERT(mutex_owned(&tty_lock));
                   1403:
1.49      cgd      1404:        if (ISSET(tp->t_lflag, PENDIN))
                   1405:                ttypend(tp);
                   1406:        nread = tp->t_canq.c_cc;
                   1407:        if (!ISSET(tp->t_lflag, ICANON)) {
                   1408:                nread += tp->t_rawq.c_cc;
                   1409:                if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
                   1410:                        nread = 0;
                   1411:        }
                   1412:        return (nread);
                   1413: }
                   1414:
                   1415: /*
                   1416:  * Wait for output to drain.
                   1417:  */
                   1418: int
1.138     enami    1419: ttywait(struct tty *tp)
1.49      cgd      1420: {
1.201     ad       1421:        int     error;
1.49      cgd      1422:
                   1423:        error = 0;
1.201     ad       1424:
                   1425:        mutex_spin_enter(&tty_lock);
1.49      cgd      1426:        while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1.83      mycroft  1427:            CONNECTED(tp) && tp->t_oproc) {
1.49      cgd      1428:                (*tp->t_oproc)(tp);
1.221.2.2  yamt     1429:                error = ttysleep(tp, &tp->t_outcv, true, 0);
1.65      christos 1430:                if (error)
1.49      cgd      1431:                        break;
                   1432:        }
1.201     ad       1433:        mutex_spin_exit(&tty_lock);
                   1434:
1.49      cgd      1435:        return (error);
                   1436: }
                   1437:
                   1438: /*
                   1439:  * Flush if successfully wait.
                   1440:  */
                   1441: int
1.126     lukem    1442: ttywflush(struct tty *tp)
1.49      cgd      1443: {
1.126     lukem    1444:        int     error;
1.49      cgd      1445:
1.147     pk       1446:        if ((error = ttywait(tp)) == 0) {
1.201     ad       1447:                mutex_spin_enter(&tty_lock);
1.49      cgd      1448:                ttyflush(tp, FREAD);
1.201     ad       1449:                mutex_spin_exit(&tty_lock);
1.147     pk       1450:        }
1.49      cgd      1451:        return (error);
                   1452: }
                   1453:
                   1454: /*
                   1455:  * Flush tty read and/or write queues, notifying anyone waiting.
1.201     ad       1456:  * Call with the tty lock held.
1.49      cgd      1457:  */
                   1458: void
1.126     lukem    1459: ttyflush(struct tty *tp, int rw)
1.49      cgd      1460: {
1.201     ad       1461:
                   1462:        KASSERT(mutex_owned(&tty_lock));
1.49      cgd      1463:
                   1464:        if (rw & FREAD) {
                   1465:                FLUSHQ(&tp->t_canq);
                   1466:                FLUSHQ(&tp->t_rawq);
                   1467:                tp->t_rocount = 0;
                   1468:                tp->t_rocol = 0;
                   1469:                CLR(tp->t_state, TS_LOCAL);
                   1470:                ttwakeup(tp);
                   1471:        }
                   1472:        if (rw & FWRITE) {
                   1473:                CLR(tp->t_state, TS_TTSTOP);
1.201     ad       1474:                cdev_stop(tp, rw);
1.49      cgd      1475:                FLUSHQ(&tp->t_outq);
1.221.2.2  yamt     1476:                cv_broadcast(&tp->t_outcv);
1.213     rmind    1477:                selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
1.49      cgd      1478:        }
                   1479: }
                   1480:
                   1481: /*
                   1482:  * Copy in the default termios characters.
                   1483:  */
                   1484: void
1.126     lukem    1485: ttychars(struct tty *tp)
1.49      cgd      1486: {
                   1487:
1.109     perry    1488:        memcpy(tp->t_cc, ttydefchars, sizeof(ttydefchars));
1.49      cgd      1489: }
                   1490:
                   1491: /*
                   1492:  * Send stop character on input overflow.
1.203     ad       1493:  * Call with the tty lock held.
1.49      cgd      1494:  */
                   1495: static void
1.126     lukem    1496: ttyblock(struct tty *tp)
1.49      cgd      1497: {
1.126     lukem    1498:        int     total;
1.49      cgd      1499:
1.201     ad       1500:        KASSERT(mutex_owned(&tty_lock));
                   1501:
1.49      cgd      1502:        total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
                   1503:        if (tp->t_rawq.c_cc > TTYHOG) {
                   1504:                ttyflush(tp, FREAD | FWRITE);
                   1505:                CLR(tp->t_state, TS_TBLOCK);
                   1506:        }
                   1507:        /*
                   1508:         * Block further input iff: current input > threshold
                   1509:         * AND input is available to user program.
                   1510:         */
1.101     drochner 1511:        if (total >= TTYHOG / 2 &&
                   1512:            !ISSET(tp->t_state, TS_TBLOCK) &&
                   1513:            (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) {
1.60      mycroft  1514:                if (ISSET(tp->t_iflag, IXOFF) &&
                   1515:                    tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
                   1516:                    putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
1.49      cgd      1517:                        SET(tp->t_state, TS_TBLOCK);
                   1518:                        ttstart(tp);
                   1519:                }
1.59      mycroft  1520:                /* Try to block remote output via hardware flow control. */
1.49      cgd      1521:                if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
                   1522:                    (*tp->t_hwiflow)(tp, 1) != 0)
                   1523:                        SET(tp->t_state, TS_TBLOCK);
                   1524:        }
                   1525: }
                   1526:
1.147     pk       1527: /*
                   1528:  * Delayed line discipline output
                   1529:  */
1.49      cgd      1530: void
1.126     lukem    1531: ttrstrt(void *tp_arg)
1.49      cgd      1532: {
1.126     lukem    1533:        struct tty      *tp;
1.49      cgd      1534:
                   1535: #ifdef DIAGNOSTIC
                   1536:        if (tp_arg == NULL)
                   1537:                panic("ttrstrt");
                   1538: #endif
                   1539:        tp = tp_arg;
1.201     ad       1540:        mutex_spin_enter(&tty_lock);
1.49      cgd      1541:
                   1542:        CLR(tp->t_state, TS_TIMEOUT);
1.147     pk       1543:        ttstart(tp); /* XXX - Shouldn't this be tp->l_start(tp)? */
1.49      cgd      1544:
1.201     ad       1545:        mutex_spin_exit(&tty_lock);
1.49      cgd      1546: }
                   1547:
1.147     pk       1548: /*
                   1549:  * start a line discipline
1.201     ad       1550:  * Always call with tty lock held?
1.147     pk       1551:  */
1.49      cgd      1552: int
1.126     lukem    1553: ttstart(struct tty *tp)
1.49      cgd      1554: {
                   1555:
                   1556:        if (tp->t_oproc != NULL)        /* XXX: Kludge for pty. */
                   1557:                (*tp->t_oproc)(tp);
                   1558:        return (0);
                   1559: }
                   1560:
                   1561: /*
                   1562:  * "close" a line discipline
                   1563:  */
                   1564: int
1.126     lukem    1565: ttylclose(struct tty *tp, int flag)
1.49      cgd      1566: {
                   1567:
1.147     pk       1568:        if (flag & FNONBLOCK) {
1.201     ad       1569:                mutex_spin_enter(&tty_lock);
1.49      cgd      1570:                ttyflush(tp, FREAD | FWRITE);
1.201     ad       1571:                mutex_spin_exit(&tty_lock);
1.147     pk       1572:        } else
1.49      cgd      1573:                ttywflush(tp);
                   1574:        return (0);
                   1575: }
                   1576:
                   1577: /*
                   1578:  * Handle modem control transition on a tty.
                   1579:  * Flag indicates new state of carrier.
                   1580:  * Returns 0 if the line should be turned off, otherwise 1.
                   1581:  */
                   1582: int
1.126     lukem    1583: ttymodem(struct tty *tp, int flag)
1.49      cgd      1584: {
                   1585:
1.201     ad       1586:        mutex_spin_enter(&tty_lock);
1.83      mycroft  1587:        if (flag == 0) {
1.96      kleink   1588:                if (ISSET(tp->t_state, TS_CARR_ON)) {
                   1589:                        /*
                   1590:                         * Lost carrier.
                   1591:                         */
                   1592:                        CLR(tp->t_state, TS_CARR_ON);
                   1593:                        if (ISSET(tp->t_state, TS_ISOPEN) && !CONNECTED(tp)) {
1.201     ad       1594:                                ttysig(tp, TTYSIG_LEADER, SIGHUP);
1.96      kleink   1595:                                ttyflush(tp, FREAD | FWRITE);
1.201     ad       1596:                                mutex_spin_exit(&tty_lock);
1.96      kleink   1597:                                return (0);
                   1598:                        }
1.49      cgd      1599:                }
                   1600:        } else {
1.96      kleink   1601:                if (!ISSET(tp->t_state, TS_CARR_ON)) {
                   1602:                        /*
                   1603:                         * Carrier now on.
                   1604:                         */
                   1605:                        SET(tp->t_state, TS_CARR_ON);
                   1606:                        ttwakeup(tp);
                   1607:                }
1.49      cgd      1608:        }
1.201     ad       1609:        mutex_spin_exit(&tty_lock);
                   1610:
1.49      cgd      1611:        return (1);
                   1612: }
                   1613:
                   1614: /*
                   1615:  * Default modem control routine (for other line disciplines).
                   1616:  * Return argument flag, to turn off device on carrier drop.
                   1617:  */
                   1618: int
1.126     lukem    1619: nullmodem(struct tty *tp, int flag)
1.49      cgd      1620: {
                   1621:
1.201     ad       1622:        mutex_spin_enter(&tty_lock);
1.49      cgd      1623:        if (flag)
                   1624:                SET(tp->t_state, TS_CARR_ON);
                   1625:        else {
                   1626:                CLR(tp->t_state, TS_CARR_ON);
1.83      mycroft  1627:                if (!CONNECTED(tp)) {
1.201     ad       1628:                        ttysig(tp, TTYSIG_LEADER, SIGHUP);
                   1629:                        mutex_spin_exit(&tty_lock);
1.49      cgd      1630:                        return (0);
                   1631:                }
                   1632:        }
1.201     ad       1633:        mutex_spin_exit(&tty_lock);
                   1634:
1.49      cgd      1635:        return (1);
                   1636: }
                   1637:
                   1638: /*
1.147     pk       1639:  * Reinput pending characters after state switch.
1.49      cgd      1640:  */
                   1641: void
1.126     lukem    1642: ttypend(struct tty *tp)
1.49      cgd      1643: {
1.126     lukem    1644:        struct clist    tq;
                   1645:        int             c;
1.49      cgd      1646:
1.201     ad       1647:        KASSERT(mutex_owned(&tty_lock));
                   1648:
1.49      cgd      1649:        CLR(tp->t_lflag, PENDIN);
                   1650:        SET(tp->t_state, TS_TYPEN);
                   1651:        tq = tp->t_rawq;
                   1652:        tp->t_rawq.c_cc = 0;
                   1653:        tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
                   1654:        while ((c = getc(&tq)) >= 0)
1.147     pk       1655:                ttyinput_wlock(c, tp);
1.49      cgd      1656:        CLR(tp->t_state, TS_TYPEN);
                   1657: }
                   1658:
                   1659: /*
                   1660:  * Process a read call on a tty device.
                   1661:  */
                   1662: int
1.126     lukem    1663: ttread(struct tty *tp, struct uio *uio, int flag)
1.49      cgd      1664: {
1.126     lukem    1665:        struct clist    *qp;
                   1666:        u_char          *cc;
                   1667:        struct proc     *p;
1.201     ad       1668:        int             c, first, error, has_stime, last_cc;
1.126     lukem    1669:        long            lflag, slp;
1.185     kardel   1670:        struct timeval  now, stime;
1.49      cgd      1671:
1.221.2.4! yamt     1672:        if (uio->uio_resid == 0)
        !          1673:                return 0;
        !          1674:
1.181     mrg      1675:        stime.tv_usec = 0;      /* XXX gcc */
                   1676:        stime.tv_sec = 0;       /* XXX gcc */
                   1677:
1.126     lukem    1678:        cc = tp->t_cc;
                   1679:        p = curproc;
                   1680:        error = 0;
                   1681:        has_stime = 0;
                   1682:        last_cc = 0;
                   1683:        slp = 0;
                   1684:
                   1685:  loop:
1.201     ad       1686:        mutex_spin_enter(&tty_lock);
1.126     lukem    1687:        lflag = tp->t_lflag;
1.49      cgd      1688:        /*
                   1689:         * take pending input first
                   1690:         */
                   1691:        if (ISSET(lflag, PENDIN))
                   1692:                ttypend(tp);
                   1693:
                   1694:        /*
1.209     ad       1695:         * Hang process if it's in the background.
1.49      cgd      1696:         */
                   1697:        if (isbackground(p, tp)) {
1.221.2.1  yamt     1698:                if (sigismasked(curlwp, SIGTTIN) ||
1.221.2.2  yamt     1699:                    p->p_lflag & PL_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1.201     ad       1700:                        mutex_spin_exit(&tty_lock);
1.49      cgd      1701:                        return (EIO);
1.147     pk       1702:                }
1.210     ad       1703:                mutex_spin_exit(&tty_lock);
                   1704:
1.220     ad       1705:                mutex_enter(proc_lock);
1.210     ad       1706:                pgsignal(p->p_pgrp, SIGTTIN, 1);
1.220     ad       1707:                mutex_exit(proc_lock);
1.210     ad       1708:
                   1709:                mutex_spin_enter(&tty_lock);
1.201     ad       1710:                error = ttysleep(tp, &lbolt, true, 0);
                   1711:                mutex_spin_exit(&tty_lock);
1.65      christos 1712:                if (error)
1.49      cgd      1713:                        return (error);
                   1714:                goto loop;
                   1715:        }
                   1716:
                   1717:        if (!ISSET(lflag, ICANON)) {
                   1718:                int m = cc[VMIN];
                   1719:                long t = cc[VTIME];
                   1720:
                   1721:                qp = &tp->t_rawq;
                   1722:                /*
                   1723:                 * Check each of the four combinations.
                   1724:                 * (m > 0 && t == 0) is the normal read case.
                   1725:                 * It should be fairly efficient, so we check that and its
                   1726:                 * companion case (m == 0 && t == 0) first.
                   1727:                 * For the other two cases, we compute the target sleep time
                   1728:                 * into slp.
                   1729:                 */
                   1730:                if (t == 0) {
                   1731:                        if (qp->c_cc < m)
                   1732:                                goto sleep;
                   1733:                        goto read;
                   1734:                }
1.156     dsl      1735:                t *= hz;                /* time in deca-ticks */
                   1736: /*
                   1737:  * Time difference in deca-ticks, split division to avoid numeric overflow.
                   1738:  * Ok for hz < ~200kHz
                   1739:  */
                   1740: #define        diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 10 * hz + \
                   1741:                         ((t1).tv_usec - (t2).tv_usec) / 100 * hz / 1000)
1.49      cgd      1742:                if (m > 0) {
                   1743:                        if (qp->c_cc <= 0)
                   1744:                                goto sleep;
                   1745:                        if (qp->c_cc >= m)
                   1746:                                goto read;
                   1747:                        if (!has_stime) {
                   1748:                                /* first character, start timer */
                   1749:                                has_stime = 1;
1.185     kardel   1750:                                getmicrotime(&stime);
1.49      cgd      1751:                                slp = t;
                   1752:                        } else if (qp->c_cc > last_cc) {
                   1753:                                /* got a character, restart timer */
1.185     kardel   1754:                                getmicrotime(&stime);
1.49      cgd      1755:                                slp = t;
                   1756:                        } else {
                   1757:                                /* nothing, check expiration */
1.185     kardel   1758:                                getmicrotime(&now);
                   1759:                                slp = t - diff(now, stime);
1.49      cgd      1760:                        }
                   1761:                } else {        /* m == 0 */
                   1762:                        if (qp->c_cc > 0)
                   1763:                                goto read;
                   1764:                        if (!has_stime) {
                   1765:                                has_stime = 1;
1.185     kardel   1766:                                getmicrotime(&stime);
1.49      cgd      1767:                                slp = t;
1.185     kardel   1768:                        } else {
                   1769:                                getmicrotime(&now);
                   1770:                                slp = t - diff(now, stime);
                   1771:                        }
1.49      cgd      1772:                }
1.54      mycroft  1773:                last_cc = qp->c_cc;
1.49      cgd      1774: #undef diff
                   1775:                if (slp > 0) {
                   1776:                        /*
1.156     dsl      1777:                         * Convert deca-ticks back to ticks.
1.49      cgd      1778:                         * Rounding down may make us wake up just short
                   1779:                         * of the target, so we round up.
1.156     dsl      1780:                         * Maybe we should do 'slp/10 + 1' because the
                   1781:                         * first tick maybe almost immediate.
                   1782:                         * However it is more useful for a program that sets
                   1783:                         * VTIME=10 to wakeup every second not every 1.01
                   1784:                         * seconds (if hz=100).
1.49      cgd      1785:                         */
1.156     dsl      1786:                        slp = (slp + 9)/ 10;
1.49      cgd      1787:                        goto sleep;
                   1788:                }
                   1789:        } else if ((qp = &tp->t_canq)->c_cc <= 0) {
1.126     lukem    1790:                int     carrier;
1.49      cgd      1791:
1.126     lukem    1792:  sleep:
1.49      cgd      1793:                /*
                   1794:                 * If there is no input, sleep on rawq
                   1795:                 * awaiting hardware receipt and notification.
                   1796:                 * If we have data, we don't need to check for carrier.
                   1797:                 */
1.83      mycroft  1798:                carrier = CONNECTED(tp);
1.49      cgd      1799:                if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1.201     ad       1800:                        mutex_spin_exit(&tty_lock);
1.49      cgd      1801:                        return (0);     /* EOF */
                   1802:                }
1.221.2.3  yamt     1803:                if (!has_stime || slp <= 0) {
                   1804:                        if (flag & IO_NDELAY) {
                   1805:                                mutex_spin_exit(&tty_lock);
                   1806:                                return (EWOULDBLOCK);
                   1807:                        }
1.49      cgd      1808:                }
1.221.2.2  yamt     1809:                error = ttysleep(tp, &tp->t_rawcv, true, slp);
1.201     ad       1810:                mutex_spin_exit(&tty_lock);
1.82      kleink   1811:                /* VMIN == 0: any quantity read satisfies */
                   1812:                if (cc[VMIN] == 0 && error == EWOULDBLOCK)
                   1813:                        return (0);
1.54      mycroft  1814:                if (error && error != EWOULDBLOCK)
1.49      cgd      1815:                        return (error);
                   1816:                goto loop;
                   1817:        }
1.126     lukem    1818:  read:
1.201     ad       1819:        mutex_spin_exit(&tty_lock);
1.49      cgd      1820:
                   1821:        /*
                   1822:         * Input present, check for input mapping and processing.
                   1823:         */
                   1824:        first = 1;
                   1825:        while ((c = getc(qp)) >= 0) {
                   1826:                /*
                   1827:                 * delayed suspend (^Y)
                   1828:                 */
1.81      kleink   1829:                if (CCEQ(cc[VDSUSP], c) &&
                   1830:                    ISSET(lflag, IEXTEN|ISIG) == (IEXTEN|ISIG)) {
1.201     ad       1831:                        mutex_spin_enter(&tty_lock);
                   1832:                        ttysig(tp, TTYSIG_PG1, SIGTSTP);
1.49      cgd      1833:                        if (first) {
1.201     ad       1834:                                error = ttysleep(tp, &lbolt, true, 0);
                   1835:                                mutex_spin_exit(&tty_lock);
1.65      christos 1836:                                if (error)
1.49      cgd      1837:                                        break;
                   1838:                                goto loop;
1.201     ad       1839:                        } else
                   1840:                                mutex_spin_exit(&tty_lock);
1.49      cgd      1841:                        break;
                   1842:                }
                   1843:                /*
                   1844:                 * Interpret EOF only in canonical mode.
                   1845:                 */
                   1846:                if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
                   1847:                        break;
                   1848:                /*
                   1849:                 * Give user character.
                   1850:                 */
                   1851:                error = ureadc(c, uio);
                   1852:                if (error)
                   1853:                        break;
                   1854:                if (uio->uio_resid == 0)
                   1855:                        break;
                   1856:                /*
                   1857:                 * In canonical mode check for a "break character"
                   1858:                 * marking the end of a "line of input".
                   1859:                 */
1.85      kleink   1860:                if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1.49      cgd      1861:                        break;
                   1862:                first = 0;
                   1863:        }
                   1864:        /*
                   1865:         * Look to unblock output now that (presumably)
                   1866:         * the input queue has gone down.
                   1867:         */
1.201     ad       1868:        mutex_spin_enter(&tty_lock);
1.138     enami    1869:        if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG / 5) {
1.60      mycroft  1870:                if (ISSET(tp->t_iflag, IXOFF) &&
                   1871:                    cc[VSTART] != _POSIX_VDISABLE &&
1.49      cgd      1872:                    putc(cc[VSTART], &tp->t_outq) == 0) {
                   1873:                        CLR(tp->t_state, TS_TBLOCK);
                   1874:                        ttstart(tp);
                   1875:                }
1.59      mycroft  1876:                /* Try to unblock remote output via hardware flow control. */
                   1877:                if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1.49      cgd      1878:                    (*tp->t_hwiflow)(tp, 0) != 0)
1.59      mycroft  1879:                        CLR(tp->t_state, TS_TBLOCK);
1.49      cgd      1880:        }
1.201     ad       1881:        mutex_spin_exit(&tty_lock);
                   1882:
1.49      cgd      1883:        return (error);
                   1884: }
                   1885:
                   1886: /*
                   1887:  * Check the output queue on tp for space for a kernel message (from uprintf
                   1888:  * or tprintf).  Allow some space over the normal hiwater mark so we don't
                   1889:  * lose messages due to normal flow control, but don't let the tty run amok.
                   1890:  * Sleeps here are not interruptible, but we return prematurely if new signals
                   1891:  * arrive.
1.201     ad       1892:  * Call with tty lock held.
1.49      cgd      1893:  */
1.147     pk       1894: static int
                   1895: ttycheckoutq_wlock(struct tty *tp, int wait)
1.49      cgd      1896: {
1.201     ad       1897:        int     hiwat, error;
                   1898:
                   1899:        KASSERT(mutex_owned(&tty_lock));
1.49      cgd      1900:
                   1901:        hiwat = tp->t_hiwat;
                   1902:        if (tp->t_outq.c_cc > hiwat + 200)
                   1903:                while (tp->t_outq.c_cc > hiwat) {
                   1904:                        ttstart(tp);
1.201     ad       1905:                        if (wait == 0)
1.49      cgd      1906:                                return (0);
1.221.2.2  yamt     1907:                        error = ttysleep(tp, &tp->t_outcv, true, hz);
1.112     mycroft  1908:                        if (error == EINTR)
                   1909:                                wait = 0;
1.49      cgd      1910:                }
1.147     pk       1911:
1.49      cgd      1912:        return (1);
                   1913: }
                   1914:
1.147     pk       1915: int
                   1916: ttycheckoutq(struct tty *tp, int wait)
                   1917: {
1.201     ad       1918:        int     r;
1.147     pk       1919:
1.201     ad       1920:        mutex_spin_enter(&tty_lock);
1.147     pk       1921:        r = ttycheckoutq_wlock(tp, wait);
1.201     ad       1922:        mutex_spin_exit(&tty_lock);
                   1923:
1.147     pk       1924:        return (r);
                   1925: }
                   1926:
1.49      cgd      1927: /*
                   1928:  * Process a write call on a tty device.
                   1929:  */
                   1930: int
1.126     lukem    1931: ttwrite(struct tty *tp, struct uio *uio, int flag)
1.49      cgd      1932: {
1.126     lukem    1933:        u_char          *cp;
                   1934:        struct proc     *p;
1.201     ad       1935:        int             cc, ce, i, hiwat, error;
1.126     lukem    1936:        u_char          obuf[OBUFSIZ];
1.49      cgd      1937:
1.126     lukem    1938:        cp = NULL;
1.49      cgd      1939:        hiwat = tp->t_hiwat;
                   1940:        error = 0;
                   1941:        cc = 0;
1.126     lukem    1942:  loop:
1.201     ad       1943:        mutex_spin_enter(&tty_lock);
1.83      mycroft  1944:        if (!CONNECTED(tp)) {
1.49      cgd      1945:                if (ISSET(tp->t_state, TS_ISOPEN)) {
1.201     ad       1946:                        mutex_spin_exit(&tty_lock);
1.49      cgd      1947:                        return (EIO);
                   1948:                } else if (flag & IO_NDELAY) {
1.201     ad       1949:                        mutex_spin_exit(&tty_lock);
1.49      cgd      1950:                        error = EWOULDBLOCK;
                   1951:                        goto out;
                   1952:                } else {
                   1953:                        /* Sleep awaiting carrier. */
1.221.2.2  yamt     1954:                        error = ttysleep(tp, &tp->t_rawcv, true, 0);
1.201     ad       1955:                        mutex_spin_exit(&tty_lock);
1.49      cgd      1956:                        if (error)
                   1957:                                goto out;
                   1958:                        goto loop;
                   1959:                }
                   1960:        }
1.211     ad       1961:
1.49      cgd      1962:        /*
1.209     ad       1963:         * Hang the process if it's in the background.
1.49      cgd      1964:         */
                   1965:        p = curproc;
                   1966:        if (isbackground(p, tp) &&
1.221.2.2  yamt     1967:            ISSET(tp->t_lflag, TOSTOP) && (p->p_lflag & PL_PPWAIT) == 0 &&
1.221.2.1  yamt     1968:            !sigismasked(curlwp, SIGTTOU)) {
1.86      kleink   1969:                if (p->p_pgrp->pg_jobc == 0) {
                   1970:                        error = EIO;
1.209     ad       1971:                        mutex_spin_exit(&tty_lock);
1.86      kleink   1972:                        goto out;
                   1973:                }
1.210     ad       1974:                mutex_spin_exit(&tty_lock);
                   1975:
1.220     ad       1976:                mutex_enter(proc_lock);
1.210     ad       1977:                pgsignal(p->p_pgrp, SIGTTOU, 1);
1.220     ad       1978:                mutex_exit(proc_lock);
1.210     ad       1979:
                   1980:                mutex_spin_enter(&tty_lock);
1.201     ad       1981:                error = ttysleep(tp, &lbolt, true, 0);
                   1982:                mutex_spin_exit(&tty_lock);
1.65      christos 1983:                if (error)
1.49      cgd      1984:                        goto out;
                   1985:                goto loop;
                   1986:        }
1.209     ad       1987:        mutex_spin_exit(&tty_lock);
                   1988:
1.49      cgd      1989:        /*
                   1990:         * Process the user's data in at most OBUFSIZ chunks.  Perform any
                   1991:         * output translation.  Keep track of high water mark, sleep on
                   1992:         * overflow awaiting device aid in acquiring new space.
                   1993:         */
                   1994:        while (uio->uio_resid > 0 || cc > 0) {
                   1995:                if (ISSET(tp->t_lflag, FLUSHO)) {
                   1996:                        uio->uio_resid = 0;
                   1997:                        return (0);
                   1998:                }
                   1999:                if (tp->t_outq.c_cc > hiwat)
                   2000:                        goto ovhiwat;
                   2001:                /*
                   2002:                 * Grab a hunk of data from the user, unless we have some
                   2003:                 * leftover from last time.
                   2004:                 */
                   2005:                if (cc == 0) {
                   2006:                        cc = min(uio->uio_resid, OBUFSIZ);
                   2007:                        cp = obuf;
                   2008:                        error = uiomove(cp, cc, uio);
                   2009:                        if (error) {
                   2010:                                cc = 0;
1.147     pk       2011:                                goto out;
1.49      cgd      2012:                        }
                   2013:                }
                   2014:                /*
                   2015:                 * If nothing fancy need be done, grab those characters we
                   2016:                 * can handle without any of ttyoutput's processing and
                   2017:                 * just transfer them to the output q.  For those chars
                   2018:                 * which require special processing (as indicated by the
                   2019:                 * bits in char_type), call ttyoutput.  After processing
                   2020:                 * a hunk of data, look for FLUSHO so ^O's will take effect
                   2021:                 * immediately.
                   2022:                 */
1.201     ad       2023:                mutex_spin_enter(&tty_lock);
1.49      cgd      2024:                while (cc > 0) {
                   2025:                        if (!ISSET(tp->t_oflag, OPOST))
                   2026:                                ce = cc;
                   2027:                        else {
1.77      cgd      2028:                                ce = cc - scanc((u_int)cc, cp, char_type,
                   2029:                                    CCLASSMASK);
1.49      cgd      2030:                                /*
                   2031:                                 * If ce is zero, then we're processing
                   2032:                                 * a special character through ttyoutput.
                   2033:                                 */
                   2034:                                if (ce == 0) {
                   2035:                                        tp->t_rocount = 0;
                   2036:                                        if (ttyoutput(*cp, tp) >= 0) {
                   2037:                                                /* out of space */
1.201     ad       2038:                                                mutex_spin_exit(&tty_lock);
1.49      cgd      2039:                                                goto overfull;
                   2040:                                        }
                   2041:                                        cp++;
                   2042:                                        cc--;
                   2043:                                        if (ISSET(tp->t_lflag, FLUSHO) ||
1.147     pk       2044:                                            tp->t_outq.c_cc > hiwat) {
1.201     ad       2045:                                                mutex_spin_exit(&tty_lock);
1.49      cgd      2046:                                                goto ovhiwat;
1.147     pk       2047:                                        }
1.49      cgd      2048:                                        continue;
                   2049:                                }
                   2050:                        }
                   2051:                        /*
                   2052:                         * A bunch of normal characters have been found.
                   2053:                         * Transfer them en masse to the output queue and
                   2054:                         * continue processing at the top of the loop.
                   2055:                         * If there are any further characters in this
                   2056:                         * <= OBUFSIZ chunk, the first should be a character
                   2057:                         * requiring special handling by ttyoutput.
                   2058:                         */
                   2059:                        tp->t_rocount = 0;
                   2060:                        i = b_to_q(cp, ce, &tp->t_outq);
                   2061:                        ce -= i;
                   2062:                        tp->t_column += ce;
                   2063:                        cp += ce, cc -= ce, tk_nout += ce;
                   2064:                        tp->t_outcc += ce;
                   2065:                        if (i > 0) {
                   2066:                                /* out of space */
1.201     ad       2067:                                mutex_spin_exit(&tty_lock);
1.49      cgd      2068:                                goto overfull;
                   2069:                        }
                   2070:                        if (ISSET(tp->t_lflag, FLUSHO) ||
                   2071:                            tp->t_outq.c_cc > hiwat)
                   2072:                                break;
                   2073:                }
1.205     ad       2074:                ttstart(tp);
1.201     ad       2075:                mutex_spin_exit(&tty_lock);
1.49      cgd      2076:        }
1.147     pk       2077:
1.126     lukem    2078:  out:
1.49      cgd      2079:        /*
                   2080:         * If cc is nonzero, we leave the uio structure inconsistent, as the
                   2081:         * offset and iov pointers have moved forward, but it doesn't matter
                   2082:         * (the call will either return short or restart with a new uio).
                   2083:         */
                   2084:        uio->uio_resid += cc;
                   2085:        return (error);
                   2086:
1.126     lukem    2087:  overfull:
1.49      cgd      2088:        /*
                   2089:         * Since we are using ring buffers, if we can't insert any more into
                   2090:         * the output queue, we can assume the ring is full and that someone
                   2091:         * forgot to set the high water mark correctly.  We set it and then
                   2092:         * proceed as normal.
                   2093:         */
                   2094:        hiwat = tp->t_outq.c_cc - 1;
                   2095:
1.126     lukem    2096:  ovhiwat:
1.205     ad       2097:        mutex_spin_enter(&tty_lock);
1.49      cgd      2098:        ttstart(tp);
                   2099:        /*
                   2100:         * This can only occur if FLUSHO is set in t_lflag,
                   2101:         * or if ttstart/oproc is synchronous (or very fast).
                   2102:         */
                   2103:        if (tp->t_outq.c_cc <= hiwat) {
1.201     ad       2104:                mutex_spin_exit(&tty_lock);
1.49      cgd      2105:                goto loop;
                   2106:        }
                   2107:        if (flag & IO_NDELAY) {
1.201     ad       2108:                mutex_spin_exit(&tty_lock);
1.187     christos 2109:                error = EWOULDBLOCK;
1.147     pk       2110:                goto out;
1.49      cgd      2111:        }
1.221.2.2  yamt     2112:        error = ttysleep(tp, &tp->t_outcv, true, 0);
1.201     ad       2113:        mutex_spin_exit(&tty_lock);
1.49      cgd      2114:        if (error)
                   2115:                goto out;
                   2116:        goto loop;
                   2117: }
                   2118:
                   2119: /*
1.203     ad       2120:  * Try to pull more output from the producer.  Return non-zero if
                   2121:  * there is output ready to be sent.
                   2122:  */
                   2123: bool
                   2124: ttypull(struct tty *tp)
                   2125: {
                   2126:
                   2127:        /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
                   2128:
                   2129:        if (tp->t_outq.c_cc <= tp->t_lowat) {
1.221.2.2  yamt     2130:                cv_broadcast(&tp->t_outcv);
1.213     rmind    2131:                selnotify(&tp->t_wsel, 0, NOTE_SUBMIT);
1.203     ad       2132:        }
                   2133:        return tp->t_outq.c_cc != 0;
                   2134: }
                   2135:
                   2136: /*
1.49      cgd      2137:  * Rubout one character from the rawq of tp
                   2138:  * as cleanly as possible.
1.201     ad       2139:  * Called with tty lock held.
1.49      cgd      2140:  */
                   2141: void
1.126     lukem    2142: ttyrub(int c, struct tty *tp)
1.49      cgd      2143: {
1.126     lukem    2144:        u_char  *cp;
1.201     ad       2145:        int     savecol, tabc;
                   2146:
                   2147:        KASSERT(mutex_owned(&tty_lock));
1.49      cgd      2148:
                   2149:        if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
                   2150:                return;
                   2151:        CLR(tp->t_lflag, FLUSHO);
                   2152:        if (ISSET(tp->t_lflag, ECHOE)) {
                   2153:                if (tp->t_rocount == 0) {
                   2154:                        /*
                   2155:                         * Screwed by ttwrite; retype
                   2156:                         */
                   2157:                        ttyretype(tp);
                   2158:                        return;
                   2159:                }
                   2160:                if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
                   2161:                        ttyrubo(tp, 2);
                   2162:                else {
                   2163:                        CLR(c, ~TTY_CHARMASK);
                   2164:                        switch (CCLASS(c)) {
                   2165:                        case ORDINARY:
                   2166:                                ttyrubo(tp, 1);
                   2167:                                break;
                   2168:                        case BACKSPACE:
                   2169:                        case CONTROL:
                   2170:                        case NEWLINE:
                   2171:                        case RETURN:
                   2172:                        case VTAB:
                   2173:                                if (ISSET(tp->t_lflag, ECHOCTL))
                   2174:                                        ttyrubo(tp, 2);
                   2175:                                break;
                   2176:                        case TAB:
                   2177:                                if (tp->t_rocount < tp->t_rawq.c_cc) {
                   2178:                                        ttyretype(tp);
                   2179:                                        return;
                   2180:                                }
                   2181:                                savecol = tp->t_column;
                   2182:                                SET(tp->t_state, TS_CNTTB);
                   2183:                                SET(tp->t_lflag, FLUSHO);
                   2184:                                tp->t_column = tp->t_rocol;
1.52      deraadt  2185:                                for (cp = firstc(&tp->t_rawq, &tabc); cp;
1.49      cgd      2186:                                    cp = nextc(&tp->t_rawq, cp, &tabc))
                   2187:                                        ttyecho(tabc, tp);
                   2188:                                CLR(tp->t_lflag, FLUSHO);
                   2189:                                CLR(tp->t_state, TS_CNTTB);
                   2190:
                   2191:                                /* savecol will now be length of the tab. */
                   2192:                                savecol -= tp->t_column;
                   2193:                                tp->t_column += savecol;
                   2194:                                if (savecol > 8)
                   2195:                                        savecol = 8;    /* overflow screw */
                   2196:                                while (--savecol >= 0)
                   2197:                                        (void)ttyoutput('\b', tp);
                   2198:                                break;
                   2199:                        default:                        /* XXX */
1.172     christos 2200:                                (void)printf("ttyrub: would panic c = %d, "
                   2201:                                    "val = %d\n", c, CCLASS(c));
1.49      cgd      2202:                        }
                   2203:                }
                   2204:        } else if (ISSET(tp->t_lflag, ECHOPRT)) {
                   2205:                if (!ISSET(tp->t_state, TS_ERASE)) {
                   2206:                        SET(tp->t_state, TS_ERASE);
                   2207:                        (void)ttyoutput('\\', tp);
                   2208:                }
                   2209:                ttyecho(c, tp);
                   2210:        } else
                   2211:                ttyecho(tp->t_cc[VERASE], tp);
                   2212:        --tp->t_rocount;
                   2213: }
                   2214:
                   2215: /*
                   2216:  * Back over cnt characters, erasing them.
1.201     ad       2217:  * Called with tty lock held.
1.49      cgd      2218:  */
                   2219: static void
1.126     lukem    2220: ttyrubo(struct tty *tp, int cnt)
1.49      cgd      2221: {
                   2222:
1.201     ad       2223:        KASSERT(mutex_owned(&tty_lock));
                   2224:
1.49      cgd      2225:        while (cnt-- > 0) {
                   2226:                (void)ttyoutput('\b', tp);
                   2227:                (void)ttyoutput(' ', tp);
                   2228:                (void)ttyoutput('\b', tp);
                   2229:        }
                   2230: }
                   2231:
                   2232: /*
                   2233:  * ttyretype --
                   2234:  *     Reprint the rawq line.  Note, it is assumed that c_cc has already
                   2235:  *     been checked.
1.147     pk       2236:  *
1.201     ad       2237:  * Called with tty lock held.
1.49      cgd      2238:  */
                   2239: void
1.126     lukem    2240: ttyretype(struct tty *tp)
1.49      cgd      2241: {
1.126     lukem    2242:        u_char  *cp;
1.201     ad       2243:        int     c;
                   2244:
                   2245:        KASSERT(mutex_owned(&tty_lock));
1.49      cgd      2246:
                   2247:        /* Echo the reprint character. */
                   2248:        if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
                   2249:                ttyecho(tp->t_cc[VREPRINT], tp);
                   2250:
                   2251:        (void)ttyoutput('\n', tp);
                   2252:
                   2253:        for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
                   2254:                ttyecho(c, tp);
                   2255:        for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
                   2256:                ttyecho(c, tp);
                   2257:        CLR(tp->t_state, TS_ERASE);
                   2258:
                   2259:        tp->t_rocount = tp->t_rawq.c_cc;
                   2260:        tp->t_rocol = 0;
                   2261: }
                   2262:
                   2263: /*
                   2264:  * Echo a typed character to the terminal.
1.201     ad       2265:  * Called with tty lock held.
1.49      cgd      2266:  */
                   2267: static void
1.126     lukem    2268: ttyecho(int c, struct tty *tp)
1.49      cgd      2269: {
                   2270:
1.201     ad       2271:        KASSERT(mutex_owned(&tty_lock));
                   2272:
1.49      cgd      2273:        if (!ISSET(tp->t_state, TS_CNTTB))
                   2274:                CLR(tp->t_lflag, FLUSHO);
                   2275:        if ((!ISSET(tp->t_lflag, ECHO) &&
1.64      pk       2276:            (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) ||
1.49      cgd      2277:            ISSET(tp->t_lflag, EXTPROC))
                   2278:                return;
1.65      christos 2279:        if (((ISSET(tp->t_lflag, ECHOCTL) &&
1.138     enami    2280:            (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) ||
1.49      cgd      2281:            ISSET(c, TTY_CHARMASK) == 0177)) {
                   2282:                (void)ttyoutput('^', tp);
                   2283:                CLR(c, ~TTY_CHARMASK);
                   2284:                if (c == 0177)
                   2285:                        c = '?';
                   2286:                else
                   2287:                        c += 'A' - 1;
                   2288:        }
                   2289:        (void)ttyoutput(c, tp);
                   2290: }
                   2291:
                   2292: /*
                   2293:  * Wake up any readers on a tty.
1.201     ad       2294:  * Called with tty lock held.
1.49      cgd      2295:  */
                   2296: void
1.126     lukem    2297: ttwakeup(struct tty *tp)
1.49      cgd      2298: {
                   2299:
1.201     ad       2300:        KASSERT(mutex_owned(&tty_lock));
                   2301:
1.213     rmind    2302:        selnotify(&tp->t_rsel, 0, NOTE_SUBMIT);
1.201     ad       2303:        if (ISSET(tp->t_state, TS_ASYNC))
                   2304:                ttysig(tp, TTYSIG_PG2, SIGIO);
1.221.2.2  yamt     2305:        cv_broadcast(&tp->t_rawcv);
1.49      cgd      2306: }
                   2307:
                   2308: /*
                   2309:  * Look up a code for a specified speed in a conversion table;
                   2310:  * used by drivers to map software speed values to hardware parameters.
                   2311:  */
                   2312: int
1.166     matt     2313: ttspeedtab(int speed, const struct speedtab *table)
1.49      cgd      2314: {
                   2315:
1.138     enami    2316:        for (; table->sp_speed != -1; table++)
1.49      cgd      2317:                if (table->sp_speed == speed)
                   2318:                        return (table->sp_code);
                   2319:        return (-1);
                   2320: }
                   2321:
                   2322: /*
                   2323:  * Set tty hi and low water marks.
                   2324:  *
                   2325:  * Try to arrange the dynamics so there's about one second
                   2326:  * from hi to low water.
                   2327:  */
                   2328: void
1.126     lukem    2329: ttsetwater(struct tty *tp)
1.49      cgd      2330: {
1.126     lukem    2331:        int     cps, x;
1.49      cgd      2332:
1.201     ad       2333:        /* XXX not yet KASSERT(mutex_owned(&tty_lock)); */
                   2334:
1.126     lukem    2335: #define        CLAMP(x, h, l)  ((x) > h ? h : ((x) < l) ? l : (x))
1.49      cgd      2336:
                   2337:        cps = tp->t_ospeed / 10;
                   2338:        tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
                   2339:        x += cps;
                   2340:        x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
                   2341:        tp->t_hiwat = roundup(x, CBSIZE);
                   2342: #undef CLAMP
                   2343: }
                   2344:
                   2345: /*
1.215     ad       2346:  * Prepare report on state of foreground process group.
1.220     ad       2347:  * Call with proc_lock held.
1.49      cgd      2348:  */
                   2349: void
1.215     ad       2350: ttygetinfo(struct tty *tp, int fromsig, char *buf, size_t bufsz)
1.49      cgd      2351: {
1.145     thorpej  2352:        struct lwp      *l;
1.184     christos 2353:        struct proc     *p, *pick = NULL;
1.126     lukem    2354:        struct timeval  utime, stime;
                   2355:        int             tmp;
1.196     yamt     2356:        fixpt_t         pctcpu = 0;
1.183     christos 2357:        const char      *msg;
1.215     ad       2358:        char            lmsg[100];
                   2359:        long            rss;
1.49      cgd      2360:
1.220     ad       2361:        KASSERT(mutex_owned(proc_lock));
1.215     ad       2362:
                   2363:        *buf = '\0';
1.49      cgd      2364:
                   2365:        if (tp->t_session == NULL)
1.183     christos 2366:                msg = "not a controlling terminal\n";
1.49      cgd      2367:        else if (tp->t_pgrp == NULL)
1.183     christos 2368:                msg = "no foreground process group\n";
                   2369:        else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL)
                   2370:                msg = "empty foreground process group\n";
1.49      cgd      2371:        else {
                   2372:                /* Pick interesting process. */
1.215     ad       2373:                for (; p != NULL; p = LIST_NEXT(p, p_pglist)) {
1.217     yamt     2374:                        struct proc *oldpick;
                   2375:
1.215     ad       2376:                        if (pick == NULL) {
                   2377:                                pick = p;
                   2378:                                continue;
                   2379:                        }
1.221     ad       2380:                        if (pick->p_lock < p->p_lock) {
                   2381:                                mutex_enter(pick->p_lock);
                   2382:                                mutex_enter(p->p_lock);
                   2383:                        } else if (pick->p_lock > p->p_lock) {
                   2384:                                mutex_enter(p->p_lock);
                   2385:                                mutex_enter(pick->p_lock);
                   2386:                        } else
                   2387:                                mutex_enter(p->p_lock);
1.217     yamt     2388:                        oldpick = pick;
1.49      cgd      2389:                        if (proc_compare(pick, p))
                   2390:                                pick = p;
1.221     ad       2391:                        mutex_exit(p->p_lock);
                   2392:                        if (p->p_lock != oldpick->p_lock)
                   2393:                                mutex_exit(oldpick->p_lock);
1.215     ad       2394:                }
1.183     christos 2395:                if (fromsig &&
                   2396:                    (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
                   2397:                    SA_NOKERNINFO))
                   2398:                        return;
                   2399:                msg = NULL;
                   2400:        }
                   2401:
                   2402:        /* Print load average. */
                   2403:        tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
1.215     ad       2404:        snprintf(lmsg, sizeof(lmsg), "load: %d.%02d ", tmp / 100, tmp % 100);
                   2405:        strlcat(buf, lmsg, bufsz);
1.49      cgd      2406:
1.184     christos 2407:        if (pick == NULL) {
1.215     ad       2408:                strlcat(buf, msg, bufsz);
1.183     christos 2409:                return;
                   2410:        }
                   2411:
1.215     ad       2412:        snprintf(lmsg, sizeof(lmsg), " cmd: %s %d [", pick->p_comm,
                   2413:            pick->p_pid);
                   2414:        strlcat(buf, lmsg, bufsz);
                   2415:
1.221     ad       2416:        mutex_enter(pick->p_lock);
1.196     yamt     2417:        LIST_FOREACH(l, &pick->p_lwps, l_sibling) {
1.214     yamt     2418:                lwp_lock(l);
                   2419:                snprintf(lmsg, sizeof(lmsg), "%s%s",
                   2420:                    l->l_stat == LSONPROC ? "running" :
                   2421:                    l->l_stat == LSRUN ? "runnable" :
                   2422:                    l->l_wchan ? l->l_wmesg : "iowait",
                   2423:                    (LIST_NEXT(l, l_sibling) != NULL) ? " " : "] ");
                   2424:                lwp_unlock(l);
1.215     ad       2425:                strlcat(buf, lmsg, bufsz);
1.214     yamt     2426:                pctcpu += l->l_pctcpu;
1.196     yamt     2427:        }
                   2428:        pctcpu += pick->p_pctcpu;
1.190     ad       2429:        calcru(pick, &utime, &stime, NULL, NULL);
1.221     ad       2430:        mutex_exit(pick->p_lock);
1.183     christos 2431:
1.215     ad       2432:        /* Round up and print user+system time, %CPU and RSS. */
1.183     christos 2433:        utime.tv_usec += 5000;
                   2434:        if (utime.tv_usec >= 1000000) {
                   2435:                utime.tv_sec += 1;
                   2436:                utime.tv_usec -= 1000000;
                   2437:        }
                   2438:        stime.tv_usec += 5000;
                   2439:        if (stime.tv_usec >= 1000000) {
                   2440:                stime.tv_sec += 1;
                   2441:                stime.tv_usec -= 1000000;
                   2442:        }
1.123     thorpej  2443: #define        pgtok(a)        (((u_long) ((a) * PAGE_SIZE) / 1024))
1.196     yamt     2444:        tmp = (pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
1.215     ad       2445:        if (pick->p_stat == SIDL || P_ZOMBIE(pick))
                   2446:                rss = 0;
                   2447:        else
                   2448:                rss = pgtok(vm_resident_count(pick->p_vmspace));
                   2449:
                   2450:        snprintf(lmsg, sizeof(lmsg), "%ld.%02ldu %ld.%02lds %d%% %ldk",
                   2451:            (long)utime.tv_sec, (long)utime.tv_usec / 10000,
                   2452:            (long)stime.tv_sec, (long)stime.tv_usec / 10000,
                   2453:            tmp / 100, rss);
                   2454:        strlcat(buf, lmsg, bufsz);
                   2455: }
1.183     christos 2456:
1.215     ad       2457: /*
                   2458:  * Print report on state of foreground process group.
                   2459:  * Call with tty_lock held.
                   2460:  */
                   2461: void
                   2462: ttyputinfo(struct tty *tp, char *buf)
                   2463: {
                   2464:
                   2465:        KASSERT(mutex_owned(&tty_lock));
                   2466:
                   2467:        if (ttycheckoutq_wlock(tp, 0) == 0)
                   2468:                return;
                   2469:        ttyprintf_nolock(tp, "%s\n", buf);
1.49      cgd      2470:        tp->t_rocount = 0;      /* so pending input will be retyped if BS */
                   2471: }
                   2472:
                   2473: /*
                   2474:  * Returns 1 if p2 is "better" than p1
                   2475:  *
                   2476:  * The algorithm for picking the "interesting" process is thus:
                   2477:  *
                   2478:  *     1) Only foreground processes are eligible - implied.
                   2479:  *     2) Runnable processes are favored over anything else.  The runner
1.200     ad       2480:  *        with the highest CPU utilization is picked (l_pctcpu).  Ties are
1.49      cgd      2481:  *        broken by picking the highest pid.
                   2482:  *     3) The sleeper with the shortest sleep time is next.  With ties,
                   2483:  *        we pick out just "short-term" sleepers (P_SINTR == 0).
                   2484:  *     4) Further ties are broken by picking the highest pid.
                   2485:  */
1.145     thorpej  2486: #define        ISRUN(p)        ((p)->p_nrlwps > 0)
1.138     enami    2487: #define        TESTAB(a, b)    ((a)<<1 | (b))
                   2488: #define        ONLYA   2
                   2489: #define        ONLYB   1
                   2490: #define        BOTH    3
1.49      cgd      2491:
                   2492: static int
1.126     lukem    2493: proc_compare(struct proc *p1, struct proc *p2)
1.49      cgd      2494: {
1.200     ad       2495:        lwp_t *l1, *l2;
1.49      cgd      2496:
1.221     ad       2497:        KASSERT(mutex_owned(p1->p_lock));
                   2498:        KASSERT(mutex_owned(p2->p_lock));
1.215     ad       2499:
                   2500:        if ((l1 = LIST_FIRST(&p1->p_lwps)) == NULL)
1.49      cgd      2501:                return (1);
1.215     ad       2502:        if ((l2 = LIST_FIRST(&p2->p_lwps)) == NULL)
                   2503:                return (0);
1.49      cgd      2504:        /*
                   2505:         * see if at least one of them is runnable
                   2506:         */
                   2507:        switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
                   2508:        case ONLYA:
                   2509:                return (0);
                   2510:        case ONLYB:
                   2511:                return (1);
                   2512:        case BOTH:
                   2513:                /*
1.161     wiz      2514:                 * tie - favor one with highest recent CPU utilization
1.49      cgd      2515:                 */
1.200     ad       2516:                if (l2->l_pctcpu > l1->l_pctcpu)
1.49      cgd      2517:                        return (1);
                   2518:                return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
                   2519:        }
                   2520:        /*
                   2521:         * weed out zombies
                   2522:         */
1.114     thorpej  2523:        switch (TESTAB(P_ZOMBIE(p1), P_ZOMBIE(p2))) {
1.49      cgd      2524:        case ONLYA:
                   2525:                return (1);
                   2526:        case ONLYB:
                   2527:                return (0);
                   2528:        case BOTH:
1.138     enami    2529:                return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
1.49      cgd      2530:        }
                   2531:        /*
                   2532:         * pick the one with the smallest sleep time
                   2533:         */
1.215     ad       2534:        if (l2->l_slptime > l2->l_slptime)
1.49      cgd      2535:                return (0);
1.215     ad       2536:        if (l2->l_slptime > l2->l_slptime)
1.49      cgd      2537:                return (1);
                   2538:        /*
                   2539:         * favor one sleeping in a non-interruptible sleep
                   2540:         */
1.215     ad       2541:        if (l2->l_flag & LW_SINTR && (l2->l_flag & LW_SINTR) == 0)
1.49      cgd      2542:                return (1);
1.215     ad       2543:        if (l2->l_flag & LW_SINTR && (l2->l_flag & LW_SINTR) == 0)
1.49      cgd      2544:                return (0);
                   2545:        return (p2->p_pid > p1->p_pid);         /* tie - return highest pid */
                   2546: }
                   2547:
                   2548: /*
                   2549:  * Output char to tty; console putchar style.
1.147     pk       2550:  * Can be called with tty lock held through kprintf() machinery..
1.49      cgd      2551:  */
                   2552: int
1.149     christos 2553: tputchar(int c, int flags, struct tty *tp)
1.49      cgd      2554: {
1.201     ad       2555:        int r = 0;
1.49      cgd      2556:
1.149     christos 2557:        if ((flags & NOLOCK) == 0)
1.201     ad       2558:                mutex_spin_enter(&tty_lock);
1.147     pk       2559:        if (!CONNECTED(tp)) {
                   2560:                r = -1;
                   2561:                goto out;
1.49      cgd      2562:        }
                   2563:        if (c == '\n')
                   2564:                (void)ttyoutput('\r', tp);
                   2565:        (void)ttyoutput(c, tp);
                   2566:        ttstart(tp);
1.147     pk       2567: out:
1.149     christos 2568:        if ((flags & NOLOCK) == 0)
1.201     ad       2569:                mutex_spin_exit(&tty_lock);
1.147     pk       2570:        return (r);
1.49      cgd      2571: }
                   2572:
                   2573: /*
                   2574:  * Sleep on chan, returning ERESTART if tty changed while we napped and
                   2575:  * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep.  If
                   2576:  * the tty is revoked, restarting a pending call will redo validation done
                   2577:  * at the start of the call.
1.147     pk       2578:  *
1.201     ad       2579:  * Must be called with the tty lock held.
1.49      cgd      2580:  */
                   2581: int
1.201     ad       2582: ttysleep(struct tty *tp, kcondvar_t *cv, bool catch, int timo)
1.49      cgd      2583: {
1.126     lukem    2584:        int     error;
                   2585:        short   gen;
1.49      cgd      2586:
1.201     ad       2587:        KASSERT(mutex_owned(&tty_lock));
                   2588:
1.49      cgd      2589:        gen = tp->t_gen;
1.201     ad       2590:        if (catch)
                   2591:                error = cv_timedwait_sig(cv, &tty_lock, timo);
                   2592:        else
                   2593:                error = cv_timedwait(cv, &tty_lock, timo);
                   2594:        if (error != 0)
1.49      cgd      2595:                return (error);
                   2596:        return (tp->t_gen == gen ? 0 : ERESTART);
                   2597: }
                   2598:
                   2599: /*
1.69      mrg      2600:  * Attach a tty to the tty list.
1.72      mrg      2601:  *
                   2602:  * This should be called ONLY once per real tty (including pty's).
                   2603:  * eg, on the sparc, the keyboard and mouse have struct tty's that are
                   2604:  * distinctly NOT usable as tty's, and thus should not be attached to
                   2605:  * the ttylist.  This is why this call is not done from ttymalloc().
                   2606:  *
                   2607:  * Device drivers should attach tty's at a similar time that they are
                   2608:  * ttymalloc()'ed, or, for the case of statically allocated struct tty's
                   2609:  * either in the attach or (first) open routine.
1.69      mrg      2610:  */
                   2611: void
1.126     lukem    2612: tty_attach(struct tty *tp)
1.69      mrg      2613: {
1.71      cgd      2614:
1.201     ad       2615:        mutex_spin_enter(&tty_lock);
1.69      mrg      2616:        TAILQ_INSERT_TAIL(&ttylist, tp, tty_link);
                   2617:        ++tty_count;
1.201     ad       2618:        mutex_spin_exit(&tty_lock);
1.69      mrg      2619: }
                   2620:
                   2621: /*
                   2622:  * Remove a tty from the tty list.
                   2623:  */
                   2624: void
1.126     lukem    2625: tty_detach(struct tty *tp)
1.69      mrg      2626: {
1.71      cgd      2627:
1.201     ad       2628:        mutex_spin_enter(&tty_lock);
1.69      mrg      2629:        --tty_count;
                   2630: #ifdef DIAGNOSTIC
                   2631:        if (tty_count < 0)
                   2632:                panic("tty_detach: tty_count < 0");
                   2633: #endif
1.70      mrg      2634:        TAILQ_REMOVE(&ttylist, tp, tty_link);
1.201     ad       2635:        mutex_spin_exit(&tty_lock);
1.69      mrg      2636: }
                   2637:
                   2638: /*
1.49      cgd      2639:  * Allocate a tty structure and its associated buffers.
                   2640:  */
                   2641: struct tty *
1.126     lukem    2642: ttymalloc(void)
1.49      cgd      2643: {
1.126     lukem    2644:        struct tty      *tp;
1.202     ad       2645:        int i;
1.49      cgd      2646:
1.216     ad       2647:        tp = kmem_zalloc(sizeof(*tp), KM_SLEEP);
1.197     ad       2648:        callout_init(&tp->t_rstrt_ch, 0);
1.199     joerg    2649:        callout_setfunc(&tp->t_rstrt_ch, ttrstrt, tp);
1.84      mycroft  2650:        /* XXX: default to 1024 chars for now */
                   2651:        clalloc(&tp->t_rawq, 1024, 1);
1.221.2.2  yamt     2652:        cv_init(&tp->t_rawcv, "ttyraw");
                   2653:        cv_init(&tp->t_rawcvf, "ttyrawf");
1.84      mycroft  2654:        clalloc(&tp->t_canq, 1024, 1);
1.221.2.2  yamt     2655:        cv_init(&tp->t_cancv, "ttycan");
                   2656:        cv_init(&tp->t_cancvf, "ttycanf");
1.49      cgd      2657:        /* output queue doesn't need quoting */
1.84      mycroft  2658:        clalloc(&tp->t_outq, 1024, 0);
1.221.2.2  yamt     2659:        cv_init(&tp->t_outcv, "ttyout");
                   2660:        cv_init(&tp->t_outcvf, "ttyoutf");
1.121     eeh      2661:        /* Set default line discipline. */
1.177     thorpej  2662:        tp->t_linesw = ttyldisc_default();
1.198     ad       2663:        selinit(&tp->t_rsel);
                   2664:        selinit(&tp->t_wsel);
1.202     ad       2665:        for (i = 0; i < TTYSIG_COUNT; i++)
                   2666:                sigemptyset(&tp->t_sigs[i]);
1.138     enami    2667:        return (tp);
1.49      cgd      2668: }
                   2669:
                   2670: /*
                   2671:  * Free a tty structure and its buffers.
1.73      mrg      2672:  *
                   2673:  * Be sure to call tty_detach() for any tty that has been
                   2674:  * tty_attach()ed.
1.49      cgd      2675:  */
                   2676: void
1.126     lukem    2677: ttyfree(struct tty *tp)
1.49      cgd      2678: {
1.202     ad       2679:        int i;
1.71      cgd      2680:
1.220     ad       2681:        mutex_enter(proc_lock);
1.201     ad       2682:        mutex_enter(&tty_lock);
1.202     ad       2683:        for (i = 0; i < TTYSIG_COUNT; i++)
                   2684:                sigemptyset(&tp->t_sigs[i]);
1.201     ad       2685:        if (tp->t_sigcount != 0)
                   2686:                TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
                   2687:        mutex_exit(&tty_lock);
1.220     ad       2688:        mutex_exit(proc_lock);
1.201     ad       2689:
1.219     ad       2690:        callout_halt(&tp->t_rstrt_ch, NULL);
1.216     ad       2691:        callout_destroy(&tp->t_rstrt_ch);
1.177     thorpej  2692:        ttyldisc_release(tp->t_linesw);
1.49      cgd      2693:        clfree(&tp->t_rawq);
                   2694:        clfree(&tp->t_canq);
                   2695:        clfree(&tp->t_outq);
1.221.2.2  yamt     2696:        cv_destroy(&tp->t_rawcv);
                   2697:        cv_destroy(&tp->t_rawcvf);
                   2698:        cv_destroy(&tp->t_cancv);
                   2699:        cv_destroy(&tp->t_cancvf);
                   2700:        cv_destroy(&tp->t_outcv);
                   2701:        cv_destroy(&tp->t_outcvf);
1.198     ad       2702:        seldestroy(&tp->t_rsel);
                   2703:        seldestroy(&tp->t_wsel);
1.216     ad       2704:        kmem_free(tp, sizeof(*tp));
1.149     christos 2705: }
                   2706:
                   2707: /*
                   2708:  * ttyprintf_nolock: send a message to a specific tty, without locking.
                   2709:  *
                   2710:  * => should be used only by tty driver or anything that knows the
                   2711:  *    underlying tty will not be revoked(2)'d away.  [otherwise,
                   2712:  *    use tprintf]
                   2713:  */
                   2714: static void
                   2715: ttyprintf_nolock(struct tty *tp, const char *fmt, ...)
                   2716: {
                   2717:        va_list ap;
                   2718:
                   2719:        /* No mutex needed; going to process TTY. */
                   2720:        va_start(ap, fmt);
                   2721:        kprintf(fmt, TOTTY|NOLOCK, tp, NULL, ap);
                   2722:        va_end(ap);
1.49      cgd      2723: }
1.201     ad       2724:
1.221.2.4! yamt     2725: static int
        !          2726: tty_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
        !          2727:     void *arg0, void *arg1, void *arg2, void *arg3)
        !          2728: {
        !          2729:        struct tty *tty;
        !          2730:        int result;
        !          2731:
        !          2732:        result = KAUTH_RESULT_DEFER;
        !          2733:
        !          2734:        if (action != KAUTH_DEVICE_TTY_OPEN)
        !          2735:                return result;
        !          2736:
        !          2737:        tty = arg0;
        !          2738:
        !          2739:        /* If it's not opened, we allow. */
        !          2740:        if ((tty->t_state & TS_ISOPEN) == 0)
        !          2741:                result = KAUTH_RESULT_ALLOW;
        !          2742:        else {
        !          2743:                /*
        !          2744:                 * If it's opened, we can only allow if it's not exclusively
        !          2745:                 * opened; otherwise, that's a privileged operation and we
        !          2746:                 * let the secmodel handle it.
        !          2747:                 */
        !          2748:                if ((tty->t_state & TS_XCLUDE) == 0)
        !          2749:                        result = KAUTH_RESULT_ALLOW;
        !          2750:        }
        !          2751:
        !          2752:        return result;
        !          2753: }
        !          2754:
1.201     ad       2755: /*
                   2756:  * Initialize the tty subsystem.
                   2757:  */
                   2758: void
                   2759: tty_init(void)
                   2760: {
                   2761:
                   2762:        mutex_init(&tty_lock, MUTEX_DEFAULT, IPL_VM);
1.221.2.2  yamt     2763:        rw_init(&ttcompat_lock);
1.201     ad       2764:        tty_sigsih = softint_establish(SOFTINT_CLOCK, ttysigintr, NULL);
                   2765:        KASSERT(tty_sigsih != NULL);
1.221.2.4! yamt     2766:
        !          2767:        tty_listener = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
        !          2768:            tty_listener_cb, NULL);
1.201     ad       2769: }
                   2770:
                   2771: /*
                   2772:  * Send a signal from a tty to its process group or session leader.
                   2773:  * Handoff to the target is deferred to a soft interrupt.
                   2774:  */
                   2775: void
                   2776: ttysig(struct tty *tp, enum ttysigtype st, int sig)
                   2777: {
1.202     ad       2778:        sigset_t *sp;
1.201     ad       2779:
                   2780:        /* XXXSMP not yet KASSERT(mutex_owned(&tty_lock)); */
                   2781:
1.202     ad       2782:        sp = &tp->t_sigs[st];
                   2783:        if (sigismember(sp, sig))
                   2784:                return;
                   2785:        sigaddset(sp, sig);
                   2786:        if (tp->t_sigcount++ == 0)
                   2787:                TAILQ_INSERT_TAIL(&tty_sigqueue, tp, t_sigqueue);
1.201     ad       2788:        softint_schedule(tty_sigsih);
                   2789: }
                   2790:
                   2791: /*
                   2792:  * Deliver deferred signals from ttys.  Note that the process groups
                   2793:  * and sessions associated with the ttys may have changed from when
                   2794:  * the signal was originally sent, but in practice it should not matter.
                   2795:  * For signals produced as a result of a syscall, the soft interrupt
                   2796:  * will fire before the syscall returns to the user.
                   2797:  */
                   2798: static void
                   2799: ttysigintr(void *cookie)
                   2800: {
                   2801:        struct tty *tp;
                   2802:        enum ttysigtype st;
                   2803:        struct pgrp *pgrp;
                   2804:        struct session *sess;
1.215     ad       2805:        int sig, lflag;
                   2806:        char infobuf[200];
1.201     ad       2807:
1.220     ad       2808:        mutex_enter(proc_lock);
1.215     ad       2809:        mutex_spin_enter(&tty_lock);
                   2810:        while ((tp = TAILQ_FIRST(&tty_sigqueue)) != NULL) {
1.201     ad       2811:                KASSERT(tp->t_sigcount > 0);
1.202     ad       2812:                for (st = 0; st < TTYSIG_COUNT; st++) {
                   2813:                        if ((sig = firstsig(&tp->t_sigs[st])) != 0)
                   2814:                                break;
1.201     ad       2815:                }
1.202     ad       2816:                KASSERT(st < TTYSIG_COUNT);
                   2817:                sigdelset(&tp->t_sigs[st], sig);
1.201     ad       2818:                if (--tp->t_sigcount == 0)
                   2819:                        TAILQ_REMOVE(&tty_sigqueue, tp, t_sigqueue);
                   2820:                pgrp = tp->t_pgrp;
                   2821:                sess = tp->t_session;
1.215     ad       2822:                lflag = tp->t_lflag;
                   2823:                if  (sig == SIGINFO) {
                   2824:                        if (ISSET(tp->t_state, TS_SIGINFO)) {
                   2825:                                /* Via ioctl: ignore tty option. */
                   2826:                                tp->t_state &= ~TS_SIGINFO;
1.218     ad       2827:                                lflag |= ISIG;
1.215     ad       2828:                        }
                   2829:                        if (!ISSET(lflag, NOKERNINFO)) {
                   2830:                                mutex_spin_exit(&tty_lock);
                   2831:                                ttygetinfo(tp, 1, infobuf, sizeof(infobuf));
                   2832:                                mutex_spin_enter(&tty_lock);
                   2833:                                ttyputinfo(tp, infobuf);
                   2834:                        }
                   2835:                        if (!ISSET(lflag, ISIG))
                   2836:                                continue;
                   2837:                }
1.201     ad       2838:                mutex_spin_exit(&tty_lock);
1.215     ad       2839:                KASSERT(sig != 0);
1.201     ad       2840:                switch (st) {
                   2841:                case TTYSIG_PG1:
                   2842:                        if (pgrp != NULL)
                   2843:                                pgsignal(pgrp, sig, 1);
                   2844:                        break;
                   2845:                case TTYSIG_PG2:
1.203     ad       2846:                        if (pgrp != NULL)
                   2847:                                pgsignal(pgrp, sig, sess != NULL);
1.201     ad       2848:                        break;
                   2849:                case TTYSIG_LEADER:
                   2850:                        if (sess != NULL && sess->s_leader != NULL)
                   2851:                                psignal(sess->s_leader, sig);
                   2852:                        break;
1.202     ad       2853:                default:
                   2854:                        /* NOTREACHED */
                   2855:                        break;
1.201     ad       2856:                }
1.215     ad       2857:                mutex_spin_enter(&tty_lock);
1.201     ad       2858:        }
1.215     ad       2859:        mutex_spin_exit(&tty_lock);
1.220     ad       2860:        mutex_exit(proc_lock);
1.201     ad       2861: }

CVSweb <webmaster@jp.NetBSD.org>