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

Cache object: 74bf7868704bcfb706b9a0f3b421af60


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