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

Cache object: 5d4c8092e96cebf28c0d17a4425cdc32


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