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

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

CVSweb <webmaster@jp.NetBSD.org>