home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / bsdss4.tz / bsdss4 / bsdss / server / kern / tty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-28  |  41.8 KB  |  1,920 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon 
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    tty.c,v $
  29.  * Revision 2.2  92/05/28  17:41:44  rwd
  30.  *     Call ttsetwater at open time to get values in hiwat and lowat.
  31.  *     [92/05/28            rwd]
  32.  * 
  33.  * Revision 2.1  92/04/21  17:13:07  rwd
  34.  * BSDSS
  35.  * 
  36.  *
  37.  */
  38.  
  39. /*-
  40.  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
  41.  * Copyright (c) 1991 The Regents of the University of California.
  42.  * All rights reserved.
  43.  *
  44.  * Redistribution and use in source and binary forms, with or without
  45.  * modification, are permitted provided that the following conditions
  46.  * are met:
  47.  * 1. Redistributions of source code must retain the above copyright
  48.  *    notice, this list of conditions and the following disclaimer.
  49.  * 2. Redistributions in binary form must reproduce the above copyright
  50.  *    notice, this list of conditions and the following disclaimer in the
  51.  *    documentation and/or other materials provided with the distribution.
  52.  * 3. All advertising materials mentioning features or use of this software
  53.  *    must display the following acknowledgement:
  54.  *    This product includes software developed by the University of
  55.  *    California, Berkeley and its contributors.
  56.  * 4. Neither the name of the University nor the names of its contributors
  57.  *    may be used to endorse or promote products derived from this software
  58.  *    without specific prior written permission.
  59.  *
  60.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  61.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  62.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  63.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  64.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  65.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  66.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  67.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  68.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  69.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  70.  * SUCH DAMAGE.
  71.  *
  72.  *    @(#)tty.c    7.44 (Berkeley) 5/28/91
  73.  */
  74.  
  75. #include <diagnostic.h>
  76.  
  77. #include <sys/param.h>
  78. #include <sys/systm.h>
  79. #include <sys/ioctl.h>
  80. #define TTYDEFCHARS
  81. #include <sys/tty.h>
  82. #undef TTYDEFCHARS
  83. #include <sys/proc.h>
  84. #include <sys/file.h>
  85. #include <sys/conf.h>
  86. #include <sys/dkstat.h>
  87. #include <sys/uio.h>
  88. #include <sys/kernel.h>
  89. #include <sys/vnode.h>
  90. #include <sys/syslog.h>
  91. #include <sys/synch.h>
  92.  
  93. #include <uxkern/import_mach.h>
  94.  
  95.  
  96. static int proc_compare __P((struct proc *p1, struct proc *p2));
  97.  
  98. /* symbolic sleep message strings */
  99. char ttyin[] = "ttyin";
  100. char ttyout[] = "ttyout";
  101. char ttopen[] = "ttyopn";
  102. char ttclos[] = "ttycls";
  103. char ttybg[] = "ttybg";
  104. char ttybuf[] = "ttybuf";
  105.  
  106. /*
  107.  * Table giving parity for characters and indicating
  108.  * character classes to tty driver. The 8th bit
  109.  * indicates parity, the 7th bit indicates the character
  110.  * is an alphameric or underscore (for ALTWERASE), and the 
  111.  * low 6 bits indicate delay type.  If the low 6 bits are 0
  112.  * then the character needs no special processing on output;
  113.  * classes other than 0 might be translated or (not currently)
  114.  * require delays.
  115.  */
  116. #define    PARITY(c)    (partab[c] & 0x80)
  117. #define    ISALPHA(c)    (partab[(c)&TTY_CHARMASK] & 0x40)
  118. #define    CCLASSMASK    0x3f
  119. #define    CCLASS(c)    (partab[c] & CCLASSMASK)
  120.  
  121. #define    E    0x00    /* even parity */
  122. #define    O    0x80    /* odd parity */
  123. #define    ALPHA    0x40    /* alpha or underscore */
  124.  
  125. #define    NO    ORDINARY
  126. #define    NA    ORDINARY|ALPHA
  127. #define    CC    CONTROL
  128. #define    BS    BACKSPACE
  129. #define    NL    NEWLINE
  130. #define    TB    TAB
  131. #define    VT    VTAB
  132. #define    CR    RETURN
  133.  
  134. char partab[] = {
  135.     E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,    /* nul - bel */
  136.     O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
  137.     O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
  138.     E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
  139.     O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
  140.     E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
  141.     E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
  142.     O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
  143.     O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
  144.     E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
  145.     E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
  146.     O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
  147.     E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
  148.     O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
  149.     O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
  150.     E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
  151.     /*
  152.      * "meta" chars; should be settable per charset.
  153.      * For now, treat all as normal characters.
  154.      */
  155.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  156.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  157.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  158.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  159.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  160.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  161.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  162.     NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
  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. };
  172. #undef    NO
  173. #undef    NA
  174. #undef    CC
  175. #undef    BS
  176. #undef    NL
  177. #undef    TB
  178. #undef    VT
  179. #undef    CR
  180.  
  181. extern struct tty *constty;        /* temporary virtual console */
  182.  
  183. /*
  184.  * Is 'c' a line delimiter ("break" character)?
  185.  */
  186. #define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \
  187.     (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)
  188.  
  189. ttychars(tp)
  190.     struct tty *tp;
  191. {
  192.  
  193.     bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
  194. }
  195.  
  196. /*
  197.  * Flush tty after output has drained.
  198.  */
  199. ttywflush(tp)
  200.     struct tty *tp;
  201. {
  202.     int error;
  203.  
  204.     if ((error = ttywait(tp)) == 0)
  205.         ttyflush(tp, FREAD);
  206.     return (error);
  207. }
  208.  
  209. /*
  210.  * Wait for output to drain.
  211.  */
  212. ttywait(tp)
  213.     register struct tty *tp;
  214. {
  215.     int error = 0, s = spltty();
  216.  
  217.     while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
  218.         (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 
  219.         tp->t_oproc) {
  220.         (*tp->t_oproc)(tp);
  221.         tp->t_state |= TS_ASLEEP;
  222.         if (error = ttysleep(tp, (caddr_t)&tp->t_outq, 
  223.             TTOPRI | PCATCH, ttyout, 0))
  224.             break;
  225.     }
  226.     splx(s);
  227.     return (error);
  228. }
  229.  
  230. #define    flushq(qq) { \
  231.     register struct clist *q = qq; \
  232.     if (q->c_cc) \
  233.         ndflush(q, q->c_cc); \
  234. }
  235.  
  236. /*
  237.  * Flush TTY read and/or write queues,
  238.  * notifying anyone waiting.
  239.  */
  240. ttyflush(tp, rw)
  241.     register struct tty *tp;
  242. {
  243.     register s;
  244.  
  245.     s = spltty();
  246.     if (rw & FREAD) {
  247.         flushq(&tp->t_canq);
  248.         flushq(&tp->t_rawq);
  249.         tp->t_rocount = 0;
  250.         tp->t_rocol = 0;
  251.         tp->t_state &= ~TS_LOCAL;
  252.         ttwakeup(tp);
  253.     }
  254.     if (rw & FWRITE) {
  255.         tp->t_state &= ~TS_TTSTOP;
  256.         (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
  257.         flushq(&tp->t_outq);
  258.         wakeup((caddr_t)&tp->t_outq);
  259.         selwakeup(&tp->t_wsel);
  260.     }
  261.     splx(s);
  262. }
  263.  
  264. /*
  265.  * Send stop character on input overflow.
  266.  */
  267. ttyblock(tp)
  268.     register struct tty *tp;
  269. {
  270.     register x;
  271.  
  272.     x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
  273.     if (tp->t_rawq.c_cc > TTYHOG) {
  274.         ttyflush(tp, FREAD|FWRITE);
  275.         tp->t_state &= ~TS_TBLOCK;
  276.     }
  277.     /*
  278.      * Block further input iff:
  279.      * Current input > threshold AND input is available to user program
  280.      */
  281.     if (x >= TTYHOG/2 && (tp->t_state & TS_TBLOCK) == 0 &&
  282.         ((tp->t_lflag&ICANON) == 0) || (tp->t_canq.c_cc > 0) &&
  283.         tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
  284.         if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
  285.             tp->t_state |= TS_TBLOCK;
  286.             ttstart(tp);
  287.         }
  288.     }
  289. }
  290.  
  291. ttstart(tp)
  292.     struct tty *tp;
  293. {
  294.  
  295.     if (tp->t_oproc)        /* kludge for pty */
  296.         (*tp->t_oproc)(tp);
  297. }
  298.  
  299. ttrstrt(tp)                /* XXX */
  300.     struct tty *tp;
  301. {
  302.  
  303. #if DIAGNOSTIC
  304.     if (tp == 0)
  305.         panic("ttrstrt");
  306. #endif
  307.     tp->t_state &= ~TS_TIMEOUT;
  308.     ttstart(tp);
  309. }
  310.  
  311.  
  312. /*
  313.  * Common code for ioctls on tty devices.
  314.  * Called after line-discipline-specific ioctl
  315.  * has been called to do discipline-specific functions
  316.  * and/or reject any of these ioctl commands.
  317.  */
  318. /*ARGSUSED*/
  319. ttioctl(tp, com, data, flag)
  320.     register struct tty *tp;
  321.     caddr_t data;
  322. {
  323.         struct proc *p = (struct proc*)cthread_data(cthread_self());
  324.     extern int nldisp;
  325.     int s, error;
  326.  
  327.     /*
  328.      * If the ioctl involves modification,
  329.      * hang if in the background.
  330.      */
  331.     switch (com) {
  332.  
  333.     case TIOCSETD: 
  334.     case TIOCFLUSH:
  335.     /*case TIOCSPGRP:*/
  336.     case TIOCSTI:
  337.     case TIOCSWINSZ:
  338.     case TIOCSETA:
  339.     case TIOCSETAW:
  340.     case TIOCSETAF:
  341. #ifdef COMPAT_43
  342.     case TIOCSETP:
  343.     case TIOCSETN:
  344.     case TIOCSETC:
  345.     case TIOCSLTC:
  346.     case TIOCLBIS:
  347.     case TIOCLBIC:
  348.     case TIOCLSET:
  349.     case OTIOCSETD:
  350. #endif
  351.         while (isbackground(p, tp) && 
  352.            p->p_pgrp->pg_jobc && (p->p_flag&SPPWAIT) == 0 &&
  353.            (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
  354.            (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
  355.             pgsignal(p->p_pgrp, SIGTTOU, 1);
  356.             if (error = ttysleep(tp, (caddr_t)&lbolt, 
  357.                 TTOPRI | PCATCH, ttybg, 0)) 
  358.                 return (error);
  359.         }
  360.         break;
  361.     }
  362.  
  363.     /*
  364.      * Process the ioctl.
  365.      */
  366.     switch (com) {
  367.  
  368.     /* get discipline number */
  369.     case TIOCGETD:
  370.         *(int *)data = tp->t_line;
  371.         break;
  372.  
  373.     /* set line discipline */
  374.     case TIOCSETD: {
  375.         register int t = *(int *)data;
  376.         dev_t dev = tp->t_dev;
  377.  
  378.         if ((unsigned)t >= nldisp)
  379.             return (ENXIO);
  380.         if (t != tp->t_line) {
  381.             s = spltty();
  382.             (*linesw[tp->t_line].l_close)(tp, flag);
  383.             error = (*linesw[t].l_open)(dev, tp);
  384.             if (error) {
  385.                 (void)(*linesw[tp->t_line].l_open)(dev, tp);
  386.                 splx(s);
  387.                 return (error);
  388.             }
  389.             tp->t_line = t;
  390.             splx(s);
  391.         }
  392.         break;
  393.     }
  394.  
  395.     /* prevent more opens on channel */
  396.     case TIOCEXCL:
  397.         tp->t_state |= TS_XCLUDE;
  398.         break;
  399.  
  400.     case TIOCNXCL:
  401.         tp->t_state &= ~TS_XCLUDE;
  402.         break;
  403.  
  404.     case TIOCHPCL:
  405.         tp->t_cflag |= HUPCL;
  406.         break;
  407.  
  408.     case TIOCFLUSH: {
  409.         register int flags = *(int *)data;
  410.  
  411.         if (flags == 0)
  412.             flags = FREAD|FWRITE;
  413.         else
  414.             flags &= FREAD|FWRITE;
  415.         ttyflush(tp, flags);
  416.         break;
  417.     }
  418.  
  419.     case FIOASYNC:
  420.         if (*(int *)data)
  421.             tp->t_state |= TS_ASYNC;
  422.         else
  423.             tp->t_state &= ~TS_ASYNC;
  424.         break;
  425.  
  426.     case FIONBIO:
  427.         break;    /* XXX remove */
  428.  
  429.     /* return number of characters immediately available */
  430.     case FIONREAD:
  431.         *(off_t *)data = ttnread(tp);
  432.         break;
  433.  
  434.     case TIOCOUTQ:
  435.         *(int *)data = tp->t_outq.c_cc;
  436.         break;
  437.  
  438.     case TIOCSTOP:
  439.         s = spltty();
  440.         if ((tp->t_state&TS_TTSTOP) == 0) {
  441.             tp->t_state |= TS_TTSTOP;
  442.             (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
  443.         }
  444.         splx(s);
  445.         break;
  446.  
  447.     case TIOCSTART:
  448.         s = spltty();
  449.         if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) {
  450.             tp->t_state &= ~TS_TTSTOP;
  451.             tp->t_lflag &= ~FLUSHO;
  452.             ttstart(tp);
  453.         }
  454.         splx(s);
  455.         break;
  456.  
  457.     /*
  458.      * Simulate typing of a character at the terminal.
  459.      */
  460.     case TIOCSTI:
  461.         if (p->p_ucred->cr_uid && (flag & FREAD) == 0)
  462.             return (EPERM);
  463.         if (p->p_ucred->cr_uid && !isctty(p, tp))
  464.             return (EACCES);
  465.         (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
  466.         break;
  467.  
  468.     case TIOCGETA: {
  469.         struct termios *t = (struct termios *)data;
  470.  
  471.         bcopy(&tp->t_termios, t, sizeof(struct termios));
  472.         break;
  473.     }
  474.  
  475.     case TIOCSETA:
  476.     case TIOCSETAW:
  477.     case TIOCSETAF: {
  478.         register struct termios *t = (struct termios *)data;
  479.  
  480.         s = spltty();
  481.         if (com == TIOCSETAW || com == TIOCSETAF) {
  482.             if (error = ttywait(tp)) {
  483.                 splx(s);
  484.                 return (error);
  485.             }
  486.             if (com == TIOCSETAF)
  487.                 ttyflush(tp, FREAD);
  488.         }
  489.         if ((t->c_cflag&CIGNORE) == 0) {
  490.             /*
  491.              * set device hardware
  492.              */
  493.             if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
  494.                 splx(s);
  495.                 return (error);
  496.             } else {
  497.                 if ((tp->t_state&TS_CARR_ON) == 0 &&
  498.                     (tp->t_cflag&CLOCAL) &&
  499.                     (t->c_cflag&CLOCAL) == 0) {
  500.                     tp->t_state &= ~TS_ISOPEN;
  501.                     tp->t_state |= TS_WOPEN;
  502.                     ttwakeup(tp);
  503.                 }
  504.                 tp->t_cflag = t->c_cflag;
  505.                 tp->t_ispeed = t->c_ispeed;
  506.                 tp->t_ospeed = t->c_ospeed;
  507.             }
  508.             ttsetwater(tp);
  509.         }
  510.         if (com != TIOCSETAF) {
  511.             if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON))
  512.                 if (t->c_lflag&ICANON) {    
  513.                     tp->t_lflag |= PENDIN;
  514.                     ttwakeup(tp);
  515.                 }
  516.                 else {
  517.                     struct clist tq;
  518.  
  519.                     catq(&tp->t_rawq, &tp->t_canq);
  520.                     tq = tp->t_rawq;
  521.                     tp->t_rawq = tp->t_canq;
  522.                     tp->t_canq = tq;
  523.                 }
  524.         }
  525.         tp->t_iflag = t->c_iflag;
  526.         tp->t_oflag = t->c_oflag;
  527.         /*
  528.          * Make the EXTPROC bit read only.
  529.          */
  530.         if (tp->t_lflag&EXTPROC)
  531.             t->c_lflag |= EXTPROC;
  532.         else
  533.             t->c_lflag &= ~EXTPROC;
  534.         tp->t_lflag = t->c_lflag;
  535.         bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
  536.         splx(s);
  537.         break;
  538.     }
  539.  
  540.     /*
  541.      * Set controlling terminal.
  542.      * Session ctty vnode pointer set in vnode layer.
  543.      */
  544.     case TIOCSCTTY:
  545.         if (!SESS_LEADER(p) || 
  546.            (p->p_session->s_ttyvp || tp->t_session) &&
  547.            (tp->t_session != p->p_session))
  548.             return (EPERM);
  549.         tp->t_session = p->p_session;
  550.         tp->t_pgrp = p->p_pgrp;
  551.         p->p_session->s_ttyp = tp;
  552.         p->p_flag |= SCTTY;
  553.         break;
  554.         
  555.     /*
  556.      * Set terminal process group.
  557.      */
  558.     case TIOCSPGRP: {
  559.         register struct pgrp *pgrp = pgfind(*(int *)data);
  560.  
  561.         if (!isctty(p, tp))
  562.             return (ENOTTY);
  563.         else if (pgrp == NULL || pgrp->pg_session != p->p_session)
  564.             return (EPERM);
  565.         tp->t_pgrp = pgrp;
  566.         break;
  567.     }
  568.  
  569.     case TIOCGPGRP:
  570.         if (!isctty(p, tp))
  571.             return (ENOTTY);
  572.         *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
  573.         break;
  574.  
  575.     case TIOCSWINSZ:
  576.         if (bcmp((caddr_t)&tp->t_winsize, data,
  577.             sizeof (struct winsize))) {
  578.             tp->t_winsize = *(struct winsize *)data;
  579.             pgsignal(tp->t_pgrp, SIGWINCH, 1);
  580.         }
  581.         break;
  582.  
  583.     case TIOCGWINSZ:
  584.         *(struct winsize *)data = tp->t_winsize;
  585.         break;
  586.  
  587.     case TIOCCONS:
  588.         if (*(int *)data) {
  589.             if (constty && constty != tp &&
  590.                 (constty->t_state & (TS_CARR_ON|TS_ISOPEN)) ==
  591.                 (TS_CARR_ON|TS_ISOPEN))
  592.                 return (EBUSY);
  593. #ifndef    UCONSOLE
  594.             if (error = suser(p->p_ucred, &p->p_acflag))
  595.                 return (error);
  596. #endif
  597.             constty = tp;
  598.         } else if (tp == constty)
  599.             constty = NULL;
  600.         break;
  601.  
  602.     case TIOCDRAIN:
  603.         if (error = ttywait(tp))
  604.             return (error);
  605.         break;
  606.  
  607.     default:
  608. #ifdef COMPAT_43
  609.         return (ttcompat(tp, com, data, flag));
  610. #else
  611.         return (-1);
  612. #endif
  613.     }
  614.     return (0);
  615. }
  616.  
  617. ttnread(tp)
  618.     struct tty *tp;
  619. {
  620.     int nread = 0;
  621.  
  622.     if (tp->t_lflag & PENDIN)
  623.         ttypend(tp);
  624.     nread = tp->t_canq.c_cc;
  625.     if ((tp->t_lflag & ICANON) == 0)
  626.         nread += tp->t_rawq.c_cc;
  627.     return (nread);
  628. }
  629.  
  630. ttselect(dev, rw)
  631.     dev_t dev;
  632.     int rw;
  633. {
  634.         struct proc *curproc = (struct proc*)cthread_data(cthread_self());
  635.     register struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
  636.     int nread;
  637.     int s = spltty();
  638.  
  639.     switch (rw) {
  640.  
  641.     case FREAD:
  642.         nread = ttnread(tp);
  643.         if (nread > 0 || 
  644.            ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0))
  645.             goto win;
  646.         selenter(curproc, &tp->t_rsel);
  647.         break;
  648.  
  649.     case FWRITE:
  650.         if (tp->t_outq.c_cc <= tp->t_lowat)
  651.             goto win;
  652.         selenter(curproc, &tp->t_wsel);
  653.         break;
  654.     }
  655.     splx(s);
  656.     return (0);
  657. win:
  658.     splx(s);
  659.     return (1);
  660. }
  661.  
  662. /*
  663.  * Initial open of tty, or (re)entry to standard tty line discipline.
  664.  */
  665. ttyopen(dev, tp)
  666.     dev_t dev;
  667.     register struct tty *tp;
  668. {
  669.  
  670.     tp->t_dev = dev;
  671.  
  672.     tp->t_state &= ~TS_WOPEN;
  673.     if ((tp->t_state & TS_ISOPEN) == 0) {
  674.         tp->t_state |= TS_ISOPEN;
  675.         bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
  676.     }
  677.     ttsetwater(tp);
  678.     return (0);
  679. }
  680.  
  681. /*
  682.  * "close" a line discipline
  683.  */
  684. ttylclose(tp, flag)
  685.     struct tty *tp;
  686.     int flag;
  687. {
  688.  
  689.     if (flag&IO_NDELAY)
  690.         ttyflush(tp, FREAD|FWRITE);
  691.     else
  692.         ttywflush(tp);
  693. }
  694.  
  695. /*
  696.  * Handle close() on a tty line: flush and set to initial state,
  697.  * bumping generation number so that pending read/write calls
  698.  * can detect recycling of the tty.
  699.  */
  700. ttyclose(tp)
  701.     register struct tty *tp;
  702. {
  703.     if (constty == tp)
  704.         constty = NULL;
  705.     ttyflush(tp, FREAD|FWRITE);
  706.     tp->t_session = NULL;
  707.     tp->t_pgrp = NULL;
  708.     tp->t_state = 0;
  709.     tp->t_gen++;
  710.     return (0);
  711. }
  712.  
  713. /*
  714.  * Handle modem control transition on a tty.
  715.  * Flag indicates new state of carrier.
  716.  * Returns 0 if the line should be turned off, otherwise 1.
  717.  */
  718. ttymodem(tp, flag)
  719.     register struct tty *tp;
  720. {
  721.  
  722.     if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) {
  723.         /*
  724.          * MDMBUF: do flow control according to carrier flag
  725.          */
  726.         if (flag) {
  727.             tp->t_state &= ~TS_TTSTOP;
  728.             ttstart(tp);
  729.         } else if ((tp->t_state&TS_TTSTOP) == 0) {
  730.             tp->t_state |= TS_TTSTOP;
  731.             (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
  732.         }
  733.     } else if (flag == 0) {
  734.         /*
  735.          * Lost carrier.
  736.          */
  737.         tp->t_state &= ~TS_CARR_ON;
  738.         if (tp->t_state&TS_ISOPEN && (tp->t_cflag&CLOCAL) == 0) {
  739.             if (tp->t_session && tp->t_session->s_leader)
  740.                 psignal(tp->t_session->s_leader, SIGHUP);
  741.             ttyflush(tp, FREAD|FWRITE);
  742.             return (0);
  743.         }
  744.     } else {
  745.         /*
  746.          * Carrier now on.
  747.          */
  748.         tp->t_state |= TS_CARR_ON;
  749.         ttwakeup(tp);
  750.     }
  751.     return (1);
  752. }
  753.  
  754. /*
  755.  * Default modem control routine (for other line disciplines).
  756.  * Return argument flag, to turn off device on carrier drop.
  757.  */
  758. nullmodem(tp, flag)
  759.     register struct tty *tp;
  760.     int flag;
  761. {
  762.     
  763.     if (flag)
  764.         tp->t_state |= TS_CARR_ON;
  765.     else {
  766.         tp->t_state &= ~TS_CARR_ON;
  767.         if ((tp->t_cflag&CLOCAL) == 0) {
  768.             if (tp->t_session && tp->t_session->s_leader)
  769.                 psignal(tp->t_session->s_leader, SIGHUP);
  770.             return (0);
  771.         }
  772.     }
  773.     return (1);
  774. }
  775.  
  776. /*
  777.  * reinput pending characters after state switch
  778.  * call at spltty().
  779.  */
  780. ttypend(tp)
  781.     register struct tty *tp;
  782. {
  783.     struct clist tq;
  784.     register c;
  785.  
  786.     tp->t_lflag &= ~PENDIN;
  787.     tp->t_state |= TS_TYPEN;
  788.     tq = tp->t_rawq;
  789.     tp->t_rawq.c_cc = 0;
  790.     tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
  791.     while ((c = getc(&tq)) >= 0)
  792.         ttyinput(c, tp);
  793.     tp->t_state &= ~TS_TYPEN;
  794. }
  795.  
  796. /*
  797.  * Process input of a single character received on a tty.
  798.  */
  799. ttyinput(c, tp)
  800.     register c;
  801.     register struct tty *tp;
  802. {
  803.     register int iflag = tp->t_iflag;
  804.     register int lflag = tp->t_lflag;
  805.     register u_char *cc = tp->t_cc;
  806.     int i, err;
  807.  
  808.     /*
  809.      * If input is pending take it first.
  810.      */
  811.     if (lflag&PENDIN)
  812.         ttypend(tp);
  813.     /*
  814.      * Gather stats.
  815.      */
  816.     tk_nin++;
  817.     if (lflag&ICANON) {
  818.         tk_cancc++;
  819.         tp->t_cancc++;
  820.     } else {
  821.         tk_rawcc++;
  822.         tp->t_rawcc++;
  823.     }
  824.     /*
  825.      * Handle exceptional conditions (break, parity, framing).
  826.      */
  827.     if (err = (c&TTY_ERRORMASK)) {
  828.         c &= ~TTY_ERRORMASK;
  829.         if (err&TTY_FE && !c) {        /* break */
  830.             if (iflag&IGNBRK)
  831.                 goto endcase;
  832.             else if (iflag&BRKINT && lflag&ISIG && 
  833.                 (cc[VINTR] != _POSIX_VDISABLE))
  834.                 c = cc[VINTR];
  835.             else if (iflag&PARMRK)
  836.                 goto parmrk;
  837.         } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) {
  838.             if (iflag&IGNPAR)
  839.                 goto endcase;
  840.             else if (iflag&PARMRK) {
  841. parmrk:
  842.                 putc(0377|TTY_QUOTE, &tp->t_rawq);
  843.                 putc(0|TTY_QUOTE, &tp->t_rawq);
  844.                 putc(c|TTY_QUOTE, &tp->t_rawq);
  845.                 goto endcase;
  846.             } else
  847.                 c = 0;
  848.         }
  849.     }
  850.     /*
  851.      * In tandem mode, check high water mark.
  852.      */
  853.     if (iflag&IXOFF)
  854.         ttyblock(tp);
  855.     if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP))
  856.         c &= ~0x80;
  857.     if ((tp->t_lflag&EXTPROC) == 0) {
  858.         /*
  859.          * Check for literal nexting very first
  860.          */
  861.         if (tp->t_state&TS_LNCH) {
  862.             c |= TTY_QUOTE;
  863.             tp->t_state &= ~TS_LNCH;
  864.         }
  865.         /*
  866.          * Scan for special characters.  This code
  867.          * is really just a big case statement with
  868.          * non-constant cases.  The bottom of the
  869.          * case statement is labeled ``endcase'', so goto
  870.          * it after a case match, or similar.
  871.          */
  872.  
  873.         /*
  874.          * Control chars which aren't controlled
  875.          * by ICANON, ISIG, or IXON.
  876.          */
  877.         if (lflag&IEXTEN) {
  878.             if (CCEQ(cc[VLNEXT], c)) {
  879.                 if (lflag&ECHO) {
  880.                     if (lflag&ECHOE)
  881.                         ttyoutstr("^\b", tp);
  882.                     else
  883.                         ttyecho(c, tp);
  884.                 }
  885.                 tp->t_state |= TS_LNCH;
  886.                 goto endcase;
  887.             }
  888.             if (CCEQ(cc[VDISCARD], c)) {
  889.                 if (lflag&FLUSHO)
  890.                     tp->t_lflag &= ~FLUSHO;
  891.                 else {
  892.                     ttyflush(tp, FWRITE);
  893.                     ttyecho(c, tp);
  894.                     if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
  895.                         ttyretype(tp);
  896.                     tp->t_lflag |= FLUSHO;
  897.                 }
  898.                 goto startoutput;
  899.             }
  900.         }
  901.         /*
  902.          * Signals.
  903.          */
  904.         if (lflag&ISIG) {
  905.             if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
  906.                 if ((lflag&NOFLSH) == 0)
  907.                     ttyflush(tp, FREAD|FWRITE);
  908.                 ttyecho(c, tp);
  909.                 pgsignal(tp->t_pgrp,
  910.                     CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
  911.                 goto endcase;
  912.             }
  913.             if (CCEQ(cc[VSUSP], c)) {
  914.                 if ((lflag&NOFLSH) == 0)
  915.                     ttyflush(tp, FREAD);
  916.                 ttyecho(c, tp);
  917.                 pgsignal(tp->t_pgrp, SIGTSTP, 1);
  918.                 goto endcase;
  919.             }
  920.         }
  921.         /*
  922.          * Handle start/stop characters.
  923.          */
  924.         if (iflag&IXON) {
  925.             if (CCEQ(cc[VSTOP], c)) {
  926.                 if ((tp->t_state&TS_TTSTOP) == 0) {
  927.                     tp->t_state |= TS_TTSTOP;
  928.                     (*cdevsw[major(tp->t_dev)].d_stop)(tp,
  929.                        0);
  930.                     return;
  931.                 }
  932.                 if (!CCEQ(cc[VSTART], c))
  933.                     return;
  934.                 /* 
  935.                  * if VSTART == VSTOP then toggle 
  936.                  */
  937.                 goto endcase;
  938.             }
  939.             if (CCEQ(cc[VSTART], c))
  940.                 goto restartoutput;
  941.         }
  942.         /*
  943.          * IGNCR, ICRNL, & INLCR
  944.          */
  945.         if (c == '\r') {
  946.             if (iflag&IGNCR)
  947.                 goto endcase;
  948.             else if (iflag&ICRNL)
  949.                 c = '\n';
  950.         } else if (c == '\n' && iflag&INLCR)
  951.             c = '\r';
  952.     }
  953.     if ((tp->t_lflag&EXTPROC) == 0 && lflag&ICANON) {
  954.         /*
  955.          * From here on down canonical mode character
  956.          * processing takes place.
  957.          */
  958.         /*
  959.          * erase (^H / ^?)
  960.          */
  961.         if (CCEQ(cc[VERASE], c)) {
  962.             if (tp->t_rawq.c_cc)
  963.                 ttyrub(unputc(&tp->t_rawq), tp);
  964.             goto endcase;
  965.         }
  966.         /*
  967.          * kill (^U)
  968.          */
  969.         if (CCEQ(cc[VKILL], c)) {
  970.             if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount &&
  971.                 (lflag&ECHOPRT) == 0) {
  972.                 while (tp->t_rawq.c_cc)
  973.                     ttyrub(unputc(&tp->t_rawq), tp);
  974.             } else {
  975.                 ttyecho(c, tp);
  976.                 if (lflag&ECHOK || lflag&ECHOKE)
  977.                     ttyecho('\n', tp);
  978.                 while (getc(&tp->t_rawq) > 0)
  979.                     ;
  980.                 tp->t_rocount = 0;
  981.             }
  982.             tp->t_state &= ~TS_LOCAL;
  983.             goto endcase;
  984.         }
  985.         /*
  986.          * word erase (^W)
  987.          */
  988.         if (CCEQ(cc[VWERASE], c)) {    
  989.             int ctype;
  990.             int alt = lflag&ALTWERASE;
  991.  
  992.             /* 
  993.              * erase whitespace 
  994.              */
  995.             while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
  996.                 ttyrub(c, tp);
  997.             if (c == -1)
  998.                 goto endcase;
  999.             /*
  1000.              * erase last char of word and remember the
  1001.              * next chars type (for ALTWERASE)
  1002.              */
  1003.             ttyrub(c, tp);
  1004.             c = unputc(&tp->t_rawq);
  1005.             if (c == -1)
  1006.                 goto endcase;
  1007.             ctype = ISALPHA(c);
  1008.             /*
  1009.              * erase rest of word
  1010.              */
  1011.             do {
  1012.                 ttyrub(c, tp);
  1013.                 c = unputc(&tp->t_rawq);
  1014.                 if (c == -1)
  1015.                     goto endcase;
  1016.             } while (c != ' ' && c != '\t' && 
  1017.                 (alt == 0 || ISALPHA(c) == ctype));
  1018.             (void) putc(c, &tp->t_rawq);
  1019.             goto endcase;
  1020.         }
  1021.         /*
  1022.          * reprint line (^R)
  1023.          */
  1024.         if (CCEQ(cc[VREPRINT], c)) {
  1025.             ttyretype(tp);
  1026.             goto endcase;
  1027.         }
  1028.         /*
  1029.          * ^T - kernel info and generate SIGINFO
  1030.          */
  1031.         if (CCEQ(cc[VSTATUS], c)) {
  1032.             pgsignal(tp->t_pgrp, SIGINFO, 1);
  1033.             if ((lflag&NOKERNINFO) == 0)
  1034.                 ttyinfo(tp);
  1035.             goto endcase;
  1036.         }
  1037.     }
  1038.     /*
  1039.      * Check for input buffer overflow
  1040.      */
  1041.     if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
  1042.         if (iflag&IMAXBEL) {
  1043.             if (tp->t_outq.c_cc < tp->t_hiwat)
  1044.                 (void) ttyoutput(CTRL('g'), tp);
  1045.         } else
  1046.             ttyflush(tp, FREAD | FWRITE);
  1047.         goto endcase;
  1048.     }
  1049.     /*
  1050.      * Put data char in q for user and
  1051.      * wakeup on seeing a line delimiter.
  1052.      */
  1053.     if (putc(c, &tp->t_rawq) >= 0) {
  1054.         if ((lflag&ICANON) == 0) {
  1055.             ttwakeup(tp);
  1056.             ttyecho(c, tp);
  1057.             goto endcase;
  1058.         }
  1059.         if (ttbreakc(c)) {
  1060.             tp->t_rocount = 0;
  1061.             catq(&tp->t_rawq, &tp->t_canq);
  1062.             ttwakeup(tp);
  1063.         } else if (tp->t_rocount++ == 0)
  1064.             tp->t_rocol = tp->t_col;
  1065.         if (tp->t_state&TS_ERASE) {
  1066.             /*
  1067.              * end of prterase \.../
  1068.              */
  1069.             tp->t_state &= ~TS_ERASE;
  1070.             (void) ttyoutput('/', tp);
  1071.         }
  1072.         i = tp->t_col;
  1073.         ttyecho(c, tp);
  1074.         if (CCEQ(cc[VEOF], c) && lflag&ECHO) {
  1075.             /*
  1076.              * Place the cursor over the '^' of the ^D.
  1077.              */
  1078.             i = MIN(2, tp->t_col - i);
  1079.             while (i > 0) {
  1080.                 (void) ttyoutput('\b', tp);
  1081.                 i--;
  1082.             }
  1083.         }
  1084.     }
  1085. endcase:
  1086.     /*
  1087.      * IXANY means allow any character to restart output.
  1088.      */
  1089.     if ((tp->t_state&TS_TTSTOP) && (iflag&IXANY) == 0 && 
  1090.         cc[VSTART] != cc[VSTOP])
  1091.         return;
  1092. restartoutput:
  1093.     tp->t_state &= ~TS_TTSTOP;
  1094.     tp->t_lflag &= ~FLUSHO;
  1095. startoutput:
  1096.     ttstart(tp);
  1097. }
  1098.  
  1099. /*
  1100.  * Output a single character on a tty, doing output processing
  1101.  * as needed (expanding tabs, newline processing, etc.).
  1102.  * Returns < 0 if putc succeeds, otherwise returns char to resend.
  1103.  * Must be recursive.
  1104.  */
  1105. ttyoutput(c, tp)
  1106.     register c;
  1107.     register struct tty *tp;
  1108. {
  1109.     register int col;
  1110.     register long oflag = tp->t_oflag;
  1111.     
  1112.     if ((oflag&OPOST) == 0) {
  1113.         if (tp->t_lflag&FLUSHO) 
  1114.             return (-1);
  1115.         if (putc(c, &tp->t_outq))
  1116.             return (c);
  1117.         tk_nout++;
  1118.         tp->t_outcc++;
  1119.         return (-1);
  1120.     }
  1121.     c &= TTY_CHARMASK;
  1122.     /*
  1123.      * Do tab expansion if OXTABS is set.
  1124.      * Special case if we have external processing, we don't
  1125.      * do the tab expansion because we'll probably get it
  1126.      * wrong.  If tab expansion needs to be done, let it
  1127.      * happen externally.
  1128.      */
  1129.     if (c == '\t' && oflag&OXTABS && (tp->t_lflag&EXTPROC) == 0) {
  1130.         register int s;
  1131.  
  1132.         c = 8 - (tp->t_col&7);
  1133.         if ((tp->t_lflag&FLUSHO) == 0) {
  1134.             s = spltty();        /* don't interrupt tabs */
  1135.             c -= b_to_q("        ", c, &tp->t_outq);
  1136.             tk_nout += c;
  1137.             tp->t_outcc += c;
  1138.             splx(s);
  1139.         }
  1140.         tp->t_col += c;
  1141.         return (c ? -1 : '\t');
  1142.     }
  1143.     if (c == CEOT && oflag&ONOEOT)
  1144.         return (-1);
  1145.     tk_nout++;
  1146.     tp->t_outcc++;
  1147.     /*
  1148.      * Newline translation: if ONLCR is set,
  1149.      * translate newline into "\r\n".
  1150.      */
  1151.     if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0)
  1152.         return (c);
  1153.     if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq))
  1154.         return (c);
  1155.  
  1156.     col = tp->t_col;
  1157.     switch (CCLASS(c)) {
  1158.  
  1159.     case ORDINARY:
  1160.         col++;
  1161.  
  1162.     case CONTROL:
  1163.         break;
  1164.  
  1165.     case BACKSPACE:
  1166.         if (col > 0)
  1167.             col--;
  1168.         break;
  1169.  
  1170.     case NEWLINE:
  1171.         col = 0;
  1172.         break;
  1173.  
  1174.     case TAB:
  1175.         col = (col + 8) &~ 0x7;
  1176.         break;
  1177.  
  1178.     case RETURN:
  1179.         col = 0;
  1180.     }
  1181.     tp->t_col = col;
  1182.     return (-1);
  1183. }
  1184.  
  1185. /*
  1186.  * Process a read call on a tty device.
  1187.  */
  1188. ttread(tp, uio, flag)
  1189.     register struct tty *tp;
  1190.     struct uio *uio;
  1191. {
  1192.     register struct clist *qp;
  1193.     register int c;
  1194.     register long lflag;
  1195.     register u_char *cc = tp->t_cc;
  1196.         register struct proc *p = (struct proc*)cthread_data(cthread_self());
  1197.     int s, first, error = 0;
  1198.  
  1199. loop:
  1200.     lflag = tp->t_lflag;
  1201.     s = spltty();
  1202.     /*
  1203.      * take pending input first 
  1204.      */
  1205.     if (lflag&PENDIN)
  1206.         ttypend(tp);
  1207.     splx(s);
  1208.  
  1209.     /*
  1210.      * Hang process if it's in the background.
  1211.      */
  1212.     if (isbackground(p, tp)) {
  1213.         if ((p->p_sigignore & sigmask(SIGTTIN)) ||
  1214.            (p->p_sigmask & sigmask(SIGTTIN)) ||
  1215.             p->p_flag&SPPWAIT || p->p_pgrp->pg_jobc == 0)
  1216.             return (EIO);
  1217.         pgsignal(p->p_pgrp, SIGTTIN, 1);
  1218.         if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 
  1219.             ttybg, 0)) 
  1220.             return (error);
  1221.         goto loop;
  1222.     }
  1223.  
  1224.     /*
  1225.      * If canonical, use the canonical queue,
  1226.      * else use the raw queue.
  1227.      *
  1228.      * (should get rid of clists...)
  1229.      */
  1230.     qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq;
  1231.  
  1232.     /*
  1233.      * If there is no input, sleep on rawq
  1234.      * awaiting hardware receipt and notification.
  1235.      * If we have data, we don't need to check for carrier.
  1236.      */
  1237.     s = spltty();
  1238.     if (qp->c_cc <= 0) {
  1239.         int carrier;
  1240.  
  1241.         carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL);
  1242.         if (!carrier && tp->t_state&TS_ISOPEN) {
  1243.             splx(s);
  1244.             return (0);    /* EOF */
  1245.         }
  1246.         if (flag & IO_NDELAY) {
  1247.             splx(s);
  1248.             return (EWOULDBLOCK);
  1249.         }
  1250.         error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
  1251.             carrier ? ttyin : ttopen, 0);
  1252.         splx(s);
  1253.         if (error)
  1254.             return (error);
  1255.         goto loop;
  1256.     }
  1257.     splx(s);
  1258.  
  1259.     /*
  1260.      * Input present, check for input mapping and processing.
  1261.      */
  1262.     first = 1;
  1263.     while ((c = getc(qp)) >= 0) {
  1264.         /*
  1265.          * delayed suspend (^Y)
  1266.          */
  1267.         if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) {
  1268.             pgsignal(tp->t_pgrp, SIGTSTP, 1);
  1269.             if (first) {
  1270.                 if (error = ttysleep(tp, (caddr_t)&lbolt,
  1271.                     TTIPRI | PCATCH, ttybg, 0))
  1272.                     break;
  1273.                 goto loop;
  1274.             }
  1275.             break;
  1276.         }
  1277.         /*
  1278.          * Interpret EOF only in canonical mode.
  1279.          */
  1280.         if (CCEQ(cc[VEOF], c) && lflag&ICANON)
  1281.             break;
  1282.         /*
  1283.          * Give user character.
  1284.          */
  1285.          error = ureadc(c, uio);
  1286.         if (error)
  1287.             break;
  1288.          if (uio->uio_resid == 0)
  1289.             break;
  1290.         /*
  1291.          * In canonical mode check for a "break character"
  1292.          * marking the end of a "line of input".
  1293.          */
  1294.         if (lflag&ICANON && ttbreakc(c))
  1295.             break;
  1296.         first = 0;
  1297.     }
  1298.     /*
  1299.      * Look to unblock output now that (presumably)
  1300.      * the input queue has gone down.
  1301.      */
  1302.     if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
  1303.         if (cc[VSTART] != _POSIX_VDISABLE &&
  1304.             putc(cc[VSTART], &tp->t_outq) == 0) {
  1305.             tp->t_state &= ~TS_TBLOCK;
  1306.             ttstart(tp);
  1307.         }
  1308.     }
  1309.     return (error);
  1310. }
  1311.  
  1312. /*
  1313.  * Check the output queue on tp for space for a kernel message
  1314.  * (from uprintf/tprintf).  Allow some space over the normal
  1315.  * hiwater mark so we don't lose messages due to normal flow
  1316.  * control, but don't let the tty run amok.
  1317.  * Sleeps here are not interruptible, but we return prematurely
  1318.  * if new signals come in.
  1319.  */
  1320. ttycheckoutq(tp, wait)
  1321.     register struct tty *tp;
  1322.     int wait;
  1323. {
  1324.         struct proc *curproc = (struct proc*)cthread_data(cthread_self());
  1325.     int hiwat, s, oldsig;
  1326.     extern int wakeup();
  1327.  
  1328.     hiwat = tp->t_hiwat;
  1329.     s = spltty();
  1330.     oldsig = curproc->p_sig;
  1331.     if (tp->t_outq.c_cc > hiwat + 200)
  1332.         while (tp->t_outq.c_cc > hiwat) {
  1333.             ttstart(tp);
  1334.             if (wait == 0 || curproc->p_sig != oldsig) {
  1335.                 splx(s);
  1336.                 return (0);
  1337.             }
  1338.             timeout(wakeup, (caddr_t)&tp->t_outq, hz);
  1339.             tp->t_state |= TS_ASLEEP;
  1340.             sleep((caddr_t)&tp->t_outq, PZERO - 1);
  1341.         }
  1342.     splx(s);
  1343.     return (1);
  1344. }
  1345.  
  1346. /*
  1347.  * Process a write call on a tty device.
  1348.  */
  1349. ttwrite(tp, uio, flag)
  1350.     register struct tty *tp;
  1351.     register struct uio *uio;
  1352. {
  1353.     register char *cp;
  1354.     register int cc = 0, ce;
  1355.         struct proc *p = (struct proc*)cthread_data(cthread_self());
  1356.     int i, hiwat, cnt, error, s;
  1357.     char obuf[OBUFSIZ];
  1358.  
  1359.     hiwat = tp->t_hiwat;
  1360.     cnt = uio->uio_resid;
  1361.     error = 0;
  1362. loop:
  1363.     s = spltty();
  1364.     if ((tp->t_state&TS_CARR_ON) == 0 && (tp->t_cflag&CLOCAL) == 0) {
  1365.         if (tp->t_state&TS_ISOPEN) {
  1366.             splx(s);
  1367.             return (EIO);
  1368.         } else if (flag & IO_NDELAY) {
  1369.             splx(s);
  1370.             error = EWOULDBLOCK;
  1371.             goto out;
  1372.         } else {
  1373.             /*
  1374.              * sleep awaiting carrier
  1375.              */
  1376.             error = ttysleep(tp, (caddr_t)&tp->t_rawq, 
  1377.                     TTIPRI | PCATCH,ttopen, 0);
  1378.             splx(s);
  1379.             if (error)
  1380.                 goto out;
  1381.             goto loop;
  1382.         }
  1383.     }
  1384.     splx(s);
  1385.     /*
  1386.      * Hang the process if it's in the background.
  1387.      */
  1388.     if (isbackground(p, tp) && 
  1389.         tp->t_lflag&TOSTOP && (p->p_flag&SPPWAIT) == 0 &&
  1390.         (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
  1391.         (p->p_sigmask & sigmask(SIGTTOU)) == 0 &&
  1392.          p->p_pgrp->pg_jobc) {
  1393.         pgsignal(p->p_pgrp, SIGTTOU, 1);
  1394.         if (error = ttysleep(tp, (caddr_t)&lbolt, TTIPRI | PCATCH, 
  1395.             ttybg, 0))
  1396.             goto out;
  1397.         goto loop;
  1398.     }
  1399.     /*
  1400.      * Process the user's data in at most OBUFSIZ
  1401.      * chunks.  Perform any output translation.
  1402.      * Keep track of high water mark, sleep on overflow
  1403.      * awaiting device aid in acquiring new space.
  1404.      */
  1405.     while (uio->uio_resid > 0 || cc > 0) {
  1406.         if (tp->t_lflag&FLUSHO) {
  1407.             uio->uio_resid = 0;
  1408.             return (0);
  1409.         }
  1410.         if (tp->t_outq.c_cc > hiwat)
  1411.             goto ovhiwat;
  1412.         /*
  1413.          * Grab a hunk of data from the user,
  1414.          * unless we have some leftover from last time.
  1415.          */
  1416.         if (cc == 0) {
  1417.             cc = min(uio->uio_resid, OBUFSIZ);
  1418.             cp = obuf;
  1419.             error = uiomove(cp, cc, uio);
  1420.             if (error) {
  1421.                 cc = 0;
  1422.                 break;
  1423.             }
  1424.         }
  1425.         /*
  1426.          * If nothing fancy need be done, grab those characters we
  1427.          * can handle without any of ttyoutput's processing and
  1428.          * just transfer them to the output q.  For those chars
  1429.          * which require special processing (as indicated by the
  1430.          * bits in partab), call ttyoutput.  After processing
  1431.          * a hunk of data, look for FLUSHO so ^O's will take effect
  1432.          * immediately.
  1433.          */
  1434.         while (cc > 0) {
  1435.             if ((tp->t_oflag&OPOST) == 0)
  1436.                 ce = cc;
  1437.             else {
  1438.                 ce = cc - scanc((unsigned)cc, (u_char *)cp,
  1439.                    (u_char *)partab, CCLASSMASK);
  1440.                 /*
  1441.                  * If ce is zero, then we're processing
  1442.                  * a special character through ttyoutput.
  1443.                  */
  1444.                 if (ce == 0) {
  1445.                     tp->t_rocount = 0;
  1446.                     if (ttyoutput(*cp, tp) >= 0) {
  1447.                         /* no c-lists, wait a bit */
  1448.                         ttstart(tp);
  1449.                         if (error = ttysleep(tp, 
  1450.                         (caddr_t)&lbolt,
  1451.                          TTOPRI | PCATCH, ttybuf, 0))
  1452.                             break;
  1453.                         goto loop;
  1454.                     }
  1455.                     cp++, cc--;
  1456.                     if ((tp->t_lflag&FLUSHO) ||
  1457.                         tp->t_outq.c_cc > hiwat)
  1458.                         goto ovhiwat;
  1459.                     continue;
  1460.                 }
  1461.             }
  1462.             /*
  1463.              * A bunch of normal characters have been found,
  1464.              * transfer them en masse to the output queue and
  1465.              * continue processing at the top of the loop.
  1466.              * If there are any further characters in this
  1467.              * <= OBUFSIZ chunk, the first should be a character
  1468.              * requiring special handling by ttyoutput.
  1469.              */
  1470.             tp->t_rocount = 0;
  1471.             i = b_to_q(cp, ce, &tp->t_outq);
  1472.             ce -= i;
  1473.             tp->t_col += ce;
  1474.             cp += ce, cc -= ce, tk_nout += ce;
  1475.             tp->t_outcc += ce;
  1476.             if (i > 0) {
  1477.                 /* out of c-lists, wait a bit */
  1478.                 ttstart(tp);
  1479.                 if (error = ttysleep(tp, (caddr_t)&lbolt,
  1480.                         TTOPRI | PCATCH, ttybuf, 0))
  1481.                     break;
  1482.                 goto loop;
  1483.             }
  1484.             if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat)
  1485.                 break;
  1486.         }
  1487.         ttstart(tp);
  1488.     }
  1489. out:
  1490.     /*
  1491.      * If cc is nonzero, we leave the uio structure inconsistent,
  1492.      * as the offset and iov pointers have moved forward,
  1493.      * but it doesn't matter (the call will either return short
  1494.      * or restart with a new uio).
  1495.      */
  1496.     uio->uio_resid += cc;
  1497.     return (error);
  1498.  
  1499. ovhiwat:
  1500.     ttstart(tp);
  1501.     s = spltty();
  1502.     /*
  1503.      * This can only occur if FLUSHO is set in t_lflag,
  1504.      * or if ttstart/oproc is synchronous (or very fast).
  1505.      */
  1506.     if (tp->t_outq.c_cc <= hiwat) {
  1507.         splx(s);
  1508.         goto loop;
  1509.     }
  1510.     if (flag & IO_NDELAY) {
  1511.         splx(s);
  1512.         uio->uio_resid += cc;
  1513.         if (uio->uio_resid == cnt)
  1514.             return (EWOULDBLOCK);
  1515.         return (0);
  1516.     }
  1517.     tp->t_state |= TS_ASLEEP;
  1518.     error = ttysleep(tp, (caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
  1519.     splx(s);
  1520.     if (error)
  1521.         goto out;
  1522.     goto loop;
  1523. }
  1524.  
  1525. /*
  1526.  * Rubout one character from the rawq of tp
  1527.  * as cleanly as possible.
  1528.  */
  1529. ttyrub(c, tp)
  1530.     register c;
  1531.     register struct tty *tp;
  1532. {
  1533.     register char *cp;
  1534.     register int savecol;
  1535.     int s;
  1536.     char *nextc();
  1537.  
  1538.     if ((tp->t_lflag&ECHO) == 0 || (tp->t_lflag&EXTPROC))
  1539.         return;
  1540.     tp->t_lflag &= ~FLUSHO;    
  1541.     if (tp->t_lflag&ECHOE) {
  1542.         if (tp->t_rocount == 0) {
  1543.             /*
  1544.              * Screwed by ttwrite; retype
  1545.              */
  1546.             ttyretype(tp);
  1547.             return;
  1548.         }
  1549.         if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE))
  1550.             ttyrubo(tp, 2);
  1551.         else switch (CCLASS(c &= TTY_CHARMASK)) {
  1552.  
  1553.         case ORDINARY:
  1554.             ttyrubo(tp, 1);
  1555.             break;
  1556.  
  1557.         case VTAB:
  1558.         case BACKSPACE:
  1559.         case CONTROL:
  1560.         case RETURN:
  1561.         case NEWLINE:
  1562.             if (tp->t_lflag&ECHOCTL)
  1563.                 ttyrubo(tp, 2);
  1564.             break;
  1565.  
  1566.         case TAB: {
  1567.             int c;
  1568.  
  1569.             if (tp->t_rocount < tp->t_rawq.c_cc) {
  1570.                 ttyretype(tp);
  1571.                 return;
  1572.             }
  1573.             s = spltty();
  1574.             savecol = tp->t_col;
  1575.             tp->t_state |= TS_CNTTB;
  1576.             tp->t_lflag |= FLUSHO;
  1577.             tp->t_col = tp->t_rocol;
  1578.             cp = tp->t_rawq.c_cf;
  1579.             if (cp)
  1580.                 c = *cp;    /* XXX FIX NEXTC */
  1581.             for (; cp; cp = nextc(&tp->t_rawq, cp, &c))
  1582.                 ttyecho(c, tp);
  1583.             tp->t_lflag &= ~FLUSHO;
  1584.             tp->t_state &= ~TS_CNTTB;
  1585.             splx(s);
  1586.             /*
  1587.              * savecol will now be length of the tab
  1588.              */
  1589.             savecol -= tp->t_col;
  1590.             tp->t_col += savecol;
  1591.             if (savecol > 8)
  1592.                 savecol = 8;        /* overflow screw */
  1593.             while (--savecol >= 0)
  1594.                 (void) ttyoutput('\b', tp);
  1595.             break;
  1596.         }
  1597.  
  1598.         default:
  1599.             /* XXX */
  1600.             printf("ttyrub: would panic c = %d, val = %d\n",
  1601.                 c, CCLASS(c));
  1602.             /*panic("ttyrub");*/
  1603.         }
  1604.     } else if (tp->t_lflag&ECHOPRT) {
  1605.         if ((tp->t_state&TS_ERASE) == 0) {
  1606.             (void) ttyoutput('\\', tp);
  1607.             tp->t_state |= TS_ERASE;
  1608.         }
  1609.         ttyecho(c, tp);
  1610.     } else
  1611.         ttyecho(tp->t_cc[VERASE], tp);
  1612.     tp->t_rocount--;
  1613. }
  1614.  
  1615. /*
  1616.  * Crt back over cnt chars perhaps
  1617.  * erasing them.
  1618.  */
  1619. ttyrubo(tp, cnt)
  1620.     register struct tty *tp;
  1621.     int cnt;
  1622. {
  1623.  
  1624.     while (--cnt >= 0)
  1625.         ttyoutstr("\b \b", tp);
  1626. }
  1627.  
  1628. /*
  1629.  * Reprint the rawq line.
  1630.  * We assume c_cc has already been checked.
  1631.  */
  1632. ttyretype(tp)
  1633.     register struct tty *tp;
  1634. {
  1635.     register char *cp;
  1636.     char *nextc();
  1637.     int s, c;
  1638.  
  1639.     if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
  1640.         ttyecho(tp->t_cc[VREPRINT], tp);
  1641.     (void) ttyoutput('\n', tp);
  1642.     s = spltty();
  1643.     /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE
  1644.       BIT OF FIRST CHAR ****/
  1645.     for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) {
  1646.         ttyecho(c, tp);
  1647.     }
  1648.     for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) {
  1649.         ttyecho(c, tp);
  1650.     }
  1651.     tp->t_state &= ~TS_ERASE;
  1652.     splx(s);
  1653.     tp->t_rocount = tp->t_rawq.c_cc;
  1654.     tp->t_rocol = 0;
  1655. }
  1656.  
  1657. /*
  1658.  * Echo a typed character to the terminal.
  1659.  */
  1660. ttyecho(c, tp)
  1661.     register c;
  1662.     register struct tty *tp;
  1663. {
  1664.     if ((tp->t_state&TS_CNTTB) == 0)
  1665.         tp->t_lflag &= ~FLUSHO;
  1666.     if (((tp->t_lflag&ECHO) == 0 &&
  1667.         ((tp->t_lflag&ECHONL) == 0 || c == '\n')) || (tp->t_lflag&EXTPROC))
  1668.         return;
  1669.     if (tp->t_lflag&ECHOCTL) {
  1670.         if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' ||
  1671.             c == 0177) {
  1672.             (void) ttyoutput('^', tp);
  1673.             c &= TTY_CHARMASK;
  1674.             if (c == 0177)
  1675.                 c = '?';
  1676.             else
  1677.                 c += 'A' - 1;
  1678.         }
  1679.     }
  1680.     (void) ttyoutput(c, tp);
  1681. }
  1682.  
  1683. /*
  1684.  * send string cp to tp
  1685.  */
  1686. ttyoutstr(cp, tp)
  1687.     register char *cp;
  1688.     register struct tty *tp;
  1689. {
  1690.     register char c;
  1691.  
  1692.     while (c = *cp++)
  1693.         (void) ttyoutput(c, tp);
  1694. }
  1695.  
  1696. /*
  1697.  * Wake up any readers on a tty.
  1698.  */
  1699. ttwakeup(tp)
  1700.     register struct tty *tp;
  1701. {
  1702.  
  1703.         selwakeup(&tp->t_rsel);
  1704.     if (tp->t_state & TS_ASYNC)
  1705.         pgsignal(tp->t_pgrp, SIGIO, 1); 
  1706.     wakeup((caddr_t)&tp->t_rawq);
  1707. }
  1708.  
  1709. /*
  1710.  * Look up a code for a specified speed in a conversion table;
  1711.  * used by drivers to map software speed values to hardware parameters.
  1712.  */
  1713. ttspeedtab(speed, table)
  1714.     register struct speedtab *table;
  1715. {
  1716.  
  1717.     for ( ; table->sp_speed != -1; table++)
  1718.         if (table->sp_speed == speed)
  1719.             return (table->sp_code);
  1720.     return (-1);
  1721. }
  1722.  
  1723. /*
  1724.  * set tty hi and low water marks
  1725.  *
  1726.  * Try to arrange the dynamics so there's about one second
  1727.  * from hi to low water.
  1728.  * 
  1729.  */
  1730. ttsetwater(tp)
  1731.     struct tty *tp;
  1732. {
  1733.     register cps = tp->t_ospeed / 10;
  1734.     register x;
  1735.  
  1736. #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x))
  1737.     tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT);
  1738.     x += cps;
  1739.     x = clamp(x, TTMAXHIWAT, TTMINHIWAT);
  1740.     tp->t_hiwat = roundup(x, CBSIZE);
  1741. #undef clamp
  1742. }
  1743.  
  1744. /*
  1745.  * Report on state of foreground process group.
  1746.  */
  1747. ttyinfo(tp)
  1748.     register struct tty *tp;
  1749. {
  1750.     register struct proc *p, *pick;
  1751.     struct timeval utime, stime;
  1752.     int tmp;
  1753.  
  1754.     if (ttycheckoutq(tp,0) == 0) 
  1755.         return;
  1756.  
  1757.     /* Print load average. */
  1758.     tmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
  1759.     ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
  1760.  
  1761.     if (tp->t_session == NULL)
  1762.         ttyprintf(tp, "not a controlling terminal\n");
  1763.     else if (tp->t_pgrp == NULL)
  1764.         ttyprintf(tp, "no foreground process group\n");
  1765.     else if ((p = tp->t_pgrp->pg_mem) == NULL)
  1766.         ttyprintf(tp, "empty foreground process group\n");
  1767.     else {
  1768.         /* Pick interesting process. */
  1769.         for (pick = NULL; p != NULL; p = p->p_pgrpnxt)
  1770.             if (proc_compare(pick, p))
  1771.                 pick = p;
  1772.  
  1773.         ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
  1774.             pick->p_stat == SRUN ? "running" :
  1775.             pick->p_wmesg ? pick->p_wmesg : "iowait");
  1776.  
  1777.         /*
  1778.          * Lock out clock if process is running; get user/system
  1779.          * cpu time.
  1780.          */
  1781.         utime = pick->p_utime;
  1782.         stime = pick->p_stime;
  1783.  
  1784.         /* Print user time. */
  1785.         ttyprintf(tp, "%d.%02du ",
  1786.             utime.tv_sec, (utime.tv_usec + 5000) / 10000);
  1787.  
  1788.         /* Print system time. */
  1789.         ttyprintf(tp, "%d.%02ds ",
  1790.             stime.tv_sec, (stime.tv_usec + 5000) / 10000);
  1791.  
  1792. #define    pgtok(a)    (((a) * NBPG) / 1024)
  1793.         /* Print percentage cpu, resident set size. */
  1794.         tmp = pick->p_pctcpu * 10000 + FSCALE / 2 >> FSHIFT;
  1795.         ttyprintf(tp, "%d%% %dk\n",
  1796.            tmp / 100, /*pgtok(pick->p_vmspace->vm_rssize)XXX*/0);
  1797.     }
  1798.     tp->t_rocount = 0;    /* so pending input will be retyped if BS */
  1799. }
  1800.  
  1801. /*
  1802.  * Returns 1 if p2 is "better" than p1
  1803.  *
  1804.  * The algorithm for picking the "interesting" process is thus:
  1805.  *
  1806.  *    1) (Only foreground processes are eligable - implied)
  1807.  *    2) Runnable processes are favored over anything
  1808.  *       else.  The runner with the highest cpu
  1809.  *       utilization is picked (p_cpu).  Ties are
  1810.  *       broken by picking the highest pid.
  1811.  *    3  Next, the sleeper with the shortest sleep
  1812.  *       time is favored.  With ties, we pick out
  1813.  *       just "short-term" sleepers (SSINTR == 0).
  1814.  *       Further ties are broken by picking the highest
  1815.  *       pid.
  1816.  *
  1817.  */
  1818. #define isrun(p)    (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
  1819. #define TESTAB(a, b)    ((a)<<1 | (b))
  1820. #define ONLYA   2
  1821. #define ONLYB   1
  1822. #define BOTH    3
  1823.  
  1824. static int
  1825. proc_compare(p1, p2)
  1826.     register struct proc *p1, *p2;
  1827. {
  1828.  
  1829.     if (p1 == NULL)
  1830.         return (1);
  1831.     /*
  1832.      * see if at least one of them is runnable
  1833.      */
  1834.     switch (TESTAB(isrun(p1), isrun(p2))) {
  1835.     case ONLYA:
  1836.         return (0);
  1837.     case ONLYB:
  1838.         return (1);
  1839.     case BOTH:
  1840.         /*
  1841.          * tie - favor one with highest recent cpu utilization
  1842.          */
  1843.         if (p2->p_cpu > p1->p_cpu)
  1844.             return (1);
  1845.         if (p1->p_cpu > p2->p_cpu)
  1846.             return (0);
  1847.         return (p2->p_pid > p1->p_pid);    /* tie - return highest pid */
  1848.     }
  1849.     /*
  1850.       * weed out zombies
  1851.      */
  1852.     switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
  1853.     case ONLYA:
  1854.         return (1);
  1855.     case ONLYB:
  1856.         return (0);
  1857.     case BOTH:
  1858.         return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
  1859.     }
  1860.     /* 
  1861.      * pick the one with the smallest sleep time
  1862.      */
  1863.     if (p2->p_slptime > p1->p_slptime)
  1864.         return (0);
  1865.     if (p1->p_slptime > p2->p_slptime)
  1866.         return (1);
  1867.     /*
  1868.      * favor one sleeping in a non-interruptible sleep
  1869.      */
  1870.     if (p1->p_flag&SSINTR && (p2->p_flag&SSINTR) == 0)
  1871.         return (1);
  1872.     if (p2->p_flag&SSINTR && (p1->p_flag&SSINTR) == 0)
  1873.         return (0);
  1874.     return (p2->p_pid > p1->p_pid);        /* tie - return highest pid */
  1875. }
  1876.  
  1877. /*
  1878.  * Output char to tty; console putchar style.
  1879.  */
  1880. tputchar(c, tp)
  1881.     int c;
  1882.     struct tty *tp;
  1883. {
  1884.     register s = spltty();
  1885.  
  1886.     if ((tp->t_state & (TS_CARR_ON|TS_ISOPEN)) == (TS_CARR_ON|TS_ISOPEN)) {
  1887.         if (c == '\n')
  1888.             (void) ttyoutput('\r', tp);
  1889.         (void) ttyoutput(c, tp);
  1890.         ttstart(tp);
  1891.         splx(s);
  1892.         return (0);
  1893.     }
  1894.     splx(s);
  1895.     return (-1);
  1896. }
  1897.  
  1898. /*
  1899.  * Sleep on chan, returning ERESTART if tty changed
  1900.  * while we napped and returning any errors (e.g. EINTR/ETIMEDOUT)
  1901.  * reported by tsleep.  If the tty is revoked, restarting a pending
  1902.  * call will redo validation done at the start of the call.
  1903.  */
  1904. ttysleep(tp, chan, pri, wmesg, timo)
  1905.     struct tty *tp;
  1906.     caddr_t chan;
  1907.     int pri;
  1908.     char *wmesg;
  1909.     int timo;
  1910. {
  1911.     int error;
  1912.     short gen = tp->t_gen;
  1913.  
  1914.     if (error = tsleep(chan, pri, wmesg, timo))
  1915.         return (error);
  1916.     if (tp->t_gen != gen)
  1917.         return (ERESTART);
  1918.     return (0);
  1919. }
  1920.