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

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

CVSweb <webmaster@jp.NetBSD.org>