The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/tty.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986, 1990, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Copyright (c) 2002 Networks Associates Technologies, Inc.
   11  * All rights reserved.
   12  *
   13  * Portions of this software were developed for the FreeBSD Project by
   14  * ThinkSec AS and NAI Labs, the Security Research Division of Network
   15  * Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
   16  * ("CBOSS"), as part of the DARPA CHATS research program.
   17  *
   18  * Redistribution and use in source and binary forms, with or without
   19  * modification, are permitted provided that the following conditions
   20  * are met:
   21  * 1. Redistributions of source code must retain the above copyright
   22  *    notice, this list of conditions and the following disclaimer.
   23  * 2. Redistributions in binary form must reproduce the above copyright
   24  *    notice, this list of conditions and the following disclaimer in the
   25  *    documentation and/or other materials provided with the distribution.
   26  * 3. All advertising materials mentioning features or use of this software
   27  *    must display the following acknowledgement:
   28  *      This product includes software developed by the University of
   29  *      California, Berkeley and its contributors.
   30  * 4. Neither the name of the University nor the names of its contributors
   31  *    may be used to endorse or promote products derived from this software
   32  *    without specific prior written permission.
   33  *
   34  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44  * SUCH DAMAGE.
   45  *
   46  *      @(#)tty.c       8.8 (Berkeley) 1/21/94
   47  * $FreeBSD: releng/5.1/sys/kern/tty.c 114985 2003-05-14 00:03:55Z ps $
   48  */
   49 
   50 /*-
   51  * TODO:
   52  *      o Fix races for sending the start char in ttyflush().
   53  *      o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
   54  *        With luck, there will be MIN chars before select() returns().
   55  *      o Handle CLOCAL consistently for ptys.  Perhaps disallow setting it.
   56  *      o Don't allow input in TS_ZOMBIE case.  It would be visible through
   57  *        FIONREAD.
   58  *      o Do the new sio locking stuff here and use it to avoid special
   59  *        case for EXTPROC?
   60  *      o Lock PENDIN too?
   61  *      o Move EXTPROC and/or PENDIN to t_state?
   62  *      o Wrap most of ttioctl in spltty/splx.
   63  *      o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
   64  *      o Send STOP if IXOFF is toggled off while TS_TBLOCK is set.
   65  *      o Don't allow certain termios flags to affect disciplines other
   66  *        than TTYDISC.  Cancel their effects before switch disciplines
   67  *        and ignore them if they are set while we are in another
   68  *        discipline.
   69  *      o Now that historical speed conversions are handled here, don't
   70  *        do them in drivers.
   71  *      o Check for TS_CARR_ON being set while everything is closed and not
   72  *        waiting for carrier.  TS_CARR_ON isn't cleared if nothing is open,
   73  *        so it would live until the next open even if carrier drops.
   74  *      o Restore TS_WOPEN since it is useful in pstat.  It must be cleared
   75  *        only when _all_ openers leave open().
   76  */
   77 
   78 #include "opt_compat.h"
   79 #include "opt_tty.h"
   80 
   81 #include <sys/param.h>
   82 #include <sys/systm.h>
   83 #include <sys/filio.h>
   84 #include <sys/lock.h>
   85 #include <sys/mutex.h>
   86 #include <sys/namei.h>
   87 #include <sys/sx.h>
   88 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
   89 #include <sys/ioctl_compat.h>
   90 #endif
   91 #include <sys/proc.h>
   92 #define TTYDEFCHARS
   93 #include <sys/tty.h>
   94 #undef  TTYDEFCHARS
   95 #include <sys/fcntl.h>
   96 #include <sys/conf.h>
   97 #include <sys/poll.h>
   98 #include <sys/kernel.h>
   99 #include <sys/vnode.h>
  100 #include <sys/signalvar.h>
  101 #include <sys/resourcevar.h>
  102 #include <sys/malloc.h>
  103 #include <sys/filedesc.h>
  104 #include <sys/sysctl.h>
  105 
  106 #include <vm/vm.h>
  107 #include <vm/pmap.h>
  108 #include <vm/vm_map.h>
  109 
  110 MALLOC_DEFINE(M_TTYS, "ttys", "tty data structures");
  111 
  112 long tk_cancc;
  113 long tk_nin;
  114 long tk_nout;
  115 long tk_rawcc;
  116 
  117 static int      proc_compare(struct proc *p1, struct proc *p2);
  118 static int      ttnread(struct tty *tp);
  119 static void     ttyecho(int c, struct tty *tp);
  120 static int      ttyoutput(int c, struct tty *tp);
  121 static void     ttypend(struct tty *tp);
  122 static void     ttyretype(struct tty *tp);
  123 static void     ttyrub(int c, struct tty *tp);
  124 static void     ttyrubo(struct tty *tp, int cnt);
  125 static void     ttyunblock(struct tty *tp);
  126 static int      ttywflush(struct tty *tp);
  127 static int      filt_ttyread(struct knote *kn, long hint);
  128 static void     filt_ttyrdetach(struct knote *kn);
  129 static int      filt_ttywrite(struct knote *kn, long hint);
  130 static void     filt_ttywdetach(struct knote *kn);
  131 
  132 /*
  133  * Table with character classes and parity. The 8th bit indicates parity,
  134  * the 7th bit indicates the character is an alphameric or underscore (for
  135  * ALTWERASE), and the low 6 bits indicate delay type.  If the low 6 bits
  136  * are 0 then the character needs no special processing on output; classes
  137  * other than 0 might be translated or (not currently) require delays.
  138  */
  139 #define E       0x00    /* Even parity. */
  140 #define O       0x80    /* Odd parity. */
  141 #define PARITY(c)       (char_type[c] & O)
  142 
  143 #define ALPHA   0x40    /* Alpha or underscore. */
  144 #define ISALPHA(c)      (char_type[(c) & TTY_CHARMASK] & ALPHA)
  145 
  146 #define CCLASSMASK      0x3f
  147 #define CCLASS(c)       (char_type[c] & CCLASSMASK)
  148 
  149 #define BS      BACKSPACE
  150 #define CC      CONTROL
  151 #define CR      RETURN
  152 #define NA      ORDINARY | ALPHA
  153 #define NL      NEWLINE
  154 #define NO      ORDINARY
  155 #define TB      TAB
  156 #define VT      VTAB
  157 
  158 static u_char const char_type[] = {
  159         E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
  160         O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
  161         O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
  162         E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
  163         O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
  164         E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
  165         E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
  166         O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
  167         O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
  168         E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
  169         E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
  170         O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
  171         E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
  172         O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
  173         O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
  174         E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
  175         /*
  176          * Meta chars; should be settable per character set;
  177          * for now, treat them all as normal characters.
  178          */
  179         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  180         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  181         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  182         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  183         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  184         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  185         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  186         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  187         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  188         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  189         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  190         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  191         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  192         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  193         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  194         NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  195 };
  196 #undef  BS
  197 #undef  CC
  198 #undef  CR
  199 #undef  NA
  200 #undef  NL
  201 #undef  NO
  202 #undef  TB
  203 #undef  VT
  204 
  205 /* Macros to clear/set/test flags. */
  206 #define SET(t, f)       (t) |= (f)
  207 #define CLR(t, f)       (t) &= ~(f)
  208 #define ISSET(t, f)     ((t) & (f))
  209 
  210 #undef MAX_INPUT                /* XXX wrong in <sys/syslimits.h> */
  211 #define MAX_INPUT       TTYHOG  /* XXX limit is usually larger for !ICANON */
  212 
  213 /*
  214  * list of struct tty where pstat(8) can pick it up with sysctl
  215  */
  216 static SLIST_HEAD(, tty) tty_list;
  217 
  218 static int  drainwait = 5*60;
  219 SYSCTL_INT(_kern, OID_AUTO, drainwait, CTLFLAG_RW, &drainwait,
  220         0, "Output drain timeout in seconds");
  221 
  222 /*
  223  * Initial open of tty, or (re)entry to standard tty line discipline.
  224  */
  225 int
  226 ttyopen(dev_t device, struct tty *tp)
  227 {
  228         int s;
  229 
  230         s = spltty();
  231         tp->t_dev = device;
  232         if (!ISSET(tp->t_state, TS_ISOPEN)) {
  233                 SET(tp->t_state, TS_ISOPEN);
  234                 if (ISSET(tp->t_cflag, CLOCAL))
  235                         SET(tp->t_state, TS_CONNECTED);
  236                 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
  237         }
  238         /* XXX don't hang forever on output */
  239         if (tp->t_timeout < 0)
  240                 tp->t_timeout = drainwait*hz;
  241         ttsetwater(tp);
  242         splx(s);
  243         return (0);
  244 }
  245 
  246 /*
  247  * Handle close() on a tty line: flush and set to initial state,
  248  * bumping generation number so that pending read/write calls
  249  * can detect recycling of the tty.
  250  * XXX our caller should have done `spltty(); l_close(); ttyclose();'
  251  * and l_close() should have flushed, but we repeat the spltty() and
  252  * the flush in case there are buggy callers.
  253  */
  254 int
  255 ttyclose(struct tty *tp)
  256 {
  257         int s;
  258 
  259         funsetown(&tp->t_sigio);
  260         s = spltty();
  261         if (constty == tp)
  262                 constty = NULL;
  263 
  264         ttyflush(tp, FREAD | FWRITE);
  265         clist_free_cblocks(&tp->t_canq);
  266         clist_free_cblocks(&tp->t_outq);
  267         clist_free_cblocks(&tp->t_rawq);
  268 
  269         tp->t_gen++;
  270         tp->t_line = TTYDISC;
  271         tp->t_pgrp = NULL;
  272         tp->t_session = NULL;
  273         tp->t_state = 0;
  274         splx(s);
  275         return (0);
  276 }
  277 
  278 #define FLUSHQ(q) {                                                     \
  279         if ((q)->c_cc)                                                  \
  280                 ndflush(q, (q)->c_cc);                                  \
  281 }
  282 
  283 /* Is 'c' a line delimiter ("break" character)? */
  284 #define TTBREAKC(c, lflag)                                                      \
  285         ((c) == '\n' || (((c) == cc[VEOF] ||                            \
  286           (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) &&   \
  287          (c) != _POSIX_VDISABLE))
  288 
  289 /*
  290  * Process input of a single character received on a tty.
  291  */
  292 int
  293 ttyinput(int c, struct tty *tp)
  294 {
  295         tcflag_t iflag, lflag;
  296         cc_t *cc;
  297         int i, err;
  298 
  299         /*
  300          * If input is pending take it first.
  301          */
  302         lflag = tp->t_lflag;
  303         if (ISSET(lflag, PENDIN))
  304                 ttypend(tp);
  305         /*
  306          * Gather stats.
  307          */
  308         if (ISSET(lflag, ICANON)) {
  309                 ++tk_cancc;
  310                 ++tp->t_cancc;
  311         } else {
  312                 ++tk_rawcc;
  313                 ++tp->t_rawcc;
  314         }
  315         ++tk_nin;
  316 
  317         /*
  318          * Block further input iff:
  319          * current input > threshold AND input is available to user program
  320          * AND input flow control is enabled and not yet invoked.
  321          * The 3 is slop for PARMRK.
  322          */
  323         iflag = tp->t_iflag;
  324         if (tp->t_rawq.c_cc + tp->t_canq.c_cc > tp->t_ihiwat - 3 &&
  325             (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
  326             (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
  327             !ISSET(tp->t_state, TS_TBLOCK))
  328                 ttyblock(tp);
  329 
  330         /* Handle exceptional conditions (break, parity, framing). */
  331         cc = tp->t_cc;
  332         err = (ISSET(c, TTY_ERRORMASK));
  333         if (err) {
  334                 CLR(c, TTY_ERRORMASK);
  335                 if (ISSET(err, TTY_BI)) {
  336                         if (ISSET(iflag, IGNBRK))
  337                                 return (0);
  338                         if (ISSET(iflag, BRKINT)) {
  339                                 ttyflush(tp, FREAD | FWRITE);
  340                                 if (tp->t_pgrp != NULL) {
  341                                         PGRP_LOCK(tp->t_pgrp);
  342                                         pgsignal(tp->t_pgrp, SIGINT, 1);
  343                                         PGRP_UNLOCK(tp->t_pgrp);
  344                                 }
  345                                 goto endcase;
  346                         }
  347                         if (ISSET(iflag, PARMRK))
  348                                 goto parmrk;
  349                 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
  350                         || ISSET(err, TTY_FE)) {
  351                         if (ISSET(iflag, IGNPAR))
  352                                 return (0);
  353                         else if (ISSET(iflag, PARMRK)) {
  354 parmrk:
  355                                 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
  356                                     MAX_INPUT - 3)
  357                                         goto input_overflow;
  358                                 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
  359                                 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
  360                                 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
  361                                 goto endcase;
  362                         } else
  363                                 c = 0;
  364                 }
  365         }
  366 
  367         if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
  368                 CLR(c, 0x80);
  369         if (!ISSET(lflag, EXTPROC)) {
  370                 /*
  371                  * Check for literal nexting very first
  372                  */
  373                 if (ISSET(tp->t_state, TS_LNCH)) {
  374                         SET(c, TTY_QUOTE);
  375                         CLR(tp->t_state, TS_LNCH);
  376                 }
  377                 /*
  378                  * Scan for special characters.  This code
  379                  * is really just a big case statement with
  380                  * non-constant cases.  The bottom of the
  381                  * case statement is labeled ``endcase'', so goto
  382                  * it after a case match, or similar.
  383                  */
  384 
  385                 /*
  386                  * Control chars which aren't controlled
  387                  * by ICANON, ISIG, or IXON.
  388                  */
  389                 if (ISSET(lflag, IEXTEN)) {
  390                         if (CCEQ(cc[VLNEXT], c)) {
  391                                 if (ISSET(lflag, ECHO)) {
  392                                         if (ISSET(lflag, ECHOE)) {
  393                                                 (void)ttyoutput('^', tp);
  394                                                 (void)ttyoutput('\b', tp);
  395                                         } else
  396                                                 ttyecho(c, tp);
  397                                 }
  398                                 SET(tp->t_state, TS_LNCH);
  399                                 goto endcase;
  400                         }
  401                         if (CCEQ(cc[VDISCARD], c)) {
  402                                 if (ISSET(lflag, FLUSHO))
  403                                         CLR(tp->t_lflag, FLUSHO);
  404                                 else {
  405                                         ttyflush(tp, FWRITE);
  406                                         ttyecho(c, tp);
  407                                         if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
  408                                                 ttyretype(tp);
  409                                         SET(tp->t_lflag, FLUSHO);
  410                                 }
  411                                 goto startoutput;
  412                         }
  413                 }
  414                 /*
  415                  * Signals.
  416                  */
  417                 if (ISSET(lflag, ISIG)) {
  418                         if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
  419                                 if (!ISSET(lflag, NOFLSH))
  420                                         ttyflush(tp, FREAD | FWRITE);
  421                                 ttyecho(c, tp);
  422                                 if (tp->t_pgrp != NULL) {
  423                                         PGRP_LOCK(tp->t_pgrp);
  424                                         pgsignal(tp->t_pgrp,
  425                                             CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
  426                                         PGRP_UNLOCK(tp->t_pgrp);
  427                                 }
  428                                 goto endcase;
  429                         }
  430                         if (CCEQ(cc[VSUSP], c)) {
  431                                 if (!ISSET(lflag, NOFLSH))
  432                                         ttyflush(tp, FREAD);
  433                                 ttyecho(c, tp);
  434                                 if (tp->t_pgrp != NULL) {
  435                                         PGRP_LOCK(tp->t_pgrp);
  436                                         pgsignal(tp->t_pgrp, SIGTSTP, 1);
  437                                         PGRP_UNLOCK(tp->t_pgrp);
  438                                 }
  439                                 goto endcase;
  440                         }
  441                 }
  442                 /*
  443                  * Handle start/stop characters.
  444                  */
  445                 if (ISSET(iflag, IXON)) {
  446                         if (CCEQ(cc[VSTOP], c)) {
  447                                 if (!ISSET(tp->t_state, TS_TTSTOP)) {
  448                                         SET(tp->t_state, TS_TTSTOP);
  449                                         (*tp->t_stop)(tp, 0);
  450                                         return (0);
  451                                 }
  452                                 if (!CCEQ(cc[VSTART], c))
  453                                         return (0);
  454                                 /*
  455                                  * if VSTART == VSTOP then toggle
  456                                  */
  457                                 goto endcase;
  458                         }
  459                         if (CCEQ(cc[VSTART], c))
  460                                 goto restartoutput;
  461                 }
  462                 /*
  463                  * IGNCR, ICRNL, & INLCR
  464                  */
  465                 if (c == '\r') {
  466                         if (ISSET(iflag, IGNCR))
  467                                 return (0);
  468                         else if (ISSET(iflag, ICRNL))
  469                                 c = '\n';
  470                 } else if (c == '\n' && ISSET(iflag, INLCR))
  471                         c = '\r';
  472         }
  473         if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
  474                 /*
  475                  * From here on down canonical mode character
  476                  * processing takes place.
  477                  */
  478                 /*
  479                  * erase or erase2 (^H / ^?)
  480                  */
  481                 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c) ) {
  482                         if (tp->t_rawq.c_cc)
  483                                 ttyrub(unputc(&tp->t_rawq), tp);
  484                         goto endcase;
  485                 }
  486                 /*
  487                  * kill (^U)
  488                  */
  489                 if (CCEQ(cc[VKILL], c)) {
  490                         if (ISSET(lflag, ECHOKE) &&
  491                             tp->t_rawq.c_cc == tp->t_rocount &&
  492                             !ISSET(lflag, ECHOPRT))
  493                                 while (tp->t_rawq.c_cc)
  494                                         ttyrub(unputc(&tp->t_rawq), tp);
  495                         else {
  496                                 ttyecho(c, tp);
  497                                 if (ISSET(lflag, ECHOK) ||
  498                                     ISSET(lflag, ECHOKE))
  499                                         ttyecho('\n', tp);
  500                                 FLUSHQ(&tp->t_rawq);
  501                                 tp->t_rocount = 0;
  502                         }
  503                         CLR(tp->t_state, TS_LOCAL);
  504                         goto endcase;
  505                 }
  506                 /*
  507                  * word erase (^W)
  508                  */
  509                 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
  510                         int ctype;
  511 
  512                         /*
  513                          * erase whitespace
  514                          */
  515                         while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
  516                                 ttyrub(c, tp);
  517                         if (c == -1)
  518                                 goto endcase;
  519                         /*
  520                          * erase last char of word and remember the
  521                          * next chars type (for ALTWERASE)
  522                          */
  523                         ttyrub(c, tp);
  524                         c = unputc(&tp->t_rawq);
  525                         if (c == -1)
  526                                 goto endcase;
  527                         if (c == ' ' || c == '\t') {
  528                                 (void)putc(c, &tp->t_rawq);
  529                                 goto endcase;
  530                         }
  531                         ctype = ISALPHA(c);
  532                         /*
  533                          * erase rest of word
  534                          */
  535                         do {
  536                                 ttyrub(c, tp);
  537                                 c = unputc(&tp->t_rawq);
  538                                 if (c == -1)
  539                                         goto endcase;
  540                         } while (c != ' ' && c != '\t' &&
  541                             (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
  542                         (void)putc(c, &tp->t_rawq);
  543                         goto endcase;
  544                 }
  545                 /*
  546                  * reprint line (^R)
  547                  */
  548                 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
  549                         ttyretype(tp);
  550                         goto endcase;
  551                 }
  552                 /*
  553                  * ^T - kernel info and generate SIGINFO
  554                  */
  555                 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
  556                         if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) {
  557                                 PGRP_LOCK(tp->t_pgrp);
  558                                 pgsignal(tp->t_pgrp, SIGINFO, 1);
  559                                 PGRP_UNLOCK(tp->t_pgrp);
  560                         }
  561                         if (!ISSET(lflag, NOKERNINFO))
  562                                 ttyinfo(tp);
  563                         goto endcase;
  564                 }
  565         }
  566         /*
  567          * Check for input buffer overflow
  568          */
  569         if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
  570 input_overflow:
  571                 if (ISSET(iflag, IMAXBEL)) {
  572                         if (tp->t_outq.c_cc < tp->t_ohiwat)
  573                                 (void)ttyoutput(CTRL('g'), tp);
  574                 }
  575                 goto endcase;
  576         }
  577 
  578         if (   c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
  579              && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
  580                 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
  581 
  582         /*
  583          * Put data char in q for user and
  584          * wakeup on seeing a line delimiter.
  585          */
  586         if (putc(c, &tp->t_rawq) >= 0) {
  587                 if (!ISSET(lflag, ICANON)) {
  588                         ttwakeup(tp);
  589                         ttyecho(c, tp);
  590                         goto endcase;
  591                 }
  592                 if (TTBREAKC(c, lflag)) {
  593                         tp->t_rocount = 0;
  594                         catq(&tp->t_rawq, &tp->t_canq);
  595                         ttwakeup(tp);
  596                 } else if (tp->t_rocount++ == 0)
  597                         tp->t_rocol = tp->t_column;
  598                 if (ISSET(tp->t_state, TS_ERASE)) {
  599                         /*
  600                          * end of prterase \.../
  601                          */
  602                         CLR(tp->t_state, TS_ERASE);
  603                         (void)ttyoutput('/', tp);
  604                 }
  605                 i = tp->t_column;
  606                 ttyecho(c, tp);
  607                 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
  608                         /*
  609                          * Place the cursor over the '^' of the ^D.
  610                          */
  611                         i = imin(2, tp->t_column - i);
  612                         while (i > 0) {
  613                                 (void)ttyoutput('\b', tp);
  614                                 i--;
  615                         }
  616                 }
  617         }
  618 endcase:
  619         /*
  620          * IXANY means allow any character to restart output.
  621          */
  622         if (ISSET(tp->t_state, TS_TTSTOP) &&
  623             !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
  624                 return (0);
  625 restartoutput:
  626         CLR(tp->t_lflag, FLUSHO);
  627         CLR(tp->t_state, TS_TTSTOP);
  628 startoutput:
  629         return (ttstart(tp));
  630 }
  631 
  632 /*
  633  * Output a single character on a tty, doing output processing
  634  * as needed (expanding tabs, newline processing, etc.).
  635  * Returns < 0 if succeeds, otherwise returns char to resend.
  636  * Must be recursive.
  637  */
  638 static int
  639 ttyoutput(int c, struct tty *tp)
  640 {
  641         tcflag_t oflag;
  642         int col, s;
  643 
  644         oflag = tp->t_oflag;
  645         if (!ISSET(oflag, OPOST)) {
  646                 if (ISSET(tp->t_lflag, FLUSHO))
  647                         return (-1);
  648                 if (putc(c, &tp->t_outq))
  649                         return (c);
  650                 tk_nout++;
  651                 tp->t_outcc++;
  652                 return (-1);
  653         }
  654         /*
  655          * Do tab expansion if OXTABS is set.  Special case if we external
  656          * processing, we don't do the tab expansion because we'll probably
  657          * get it wrong.  If tab expansion needs to be done, let it happen
  658          * externally.
  659          */
  660         CLR(c, ~TTY_CHARMASK);
  661         if (c == '\t' &&
  662             ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
  663                 c = 8 - (tp->t_column & 7);
  664                 if (!ISSET(tp->t_lflag, FLUSHO)) {
  665                         s = spltty();           /* Don't interrupt tabs. */
  666                         c -= b_to_q("        ", c, &tp->t_outq);
  667                         tk_nout += c;
  668                         tp->t_outcc += c;
  669                         splx(s);
  670                 }
  671                 tp->t_column += c;
  672                 return (c ? -1 : '\t');
  673         }
  674         if (c == CEOT && ISSET(oflag, ONOEOT))
  675                 return (-1);
  676 
  677         /*
  678          * Newline translation: if ONLCR is set,
  679          * translate newline into "\r\n".
  680          */
  681         if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
  682                 tk_nout++;
  683                 tp->t_outcc++;
  684                 if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq))
  685                         return (c);
  686         }
  687         /* If OCRNL is set, translate "\r" into "\n". */
  688         else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
  689                 c = '\n';
  690         /* If ONOCR is set, don't transmit CRs when on column 0. */
  691         else if (c == '\r' && ISSET(tp->t_oflag, ONOCR) && tp->t_column == 0)
  692                 return (-1);
  693 
  694         tk_nout++;
  695         tp->t_outcc++;
  696         if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
  697                 return (c);
  698 
  699         col = tp->t_column;
  700         switch (CCLASS(c)) {
  701         case BACKSPACE:
  702                 if (col > 0)
  703                         --col;
  704                 break;
  705         case CONTROL:
  706                 break;
  707         case NEWLINE:
  708                 if (ISSET(tp->t_oflag, ONLCR | ONLRET))
  709                         col = 0;
  710                 break;
  711         case RETURN:
  712                 col = 0;
  713                 break;
  714         case ORDINARY:
  715                 ++col;
  716                 break;
  717         case TAB:
  718                 col = (col + 8) & ~7;
  719                 break;
  720         }
  721         tp->t_column = col;
  722         return (-1);
  723 }
  724 
  725 /*
  726  * Ioctls for all tty devices.  Called after line-discipline specific ioctl
  727  * has been called to do discipline-specific functions and/or reject any
  728  * of these ioctl commands.
  729  */
  730 /* ARGSUSED */
  731 int
  732 ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
  733 {
  734         struct proc *p;
  735         struct thread *td;
  736         struct pgrp *pgrp;
  737         int s, error;
  738 
  739         td = curthread;                 /* XXX */
  740         p = td->td_proc;
  741 
  742         /* If the ioctl involves modification, hang if in the background. */
  743         switch (cmd) {
  744         case  TIOCCBRK:
  745         case  TIOCCONS:
  746         case  TIOCDRAIN:
  747         case  TIOCEXCL:
  748         case  TIOCFLUSH:
  749 #ifdef TIOCHPCL
  750         case  TIOCHPCL:
  751 #endif
  752         case  TIOCNXCL:
  753         case  TIOCSBRK:
  754         case  TIOCSCTTY:
  755         case  TIOCSDRAINWAIT:
  756         case  TIOCSETA:
  757         case  TIOCSETAF:
  758         case  TIOCSETAW:
  759         case  TIOCSETD:
  760         case  TIOCSPGRP:
  761         case  TIOCSTART:
  762         case  TIOCSTAT:
  763         case  TIOCSTI:
  764         case  TIOCSTOP:
  765         case  TIOCSWINSZ:
  766 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
  767         case  TIOCLBIC:
  768         case  TIOCLBIS:
  769         case  TIOCLSET:
  770         case  TIOCSETC:
  771         case OTIOCSETD:
  772         case  TIOCSETN:
  773         case  TIOCSETP:
  774         case  TIOCSLTC:
  775 #endif
  776                 sx_slock(&proctree_lock);
  777                 PROC_LOCK(p);
  778                 while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) &&
  779                     !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) &&
  780                     !SIGISMEMBER(td->td_sigmask, SIGTTOU)) {
  781                         pgrp = p->p_pgrp;
  782                         PROC_UNLOCK(p);
  783                         if (pgrp->pg_jobc == 0) {
  784                                 sx_sunlock(&proctree_lock);
  785                                 return (EIO);
  786                         }
  787                         PGRP_LOCK(pgrp);
  788                         sx_sunlock(&proctree_lock);
  789                         pgsignal(pgrp, SIGTTOU, 1);
  790                         PGRP_UNLOCK(pgrp);
  791                         error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1",
  792                                          0);
  793                         if (error)
  794                                 return (error);
  795                         sx_slock(&proctree_lock);
  796                         PROC_LOCK(p);
  797                 }
  798                 PROC_UNLOCK(p);
  799                 sx_sunlock(&proctree_lock);
  800                 break;
  801         }
  802 
  803         switch (cmd) {                  /* Process the ioctl. */
  804         case FIOASYNC:                  /* set/clear async i/o */
  805                 s = spltty();
  806                 if (*(int *)data)
  807                         SET(tp->t_state, TS_ASYNC);
  808                 else
  809                         CLR(tp->t_state, TS_ASYNC);
  810                 splx(s);
  811                 break;
  812         case FIONBIO:                   /* set/clear non-blocking i/o */
  813                 break;                  /* XXX: delete. */
  814         case FIONREAD:                  /* get # bytes to read */
  815                 s = spltty();
  816                 *(int *)data = ttnread(tp);
  817                 splx(s);
  818                 break;
  819 
  820         case FIOSETOWN:
  821                 /*
  822                  * Policy -- Don't allow FIOSETOWN on someone else's
  823                  *           controlling tty
  824                  */
  825                 if (tp->t_session != NULL && !isctty(p, tp))
  826                         return (ENOTTY);
  827 
  828                 error = fsetown(*(int *)data, &tp->t_sigio);
  829                 if (error)
  830                         return (error);
  831                 break;
  832         case FIOGETOWN:
  833                 if (tp->t_session != NULL && !isctty(p, tp))
  834                         return (ENOTTY);
  835                 *(int *)data = fgetown(&tp->t_sigio);
  836                 break;
  837 
  838         case TIOCEXCL:                  /* set exclusive use of tty */
  839                 s = spltty();
  840                 SET(tp->t_state, TS_XCLUDE);
  841                 splx(s);
  842                 break;
  843         case TIOCFLUSH: {               /* flush buffers */
  844                 int flags = *(int *)data;
  845 
  846                 if (flags == 0)
  847                         flags = FREAD | FWRITE;
  848                 else
  849                         flags &= FREAD | FWRITE;
  850                 ttyflush(tp, flags);
  851                 break;
  852         }
  853         case TIOCCONS:                  /* become virtual console */
  854                 if (*(int *)data) {
  855                         struct nameidata nid;
  856 
  857                         if (constty && constty != tp &&
  858                             ISSET(constty->t_state, TS_CONNECTED))
  859                                 return (EBUSY);
  860 
  861                         /* Ensure user can open the real console. */
  862                         NDINIT(&nid, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE,
  863                             "/dev/console", td);
  864                         if ((error = namei(&nid)) != 0)
  865                                 return (error);
  866                         NDFREE(&nid, NDF_ONLY_PNBUF);
  867                         error = VOP_ACCESS(nid.ni_vp, VREAD, td->td_ucred, td);
  868                         vput(nid.ni_vp);
  869                         if (error)
  870                                 return (error);
  871 
  872                         constty = tp;
  873                 } else if (tp == constty)
  874                         constty = NULL;
  875                 break;
  876         case TIOCDRAIN:                 /* wait till output drained */
  877                 error = ttywait(tp);
  878                 if (error)
  879                         return (error);
  880                 break;
  881         case TIOCGETA: {                /* get termios struct */
  882                 struct termios *t = (struct termios *)data;
  883 
  884                 bcopy(&tp->t_termios, t, sizeof(struct termios));
  885                 break;
  886         }
  887         case TIOCGETD:                  /* get line discipline */
  888                 *(int *)data = tp->t_line;
  889                 break;
  890         case TIOCGWINSZ:                /* get window size */
  891                 *(struct winsize *)data = tp->t_winsize;
  892                 break;
  893         case TIOCGPGRP:                 /* get pgrp of tty */
  894                 if (!isctty(p, tp))
  895                         return (ENOTTY);
  896                 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
  897                 break;
  898 #ifdef TIOCHPCL
  899         case TIOCHPCL:                  /* hang up on last close */
  900                 s = spltty();
  901                 SET(tp->t_cflag, HUPCL);
  902                 splx(s);
  903                 break;
  904 #endif
  905         case TIOCNXCL:                  /* reset exclusive use of tty */
  906                 s = spltty();
  907                 CLR(tp->t_state, TS_XCLUDE);
  908                 splx(s);
  909                 break;
  910         case TIOCOUTQ:                  /* output queue size */
  911                 *(int *)data = tp->t_outq.c_cc;
  912                 break;
  913         case TIOCSETA:                  /* set termios struct */
  914         case TIOCSETAW:                 /* drain output, set */
  915         case TIOCSETAF: {               /* drn out, fls in, set */
  916                 struct termios *t = (struct termios *)data;
  917 
  918                 if (t->c_ispeed == 0)
  919                         t->c_ispeed = t->c_ospeed;
  920                 if (t->c_ispeed == 0)
  921                         t->c_ispeed = tp->t_ospeed;
  922                 if (t->c_ispeed == 0)
  923                         return (EINVAL);
  924                 s = spltty();
  925                 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
  926                         error = ttywait(tp);
  927                         if (error) {
  928                                 splx(s);
  929                                 return (error);
  930                         }
  931                         if (cmd == TIOCSETAF)
  932                                 ttyflush(tp, FREAD);
  933                 }
  934                 if (!ISSET(t->c_cflag, CIGNORE)) {
  935                         /*
  936                          * Set device hardware.
  937                          */
  938                         if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
  939                                 splx(s);
  940                                 return (error);
  941                         }
  942                         if (ISSET(t->c_cflag, CLOCAL) &&
  943                             !ISSET(tp->t_cflag, CLOCAL)) {
  944                                 /*
  945                                  * XXX disconnections would be too hard to
  946                                  * get rid of without this kludge.  The only
  947                                  * way to get rid of controlling terminals
  948                                  * is to exit from the session leader.
  949                                  */
  950                                 CLR(tp->t_state, TS_ZOMBIE);
  951 
  952                                 wakeup(TSA_CARR_ON(tp));
  953                                 ttwakeup(tp);
  954                                 ttwwakeup(tp);
  955                         }
  956                         if ((ISSET(tp->t_state, TS_CARR_ON) ||
  957                              ISSET(t->c_cflag, CLOCAL)) &&
  958                             !ISSET(tp->t_state, TS_ZOMBIE))
  959                                 SET(tp->t_state, TS_CONNECTED);
  960                         else
  961                                 CLR(tp->t_state, TS_CONNECTED);
  962                         tp->t_cflag = t->c_cflag;
  963                         tp->t_ispeed = t->c_ispeed;
  964                         if (t->c_ospeed != 0)
  965                                 tp->t_ospeed = t->c_ospeed;
  966                         ttsetwater(tp);
  967                 }
  968                 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
  969                     cmd != TIOCSETAF) {
  970                         if (ISSET(t->c_lflag, ICANON))
  971                                 SET(tp->t_lflag, PENDIN);
  972                         else {
  973                                 /*
  974                                  * XXX we really shouldn't allow toggling
  975                                  * ICANON while we're in a non-termios line
  976                                  * discipline.  Now we have to worry about
  977                                  * panicing for a null queue.
  978                                  */
  979                                 if (tp->t_canq.c_cbreserved > 0 &&
  980                                     tp->t_rawq.c_cbreserved > 0) {
  981                                         catq(&tp->t_rawq, &tp->t_canq);
  982                                         /*
  983                                          * XXX the queue limits may be
  984                                          * different, so the old queue
  985                                          * swapping method no longer works.
  986                                          */
  987                                         catq(&tp->t_canq, &tp->t_rawq);
  988                                 }
  989                                 CLR(tp->t_lflag, PENDIN);
  990                         }
  991                         ttwakeup(tp);
  992                 }
  993                 tp->t_iflag = t->c_iflag;
  994                 tp->t_oflag = t->c_oflag;
  995                 /*
  996                  * Make the EXTPROC bit read only.
  997                  */
  998                 if (ISSET(tp->t_lflag, EXTPROC))
  999                         SET(t->c_lflag, EXTPROC);
 1000                 else
 1001                         CLR(t->c_lflag, EXTPROC);
 1002                 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
 1003                 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
 1004                     t->c_cc[VTIME] != tp->t_cc[VTIME])
 1005                         ttwakeup(tp);
 1006                 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
 1007                 splx(s);
 1008                 break;
 1009         }
 1010         case TIOCSETD: {                /* set line discipline */
 1011                 int t = *(int *)data;
 1012                 dev_t device = tp->t_dev;
 1013 
 1014                 if ((u_int)t >= nlinesw)
 1015                         return (ENXIO);
 1016                 if (t != tp->t_line) {
 1017                         s = spltty();
 1018                         (*linesw[tp->t_line].l_close)(tp, flag);
 1019                         error = (*linesw[t].l_open)(device, tp);
 1020                         if (error) {
 1021                                 (void)(*linesw[tp->t_line].l_open)(device, tp);
 1022                                 splx(s);
 1023                                 return (error);
 1024                         }
 1025                         tp->t_line = t;
 1026                         splx(s);
 1027                 }
 1028                 break;
 1029         }
 1030         case TIOCSTART:                 /* start output, like ^Q */
 1031                 s = spltty();
 1032                 if (ISSET(tp->t_state, TS_TTSTOP) ||
 1033                     ISSET(tp->t_lflag, FLUSHO)) {
 1034                         CLR(tp->t_lflag, FLUSHO);
 1035                         CLR(tp->t_state, TS_TTSTOP);
 1036                         ttstart(tp);
 1037                 }
 1038                 splx(s);
 1039                 break;
 1040         case TIOCSTI:                   /* simulate terminal input */
 1041                 if ((flag & FREAD) == 0 && suser(td))
 1042                         return (EPERM);
 1043                 if (!isctty(p, tp) && suser(td))
 1044                         return (EACCES);
 1045                 s = spltty();
 1046                 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
 1047                 splx(s);
 1048                 break;
 1049         case TIOCSTOP:                  /* stop output, like ^S */
 1050                 s = spltty();
 1051                 if (!ISSET(tp->t_state, TS_TTSTOP)) {
 1052                         SET(tp->t_state, TS_TTSTOP);
 1053                         (*tp->t_stop)(tp, 0);
 1054                 }
 1055                 splx(s);
 1056                 break;
 1057         case TIOCSCTTY:                 /* become controlling tty */
 1058                 /* Session ctty vnode pointer set in vnode layer. */
 1059                 sx_slock(&proctree_lock);
 1060                 if (!SESS_LEADER(p) ||
 1061                     ((p->p_session->s_ttyvp || tp->t_session) &&
 1062                      (tp->t_session != p->p_session))) {
 1063                         sx_sunlock(&proctree_lock);
 1064                         return (EPERM);
 1065                 }
 1066                 tp->t_session = p->p_session;
 1067                 tp->t_pgrp = p->p_pgrp;
 1068                 SESS_LOCK(p->p_session);
 1069                 p->p_session->s_ttyp = tp;
 1070                 SESS_UNLOCK(p->p_session);
 1071                 PROC_LOCK(p);
 1072                 p->p_flag |= P_CONTROLT;
 1073                 PROC_UNLOCK(p);
 1074                 sx_sunlock(&proctree_lock);
 1075                 break;
 1076         case TIOCSPGRP: {               /* set pgrp of tty */
 1077                 sx_slock(&proctree_lock);
 1078                 pgrp = pgfind(*(int *)data);
 1079                 if (!isctty(p, tp)) {
 1080                         if (pgrp != NULL)
 1081                                 PGRP_UNLOCK(pgrp);
 1082                         sx_sunlock(&proctree_lock);
 1083                         return (ENOTTY);
 1084                 }
 1085                 if (pgrp == NULL) {
 1086                         sx_sunlock(&proctree_lock);
 1087                         return (EPERM);
 1088                 }
 1089                 PGRP_UNLOCK(pgrp);
 1090                 if (pgrp->pg_session != p->p_session) {
 1091                         sx_sunlock(&proctree_lock);
 1092                         return (EPERM);
 1093                 }
 1094                 sx_sunlock(&proctree_lock);
 1095                 tp->t_pgrp = pgrp;
 1096                 break;
 1097         }
 1098         case TIOCSTAT:                  /* simulate control-T */
 1099                 s = spltty();
 1100                 ttyinfo(tp);
 1101                 splx(s);
 1102                 break;
 1103         case TIOCSWINSZ:                /* set window size */
 1104                 if (bcmp((caddr_t)&tp->t_winsize, data,
 1105                     sizeof (struct winsize))) {
 1106                         tp->t_winsize = *(struct winsize *)data;
 1107                         if (tp->t_pgrp != NULL) {
 1108                                 PGRP_LOCK(tp->t_pgrp);
 1109                                 pgsignal(tp->t_pgrp, SIGWINCH, 1);
 1110                                 PGRP_UNLOCK(tp->t_pgrp);
 1111                         }
 1112                 }
 1113                 break;
 1114         case TIOCSDRAINWAIT:
 1115                 error = suser(td);
 1116                 if (error)
 1117                         return (error);
 1118                 tp->t_timeout = *(int *)data * hz;
 1119                 wakeup(TSA_OCOMPLETE(tp));
 1120                 wakeup(TSA_OLOWAT(tp));
 1121                 break;
 1122         case TIOCGDRAINWAIT:
 1123                 *(int *)data = tp->t_timeout / hz;
 1124                 break;
 1125         default:
 1126 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1127                 return (ttcompat(tp, cmd, data, flag));
 1128 #else
 1129                 return (ENOIOCTL);
 1130 #endif
 1131         }
 1132         return (0);
 1133 }
 1134 
 1135 int
 1136 ttypoll(dev_t dev, int events, struct thread *td)
 1137 {
 1138         int s;
 1139         int revents = 0;
 1140         struct tty *tp;
 1141 
 1142         tp = dev->si_tty;
 1143         if (tp == NULL) /* XXX used to return ENXIO, but that means true! */
 1144                 return ((events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM))
 1145                         | POLLHUP);
 1146 
 1147         s = spltty();
 1148         if (events & (POLLIN | POLLRDNORM)) {
 1149                 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
 1150                         revents |= events & (POLLIN | POLLRDNORM);
 1151                 else
 1152                         selrecord(td, &tp->t_rsel);
 1153         }
 1154         if (events & (POLLOUT | POLLWRNORM)) {
 1155                 if ((tp->t_outq.c_cc <= tp->t_olowat &&
 1156                      ISSET(tp->t_state, TS_CONNECTED))
 1157                     || ISSET(tp->t_state, TS_ZOMBIE))
 1158                         revents |= events & (POLLOUT | POLLWRNORM);
 1159                 else
 1160                         selrecord(td, &tp->t_wsel);
 1161         }
 1162         splx(s);
 1163         return (revents);
 1164 }
 1165 
 1166 static struct filterops ttyread_filtops =
 1167         { 1, NULL, filt_ttyrdetach, filt_ttyread };
 1168 static struct filterops ttywrite_filtops =
 1169         { 1, NULL, filt_ttywdetach, filt_ttywrite };
 1170 
 1171 int
 1172 ttykqfilter(dev_t dev, struct knote *kn)
 1173 {
 1174         struct tty *tp = dev->si_tty;
 1175         struct klist *klist;
 1176         int s;
 1177 
 1178         switch (kn->kn_filter) {
 1179         case EVFILT_READ:
 1180                 klist = &tp->t_rsel.si_note;
 1181                 kn->kn_fop = &ttyread_filtops;
 1182                 break;
 1183         case EVFILT_WRITE:
 1184                 klist = &tp->t_wsel.si_note;
 1185                 kn->kn_fop = &ttywrite_filtops;
 1186                 break;
 1187         default:
 1188                 return (1);
 1189         }
 1190 
 1191         kn->kn_hook = (caddr_t)dev;
 1192 
 1193         s = spltty();
 1194         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
 1195         splx(s);
 1196 
 1197         return (0);
 1198 }
 1199 
 1200 static void
 1201 filt_ttyrdetach(struct knote *kn)
 1202 {
 1203         struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
 1204         int s = spltty();
 1205 
 1206         SLIST_REMOVE(&tp->t_rsel.si_note, kn, knote, kn_selnext);
 1207         splx(s);
 1208 }
 1209 
 1210 static int
 1211 filt_ttyread(struct knote *kn, long hint)
 1212 {
 1213         struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
 1214 
 1215         kn->kn_data = ttnread(tp);
 1216         if (ISSET(tp->t_state, TS_ZOMBIE)) {
 1217                 kn->kn_flags |= EV_EOF;
 1218                 return (1);
 1219         }
 1220         return (kn->kn_data > 0);
 1221 }
 1222 
 1223 static void
 1224 filt_ttywdetach(struct knote *kn)
 1225 {
 1226         struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
 1227         int s = spltty();
 1228 
 1229         SLIST_REMOVE(&tp->t_wsel.si_note, kn, knote, kn_selnext);
 1230         splx(s);
 1231 }
 1232 
 1233 static int
 1234 filt_ttywrite(struct knote *kn, long hint)
 1235 {
 1236         struct tty *tp = ((dev_t)kn->kn_hook)->si_tty;
 1237 
 1238         kn->kn_data = tp->t_outq.c_cc;
 1239         if (ISSET(tp->t_state, TS_ZOMBIE))
 1240                 return (1);
 1241         return (kn->kn_data <= tp->t_olowat &&
 1242             ISSET(tp->t_state, TS_CONNECTED));
 1243 }
 1244 
 1245 /*
 1246  * Must be called at spltty().
 1247  */
 1248 static int
 1249 ttnread(struct tty *tp)
 1250 {
 1251         int nread;
 1252 
 1253         if (ISSET(tp->t_lflag, PENDIN))
 1254                 ttypend(tp);
 1255         nread = tp->t_canq.c_cc;
 1256         if (!ISSET(tp->t_lflag, ICANON)) {
 1257                 nread += tp->t_rawq.c_cc;
 1258                 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
 1259                         nread = 0;
 1260         }
 1261         return (nread);
 1262 }
 1263 
 1264 /*
 1265  * Wait for output to drain.
 1266  */
 1267 int
 1268 ttywait(struct tty *tp)
 1269 {
 1270         int error, s;
 1271 
 1272         error = 0;
 1273         s = spltty();
 1274         while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
 1275                ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
 1276                 (*tp->t_oproc)(tp);
 1277                 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
 1278                     ISSET(tp->t_state, TS_CONNECTED)) {
 1279                         SET(tp->t_state, TS_SO_OCOMPLETE);
 1280                         error = ttysleep(tp, TSA_OCOMPLETE(tp),
 1281                                          TTOPRI | PCATCH, "ttywai",
 1282                                          tp->t_timeout);
 1283                         if (error) {
 1284                                 if (error == EWOULDBLOCK)
 1285                                         error = EIO;
 1286                                 break;
 1287                         }
 1288                 } else
 1289                         break;
 1290         }
 1291         if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
 1292                 error = EIO;
 1293         splx(s);
 1294         return (error);
 1295 }
 1296 
 1297 /*
 1298  * Flush if successfully wait.
 1299  */
 1300 static int
 1301 ttywflush(struct tty *tp)
 1302 {
 1303         int error;
 1304 
 1305         if ((error = ttywait(tp)) == 0)
 1306                 ttyflush(tp, FREAD);
 1307         return (error);
 1308 }
 1309 
 1310 /*
 1311  * Flush tty read and/or write queues, notifying anyone waiting.
 1312  */
 1313 void
 1314 ttyflush(struct tty *tp, int rw)
 1315 {
 1316         int s;
 1317 
 1318         s = spltty();
 1319 #if 0
 1320 again:
 1321 #endif
 1322         if (rw & FWRITE) {
 1323                 FLUSHQ(&tp->t_outq);
 1324                 CLR(tp->t_state, TS_TTSTOP);
 1325         }
 1326         (*tp->t_stop)(tp, rw);
 1327         if (rw & FREAD) {
 1328                 FLUSHQ(&tp->t_canq);
 1329                 FLUSHQ(&tp->t_rawq);
 1330                 CLR(tp->t_lflag, PENDIN);
 1331                 tp->t_rocount = 0;
 1332                 tp->t_rocol = 0;
 1333                 CLR(tp->t_state, TS_LOCAL);
 1334                 ttwakeup(tp);
 1335                 if (ISSET(tp->t_state, TS_TBLOCK)) {
 1336                         if (rw & FWRITE)
 1337                                 FLUSHQ(&tp->t_outq);
 1338                         ttyunblock(tp);
 1339 
 1340                         /*
 1341                          * Don't let leave any state that might clobber the
 1342                          * next line discipline (although we should do more
 1343                          * to send the START char).  Not clearing the state
 1344                          * may have caused the "putc to a clist with no
 1345                          * reserved cblocks" panic/printf.
 1346                          */
 1347                         CLR(tp->t_state, TS_TBLOCK);
 1348 
 1349 #if 0 /* forget it, sleeping isn't always safe and we don't know when it is */
 1350                         if (ISSET(tp->t_iflag, IXOFF)) {
 1351                                 /*
 1352                                  * XXX wait a bit in the hope that the stop
 1353                                  * character (if any) will go out.  Waiting
 1354                                  * isn't good since it allows races.  This
 1355                                  * will be fixed when the stop character is
 1356                                  * put in a special queue.  Don't bother with
 1357                                  * the checks in ttywait() since the timeout
 1358                                  * will save us.
 1359                                  */
 1360                                 SET(tp->t_state, TS_SO_OCOMPLETE);
 1361                                 ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI,
 1362                                          "ttyfls", hz / 10);
 1363                                 /*
 1364                                  * Don't try sending the stop character again.
 1365                                  */
 1366                                 CLR(tp->t_state, TS_TBLOCK);
 1367                                 goto again;
 1368                         }
 1369 #endif
 1370                 }
 1371         }
 1372         if (rw & FWRITE) {
 1373                 FLUSHQ(&tp->t_outq);
 1374                 ttwwakeup(tp);
 1375         }
 1376         splx(s);
 1377 }
 1378 
 1379 /*
 1380  * Copy in the default termios characters.
 1381  */
 1382 void
 1383 termioschars(struct termios *t)
 1384 {
 1385 
 1386         bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
 1387 }
 1388 
 1389 /*
 1390  * Old interface.
 1391  */
 1392 void
 1393 ttychars(struct tty *tp)
 1394 {
 1395 
 1396         termioschars(&tp->t_termios);
 1397 }
 1398 
 1399 /*
 1400  * Handle input high water.  Send stop character for the IXOFF case.  Turn
 1401  * on our input flow control bit and propagate the changes to the driver.
 1402  * XXX the stop character should be put in a special high priority queue.
 1403  */
 1404 void
 1405 ttyblock(struct tty *tp)
 1406 {
 1407 
 1408         SET(tp->t_state, TS_TBLOCK);
 1409         if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
 1410             putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
 1411                 CLR(tp->t_state, TS_TBLOCK);    /* try again later */
 1412         ttstart(tp);
 1413 }
 1414 
 1415 /*
 1416  * Handle input low water.  Send start character for the IXOFF case.  Turn
 1417  * off our input flow control bit and propagate the changes to the driver.
 1418  * XXX the start character should be put in a special high priority queue.
 1419  */
 1420 static void
 1421 ttyunblock(struct tty *tp)
 1422 {
 1423 
 1424         CLR(tp->t_state, TS_TBLOCK);
 1425         if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
 1426             putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
 1427                 SET(tp->t_state, TS_TBLOCK);    /* try again later */
 1428         ttstart(tp);
 1429 }
 1430 
 1431 #ifdef notyet
 1432 /* Not used by any current (i386) drivers. */
 1433 /*
 1434  * Restart after an inter-char delay.
 1435  */
 1436 void
 1437 ttrstrt(void *tp_arg)
 1438 {
 1439         struct tty *tp;
 1440         int s;
 1441 
 1442         KASSERT(tp_arg != NULL, ("ttrstrt"));
 1443 
 1444         tp = tp_arg;
 1445         s = spltty();
 1446 
 1447         CLR(tp->t_state, TS_TIMEOUT);
 1448         ttstart(tp);
 1449 
 1450         splx(s);
 1451 }
 1452 #endif
 1453 
 1454 int
 1455 ttstart(struct tty *tp)
 1456 {
 1457 
 1458         if (tp->t_oproc != NULL)        /* XXX: Kludge for pty. */
 1459                 (*tp->t_oproc)(tp);
 1460         return (0);
 1461 }
 1462 
 1463 /*
 1464  * "close" a line discipline
 1465  */
 1466 int
 1467 ttylclose(struct tty *tp, int flag)
 1468 {
 1469 
 1470         if (flag & FNONBLOCK || ttywflush(tp))
 1471                 ttyflush(tp, FREAD | FWRITE);
 1472         return (0);
 1473 }
 1474 
 1475 /*
 1476  * Handle modem control transition on a tty.
 1477  * Flag indicates new state of carrier.
 1478  * Returns 0 if the line should be turned off, otherwise 1.
 1479  */
 1480 int
 1481 ttymodem(struct tty *tp, int flag)
 1482 {
 1483 
 1484         if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
 1485                 /*
 1486                  * MDMBUF: do flow control according to carrier flag
 1487                  * XXX TS_CAR_OFLOW doesn't do anything yet.  TS_TTSTOP
 1488                  * works if IXON and IXANY are clear.
 1489                  */
 1490                 if (flag) {
 1491                         CLR(tp->t_state, TS_CAR_OFLOW);
 1492                         CLR(tp->t_state, TS_TTSTOP);
 1493                         ttstart(tp);
 1494                 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
 1495                         SET(tp->t_state, TS_CAR_OFLOW);
 1496                         SET(tp->t_state, TS_TTSTOP);
 1497                         (*tp->t_stop)(tp, 0);
 1498                 }
 1499         } else if (flag == 0) {
 1500                 /*
 1501                  * Lost carrier.
 1502                  */
 1503                 CLR(tp->t_state, TS_CARR_ON);
 1504                 if (ISSET(tp->t_state, TS_ISOPEN) &&
 1505                     !ISSET(tp->t_cflag, CLOCAL)) {
 1506                         SET(tp->t_state, TS_ZOMBIE);
 1507                         CLR(tp->t_state, TS_CONNECTED);
 1508                         if (tp->t_session) {
 1509                                 sx_slock(&proctree_lock);
 1510                                 if (tp->t_session->s_leader) {
 1511                                         struct proc *p;
 1512 
 1513                                         p = tp->t_session->s_leader;
 1514                                         PROC_LOCK(p);
 1515                                         psignal(p, SIGHUP);
 1516                                         PROC_UNLOCK(p);
 1517                                 }
 1518                                 sx_sunlock(&proctree_lock);
 1519                         }
 1520                         ttyflush(tp, FREAD | FWRITE);
 1521                         return (0);
 1522                 }
 1523         } else {
 1524                 /*
 1525                  * Carrier now on.
 1526                  */
 1527                 SET(tp->t_state, TS_CARR_ON);
 1528                 if (!ISSET(tp->t_state, TS_ZOMBIE))
 1529                         SET(tp->t_state, TS_CONNECTED);
 1530                 wakeup(TSA_CARR_ON(tp));
 1531                 ttwakeup(tp);
 1532                 ttwwakeup(tp);
 1533         }
 1534         return (1);
 1535 }
 1536 
 1537 /*
 1538  * Reinput pending characters after state switch
 1539  * call at spltty().
 1540  */
 1541 static void
 1542 ttypend(struct tty *tp)
 1543 {
 1544         struct clist tq;
 1545         int c;
 1546 
 1547         CLR(tp->t_lflag, PENDIN);
 1548         SET(tp->t_state, TS_TYPEN);
 1549         /*
 1550          * XXX this assumes too much about clist internals.  It may even
 1551          * fail if the cblock slush pool is empty.  We can't allocate more
 1552          * cblocks here because we are called from an interrupt handler
 1553          * and clist_alloc_cblocks() can wait.
 1554          */
 1555         tq = tp->t_rawq;
 1556         bzero(&tp->t_rawq, sizeof tp->t_rawq);
 1557         tp->t_rawq.c_cbmax = tq.c_cbmax;
 1558         tp->t_rawq.c_cbreserved = tq.c_cbreserved;
 1559         while ((c = getc(&tq)) >= 0)
 1560                 ttyinput(c, tp);
 1561         CLR(tp->t_state, TS_TYPEN);
 1562 }
 1563 
 1564 /*
 1565  * Process a read call on a tty device.
 1566  */
 1567 int
 1568 ttread(struct tty *tp, struct uio *uio, int flag)
 1569 {
 1570         struct clist *qp;
 1571         int c;
 1572         tcflag_t lflag;
 1573         cc_t *cc = tp->t_cc;
 1574         struct thread *td;
 1575         struct proc *p;
 1576         int s, first, error = 0;
 1577         int has_stime = 0, last_cc = 0;
 1578         long slp = 0;           /* XXX this should be renamed `timo'. */
 1579         struct timeval stime;
 1580         struct pgrp *pg;
 1581 
 1582         td = curthread;
 1583         p = td->td_proc;
 1584 loop:
 1585         s = spltty();
 1586         lflag = tp->t_lflag;
 1587         /*
 1588          * take pending input first
 1589          */
 1590         if (ISSET(lflag, PENDIN)) {
 1591                 ttypend(tp);
 1592                 splx(s);        /* reduce latency */
 1593                 s = spltty();
 1594                 lflag = tp->t_lflag;    /* XXX ttypend() clobbers it */
 1595         }
 1596 
 1597         /*
 1598          * Hang process if it's in the background.
 1599          */
 1600         if (isbackground(p, tp)) {
 1601                 splx(s);
 1602                 sx_slock(&proctree_lock);
 1603                 PROC_LOCK(p);
 1604                 if (SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTIN) ||
 1605                     SIGISMEMBER(td->td_sigmask, SIGTTIN) ||
 1606                     (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) {
 1607                         PROC_UNLOCK(p);
 1608                         sx_sunlock(&proctree_lock);
 1609                         return (EIO);
 1610                 }
 1611                 pg = p->p_pgrp;
 1612                 PROC_UNLOCK(p);
 1613                 PGRP_LOCK(pg);
 1614                 sx_sunlock(&proctree_lock);
 1615                 pgsignal(pg, SIGTTIN, 1);
 1616                 PGRP_UNLOCK(pg);
 1617                 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);
 1618                 if (error)
 1619                         return (error);
 1620                 goto loop;
 1621         }
 1622 
 1623         if (ISSET(tp->t_state, TS_ZOMBIE)) {
 1624                 splx(s);
 1625                 return (0);     /* EOF */
 1626         }
 1627 
 1628         /*
 1629          * If canonical, use the canonical queue,
 1630          * else use the raw queue.
 1631          *
 1632          * (should get rid of clists...)
 1633          */
 1634         qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
 1635 
 1636         if (flag & IO_NDELAY) {
 1637                 if (qp->c_cc > 0)
 1638                         goto read;
 1639                 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
 1640                         splx(s);
 1641                         return (0);
 1642                 }
 1643                 splx(s);
 1644                 return (EWOULDBLOCK);
 1645         }
 1646         if (!ISSET(lflag, ICANON)) {
 1647                 int m = cc[VMIN];
 1648                 long t = cc[VTIME];
 1649                 struct timeval timecopy;
 1650 
 1651                 /*
 1652                  * Check each of the four combinations.
 1653                  * (m > 0 && t == 0) is the normal read case.
 1654                  * It should be fairly efficient, so we check that and its
 1655                  * companion case (m == 0 && t == 0) first.
 1656                  * For the other two cases, we compute the target sleep time
 1657                  * into slp.
 1658                  */
 1659                 if (t == 0) {
 1660                         if (qp->c_cc < m)
 1661                                 goto sleep;
 1662                         if (qp->c_cc > 0)
 1663                                 goto read;
 1664 
 1665                         /* m, t and qp->c_cc are all 0.  0 is enough input. */
 1666                         splx(s);
 1667                         return (0);
 1668                 }
 1669                 t *= 100000;            /* time in us */
 1670 #define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
 1671                          ((t1).tv_usec - (t2).tv_usec))
 1672                 if (m > 0) {
 1673                         if (qp->c_cc <= 0)
 1674                                 goto sleep;
 1675                         if (qp->c_cc >= m)
 1676                                 goto read;
 1677                         getmicrotime(&timecopy);
 1678                         if (!has_stime) {
 1679                                 /* first character, start timer */
 1680                                 has_stime = 1;
 1681                                 stime = timecopy;
 1682                                 slp = t;
 1683                         } else if (qp->c_cc > last_cc) {
 1684                                 /* got a character, restart timer */
 1685                                 stime = timecopy;
 1686                                 slp = t;
 1687                         } else {
 1688                                 /* nothing, check expiration */
 1689                                 slp = t - diff(timecopy, stime);
 1690                                 if (slp <= 0)
 1691                                         goto read;
 1692                         }
 1693                         last_cc = qp->c_cc;
 1694                 } else {        /* m == 0 */
 1695                         if (qp->c_cc > 0)
 1696                                 goto read;
 1697                         getmicrotime(&timecopy);
 1698                         if (!has_stime) {
 1699                                 has_stime = 1;
 1700                                 stime = timecopy;
 1701                                 slp = t;
 1702                         } else {
 1703                                 slp = t - diff(timecopy, stime);
 1704                                 if (slp <= 0) {
 1705                                         /* Timed out, but 0 is enough input. */
 1706                                         splx(s);
 1707                                         return (0);
 1708                                 }
 1709                         }
 1710                 }
 1711 #undef diff
 1712                 /*
 1713                  * Rounding down may make us wake up just short
 1714                  * of the target, so we round up.
 1715                  * The formula is ceiling(slp * hz/1000000).
 1716                  * 32-bit arithmetic is enough for hz < 169.
 1717                  * XXX see tvtohz() for how to avoid overflow if hz
 1718                  * is large (divide by `tick' and/or arrange to
 1719                  * use tvtohz() if hz is large).
 1720                  */
 1721                 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
 1722                 goto sleep;
 1723         }
 1724         if (qp->c_cc <= 0) {
 1725 sleep:
 1726                 /*
 1727                  * There is no input, or not enough input and we can block.
 1728                  */
 1729                 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
 1730                                  ISSET(tp->t_state, TS_CONNECTED) ?
 1731                                  "ttyin" : "ttyhup", (int)slp);
 1732                 splx(s);
 1733                 if (error == EWOULDBLOCK)
 1734                         error = 0;
 1735                 else if (error)
 1736                         return (error);
 1737                 /*
 1738                  * XXX what happens if another process eats some input
 1739                  * while we are asleep (not just here)?  It would be
 1740                  * safest to detect changes and reset our state variables
 1741                  * (has_stime and last_cc).
 1742                  */
 1743                 slp = 0;
 1744                 goto loop;
 1745         }
 1746 read:
 1747         splx(s);
 1748         /*
 1749          * Input present, check for input mapping and processing.
 1750          */
 1751         first = 1;
 1752         if (ISSET(lflag, ICANON | ISIG))
 1753                 goto slowcase;
 1754         for (;;) {
 1755                 char ibuf[IBUFSIZ];
 1756                 int icc;
 1757 
 1758                 icc = imin(uio->uio_resid, IBUFSIZ);
 1759                 icc = q_to_b(qp, ibuf, icc);
 1760                 if (icc <= 0) {
 1761                         if (first)
 1762                                 goto loop;
 1763                         break;
 1764                 }
 1765                 error = uiomove(ibuf, icc, uio);
 1766                 /*
 1767                  * XXX if there was an error then we should ungetc() the
 1768                  * unmoved chars and reduce icc here.
 1769                  */
 1770                 if (error)
 1771                         break;
 1772                 if (uio->uio_resid == 0)
 1773                         break;
 1774                 first = 0;
 1775         }
 1776         goto out;
 1777 slowcase:
 1778         for (;;) {
 1779                 c = getc(qp);
 1780                 if (c < 0) {
 1781                         if (first)
 1782                                 goto loop;
 1783                         break;
 1784                 }
 1785                 /*
 1786                  * delayed suspend (^Y)
 1787                  */
 1788                 if (CCEQ(cc[VDSUSP], c) &&
 1789                     ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
 1790                         if (tp->t_pgrp != NULL) {
 1791                                 PGRP_LOCK(tp->t_pgrp);
 1792                                 pgsignal(tp->t_pgrp, SIGTSTP, 1);
 1793                                 PGRP_UNLOCK(tp->t_pgrp);
 1794                         }
 1795                         if (first) {
 1796                                 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
 1797                                                  "ttybg3", 0);
 1798                                 if (error)
 1799                                         break;
 1800                                 goto loop;
 1801                         }
 1802                         break;
 1803                 }
 1804                 /*
 1805                  * Interpret EOF only in canonical mode.
 1806                  */
 1807                 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
 1808                         break;
 1809                 /*
 1810                  * Give user character.
 1811                  */
 1812                 error = ureadc(c, uio);
 1813                 if (error)
 1814                         /* XXX should ungetc(c, qp). */
 1815                         break;
 1816                 if (uio->uio_resid == 0)
 1817                         break;
 1818                 /*
 1819                  * In canonical mode check for a "break character"
 1820                  * marking the end of a "line of input".
 1821                  */
 1822                 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
 1823                         break;
 1824                 first = 0;
 1825         }
 1826 
 1827 out:
 1828         /*
 1829          * Look to unblock input now that (presumably)
 1830          * the input queue has gone down.
 1831          */
 1832         s = spltty();
 1833         if (ISSET(tp->t_state, TS_TBLOCK) &&
 1834             tp->t_rawq.c_cc + tp->t_canq.c_cc <= tp->t_ilowat)
 1835                 ttyunblock(tp);
 1836         splx(s);
 1837 
 1838         return (error);
 1839 }
 1840 
 1841 /*
 1842  * Check the output queue on tp for space for a kernel message (from uprintf
 1843  * or tprintf).  Allow some space over the normal hiwater mark so we don't
 1844  * lose messages due to normal flow control, but don't let the tty run amok.
 1845  * Sleeps here are not interruptible, but we return prematurely if new signals
 1846  * arrive.
 1847  */
 1848 int
 1849 ttycheckoutq(struct tty *tp, int wait)
 1850 {
 1851         int hiwat, s;
 1852         sigset_t oldmask;
 1853         struct thread *td;
 1854         struct proc *p;
 1855 
 1856         td = curthread;
 1857         p = td->td_proc;
 1858         hiwat = tp->t_ohiwat;
 1859         SIGEMPTYSET(oldmask);
 1860         s = spltty();
 1861         if (wait) {
 1862                 PROC_LOCK(p);
 1863                 oldmask = td->td_siglist;
 1864                 PROC_UNLOCK(p);
 1865         }
 1866         if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100)
 1867                 while (tp->t_outq.c_cc > hiwat) {
 1868                         ttstart(tp);
 1869                         if (tp->t_outq.c_cc <= hiwat)
 1870                                 break;
 1871                         if (!wait) {
 1872                                 splx(s);
 1873                                 return (0);
 1874                         }
 1875                         PROC_LOCK(p);
 1876                         if (!SIGSETEQ(td->td_siglist, oldmask)) {
 1877                                 PROC_UNLOCK(p);
 1878                                 splx(s);
 1879                                 return (0);
 1880                         }
 1881                         PROC_UNLOCK(p);
 1882                         SET(tp->t_state, TS_SO_OLOWAT);
 1883                         tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz);
 1884                 }
 1885         splx(s);
 1886         return (1);
 1887 }
 1888 
 1889 /*
 1890  * Process a write call on a tty device.
 1891  */
 1892 int
 1893 ttwrite(struct tty *tp, struct uio *uio, int flag)
 1894 {
 1895         char *cp = NULL;
 1896         int cc, ce;
 1897         struct thread *td;
 1898         struct proc *p;
 1899         int i, hiwat, cnt, error, s;
 1900         char obuf[OBUFSIZ];
 1901 
 1902         hiwat = tp->t_ohiwat;
 1903         cnt = uio->uio_resid;
 1904         error = 0;
 1905         cc = 0;
 1906         td = curthread;
 1907         p = td->td_proc;
 1908 loop:
 1909         s = spltty();
 1910         if (ISSET(tp->t_state, TS_ZOMBIE)) {
 1911                 splx(s);
 1912                 if (uio->uio_resid == cnt)
 1913                         error = EIO;
 1914                 goto out;
 1915         }
 1916         if (!ISSET(tp->t_state, TS_CONNECTED)) {
 1917                 if (flag & IO_NDELAY) {
 1918                         splx(s);
 1919                         error = EWOULDBLOCK;
 1920                         goto out;
 1921                 }
 1922                 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
 1923                                  "ttydcd", 0);
 1924                 splx(s);
 1925                 if (error)
 1926                         goto out;
 1927                 goto loop;
 1928         }
 1929         splx(s);
 1930         /*
 1931          * Hang the process if it's in the background.
 1932          */
 1933         sx_slock(&proctree_lock);
 1934         PROC_LOCK(p);
 1935         if (isbackground(p, tp) &&
 1936             ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) &&
 1937             !SIGISMEMBER(p->p_sigacts->ps_sigignore, SIGTTOU) &&
 1938             !SIGISMEMBER(td->td_sigmask, SIGTTOU)) {
 1939                 if (p->p_pgrp->pg_jobc == 0) {
 1940                         PROC_UNLOCK(p);
 1941                         sx_sunlock(&proctree_lock);
 1942                         error = EIO;
 1943                         goto out;
 1944                 }
 1945                 PROC_UNLOCK(p);
 1946                 PGRP_LOCK(p->p_pgrp);
 1947                 sx_sunlock(&proctree_lock);
 1948                 pgsignal(p->p_pgrp, SIGTTOU, 1);
 1949                 PGRP_UNLOCK(p->p_pgrp);
 1950                 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0);
 1951                 if (error)
 1952                         goto out;
 1953                 goto loop;
 1954         } else {
 1955                 PROC_UNLOCK(p);
 1956                 sx_sunlock(&proctree_lock);
 1957         }
 1958         /*
 1959          * Process the user's data in at most OBUFSIZ chunks.  Perform any
 1960          * output translation.  Keep track of high water mark, sleep on
 1961          * overflow awaiting device aid in acquiring new space.
 1962          */
 1963         while (uio->uio_resid > 0 || cc > 0) {
 1964                 if (ISSET(tp->t_lflag, FLUSHO)) {
 1965                         uio->uio_resid = 0;
 1966                         return (0);
 1967                 }
 1968                 if (tp->t_outq.c_cc > hiwat)
 1969                         goto ovhiwat;
 1970                 /*
 1971                  * Grab a hunk of data from the user, unless we have some
 1972                  * leftover from last time.
 1973                  */
 1974                 if (cc == 0) {
 1975                         cc = imin(uio->uio_resid, OBUFSIZ);
 1976                         cp = obuf;
 1977                         error = uiomove(cp, cc, uio);
 1978                         if (error) {
 1979                                 cc = 0;
 1980                                 break;
 1981                         }
 1982                 }
 1983                 /*
 1984                  * If nothing fancy need be done, grab those characters we
 1985                  * can handle without any of ttyoutput's processing and
 1986                  * just transfer them to the output q.  For those chars
 1987                  * which require special processing (as indicated by the
 1988                  * bits in char_type), call ttyoutput.  After processing
 1989                  * a hunk of data, look for FLUSHO so ^O's will take effect
 1990                  * immediately.
 1991                  */
 1992                 while (cc > 0) {
 1993                         if (!ISSET(tp->t_oflag, OPOST))
 1994                                 ce = cc;
 1995                         else {
 1996                                 ce = cc - scanc((u_int)cc, (u_char *)cp,
 1997                                                 char_type, CCLASSMASK);
 1998                                 /*
 1999                                  * If ce is zero, then we're processing
 2000                                  * a special character through ttyoutput.
 2001                                  */
 2002                                 if (ce == 0) {
 2003                                         tp->t_rocount = 0;
 2004                                         if (ttyoutput(*cp, tp) >= 0) {
 2005                                                 /* No Clists, wait a bit. */
 2006                                                 ttstart(tp);
 2007                                                 if (flag & IO_NDELAY) {
 2008                                                         error = EWOULDBLOCK;
 2009                                                         goto out;
 2010                                                 }
 2011                                                 error = ttysleep(tp, &lbolt,
 2012                                                                  TTOPRI|PCATCH,
 2013                                                                  "ttybf1", 0);
 2014                                                 if (error)
 2015                                                         goto out;
 2016                                                 goto loop;
 2017                                         }
 2018                                         cp++;
 2019                                         cc--;
 2020                                         if (ISSET(tp->t_lflag, FLUSHO) ||
 2021                                             tp->t_outq.c_cc > hiwat)
 2022                                                 goto ovhiwat;
 2023                                         continue;
 2024                                 }
 2025                         }
 2026                         /*
 2027                          * A bunch of normal characters have been found.
 2028                          * Transfer them en masse to the output queue and
 2029                          * continue processing at the top of the loop.
 2030                          * If there are any further characters in this
 2031                          * <= OBUFSIZ chunk, the first should be a character
 2032                          * requiring special handling by ttyoutput.
 2033                          */
 2034                         tp->t_rocount = 0;
 2035                         i = b_to_q(cp, ce, &tp->t_outq);
 2036                         ce -= i;
 2037                         tp->t_column += ce;
 2038                         cp += ce, cc -= ce, tk_nout += ce;
 2039                         tp->t_outcc += ce;
 2040                         if (i > 0) {
 2041                                 /* No Clists, wait a bit. */
 2042                                 ttstart(tp);
 2043                                 if (flag & IO_NDELAY) {
 2044                                         error = EWOULDBLOCK;
 2045                                         goto out;
 2046                                 }
 2047                                 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH,
 2048                                                  "ttybf2", 0);
 2049                                 if (error)
 2050                                         goto out;
 2051                                 goto loop;
 2052                         }
 2053                         if (ISSET(tp->t_lflag, FLUSHO) ||
 2054                             tp->t_outq.c_cc > hiwat)
 2055                                 break;
 2056                 }
 2057                 ttstart(tp);
 2058         }
 2059 out:
 2060         /*
 2061          * If cc is nonzero, we leave the uio structure inconsistent, as the
 2062          * offset and iov pointers have moved forward, but it doesn't matter
 2063          * (the call will either return short or restart with a new uio).
 2064          */
 2065         uio->uio_resid += cc;
 2066         return (error);
 2067 
 2068 ovhiwat:
 2069         ttstart(tp);
 2070         s = spltty();
 2071         /*
 2072          * This can only occur if FLUSHO is set in t_lflag,
 2073          * or if ttstart/oproc is synchronous (or very fast).
 2074          */
 2075         if (tp->t_outq.c_cc <= hiwat) {
 2076                 splx(s);
 2077                 goto loop;
 2078         }
 2079         if (flag & IO_NDELAY) {
 2080                 splx(s);
 2081                 uio->uio_resid += cc;
 2082                 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
 2083         }
 2084         SET(tp->t_state, TS_SO_OLOWAT);
 2085         error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri",
 2086                          tp->t_timeout);
 2087         splx(s);
 2088         if (error == EWOULDBLOCK)
 2089                 error = EIO;
 2090         if (error)
 2091                 goto out;
 2092         goto loop;
 2093 }
 2094 
 2095 /*
 2096  * Rubout one character from the rawq of tp
 2097  * as cleanly as possible.
 2098  */
 2099 static void
 2100 ttyrub(int c, struct tty *tp)
 2101 {
 2102         char *cp;
 2103         int savecol;
 2104         int tabc, s;
 2105 
 2106         if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
 2107                 return;
 2108         CLR(tp->t_lflag, FLUSHO);
 2109         if (ISSET(tp->t_lflag, ECHOE)) {
 2110                 if (tp->t_rocount == 0) {
 2111                         /*
 2112                          * Screwed by ttwrite; retype
 2113                          */
 2114                         ttyretype(tp);
 2115                         return;
 2116                 }
 2117                 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
 2118                         ttyrubo(tp, 2);
 2119                 else {
 2120                         CLR(c, ~TTY_CHARMASK);
 2121                         switch (CCLASS(c)) {
 2122                         case ORDINARY:
 2123                                 ttyrubo(tp, 1);
 2124                                 break;
 2125                         case BACKSPACE:
 2126                         case CONTROL:
 2127                         case NEWLINE:
 2128                         case RETURN:
 2129                         case VTAB:
 2130                                 if (ISSET(tp->t_lflag, ECHOCTL))
 2131                                         ttyrubo(tp, 2);
 2132                                 break;
 2133                         case TAB:
 2134                                 if (tp->t_rocount < tp->t_rawq.c_cc) {
 2135                                         ttyretype(tp);
 2136                                         return;
 2137                                 }
 2138                                 s = spltty();
 2139                                 savecol = tp->t_column;
 2140                                 SET(tp->t_state, TS_CNTTB);
 2141                                 SET(tp->t_lflag, FLUSHO);
 2142                                 tp->t_column = tp->t_rocol;
 2143                                 cp = tp->t_rawq.c_cf;
 2144                                 if (cp)
 2145                                         tabc = *cp;     /* XXX FIX NEXTC */
 2146                                 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
 2147                                         ttyecho(tabc, tp);
 2148                                 CLR(tp->t_lflag, FLUSHO);
 2149                                 CLR(tp->t_state, TS_CNTTB);
 2150                                 splx(s);
 2151 
 2152                                 /* savecol will now be length of the tab. */
 2153                                 savecol -= tp->t_column;
 2154                                 tp->t_column += savecol;
 2155                                 if (savecol > 8)
 2156                                         savecol = 8;    /* overflow screw */
 2157                                 while (--savecol >= 0)
 2158                                         (void)ttyoutput('\b', tp);
 2159                                 break;
 2160                         default:                        /* XXX */
 2161 #define PANICSTR        "ttyrub: would panic c = %d, val = %d\n"
 2162                                 (void)printf(PANICSTR, c, CCLASS(c));
 2163 #ifdef notdef
 2164                                 panic(PANICSTR, c, CCLASS(c));
 2165 #endif
 2166                         }
 2167                 }
 2168         } else if (ISSET(tp->t_lflag, ECHOPRT)) {
 2169                 if (!ISSET(tp->t_state, TS_ERASE)) {
 2170                         SET(tp->t_state, TS_ERASE);
 2171                         (void)ttyoutput('\\', tp);
 2172                 }
 2173                 ttyecho(c, tp);
 2174         } else {
 2175                 ttyecho(tp->t_cc[VERASE], tp);
 2176                 /*
 2177                  * This code may be executed not only when an ERASE key
 2178                  * is pressed, but also when ^U (KILL) or ^W (WERASE) are.
 2179                  * So, I didn't think it was worthwhile to pass the extra
 2180                  * information (which would need an extra parameter,
 2181                  * changing every call) needed to distinguish the ERASE2
 2182                  * case from the ERASE.
 2183                  */
 2184         }
 2185         --tp->t_rocount;
 2186 }
 2187 
 2188 /*
 2189  * Back over cnt characters, erasing them.
 2190  */
 2191 static void
 2192 ttyrubo(struct tty *tp, int cnt)
 2193 {
 2194 
 2195         while (cnt-- > 0) {
 2196                 (void)ttyoutput('\b', tp);
 2197                 (void)ttyoutput(' ', tp);
 2198                 (void)ttyoutput('\b', tp);
 2199         }
 2200 }
 2201 
 2202 /*
 2203  * ttyretype --
 2204  *      Reprint the rawq line.  Note, it is assumed that c_cc has already
 2205  *      been checked.
 2206  */
 2207 static void
 2208 ttyretype(struct tty *tp)
 2209 {
 2210         char *cp;
 2211         int s, c;
 2212 
 2213         /* Echo the reprint character. */
 2214         if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
 2215                 ttyecho(tp->t_cc[VREPRINT], tp);
 2216 
 2217         (void)ttyoutput('\n', tp);
 2218 
 2219         /*
 2220          * XXX
 2221          * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
 2222          * BIT OF FIRST CHAR.
 2223          */
 2224         s = spltty();
 2225         for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
 2226             cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
 2227                 ttyecho(c, tp);
 2228         for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
 2229             cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
 2230                 ttyecho(c, tp);
 2231         CLR(tp->t_state, TS_ERASE);
 2232         splx(s);
 2233 
 2234         tp->t_rocount = tp->t_rawq.c_cc;
 2235         tp->t_rocol = 0;
 2236 }
 2237 
 2238 /*
 2239  * Echo a typed character to the terminal.
 2240  */
 2241 static void
 2242 ttyecho(int c, struct tty *tp)
 2243 {
 2244 
 2245         if (!ISSET(tp->t_state, TS_CNTTB))
 2246                 CLR(tp->t_lflag, FLUSHO);
 2247         if ((!ISSET(tp->t_lflag, ECHO) &&
 2248              (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
 2249             ISSET(tp->t_lflag, EXTPROC))
 2250                 return;
 2251         if (ISSET(tp->t_lflag, ECHOCTL) &&
 2252             ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
 2253             ISSET(c, TTY_CHARMASK) == 0177)) {
 2254                 (void)ttyoutput('^', tp);
 2255                 CLR(c, ~TTY_CHARMASK);
 2256                 if (c == 0177)
 2257                         c = '?';
 2258                 else
 2259                         c += 'A' - 1;
 2260         }
 2261         (void)ttyoutput(c, tp);
 2262 }
 2263 
 2264 /*
 2265  * Wake up any readers on a tty.
 2266  */
 2267 void
 2268 ttwakeup(struct tty *tp)
 2269 {
 2270 
 2271         if (SEL_WAITING(&tp->t_rsel))
 2272                 selwakeup(&tp->t_rsel);
 2273         if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
 2274                 pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
 2275         wakeup(TSA_HUP_OR_INPUT(tp));
 2276         KNOTE(&tp->t_rsel.si_note, 0);
 2277 }
 2278 
 2279 /*
 2280  * Wake up any writers on a tty.
 2281  */
 2282 void
 2283 ttwwakeup(struct tty *tp)
 2284 {
 2285 
 2286         if (SEL_WAITING(&tp->t_wsel) && tp->t_outq.c_cc <= tp->t_olowat)
 2287                 selwakeup(&tp->t_wsel);
 2288         if (ISSET(tp->t_state, TS_ASYNC) && tp->t_sigio != NULL)
 2289                 pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
 2290         if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
 2291             TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
 2292                 CLR(tp->t_state, TS_SO_OCOMPLETE);
 2293                 wakeup(TSA_OCOMPLETE(tp));
 2294         }
 2295         if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
 2296             tp->t_outq.c_cc <= tp->t_olowat) {
 2297                 CLR(tp->t_state, TS_SO_OLOWAT);
 2298                 wakeup(TSA_OLOWAT(tp));
 2299         }
 2300         KNOTE(&tp->t_wsel.si_note, 0);
 2301 }
 2302 
 2303 /*
 2304  * Look up a code for a specified speed in a conversion table;
 2305  * used by drivers to map software speed values to hardware parameters.
 2306  */
 2307 int
 2308 ttspeedtab(int speed, struct speedtab *table)
 2309 {
 2310 
 2311         for ( ; table->sp_speed != -1; table++)
 2312                 if (table->sp_speed == speed)
 2313                         return (table->sp_code);
 2314         return (-1);
 2315 }
 2316 
 2317 /*
 2318  * Set input and output watermarks and buffer sizes.  For input, the
 2319  * high watermark is about one second's worth of input above empty, the
 2320  * low watermark is slightly below high water, and the buffer size is a
 2321  * driver-dependent amount above high water.  For output, the watermarks
 2322  * are near the ends of the buffer, with about 1 second's worth of input
 2323  * between them.  All this only applies to the standard line discipline.
 2324  */
 2325 void
 2326 ttsetwater(struct tty *tp)
 2327 {
 2328         int cps, ttmaxhiwat, x;
 2329 
 2330         /* Input. */
 2331         clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
 2332         switch (tp->t_ispeedwat) {
 2333         case (speed_t)-1:
 2334                 cps = tp->t_ispeed / 10;
 2335                 break;
 2336         case 0:
 2337                 /*
 2338                  * This case is for old drivers that don't know about
 2339                  * t_ispeedwat.  Arrange for them to get the old buffer
 2340                  * sizes and watermarks.
 2341                  */
 2342                 cps = TTYHOG - 2 * 256;
 2343                 tp->t_ififosize = 2 * 256;
 2344                 break;
 2345         default:
 2346                 cps = tp->t_ispeedwat / 10;
 2347                 break;
 2348         }
 2349         tp->t_ihiwat = cps;
 2350         tp->t_ilowat = 7 * cps / 8;
 2351         x = cps + tp->t_ififosize;
 2352         clist_alloc_cblocks(&tp->t_rawq, x, x);
 2353 
 2354         /* Output. */
 2355         switch (tp->t_ospeedwat) {
 2356         case (speed_t)-1:
 2357                 cps = tp->t_ospeed / 10;
 2358                 ttmaxhiwat = 2 * TTMAXHIWAT;
 2359                 break;
 2360         case 0:
 2361                 cps = tp->t_ospeed / 10;
 2362                 ttmaxhiwat = TTMAXHIWAT;
 2363                 break;
 2364         default:
 2365                 cps = tp->t_ospeedwat / 10;
 2366                 ttmaxhiwat = 8 * TTMAXHIWAT;
 2367                 break;
 2368         }
 2369 #define CLAMP(x, h, l)  ((x) > h ? h : ((x) < l) ? l : (x))
 2370         tp->t_olowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
 2371         x += cps;
 2372         x = CLAMP(x, ttmaxhiwat, TTMINHIWAT);   /* XXX clamps are too magic */
 2373         tp->t_ohiwat = roundup(x, CBSIZE);      /* XXX for compat */
 2374         x = imax(tp->t_ohiwat, TTMAXHIWAT);     /* XXX for compat/safety */
 2375         x += OBUFSIZ + 100;
 2376         clist_alloc_cblocks(&tp->t_outq, x, x);
 2377 #undef  CLAMP
 2378 }
 2379 
 2380 /*
 2381  * Report on state of foreground process group.
 2382  */
 2383 void
 2384 ttyinfo(struct tty *tp)
 2385 {
 2386         struct proc *p, *pick;
 2387         struct timeval utime, stime;
 2388         const char *stmp, *sprefix;
 2389         long ltmp;
 2390         int tmp;
 2391         struct thread *td;
 2392 
 2393         if (ttycheckoutq(tp,0) == 0)
 2394                 return;
 2395 
 2396         /* Print load average. */
 2397         tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
 2398         ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
 2399 
 2400         if (tp->t_session == NULL)
 2401                 ttyprintf(tp, "not a controlling terminal\n");
 2402         else if (tp->t_pgrp == NULL)
 2403                 ttyprintf(tp, "no foreground process group\n");
 2404         else {
 2405                 PGRP_LOCK(tp->t_pgrp);
 2406                 if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) {
 2407                         PGRP_UNLOCK(tp->t_pgrp);
 2408                         ttyprintf(tp, "empty foreground process group\n");
 2409                 } else {
 2410                         mtx_lock_spin(&sched_lock);
 2411 
 2412                         /* Pick interesting process. */
 2413                         for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
 2414                                 if (proc_compare(pick, p))
 2415                                         pick = p;
 2416                         PGRP_UNLOCK(tp->t_pgrp);
 2417 
 2418                         td = FIRST_THREAD_IN_PROC(pick);
 2419                         sprefix = "";
 2420                         if (pick->p_flag & P_THREADED) {
 2421                                 stmp = "KSE" ;  /* XXXKSE */
 2422                         } else {
 2423                                 if (td) {
 2424                                         if (TD_ON_RUNQ(td) ||
 2425                                             (TD_IS_RUNNING(td))) {
 2426                                                 stmp = "running";
 2427                                         } else if (TD_ON_LOCK(td)) {
 2428                                                 stmp = td->td_lockname;
 2429                                                 sprefix = "*";
 2430                                         } else if (td->td_wmesg) {
 2431                                                 stmp = td->td_wmesg;
 2432                                         } else {
 2433                                                 stmp = "iowait";
 2434                                         }
 2435                                 } else {
 2436                                         stmp = "threadless";
 2437                                         panic("ttyinfo: no thread!?");
 2438                                 }
 2439                         }
 2440                         calcru(pick, &utime, &stime, NULL);
 2441                         if (pick->p_state == PRS_NEW ||
 2442                             pick->p_state == PRS_ZOMBIE) {
 2443                                 ltmp = 0;
 2444                         } else {
 2445                                 ltmp = pgtok(
 2446                                     vmspace_resident_count(pick->p_vmspace));
 2447                         }
 2448                         mtx_unlock_spin(&sched_lock);
 2449 
 2450                         ttyprintf(tp, " cmd: %s %d [%s%s] ", pick->p_comm,
 2451                             pick->p_pid, sprefix, stmp);
 2452 
 2453                         /* Print user time. */
 2454                         ttyprintf(tp, "%ld.%02ldu ",
 2455                             utime.tv_sec, utime.tv_usec / 10000);
 2456 
 2457                         /* Print system time. */
 2458                         ttyprintf(tp, "%ld.%02lds ",
 2459                             (long)stime.tv_sec, stime.tv_usec / 10000);
 2460 
 2461                         /* Print percentage cpu, resident set size. */
 2462                         ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
 2463 
 2464                 }
 2465         }
 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
 2476  *         with the highest cpu utilization is picked (p_estcpu).  Ties are
 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.
 2481  */
 2482 #define ISRUN(p, val)                                           \
 2483 do {                                                            \
 2484         struct thread *td;                                      \
 2485         val = 0;                                                \
 2486         FOREACH_THREAD_IN_PROC(p, td) {                         \
 2487                 if (TD_ON_RUNQ(td) ||                           \
 2488                     TD_IS_RUNNING(td)) {                        \
 2489                         val = 1;                                \
 2490                         break;                                  \
 2491                 }                                               \
 2492         }                                                       \
 2493 } while (0)
 2494 
 2495 #define TESTAB(a, b)    ((a)<<1 | (b))
 2496 #define ONLYA   2
 2497 #define ONLYB   1
 2498 #define BOTH    3
 2499 
 2500 static int
 2501 proc_compare(struct proc *p1, struct proc *p2)
 2502 {
 2503 
 2504         int esta, estb;
 2505         struct ksegrp *kg;
 2506         mtx_assert(&sched_lock, MA_OWNED);
 2507         if (p1 == NULL)
 2508                 return (1);
 2509 
 2510         ISRUN(p1, esta);
 2511         ISRUN(p2, estb);
 2512         
 2513         /*
 2514          * see if at least one of them is runnable
 2515          */
 2516         switch (TESTAB(esta, estb)) {
 2517         case ONLYA:
 2518                 return (0);
 2519         case ONLYB:
 2520                 return (1);
 2521         case BOTH:
 2522                 /*
 2523                  * tie - favor one with highest recent cpu utilization
 2524                  */
 2525                 esta = estb = 0;
 2526                 FOREACH_KSEGRP_IN_PROC(p1,kg) {
 2527                         esta += kg->kg_estcpu;
 2528                 }
 2529                 FOREACH_KSEGRP_IN_PROC(p2,kg) {
 2530                         estb += kg->kg_estcpu;
 2531                 }
 2532                 if (estb > esta)
 2533                         return (1);
 2534                 if (esta > estb)
 2535                         return (0);
 2536                 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
 2537         }
 2538         /*
 2539          * weed out zombies
 2540          */
 2541         switch (TESTAB(p1->p_state == PRS_ZOMBIE, p2->p_state == PRS_ZOMBIE)) {
 2542         case ONLYA:
 2543                 return (1);
 2544         case ONLYB:
 2545                 return (0);
 2546         case BOTH:
 2547                 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
 2548         }
 2549 
 2550 #if 0 /* XXXKSE */
 2551         /*
 2552          * pick the one with the smallest sleep time
 2553          */
 2554         if (p2->p_slptime > p1->p_slptime)
 2555                 return (0);
 2556         if (p1->p_slptime > p2->p_slptime)
 2557                 return (1);
 2558         /*
 2559          * favor one sleeping in a non-interruptible sleep
 2560          */
 2561         if (p1->p_sflag & PS_SINTR && (p2->p_sflag & PS_SINTR) == 0)
 2562                 return (1);
 2563         if (p2->p_sflag & PS_SINTR && (p1->p_sflag & PS_SINTR) == 0)
 2564                 return (0);
 2565 #endif
 2566         return (p2->p_pid > p1->p_pid);         /* tie - return highest pid */
 2567 }
 2568 
 2569 /*
 2570  * Output char to tty; console putchar style.
 2571  */
 2572 int
 2573 tputchar(int c, struct tty *tp)
 2574 {
 2575         int s;
 2576 
 2577         s = spltty();
 2578         if (!ISSET(tp->t_state, TS_CONNECTED)) {
 2579                 splx(s);
 2580                 return (-1);
 2581         }
 2582         if (c == '\n')
 2583                 (void)ttyoutput('\r', tp);
 2584         (void)ttyoutput(c, tp);
 2585         ttstart(tp);
 2586         splx(s);
 2587         return (0);
 2588 }
 2589 
 2590 /*
 2591  * Sleep on chan, returning ERESTART if tty changed while we napped and
 2592  * returning any errors (e.g. EINTR/EWOULDBLOCK) reported by tsleep.  If
 2593  * the tty is revoked, restarting a pending call will redo validation done
 2594  * at the start of the call.
 2595  */
 2596 int
 2597 ttysleep(struct tty *tp, void *chan, int pri, char *wmesg, int timo)
 2598 {
 2599         int error;
 2600         int gen;
 2601 
 2602         gen = tp->t_gen;
 2603         error = tsleep(chan, pri, wmesg, timo);
 2604         if (error)
 2605                 return (error);
 2606         return (tp->t_gen == gen ? 0 : ERESTART);
 2607 }
 2608 
 2609 /*
 2610  * Allocate a tty struct.  Clists in the struct will be allocated by
 2611  * ttyopen().
 2612  */
 2613 struct tty *
 2614 ttymalloc(struct tty *tp)
 2615 {
 2616 
 2617         if (tp)
 2618                 return(tp);
 2619         tp = malloc(sizeof *tp, M_TTYS, M_WAITOK | M_ZERO);
 2620         ttyregister(tp);
 2621         return (tp);
 2622 }
 2623 
 2624 #if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */
 2625 /*
 2626  * Free a tty struct.  Clists in the struct should have been freed by
 2627  * ttyclose().
 2628  */
 2629 void
 2630 ttyfree(struct tty *tp)
 2631 {
 2632         free(tp, M_TTYS);
 2633 }
 2634 #endif /* 0 */
 2635 
 2636 void
 2637 ttyregister(struct tty *tp)
 2638 {
 2639         tp->t_timeout = -1;
 2640         SLIST_INSERT_HEAD(&tty_list, tp, t_list);
 2641 }
 2642 
 2643 static int
 2644 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
 2645 {
 2646         struct tty *tp;
 2647         struct xtty xt;
 2648         int error;
 2649 
 2650         SLIST_FOREACH(tp, &tty_list, t_list) {
 2651                 bzero(&xt, sizeof xt);
 2652                 xt.xt_size = sizeof xt;
 2653 #define XT_COPY(field) xt.xt_##field = tp->t_##field
 2654                 xt.xt_rawcc = tp->t_rawq.c_cc;
 2655                 xt.xt_cancc = tp->t_canq.c_cc;
 2656                 xt.xt_outcc = tp->t_outq.c_cc;
 2657                 XT_COPY(line);
 2658                 if (tp->t_dev)
 2659                         xt.xt_dev = dev2udev(tp->t_dev);
 2660                 XT_COPY(state);
 2661                 XT_COPY(flags);
 2662                 XT_COPY(timeout);
 2663                 if (tp->t_pgrp)
 2664                         xt.xt_pgid = tp->t_pgrp->pg_id;
 2665                 if (tp->t_session)
 2666                         xt.xt_sid = tp->t_session->s_sid;
 2667                 XT_COPY(termios);
 2668                 XT_COPY(winsize);
 2669                 XT_COPY(column);
 2670                 XT_COPY(rocount);
 2671                 XT_COPY(rocol);
 2672                 XT_COPY(ififosize);
 2673                 XT_COPY(ihiwat);
 2674                 XT_COPY(ilowat);
 2675                 XT_COPY(ispeedwat);
 2676                 XT_COPY(ohiwat);
 2677                 XT_COPY(olowat);
 2678                 XT_COPY(ospeedwat);
 2679 #undef XT_COPY
 2680                 error = SYSCTL_OUT(req, &xt, sizeof xt);
 2681                 if (error)
 2682                         return (error);
 2683         }
 2684         return (0);
 2685 }
 2686 
 2687 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
 2688         0, 0, sysctl_kern_ttys, "S,xtty", "All ttys");
 2689 SYSCTL_LONG(_kern, OID_AUTO, tty_nin, CTLFLAG_RD,
 2690         &tk_nin, 0, "Total TTY in characters");
 2691 SYSCTL_LONG(_kern, OID_AUTO, tty_nout, CTLFLAG_RD,
 2692         &tk_nout, 0, "Total TTY out characters");
 2693 
 2694 void
 2695 nottystop(struct tty *tp, int rw)
 2696 {
 2697 
 2698         return;
 2699 }
 2700 
 2701 int
 2702 ttyread(dev_t dev, struct uio *uio, int flag)
 2703 {
 2704         struct tty *tp;
 2705 
 2706         tp = dev->si_tty;
 2707         if (tp == NULL)
 2708                 return (ENODEV);
 2709         return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
 2710 }
 2711 
 2712 int
 2713 ttywrite(dev_t dev, struct uio *uio, int flag)
 2714 {
 2715         struct tty *tp;
 2716 
 2717         tp = dev->si_tty;
 2718         if (tp == NULL)
 2719                 return (ENODEV);
 2720         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 2721 }

Cache object: dcbcc5967830da08e2ab48414e9f8bdf


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.