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

Cache object: 9e9c70c508c5d8d9e7c94bc75789807c


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