tty.c revision 8318
195887Sjmallett/*-
290744Sjmallett * Copyright (c) 1982, 1986, 1990, 1991, 1993
390744Sjmallett *	The Regents of the University of California.  All rights reserved.
490744Sjmallett * (c) UNIX System Laboratories, Inc.
590744Sjmallett * All or some portions of this file are derived from material licensed
690744Sjmallett * to the University of California by American Telephone and Telegraph
790744Sjmallett * Co. or Unix System Laboratories, Inc. and are reproduced herein with
890744Sjmallett * the permission of UNIX System Laboratories, Inc.
990744Sjmallett *
1090744Sjmallett * Redistribution and use in source and binary forms, with or without
1190744Sjmallett * modification, are permitted provided that the following conditions
1290744Sjmallett * are met:
1390744Sjmallett * 1. Redistributions of source code must retain the above copyright
1490744Sjmallett *    notice, this list of conditions and the following disclaimer.
1590744Sjmallett * 2. Redistributions in binary form must reproduce the above copyright
1690744Sjmallett *    notice, this list of conditions and the following disclaimer in the
1790744Sjmallett *    documentation and/or other materials provided with the distribution.
1890744Sjmallett * 3. All advertising materials mentioning features or use of this software
1990744Sjmallett *    must display the following acknowledgement:
2090744Sjmallett *	This product includes software developed by the University of
2190744Sjmallett *	California, Berkeley and its contributors.
2290744Sjmallett * 4. Neither the name of the University nor the names of its contributors
2390744Sjmallett *    may be used to endorse or promote products derived from this software
2490744Sjmallett *    without specific prior written permission.
2590744Sjmallett *
2690744Sjmallett * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2790744Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2895061Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2995061Sjmallett * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3095061Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31100014Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3290744Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3390744Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3490744Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3590744Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3690744Sjmallett * SUCH DAMAGE.
3790744Sjmallett *
3890744Sjmallett *	@(#)tty.c	8.8 (Berkeley) 1/21/94
3990744Sjmallett * $Id: tty.c,v 1.42 1995/04/15 21:04:58 bde Exp $
4090744Sjmallett */
4190744Sjmallett
4290744Sjmallett#include "snp.h"
4390744Sjmallett
4490744Sjmallett#include <sys/param.h>
4590744Sjmallett#include <sys/systm.h>
4690744Sjmallett#include <sys/ioctl.h>
4790744Sjmallett#include <sys/proc.h>
4890744Sjmallett#define	TTYDEFCHARS
4990744Sjmallett#include <sys/tty.h>
5090744Sjmallett#undef	TTYDEFCHARS
5190744Sjmallett#include <sys/file.h>
5290744Sjmallett#include <sys/conf.h>
5390744Sjmallett#include <sys/dkstat.h>
5490744Sjmallett#include <sys/uio.h>
5590744Sjmallett#include <sys/kernel.h>
5690744Sjmallett#include <sys/vnode.h>
57218909Sbrucec#include <sys/syslog.h>
5890744Sjmallett#include <sys/signalvar.h>
5990744Sjmallett#include <sys/resourcevar.h>
6090744Sjmallett#include <sys/malloc.h>
6190744Sjmallett#if NSNP > 0
6290744Sjmallett#include <sys/snoop.h>
6390744Sjmallett#endif
6490744Sjmallett
6590744Sjmallett#include <vm/vm.h>
6690744Sjmallett
6790744Sjmallett
6890744Sjmallettstatic int	proc_compare __P((struct proc *p1, struct proc *p2));
6990744Sjmallettstatic int	ttnread __P((struct tty *));
7090744Sjmallettstatic void	ttyblock __P((struct tty *tp));
7190744Sjmallettstatic void	ttyecho __P((int, struct tty *tp));
7290744Sjmallettstatic void	ttyrubo __P((struct tty *, int));
7395887Sjmallett
7490744Sjmallett/* Symbolic sleep message strings. */
7590744Sjmallettchar ttclos[]	= "ttycls";
7690744Sjmallettchar ttopen[]	= "ttyopn";
7790744Sjmallettchar ttybg[]	= "ttybg";
7890744Sjmallettchar ttybuf[]	= "ttybuf";
7990744Sjmallettchar ttyin[]	= "ttyin";
8090744Sjmallettchar ttyout[]	= "ttyout";
8190744Sjmallett
8290744Sjmallett/*
8390744Sjmallett * Table with character classes and parity. The 8th bit indicates parity,
8490744Sjmallett * the 7th bit indicates the character is an alphameric or underscore (for
8590744Sjmallett * ALTWERASE), and the low 6 bits indicate delay type.  If the low 6 bits
86100014Sjmallett * are 0 then the character needs no special processing on output; classes
87100014Sjmallett * other than 0 might be translated or (not currently) require delays.
8895887Sjmallett */
8990744Sjmallett#define	E	0x00	/* Even parity. */
9090744Sjmallett#define	O	0x80	/* Odd parity. */
9190744Sjmallett#define	PARITY(c)	(char_type[c] & O)
9290744Sjmallett
9390744Sjmallett#define	ALPHA	0x40	/* Alpha or underscore. */
9490744Sjmallett#define	ISALPHA(c)	(char_type[(c) & TTY_CHARMASK] & ALPHA)
9590744Sjmallett
9690744Sjmallett#define	CCLASSMASK	0x3f
9790744Sjmallett#define	CCLASS(c)	(char_type[c] & CCLASSMASK)
9890744Sjmallett
9990744Sjmallett#define	BS	BACKSPACE
10090744Sjmallett#define	CC	CONTROL
10190744Sjmallett#define	CR	RETURN
10290744Sjmallett#define	NA	ORDINARY | ALPHA
10399939Sjmallett#define	NL	NEWLINE
10490744Sjmallett#define	NO	ORDINARY
10590744Sjmallett#define	TB	TAB
10690744Sjmallett#define	VT	VTAB
10790744Sjmallett
10890744Sjmallettchar const char_type[] = {
10990744Sjmallett	E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,	/* nul - bel */
11090744Sjmallett	O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
11190744Sjmallett	O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
11290744Sjmallett	E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
11390744Sjmallett	O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
114100014Sjmallett	E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
11590744Sjmallett	E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
11690744Sjmallett	O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
11790744Sjmallett	O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
11890744Sjmallett	E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
11990744Sjmallett	E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
120100014Sjmallett	O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
12190744Sjmallett	E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
12290744Sjmallett	O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
12390744Sjmallett	O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
12490744Sjmallett	E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
12590744Sjmallett	/*
12690744Sjmallett	 * Meta chars; should be settable per character set;
12790744Sjmallett	 * for now, treat them all as normal characters.
12895887Sjmallett	 */
12990744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13090744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13190744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13290744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13390744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13490744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13590744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
136172261Skevlo	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13790744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13890744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
13990744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
14090744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
14190744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
14290744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
14390744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
14490744Sjmallett	NA,   NA,   NA,   NA,   NA,   NA,   NA,   NA,
14595887Sjmallett};
14690744Sjmallett#undef	BS
14790744Sjmallett#undef	CC
14890744Sjmallett#undef	CR
14990744Sjmallett#undef	NA
15090744Sjmallett#undef	NL
15190744Sjmallett#undef	NO
15290744Sjmallett#undef	TB
15390744Sjmallett#undef	VT
15490744Sjmallett
15590744Sjmallett/* Macros to clear/set/test flags. */
15690744Sjmallett#define	SET(t, f)	(t) |= (f)
15790744Sjmallett#define	CLR(t, f)	(t) &= ~(f)
15890744Sjmallett#define	ISSET(t, f)	((t) & (f))
15990744Sjmallett
16090744Sjmallett/*
16190744Sjmallett * Initial open of tty, or (re)entry to standard tty line discipline.
162100014Sjmallett */
16395887Sjmallettint
16490744Sjmallettttyopen(device, tp)
16590744Sjmallett	dev_t device;
16690744Sjmallett	register struct tty *tp;
16790744Sjmallett{
16890744Sjmallett	int s;
16990744Sjmallett
17090744Sjmallett	s = spltty();
17190744Sjmallett	tp->t_dev = device;
17290744Sjmallett	if (!ISSET(tp->t_state, TS_ISOPEN)) {
17390744Sjmallett		SET(tp->t_state, TS_ISOPEN);
174100014Sjmallett		bzero(&tp->t_winsize, sizeof(tp->t_winsize));
17595887Sjmallett	}
17690744Sjmallett	CLR(tp->t_state, TS_WOPEN);
17790744Sjmallett
17890744Sjmallett	/*
17990744Sjmallett	 * Initialize or restore a cblock allocation policy suitable for
18090744Sjmallett	 * the standard line discipline.
18190744Sjmallett	 */
18290744Sjmallett	clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
18390744Sjmallett	clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + 200, 512);
184100014Sjmallett	clist_alloc_cblocks(&tp->t_rawq, TTYHOG, TTYHOG);
18590744Sjmallett
18690744Sjmallett	splx(s);
18790744Sjmallett	return (0);
18890744Sjmallett}
18990744Sjmallett
19090744Sjmallett/*
19190744Sjmallett * Handle close() on a tty line: flush and set to initial state,
19290744Sjmallett * bumping generation number so that pending read/write calls
19390744Sjmallett * can detect recycling of the tty.
19495887Sjmallett */
19590744Sjmallettint
19690744Sjmallettttyclose(tp)
19790744Sjmallett	register struct tty *tp;
19890744Sjmallett{
19990744Sjmallett	int s;
20090744Sjmallett
20195095Sjmallett	s = spltty();
20290744Sjmallett	if (constty == tp)
20390744Sjmallett		constty = NULL;
20490744Sjmallett
205100014Sjmallett	ttyflush(tp, FREAD | FWRITE);
20695887Sjmallett	clist_free_cblocks(&tp->t_canq);
20790744Sjmallett	clist_free_cblocks(&tp->t_outq);
20890744Sjmallett	clist_free_cblocks(&tp->t_rawq);
20990744Sjmallett
21090744Sjmallett#if NSNP > 0
21190744Sjmallett	if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
21290744Sjmallett		snpdown((struct snoop *)tp->t_sc);
21390744Sjmallett#endif
21490744Sjmallett
21590744Sjmallett	tp->t_gen++;
21690744Sjmallett	tp->t_pgrp = NULL;
21790744Sjmallett	tp->t_session = NULL;
21890744Sjmallett	tp->t_state = 0;
21990744Sjmallett	splx(s);
22090744Sjmallett	return (0);
22190744Sjmallett}
22290744Sjmallett
223100014Sjmallett#define	FLUSHQ(q) {							\
22495887Sjmallett	if ((q)->c_cc)							\
22590744Sjmallett		ndflush(q, (q)->c_cc);					\
22690744Sjmallett}
22790744Sjmallett
22890744Sjmallett/* Is 'c' a line delimiter ("break" character)? */
22990744Sjmallett#define	TTBREAKC(c)							\
23090744Sjmallett	((c) == '\n' || (((c) == cc[VEOF] ||				\
23190744Sjmallett	(c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE))
23290744Sjmallett
23390744Sjmallett/*-
23490744Sjmallett * TODO:
23590744Sjmallett *	o Fix races for sending the start char in ttyflush().
23690744Sjmallett *	o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect().
23790744Sjmallett *	  With luck, there will be MIN chars before select() returns().
23890744Sjmallett *	o Handle CLOCAL consistently for ptys.  Perhaps disallow setting it.
23999939Sjmallett *	o Don't allow input in TS_ZOMBIE case.  It would be visible through
24090744Sjmallett *	  FIONREAD.
24190744Sjmallett *	o Do the new sio locking stuff here and use it to avoid special
24290744Sjmallett *	  case for EXTPROC?
24390744Sjmallett *	o Lock PENDIN too?
24490744Sjmallett *	o Move EXTPROC and/or PENDIN to t_state?
24590744Sjmallett *	o Wrap most of ttioctl in spltty/splx.
24690744Sjmallett *	o Implement TIOCNOTTY or remove it from <sys/ioctl.h>.
247100014Sjmallett */
24895887Sjmallett
24990744Sjmallett
25090744Sjmallett/*
25190744Sjmallett * Process input of a single character received on a tty.
25290744Sjmallett */
25390744Sjmallettint
25490744Sjmallettttyinput(c, tp)
25590744Sjmallett	register int c;
25690744Sjmallett	register struct tty *tp;
25790744Sjmallett{
25890744Sjmallett	register int iflag, lflag;
25990744Sjmallett	register u_char *cc;
26095887Sjmallett	int i, err;
26190744Sjmallett
26290744Sjmallett	/*
26395164Sjmallett	 * If input is pending take it first.
26490744Sjmallett	 */
26590744Sjmallett	lflag = tp->t_lflag;
26690744Sjmallett	if (ISSET(lflag, PENDIN))
26790744Sjmallett		ttypend(tp);
26890744Sjmallett	/*
26990744Sjmallett	 * Gather stats.
27090744Sjmallett	 */
27190744Sjmallett	if (ISSET(lflag, ICANON)) {
27290744Sjmallett		++tk_cancc;
27390744Sjmallett		++tp->t_cancc;
27490744Sjmallett	} else {
27590744Sjmallett		++tk_rawcc;
276100014Sjmallett		++tp->t_rawcc;
27795887Sjmallett	}
27890744Sjmallett	++tk_nin;
27990744Sjmallett
28090744Sjmallett	/* Handle exceptional conditions (break, parity, framing). */
28190744Sjmallett	cc = tp->t_cc;
28290744Sjmallett	iflag = tp->t_iflag;
28390744Sjmallett	err = (ISSET(c, TTY_ERRORMASK));
28490744Sjmallett	if (err) {
28590744Sjmallett		CLR(c, TTY_ERRORMASK);
28690744Sjmallett		if (ISSET(err, TTY_BI)) { /* Break. */
28790744Sjmallett			if (ISSET(iflag, IGNBRK))
28890744Sjmallett				return (0);
28990744Sjmallett			else if (ISSET(iflag, BRKINT) &&
29090744Sjmallett			    ISSET(lflag, ISIG) &&
29190744Sjmallett			    (cc[VINTR] != _POSIX_VDISABLE))
29290744Sjmallett				c = cc[VINTR];
29390744Sjmallett			else if (ISSET(iflag, PARMRK))
29490744Sjmallett				goto parmrk;
29590744Sjmallett		} else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
29690744Sjmallett			|| ISSET(err, TTY_FE)) {
29790744Sjmallett			if (ISSET(iflag, IGNPAR))
29890744Sjmallett				return (0);
29990744Sjmallett			else if (ISSET(iflag, PARMRK)) {
30090744Sjmallettparmrk:				(void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
30190744Sjmallett				(void)putc(0 | TTY_QUOTE, &tp->t_rawq);
30290744Sjmallett				(void)putc(c | TTY_QUOTE, &tp->t_rawq);
30390744Sjmallett				goto endcase;
30490744Sjmallett			} else
30590744Sjmallett				c = 0;
30690744Sjmallett		}
30790744Sjmallett	}
30890744Sjmallett	/*
309100014Sjmallett	 * In tandem mode, check high water mark.
31095887Sjmallett	 */
31190744Sjmallett	if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CRTS_IFLOW))
31290744Sjmallett		ttyblock(tp);
31390744Sjmallett	if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
31490744Sjmallett		CLR(c, 0x80);
31590744Sjmallett	if (!ISSET(lflag, EXTPROC)) {
31690744Sjmallett		/*
31790744Sjmallett		 * Check for literal nexting very first
31890744Sjmallett		 */
31990744Sjmallett		if (ISSET(tp->t_state, TS_LNCH)) {
32090744Sjmallett			SET(c, TTY_QUOTE);
32190744Sjmallett			CLR(tp->t_state, TS_LNCH);
32290744Sjmallett		}
32390744Sjmallett		/*
324100014Sjmallett		 * Scan for special characters.  This code
32590744Sjmallett		 * is really just a big case statement with
326100014Sjmallett		 * non-constant cases.  The bottom of the
32790744Sjmallett		 * case statement is labeled ``endcase'', so goto
328100014Sjmallett		 * it after a case match, or similar.
32990744Sjmallett		 */
33090744Sjmallett
33190744Sjmallett		/*
33290744Sjmallett		 * Control chars which aren't controlled
33390744Sjmallett		 * by ICANON, ISIG, or IXON.
33490744Sjmallett		 */
33590744Sjmallett		if (ISSET(lflag, IEXTEN)) {
33690744Sjmallett			if (CCEQ(cc[VLNEXT], c)) {
33790744Sjmallett				if (ISSET(lflag, ECHO)) {
33890744Sjmallett					if (ISSET(lflag, ECHOE)) {
33990744Sjmallett						(void)ttyoutput('^', tp);
34090744Sjmallett						(void)ttyoutput('\b', tp);
34190744Sjmallett					} else
34290744Sjmallett						ttyecho(c, tp);
34390744Sjmallett				}
34490744Sjmallett				SET(tp->t_state, TS_LNCH);
34590744Sjmallett				goto endcase;
34690744Sjmallett			}
34790744Sjmallett			if (CCEQ(cc[VDISCARD], c)) {
34890744Sjmallett				if (ISSET(lflag, FLUSHO))
349100014Sjmallett					CLR(tp->t_lflag, FLUSHO);
35095887Sjmallett				else {
35190744Sjmallett					ttyflush(tp, FWRITE);
35290744Sjmallett					ttyecho(c, tp);
35390744Sjmallett					if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
35490744Sjmallett						ttyretype(tp);
355100014Sjmallett					SET(tp->t_lflag, FLUSHO);
35690744Sjmallett				}
35790744Sjmallett				goto startoutput;
35890744Sjmallett			}
35990744Sjmallett		}
36090744Sjmallett		/*
36190744Sjmallett		 * Signals.
36290744Sjmallett		 */
36390744Sjmallett		if (ISSET(lflag, ISIG)) {
36490744Sjmallett			if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
36590744Sjmallett				if (!ISSET(lflag, NOFLSH))
366100014Sjmallett					ttyflush(tp, FREAD | FWRITE);
36795887Sjmallett				ttyecho(c, tp);
36890744Sjmallett				pgsignal(tp->t_pgrp,
36990744Sjmallett				    CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
37090744Sjmallett				goto endcase;
37190744Sjmallett			}
37290744Sjmallett			if (CCEQ(cc[VSUSP], c)) {
37390744Sjmallett				if (!ISSET(lflag, NOFLSH))
37490744Sjmallett					ttyflush(tp, FREAD);
37590744Sjmallett				ttyecho(c, tp);
37690744Sjmallett				pgsignal(tp->t_pgrp, SIGTSTP, 1);
37790744Sjmallett				goto endcase;
37890744Sjmallett			}
37990744Sjmallett		}
38090744Sjmallett		/*
38190744Sjmallett		 * Handle start/stop characters.
38290744Sjmallett		 */
38390744Sjmallett		if (ISSET(iflag, IXON)) {
38490744Sjmallett			if (CCEQ(cc[VSTOP], c)) {
38590744Sjmallett				if (!ISSET(tp->t_state, TS_TTSTOP)) {
38690744Sjmallett					SET(tp->t_state, TS_TTSTOP);
38795887Sjmallett#ifdef sun4c						/* XXX */
38890744Sjmallett					(*tp->t_stop)(tp, 0);
38990744Sjmallett#else
39090744Sjmallett					(*cdevsw[major(tp->t_dev)].d_stop)(tp,
39190744Sjmallett					   0);
39290744Sjmallett#endif
39390744Sjmallett					return (0);
39490744Sjmallett				}
39590744Sjmallett				if (!CCEQ(cc[VSTART], c))
39690744Sjmallett					return (0);
39790744Sjmallett				/*
39890744Sjmallett				 * if VSTART == VSTOP then toggle
39990744Sjmallett				 */
40090744Sjmallett				goto endcase;
40190744Sjmallett			}
40290744Sjmallett			if (CCEQ(cc[VSTART], c))
40390744Sjmallett				goto restartoutput;
40490744Sjmallett		}
40590744Sjmallett		/*
40690744Sjmallett		 * IGNCR, ICRNL, & INLCR
40790744Sjmallett		 */
40890744Sjmallett		if (c == '\r') {
40990744Sjmallett			if (ISSET(iflag, IGNCR))
41090744Sjmallett				return (0);
41190744Sjmallett			else if (ISSET(iflag, ICRNL))
41290744Sjmallett				c = '\n';
41390744Sjmallett		} else if (c == '\n' && ISSET(iflag, INLCR))
41490744Sjmallett			c = '\r';
41590744Sjmallett	}
41690744Sjmallett	if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
41790744Sjmallett		/*
41890744Sjmallett		 * From here on down canonical mode character
41990744Sjmallett		 * processing takes place.
42090744Sjmallett		 */
42190744Sjmallett		/*
42290744Sjmallett		 * erase (^H / ^?)
42390744Sjmallett		 */
42490744Sjmallett		if (CCEQ(cc[VERASE], c)) {
42590744Sjmallett			if (tp->t_rawq.c_cc)
42690744Sjmallett				ttyrub(unputc(&tp->t_rawq), tp);
42790744Sjmallett			goto endcase;
42890744Sjmallett		}
42990744Sjmallett		/*
43090744Sjmallett		 * kill (^U)
43190744Sjmallett		 */
43295887Sjmallett		if (CCEQ(cc[VKILL], c)) {
43390744Sjmallett			if (ISSET(lflag, ECHOKE) &&
43490744Sjmallett			    tp->t_rawq.c_cc == tp->t_rocount &&
43590744Sjmallett			    !ISSET(lflag, ECHOPRT))
43690744Sjmallett				while (tp->t_rawq.c_cc)
43790744Sjmallett					ttyrub(unputc(&tp->t_rawq), tp);
43890744Sjmallett			else {
43990744Sjmallett				ttyecho(c, tp);
44090744Sjmallett				if (ISSET(lflag, ECHOK) ||
44190744Sjmallett				    ISSET(lflag, ECHOKE))
442100014Sjmallett					ttyecho('\n', tp);
44390744Sjmallett				FLUSHQ(&tp->t_rawq);
44490744Sjmallett				tp->t_rocount = 0;
44590744Sjmallett			}
446100014Sjmallett			CLR(tp->t_state, TS_LOCAL);
44790744Sjmallett			goto endcase;
448100014Sjmallett		}
44990744Sjmallett		/*
45090744Sjmallett		 * word erase (^W)
45190744Sjmallett		 */
45290744Sjmallett		if (CCEQ(cc[VWERASE], c)) {
45390744Sjmallett			int alt = ISSET(lflag, ALTWERASE);
45490744Sjmallett			int ctype;
45590744Sjmallett
45695887Sjmallett			/*
45790744Sjmallett			 * erase whitespace
45890744Sjmallett			 */
45990744Sjmallett			while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
46090744Sjmallett				ttyrub(c, tp);
46190744Sjmallett			if (c == -1)
46290744Sjmallett				goto endcase;
46390744Sjmallett			/*
46490744Sjmallett			 * erase last char of word and remember the
46590744Sjmallett			 * next chars type (for ALTWERASE)
466100014Sjmallett			 */
46790744Sjmallett			ttyrub(c, tp);
46890744Sjmallett			c = unputc(&tp->t_rawq);
46990744Sjmallett			if (c == -1)
470100014Sjmallett				goto endcase;
47190744Sjmallett			if (c == ' ' || c == '\t') {
47290744Sjmallett				(void)putc(c, &tp->t_rawq);
47390744Sjmallett				goto endcase;
47490744Sjmallett			}
47590744Sjmallett			ctype = ISALPHA(c);
47690744Sjmallett			/*
47790744Sjmallett			 * erase rest of word
47890744Sjmallett			 */
47990744Sjmallett			do {
48090744Sjmallett				ttyrub(c, tp);
48195887Sjmallett				c = unputc(&tp->t_rawq);
48290744Sjmallett				if (c == -1)
48390744Sjmallett					goto endcase;
48490744Sjmallett			} while (c != ' ' && c != '\t' &&
48590744Sjmallett			    (alt == 0 || ISALPHA(c) == ctype));
48690744Sjmallett			(void)putc(c, &tp->t_rawq);
48790744Sjmallett			goto endcase;
48890744Sjmallett		}
48990744Sjmallett		/*
49090744Sjmallett		 * reprint line (^R)
49190744Sjmallett		 */
49290744Sjmallett		if (CCEQ(cc[VREPRINT], c)) {
49390744Sjmallett			ttyretype(tp);
49490744Sjmallett			goto endcase;
49590744Sjmallett		}
49690744Sjmallett		/*
49790744Sjmallett		 * ^T - kernel info and generate SIGINFO
49890744Sjmallett		 */
49990744Sjmallett		if (CCEQ(cc[VSTATUS], c)) {
50090744Sjmallett			if (ISSET(lflag, ISIG))
50190744Sjmallett				pgsignal(tp->t_pgrp, SIGINFO, 1);
502129392Sstefanf			if (!ISSET(lflag, NOKERNINFO))
50390744Sjmallett				ttyinfo(tp);
50490744Sjmallett			goto endcase;
50590744Sjmallett		}
50690744Sjmallett	}
50790744Sjmallett	/*
50890744Sjmallett	 * Check for input buffer overflow
50990744Sjmallett	 */
51090744Sjmallett	if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
51190744Sjmallett		if (ISSET(iflag, IMAXBEL)) {
51290744Sjmallett			if (tp->t_outq.c_cc < tp->t_hiwat)
51390744Sjmallett				(void)ttyoutput(CTRL('g'), tp);
51490744Sjmallett		}
51590744Sjmallett		goto endcase;
51690744Sjmallett	}
51790744Sjmallett
51890744Sjmallett	if (   c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
51990744Sjmallett	     && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
52090744Sjmallett		(void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
521
522	/*
523	 * Put data char in q for user and
524	 * wakeup on seeing a line delimiter.
525	 */
526	if (putc(c, &tp->t_rawq) >= 0) {
527		if (!ISSET(lflag, ICANON)) {
528			ttwakeup(tp);
529			ttyecho(c, tp);
530			goto endcase;
531		}
532		if (TTBREAKC(c)) {
533			tp->t_rocount = 0;
534			catq(&tp->t_rawq, &tp->t_canq);
535			ttwakeup(tp);
536		} else if (tp->t_rocount++ == 0)
537			tp->t_rocol = tp->t_column;
538		if (ISSET(tp->t_state, TS_ERASE)) {
539			/*
540			 * end of prterase \.../
541			 */
542			CLR(tp->t_state, TS_ERASE);
543			(void)ttyoutput('/', tp);
544		}
545		i = tp->t_column;
546		ttyecho(c, tp);
547		if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
548			/*
549			 * Place the cursor over the '^' of the ^D.
550			 */
551			i = min(2, tp->t_column - i);
552			while (i > 0) {
553				(void)ttyoutput('\b', tp);
554				i--;
555			}
556		}
557	}
558endcase:
559	/*
560	 * IXANY means allow any character to restart output.
561	 */
562	if (ISSET(tp->t_state, TS_TTSTOP) &&
563	    !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
564		return (0);
565restartoutput:
566	CLR(tp->t_lflag, FLUSHO);
567	CLR(tp->t_state, TS_TTSTOP);
568startoutput:
569	return (ttstart(tp));
570}
571
572/*
573 * Output a single character on a tty, doing output processing
574 * as needed (expanding tabs, newline processing, etc.).
575 * Returns < 0 if succeeds, otherwise returns char to resend.
576 * Must be recursive.
577 */
578int
579ttyoutput(c, tp)
580	register int c;
581	register struct tty *tp;
582{
583	register long oflag;
584	register int col, s;
585
586	oflag = tp->t_oflag;
587	if (!ISSET(oflag, OPOST)) {
588		if (ISSET(tp->t_lflag, FLUSHO))
589			return (-1);
590		if (putc(c, &tp->t_outq))
591			return (c);
592		tk_nout++;
593		tp->t_outcc++;
594		return (-1);
595	}
596	/*
597	 * Do tab expansion if OXTABS is set.  Special case if we external
598	 * processing, we don't do the tab expansion because we'll probably
599	 * get it wrong.  If tab expansion needs to be done, let it happen
600	 * externally.
601	 */
602	CLR(c, ~TTY_CHARMASK);
603	if (c == '\t' &&
604	    ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
605		c = 8 - (tp->t_column & 7);
606		if (!ISSET(tp->t_lflag, FLUSHO)) {
607			s = spltty();		/* Don't interrupt tabs. */
608			c -= b_to_q("        ", c, &tp->t_outq);
609			tk_nout += c;
610			tp->t_outcc += c;
611			splx(s);
612		}
613		tp->t_column += c;
614		return (c ? -1 : '\t');
615	}
616	if (c == CEOT && ISSET(oflag, ONOEOT))
617		return (-1);
618
619	/*
620	 * Newline translation: if ONLCR is set,
621	 * translate newline into "\r\n".
622	 */
623	if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
624		tk_nout++;
625		tp->t_outcc++;
626		if (putc('\r', &tp->t_outq))
627			return (c);
628	}
629	tk_nout++;
630	tp->t_outcc++;
631	if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
632		return (c);
633
634	col = tp->t_column;
635	switch (CCLASS(c)) {
636	case BACKSPACE:
637		if (col > 0)
638			--col;
639		break;
640	case CONTROL:
641		break;
642	case NEWLINE:
643	case RETURN:
644		col = 0;
645		break;
646	case ORDINARY:
647		++col;
648		break;
649	case TAB:
650		col = (col + 8) & ~7;
651		break;
652	}
653	tp->t_column = col;
654	return (-1);
655}
656
657/*
658 * Ioctls for all tty devices.  Called after line-discipline specific ioctl
659 * has been called to do discipline-specific functions and/or reject any
660 * of these ioctl commands.
661 */
662/* ARGSUSED */
663int
664ttioctl(tp, cmd, data, flag)
665	register struct tty *tp;
666	int cmd, flag;
667	void *data;
668{
669	register struct proc *p;
670	int s, error;
671
672	p = curproc;			/* XXX */
673
674	/* If the ioctl involves modification, hang if in the background. */
675	switch (cmd) {
676	case  TIOCFLUSH:
677	case  TIOCSETA:
678	case  TIOCSETD:
679	case  TIOCSETAF:
680	case  TIOCSETAW:
681#ifdef notdef
682	case  TIOCSPGRP:
683#endif
684	case  TIOCSTAT:
685	case  TIOCSTI:
686	case  TIOCSWINSZ:
687#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
688	case  TIOCLBIC:
689	case  TIOCLBIS:
690	case  TIOCLSET:
691	case  TIOCSETC:
692	case OTIOCSETD:
693	case  TIOCSETN:
694	case  TIOCSETP:
695	case  TIOCSLTC:
696#endif
697		while (isbackground(curproc, tp) &&
698		    p->p_pgrp->pg_jobc && (p->p_flag & P_PPWAIT) == 0 &&
699		    (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
700		    (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
701			pgsignal(p->p_pgrp, SIGTTOU, 1);
702			error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, ttybg, 0);
703			if (error)
704				return (error);
705		}
706		break;
707	}
708
709	switch (cmd) {			/* Process the ioctl. */
710	case FIOASYNC:			/* set/clear async i/o */
711		s = spltty();
712		if (*(int *)data)
713			SET(tp->t_state, TS_ASYNC);
714		else
715			CLR(tp->t_state, TS_ASYNC);
716		splx(s);
717		break;
718	case FIONBIO:			/* set/clear non-blocking i/o */
719		break;			/* XXX: delete. */
720	case FIONREAD:			/* get # bytes to read */
721		*(int *)data = ttnread(tp);
722		break;
723	case TIOCEXCL:			/* set exclusive use of tty */
724		s = spltty();
725		SET(tp->t_state, TS_XCLUDE);
726		splx(s);
727		break;
728	case TIOCFLUSH: {		/* flush buffers */
729		register int flags = *(int *)data;
730
731		if (flags == 0)
732			flags = FREAD | FWRITE;
733		else
734			flags &= FREAD | FWRITE;
735		ttyflush(tp, flags);
736		break;
737	}
738	case TIOCCONS:			/* become virtual console */
739		if (*(int *)data) {
740			if (constty && constty != tp &&
741			    ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
742			    (TS_CARR_ON | TS_ISOPEN))
743				return (EBUSY);
744#ifndef	UCONSOLE
745			if (error = suser(p->p_ucred, &p->p_acflag))
746				return (error);
747#endif
748			constty = tp;
749		} else if (tp == constty)
750			constty = NULL;
751		break;
752	case TIOCDRAIN:			/* wait till output drained */
753		error = ttywait(tp);
754		if (error)
755			return (error);
756		break;
757	case TIOCGETA: {		/* get termios struct */
758		struct termios *t = (struct termios *)data;
759
760		bcopy(&tp->t_termios, t, sizeof(struct termios));
761		break;
762	}
763	case TIOCGETD:			/* get line discipline */
764		*(int *)data = tp->t_line;
765		break;
766	case TIOCGWINSZ:		/* get window size */
767		*(struct winsize *)data = tp->t_winsize;
768		break;
769	case TIOCGPGRP:			/* get pgrp of tty */
770		if (!isctty(p, tp))
771			return (ENOTTY);
772		*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
773		break;
774#ifdef TIOCHPCL
775	case TIOCHPCL:			/* hang up on last close */
776		s = spltty();
777		SET(tp->t_cflag, HUPCL);
778		splx(s);
779		break;
780#endif
781	case TIOCNXCL:			/* reset exclusive use of tty */
782		s = spltty();
783		CLR(tp->t_state, TS_XCLUDE);
784		splx(s);
785		break;
786	case TIOCOUTQ:			/* output queue size */
787		*(int *)data = tp->t_outq.c_cc;
788		break;
789	case TIOCSETA:			/* set termios struct */
790	case TIOCSETAW:			/* drain output, set */
791	case TIOCSETAF: {		/* drn out, fls in, set */
792		register struct termios *t = (struct termios *)data;
793
794		s = spltty();
795		if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
796			error = ttywait(tp);
797			if (error) {
798				splx(s);
799				return (error);
800			}
801			if (cmd == TIOCSETAF)
802				ttyflush(tp, FREAD);
803		}
804		if (!ISSET(t->c_cflag, CIGNORE)) {
805			/*
806			 * Set device hardware.
807			 */
808			if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
809				splx(s);
810				return (error);
811			} else {
812				if (!ISSET(tp->t_state, TS_CARR_ON) &&
813				    ISSET(tp->t_cflag, CLOCAL) &&
814				    !ISSET(t->c_cflag, CLOCAL)) {
815#if 0
816					CLR(tp->t_state, TS_ISOPEN);
817					SET(tp->t_state, TS_WOPEN);
818#endif
819					ttwakeup(tp);
820				}
821				tp->t_cflag = t->c_cflag;
822				tp->t_ispeed = t->c_ispeed;
823				tp->t_ospeed = t->c_ospeed;
824			}
825			ttsetwater(tp);
826		}
827		if (cmd != TIOCSETAF) {
828			if (ISSET(t->c_lflag, ICANON) !=
829			    ISSET(tp->t_lflag, ICANON))
830				if (ISSET(t->c_lflag, ICANON)) {
831					SET(tp->t_lflag, PENDIN);
832					ttwakeup(tp);
833				} else {
834					struct clist tq;
835
836					catq(&tp->t_rawq, &tp->t_canq);
837					tq = tp->t_rawq;
838					tp->t_rawq = tp->t_canq;
839					tp->t_canq = tq;
840					CLR(tp->t_lflag, PENDIN);
841				}
842		}
843		tp->t_iflag = t->c_iflag;
844		tp->t_oflag = t->c_oflag;
845		/*
846		 * Make the EXTPROC bit read only.
847		 */
848		if (ISSET(tp->t_lflag, EXTPROC))
849			SET(t->c_lflag, EXTPROC);
850		else
851			CLR(t->c_lflag, EXTPROC);
852		tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
853		if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
854		    t->c_cc[VTIME] != tp->t_cc[VTIME])
855			ttwakeup(tp);
856		bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
857		splx(s);
858		break;
859	}
860	case TIOCSETD: {		/* set line discipline */
861		register int t = *(int *)data;
862		dev_t device = tp->t_dev;
863
864		if ((u_int)t >= nlinesw)
865			return (ENXIO);
866		if (t != tp->t_line) {
867			s = spltty();
868			(*linesw[tp->t_line].l_close)(tp, flag);
869			error = (*linesw[t].l_open)(device, tp);
870			if (error) {
871				(void)(*linesw[tp->t_line].l_open)(device, tp);
872				splx(s);
873				return (error);
874			}
875			tp->t_line = t;
876			splx(s);
877		}
878		break;
879	}
880	case TIOCSTART:			/* start output, like ^Q */
881		s = spltty();
882		if (ISSET(tp->t_state, TS_TTSTOP) ||
883		    ISSET(tp->t_lflag, FLUSHO)) {
884			CLR(tp->t_lflag, FLUSHO);
885			CLR(tp->t_state, TS_TTSTOP);
886			ttstart(tp);
887		}
888		splx(s);
889		break;
890	case TIOCSTI:			/* simulate terminal input */
891		if (p->p_ucred->cr_uid && (flag & FREAD) == 0)
892			return (EPERM);
893		if (p->p_ucred->cr_uid && !isctty(p, tp))
894			return (EACCES);
895		(*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
896		break;
897	case TIOCSTOP:			/* stop output, like ^S */
898		s = spltty();
899		if (!ISSET(tp->t_state, TS_TTSTOP)) {
900			SET(tp->t_state, TS_TTSTOP);
901#ifdef sun4c				/* XXX */
902			(*tp->t_stop)(tp, 0);
903#else
904			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
905#endif
906		}
907		splx(s);
908		break;
909	case TIOCSCTTY:			/* become controlling tty */
910		/* Session ctty vnode pointer set in vnode layer. */
911		if (!SESS_LEADER(p) ||
912		    ((p->p_session->s_ttyvp || tp->t_session) &&
913		    (tp->t_session != p->p_session)))
914			return (EPERM);
915		tp->t_session = p->p_session;
916		tp->t_pgrp = p->p_pgrp;
917		p->p_session->s_ttyp = tp;
918		p->p_flag |= P_CONTROLT;
919		break;
920	case TIOCSPGRP: {		/* set pgrp of tty */
921		register struct pgrp *pgrp = pgfind(*(int *)data);
922
923		if (!isctty(p, tp))
924			return (ENOTTY);
925		else if (pgrp == NULL || pgrp->pg_session != p->p_session)
926			return (EPERM);
927		tp->t_pgrp = pgrp;
928		break;
929	}
930	case TIOCSTAT:			/* simulate control-T */
931		ttyinfo(tp);
932		break;
933	case TIOCSWINSZ:		/* set window size */
934		if (bcmp((caddr_t)&tp->t_winsize, data,
935		    sizeof (struct winsize))) {
936			tp->t_winsize = *(struct winsize *)data;
937			pgsignal(tp->t_pgrp, SIGWINCH, 1);
938		}
939		break;
940	case TIOCSDRAINWAIT:
941		error = suser(p->p_ucred, &p->p_acflag);
942		if (error)
943			return (error);
944		tp->t_timeout = *(int *)data * hz;
945		wakeup((caddr_t)&tp->t_outq);
946		break;
947	case TIOCGDRAINWAIT:
948		*(int *)data = tp->t_timeout / hz;
949		break;
950	default:
951#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
952		return (ttcompat(tp, cmd, data, flag));
953#else
954		return (-1);
955#endif
956	}
957	return (0);
958}
959
960int
961ttyselect(tp, rw, p)
962	struct tty *tp;
963	int rw;
964	struct proc *p;
965{
966	int nread, s;
967
968	if (tp == NULL)
969		return (ENXIO);
970
971	s = spltty();
972	switch (rw) {
973	case FREAD:
974		nread = ttnread(tp);
975		if (nread > 0 || (!ISSET(tp->t_cflag, CLOCAL) &&
976		    !ISSET(tp->t_state, TS_CARR_ON)))
977			goto win;
978		selrecord(p, &tp->t_rsel);
979		break;
980	case FWRITE:
981		if (tp->t_outq.c_cc <= tp->t_lowat) {
982win:			splx(s);
983			return (1);
984		}
985		selrecord(p, &tp->t_wsel);
986		break;
987	}
988	splx(s);
989	return (0);
990}
991
992/*
993 * This is a wrapper for compatibility with the select vector used by
994 * cdevsw.  It relies on a proper xxxdevtotty routine.
995 */
996int
997ttselect(dev, rw, p)
998	dev_t dev;
999	int rw;
1000	struct proc *p;
1001{
1002	return ttyselect((*cdevsw[major(dev)].d_devtotty)(dev), rw, p);
1003}
1004
1005/*
1006 * This is now exported to the cy driver as well; if you hack this code,
1007 * then be sure to keep /sys/i386/isa/cy.c properly advised! -jkh
1008 */
1009static int
1010ttnread(tp)
1011	struct tty *tp;
1012{
1013	int nread;
1014
1015	if (ISSET(tp->t_lflag, PENDIN))
1016		ttypend(tp);
1017	nread = tp->t_canq.c_cc;
1018	if (!ISSET(tp->t_lflag, ICANON)) {
1019		nread += tp->t_rawq.c_cc;
1020		if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1021			nread = 0;
1022	}
1023	return (nread);
1024}
1025
1026/*
1027 * Wait for output to drain.
1028 */
1029int
1030ttywait(tp)
1031	register struct tty *tp;
1032{
1033	int error, s;
1034
1035	error = 0;
1036	s = spltty();
1037	while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1038	    (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
1039	    && tp->t_oproc) {
1040		(*tp->t_oproc)(tp);
1041		if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1042		    (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))) {
1043			SET(tp->t_state, TS_ASLEEP);
1044			error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH,
1045					 ttyout, tp->t_timeout);
1046			if (error)
1047				break;
1048		}
1049	}
1050	if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1051		error = EIO;
1052	splx(s);
1053	return (error);
1054}
1055
1056/*
1057 * Flush if successfully wait.
1058 */
1059int
1060ttywflush(tp)
1061	struct tty *tp;
1062{
1063	int error;
1064
1065	if ((error = ttywait(tp)) == 0)
1066		ttyflush(tp, FREAD);
1067	return (error);
1068}
1069
1070/*
1071 * Flush tty read and/or write queues, notifying anyone waiting.
1072 */
1073void
1074ttyflush(tp, rw)
1075	register struct tty *tp;
1076	int rw;
1077{
1078	register int s;
1079
1080	s = spltty();
1081	if (rw & FWRITE)
1082		CLR(tp->t_state, TS_TTSTOP);
1083#ifdef sun4c						/* XXX */
1084	(*tp->t_stop)(tp, rw);
1085#else
1086	(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1087#endif
1088	if (rw & FREAD) {
1089		FLUSHQ(&tp->t_canq);
1090		FLUSHQ(&tp->t_rawq);
1091		tp->t_rocount = 0;
1092		tp->t_rocol = 0;
1093		CLR(tp->t_state, TS_LOCAL);
1094		ttwakeup(tp);
1095	}
1096	if (rw & FWRITE) {
1097		FLUSHQ(&tp->t_outq);
1098		wakeup((caddr_t)&tp->t_outq);
1099		selwakeup(&tp->t_wsel);
1100	}
1101	if ((rw & FREAD) &&
1102	    ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1103		int queue_full = 0;
1104
1105		if (ISSET(tp->t_iflag, IXOFF) &&
1106		    tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1107		    (queue_full = putc(tp->t_cc[VSTART], &tp->t_outq)) == 0 ||
1108		    ISSET(tp->t_cflag, CRTS_IFLOW)) {
1109			CLR(tp->t_state, TS_TBLOCK);
1110			ttstart(tp);
1111			if (queue_full) /* try again */
1112				SET(tp->t_state, TS_TBLOCK);
1113		}
1114	}
1115	splx(s);
1116}
1117
1118/*
1119 * Copy in the default termios characters.
1120 */
1121void
1122ttychars(tp)
1123	struct tty *tp;
1124{
1125
1126	bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
1127}
1128
1129/*
1130 * Send stop character on input overflow.
1131 */
1132static void
1133ttyblock(tp)
1134	register struct tty *tp;
1135{
1136	register int total;
1137
1138	total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1139	/*
1140	 * Block further input iff: current input > threshold
1141	 * AND input is available to user program.
1142	 */
1143	if (total >= TTYHOG / 2 &&
1144	    !ISSET(tp->t_state, TS_TBLOCK) &&
1145	    (!ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0)) {
1146		int queue_full = 0;
1147
1148		if (ISSET(tp->t_iflag, IXOFF) &&
1149		    tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1150		    (queue_full = putc(tp->t_cc[VSTOP], &tp->t_outq)) == 0 ||
1151		    ISSET(tp->t_cflag, CRTS_IFLOW)) {
1152			SET(tp->t_state, TS_TBLOCK);
1153			ttstart(tp);
1154			if (queue_full) /* try again */
1155				CLR(tp->t_state, TS_TBLOCK);
1156		}
1157	}
1158}
1159
1160void
1161ttrstrt(tp_arg)
1162	void *tp_arg;
1163{
1164	struct tty *tp;
1165	int s;
1166
1167#ifdef DIAGNOSTIC
1168	if (tp_arg == NULL)
1169		panic("ttrstrt");
1170#endif
1171	tp = tp_arg;
1172	s = spltty();
1173
1174	CLR(tp->t_state, TS_TIMEOUT);
1175	ttstart(tp);
1176
1177	splx(s);
1178}
1179
1180int
1181ttstart(tp)
1182	struct tty *tp;
1183{
1184
1185	if (tp->t_oproc != NULL)	/* XXX: Kludge for pty. */
1186		(*tp->t_oproc)(tp);
1187	return (0);
1188}
1189
1190/*
1191 * "close" a line discipline
1192 */
1193int
1194ttylclose(tp, flag)
1195	struct tty *tp;
1196	int flag;
1197{
1198
1199	if (flag & FNONBLOCK || ttywflush(tp))
1200		ttyflush(tp, FREAD | FWRITE);
1201	return (0);
1202}
1203
1204/*
1205 * Handle modem control transition on a tty.
1206 * Flag indicates new state of carrier.
1207 * Returns 0 if the line should be turned off, otherwise 1.
1208 */
1209int
1210ttymodem(tp, flag)
1211	register struct tty *tp;
1212	int flag;
1213{
1214
1215	if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) {
1216		/*
1217		 * MDMBUF: do flow control according to carrier flag
1218		 */
1219		if (flag) {
1220			CLR(tp->t_state, TS_TTSTOP);
1221			ttstart(tp);
1222		} else if (!ISSET(tp->t_state, TS_TTSTOP)) {
1223			SET(tp->t_state, TS_TTSTOP);
1224#ifdef sun4c						/* XXX */
1225			(*tp->t_stop)(tp, 0);
1226#else
1227			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
1228#endif
1229		}
1230	} else if (flag == 0) {
1231		/*
1232		 * Lost carrier.
1233		 */
1234		CLR(tp->t_state, TS_CARR_ON);
1235		if (ISSET(tp->t_state, TS_ISOPEN) &&
1236		    !ISSET(tp->t_cflag, CLOCAL)) {
1237			if (tp->t_session && tp->t_session->s_leader)
1238				psignal(tp->t_session->s_leader, SIGHUP);
1239			ttyflush(tp, FREAD | FWRITE);
1240			return (0);
1241		}
1242	} else {
1243		/*
1244		 * Carrier now on.
1245		 */
1246		SET(tp->t_state, TS_CARR_ON);
1247		ttwakeup(tp);
1248	}
1249	return (1);
1250}
1251
1252/*
1253 * Default modem control routine (for other line disciplines).
1254 * Return argument flag, to turn off device on carrier drop.
1255 */
1256int
1257nullmodem(tp, flag)
1258	register struct tty *tp;
1259	int flag;
1260{
1261
1262	if (flag)
1263		SET(tp->t_state, TS_CARR_ON);
1264	else {
1265		CLR(tp->t_state, TS_CARR_ON);
1266		if (!ISSET(tp->t_cflag, CLOCAL)) {
1267			if (tp->t_session && tp->t_session->s_leader)
1268				psignal(tp->t_session->s_leader, SIGHUP);
1269			return (0);
1270		}
1271	}
1272	return (1);
1273}
1274
1275/*
1276 * Reinput pending characters after state switch
1277 * call at spltty().
1278 */
1279void
1280ttypend(tp)
1281	register struct tty *tp;
1282{
1283	struct clist tq;
1284	register c;
1285
1286	CLR(tp->t_lflag, PENDIN);
1287	SET(tp->t_state, TS_TYPEN);
1288	/*
1289	 * XXX this assumes too much about clist internals.  It may even
1290	 * fail if the cblock slush pool is empty.  We can't allocate more
1291	 * cblocks here because we are called from an interrupt handler
1292	 * and clist_alloc_cblocks() can wait.
1293	 */
1294	tq = tp->t_rawq;
1295	bzero(&tp->t_rawq, sizeof tp->t_rawq);
1296	tp->t_rawq.c_cbmax = tq.c_cbmax;
1297	tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1298	while ((c = getc(&tq)) >= 0)
1299		ttyinput(c, tp);
1300	CLR(tp->t_state, TS_TYPEN);
1301}
1302
1303/*
1304 * Process a read call on a tty device.
1305 */
1306int
1307ttread(tp, uio, flag)
1308	register struct tty *tp;
1309	struct uio *uio;
1310	int flag;
1311{
1312	register struct clist *qp;
1313	register int c;
1314	register tcflag_t lflag;
1315	register cc_t *cc = tp->t_cc;
1316	register struct proc *p = curproc;
1317	int s, first, error = 0, carrier;
1318	int has_stime = 0, last_cc = 0;
1319	long slp = 0;		/* XXX this should be renamed `timo'. */
1320
1321loop:
1322	s = spltty();
1323	lflag = tp->t_lflag;
1324	/*
1325	 * take pending input first
1326	 */
1327	if (ISSET(lflag, PENDIN)) {
1328		ttypend(tp);
1329		splx(s);	/* reduce latency */
1330		s = spltty();
1331		lflag = tp->t_lflag;	/* XXX ttypend() clobbers it */
1332	}
1333
1334	/*
1335	 * Hang process if it's in the background.
1336	 */
1337	if (isbackground(p, tp)) {
1338		splx(s);
1339		if ((p->p_sigignore & sigmask(SIGTTIN)) ||
1340		   (p->p_sigmask & sigmask(SIGTTIN)) ||
1341		    p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0)
1342			return (EIO);
1343		pgsignal(p->p_pgrp, SIGTTIN, 1);
1344		error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1345		if (error)
1346			return (error);
1347		goto loop;
1348	}
1349
1350	/*
1351	 * If canonical, use the canonical queue,
1352	 * else use the raw queue.
1353	 *
1354	 * (should get rid of clists...)
1355	 */
1356	qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1357
1358	if (flag & IO_NDELAY) {
1359		if (qp->c_cc > 0)
1360			goto read;
1361		carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1362		    ISSET(tp->t_cflag, CLOCAL);
1363		if ((!carrier && ISSET(tp->t_state, TS_ISOPEN)) ||
1364		    !ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1365			splx(s);
1366			return (0);
1367		}
1368		splx(s);
1369		return (EWOULDBLOCK);
1370	}
1371	if (!ISSET(lflag, ICANON)) {
1372		int m = cc[VMIN];
1373		long t = cc[VTIME];
1374		struct timeval stime, timecopy;
1375		int x;
1376
1377		/*
1378		 * Check each of the four combinations.
1379		 * (m > 0 && t == 0) is the normal read case.
1380		 * It should be fairly efficient, so we check that and its
1381		 * companion case (m == 0 && t == 0) first.
1382		 * For the other two cases, we compute the target sleep time
1383		 * into slp.
1384		 */
1385		if (t == 0) {
1386			if (qp->c_cc < m)
1387				goto sleep;
1388			if (qp->c_cc > 0)
1389				goto read;
1390
1391			/* m, t and qp->c_cc are all 0.  0 is enough input. */
1392			splx(s);
1393			return (0);
1394		}
1395		t *= 100000;		/* time in us */
1396#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1397			 ((t1).tv_usec - (t2).tv_usec))
1398		if (m > 0) {
1399			if (qp->c_cc <= 0)
1400				goto sleep;
1401			if (qp->c_cc >= m)
1402				goto read;
1403			x = splclock();
1404			timecopy = time;
1405			splx(x);
1406			if (!has_stime) {
1407				/* first character, start timer */
1408				has_stime = 1;
1409				stime = timecopy;
1410				slp = t;
1411			} else if (qp->c_cc > last_cc) {
1412				/* got a character, restart timer */
1413				stime = timecopy;
1414				slp = t;
1415			} else {
1416				/* nothing, check expiration */
1417				slp = t - diff(timecopy, stime);
1418				if (slp <= 0)
1419					goto read;
1420			}
1421			last_cc = qp->c_cc;
1422		} else {	/* m == 0 */
1423			if (qp->c_cc > 0)
1424				goto read;
1425			x = splclock();
1426			timecopy = time;
1427			splx(x);
1428			if (!has_stime) {
1429				has_stime = 1;
1430				stime = timecopy;
1431				slp = t;
1432			} else {
1433				slp = t - diff(timecopy, stime);
1434				if (slp <= 0) {
1435					/* Timed out, but 0 is enough input. */
1436					splx(s);
1437					return (0);
1438				}
1439			}
1440		}
1441#undef diff
1442		/*
1443		 * Rounding down may make us wake up just short
1444		 * of the target, so we round up.
1445		 * The formula is ceiling(slp * hz/1000000).
1446		 * 32-bit arithmetic is enough for hz < 169.
1447		 * XXX see hzto() for how to avoid overflow if hz
1448		 * is large (divide by `tick' and/or arrange to
1449		 * use hzto() if hz is large).
1450		 */
1451		slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1452		goto sleep;
1453	}
1454
1455	/*
1456	 * If there is no input, sleep on rawq
1457	 * awaiting hardware receipt and notification.
1458	 * If we have data, we don't need to check for carrier.
1459	 */
1460	if (qp->c_cc <= 0) {
1461sleep:
1462		carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1463		    ISSET(tp->t_cflag, CLOCAL);
1464		if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1465			splx(s);
1466			return (0);	/* EOF */
1467		}
1468		error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
1469		    carrier ? ttyin : ttopen, (int)slp);
1470		splx(s);
1471		if (error == EWOULDBLOCK)
1472			error = 0;
1473		else if (error)
1474			return (error);
1475		/*
1476		 * XXX what happens if another process eats some input
1477		 * while we are asleep (not just here)?  It would be
1478		 * safest to detect changes and reset our state variables
1479		 * (has_stime and last_cc).
1480		 */
1481		slp = 0;
1482		goto loop;
1483	}
1484read:
1485	splx(s);
1486	/*
1487	 * Input present, check for input mapping and processing.
1488	 */
1489	first = 1;
1490	if (ISSET(lflag, ICANON | ISIG))
1491		goto slowcase;
1492	for (;;) {
1493		char ibuf[IBUFSIZ];
1494		int icc;
1495
1496		icc = min(uio->uio_resid, IBUFSIZ);
1497		icc = q_to_b(qp, ibuf, icc);
1498		if (icc <= 0) {
1499			if (first)
1500				goto loop;
1501			break;
1502		}
1503		error = uiomove(ibuf, icc, uio);
1504		/*
1505		 * XXX if there was an error then we should ungetc() the
1506		 * unmoved chars and reduce icc here.
1507		 */
1508#if NSNP > 0
1509		if (ISSET(tp->t_lflag, ECHO) &&
1510		    ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1511			snpin((struct snoop *)tp->t_sc, ibuf, icc);
1512#endif
1513		if (error)
1514			break;
1515 		if (uio->uio_resid == 0)
1516			break;
1517		first = 0;
1518	}
1519	goto out;
1520slowcase:
1521	for (;;) {
1522		c = getc(qp);
1523		if (c < 0) {
1524			if (first)
1525				goto loop;
1526			break;
1527		}
1528		/*
1529		 * delayed suspend (^Y)
1530		 */
1531		if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) {
1532			pgsignal(tp->t_pgrp, SIGTSTP, 1);
1533			if (first) {
1534				error = ttysleep(tp,
1535				    &lbolt, TTIPRI | PCATCH, ttybg, 0);
1536				if (error)
1537					break;
1538				goto loop;
1539			}
1540			break;
1541		}
1542		/*
1543		 * Interpret EOF only in canonical mode.
1544		 */
1545		if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1546			break;
1547		/*
1548		 * Give user character.
1549		 */
1550 		error = ureadc(c, uio);
1551		if (error)
1552			/* XXX should ungetc(c, qp). */
1553			break;
1554#if NSNP > 0
1555		/*
1556		 * Only snoop directly on input in echo mode.  Non-echoed
1557		 * input will be snooped later iff the application echoes it.
1558		 */
1559		if (ISSET(tp->t_lflag, ECHO) &&
1560		    ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1561			snpinc((struct snoop *)tp->t_sc, (char)c);
1562#endif
1563 		if (uio->uio_resid == 0)
1564			break;
1565		/*
1566		 * In canonical mode check for a "break character"
1567		 * marking the end of a "line of input".
1568		 */
1569		if (ISSET(lflag, ICANON) && TTBREAKC(c))
1570			break;
1571		first = 0;
1572	}
1573	/*
1574	 * Look to unblock input now that (presumably)
1575	 * the input queue has gone down.
1576	 */
1577out:
1578	s = spltty();
1579	if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1580		int queue_full = 0;
1581
1582		if (ISSET(tp->t_iflag, IXOFF) &&
1583		    cc[VSTART] != _POSIX_VDISABLE &&
1584		    (queue_full = putc(cc[VSTART], &tp->t_outq)) == 0 ||
1585		    ISSET(tp->t_cflag, CRTS_IFLOW)) {
1586			CLR(tp->t_state, TS_TBLOCK);
1587			ttstart(tp);
1588			if (queue_full) /* try again */
1589				SET(tp->t_state, TS_TBLOCK);
1590		}
1591	}
1592	splx(s);
1593	return (error);
1594}
1595
1596/*
1597 * Check the output queue on tp for space for a kernel message (from uprintf
1598 * or tprintf).  Allow some space over the normal hiwater mark so we don't
1599 * lose messages due to normal flow control, but don't let the tty run amok.
1600 * Sleeps here are not interruptible, but we return prematurely if new signals
1601 * arrive.
1602 */
1603int
1604ttycheckoutq(tp, wait)
1605	register struct tty *tp;
1606	int wait;
1607{
1608	int hiwat, s, oldsig;
1609
1610	hiwat = tp->t_hiwat;
1611	s = spltty();
1612	oldsig = wait ? curproc->p_siglist : 0;
1613	if (tp->t_outq.c_cc > hiwat + 200)
1614		while (tp->t_outq.c_cc > hiwat) {
1615			ttstart(tp);
1616			if (wait == 0 || curproc->p_siglist != oldsig) {
1617				splx(s);
1618				return (0);
1619			}
1620			timeout((void (*)__P((void *)))wakeup,
1621			    (void *)&tp->t_outq, hz);
1622			SET(tp->t_state, TS_ASLEEP);
1623			(void) tsleep((caddr_t)&tp->t_outq, PZERO - 1, "ttoutq", 0);
1624		}
1625	splx(s);
1626	return (1);
1627}
1628
1629/*
1630 * Process a write call on a tty device.
1631 */
1632int
1633ttwrite(tp, uio, flag)
1634	register struct tty *tp;
1635	register struct uio *uio;
1636	int flag;
1637{
1638	register char *cp = 0;
1639	register int cc, ce;
1640	register struct proc *p;
1641	int i, hiwat, cnt, error, s;
1642	char obuf[OBUFSIZ];
1643
1644	hiwat = tp->t_hiwat;
1645	cnt = uio->uio_resid;
1646	error = 0;
1647	cc = 0;
1648loop:
1649	s = spltty();
1650	if (!ISSET(tp->t_state, TS_CARR_ON) &&
1651	    !ISSET(tp->t_cflag, CLOCAL)) {
1652		if (ISSET(tp->t_state, TS_ISOPEN)) {
1653			splx(s);
1654			return (EIO);
1655		} else if (flag & IO_NDELAY) {
1656			splx(s);
1657			error = EWOULDBLOCK;
1658			goto out;
1659		} else {
1660			/* Sleep awaiting carrier. */
1661			error = ttysleep(tp,
1662			    &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0);
1663			splx(s);
1664			if (error)
1665				goto out;
1666			goto loop;
1667		}
1668	}
1669	splx(s);
1670	/*
1671	 * Hang the process if it's in the background.
1672	 */
1673	p = curproc;
1674	if (isbackground(p, tp) &&
1675	    ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
1676	    (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
1677	    (p->p_sigmask & sigmask(SIGTTOU)) == 0 &&
1678	     p->p_pgrp->pg_jobc) {
1679		pgsignal(p->p_pgrp, SIGTTOU, 1);
1680		error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1681		if (error)
1682			goto out;
1683		goto loop;
1684	}
1685	/*
1686	 * Process the user's data in at most OBUFSIZ chunks.  Perform any
1687	 * output translation.  Keep track of high water mark, sleep on
1688	 * overflow awaiting device aid in acquiring new space.
1689	 */
1690	while (uio->uio_resid > 0 || cc > 0) {
1691		if (ISSET(tp->t_lflag, FLUSHO)) {
1692			uio->uio_resid = 0;
1693			return (0);
1694		}
1695		if (tp->t_outq.c_cc > hiwat)
1696			goto ovhiwat;
1697		/*
1698		 * Grab a hunk of data from the user, unless we have some
1699		 * leftover from last time.
1700		 */
1701		if (cc == 0) {
1702			cc = min(uio->uio_resid, OBUFSIZ);
1703			cp = obuf;
1704			error = uiomove(cp, cc, uio);
1705			if (error) {
1706				cc = 0;
1707				break;
1708			}
1709#if NSNP > 0
1710			if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1711				snpin((struct snoop *)tp->t_sc, cp, cc);
1712#endif
1713		}
1714		/*
1715		 * If nothing fancy need be done, grab those characters we
1716		 * can handle without any of ttyoutput's processing and
1717		 * just transfer them to the output q.  For those chars
1718		 * which require special processing (as indicated by the
1719		 * bits in char_type), call ttyoutput.  After processing
1720		 * a hunk of data, look for FLUSHO so ^O's will take effect
1721		 * immediately.
1722		 */
1723		while (cc > 0) {
1724			if (!ISSET(tp->t_oflag, OPOST))
1725				ce = cc;
1726			else {
1727				ce = cc - scanc((u_int)cc, (u_char *)cp,
1728				   (u_char *)char_type, CCLASSMASK);
1729				/*
1730				 * If ce is zero, then we're processing
1731				 * a special character through ttyoutput.
1732				 */
1733				if (ce == 0) {
1734					tp->t_rocount = 0;
1735					if (ttyoutput(*cp, tp) >= 0) {
1736						/* No Clists, wait a bit. */
1737						ttstart(tp);
1738						if (flag & IO_NDELAY) {
1739							error = EWOULDBLOCK;
1740							goto out;
1741						}
1742						error = ttysleep(tp, &lbolt,
1743						    TTOPRI | PCATCH, ttybuf, 0);
1744						if (error)
1745							goto out;
1746						goto loop;
1747					}
1748					cp++;
1749					cc--;
1750					if (ISSET(tp->t_lflag, FLUSHO) ||
1751					    tp->t_outq.c_cc > hiwat)
1752						goto ovhiwat;
1753					continue;
1754				}
1755			}
1756			/*
1757			 * A bunch of normal characters have been found.
1758			 * Transfer them en masse to the output queue and
1759			 * continue processing at the top of the loop.
1760			 * If there are any further characters in this
1761			 * <= OBUFSIZ chunk, the first should be a character
1762			 * requiring special handling by ttyoutput.
1763			 */
1764			tp->t_rocount = 0;
1765			i = b_to_q(cp, ce, &tp->t_outq);
1766			ce -= i;
1767			tp->t_column += ce;
1768			cp += ce, cc -= ce, tk_nout += ce;
1769			tp->t_outcc += ce;
1770			if (i > 0) {
1771				/* No Clists, wait a bit. */
1772				ttstart(tp);
1773				if (flag & IO_NDELAY) {
1774					error = EWOULDBLOCK;
1775					goto out;
1776				}
1777				error = ttysleep(tp,
1778				    &lbolt, TTOPRI | PCATCH, ttybuf, 0);
1779				if (error)
1780					goto out;
1781				goto loop;
1782			}
1783			if (ISSET(tp->t_lflag, FLUSHO) ||
1784			    tp->t_outq.c_cc > hiwat)
1785				break;
1786		}
1787		ttstart(tp);
1788	}
1789out:
1790	/*
1791	 * If cc is nonzero, we leave the uio structure inconsistent, as the
1792	 * offset and iov pointers have moved forward, but it doesn't matter
1793	 * (the call will either return short or restart with a new uio).
1794	 */
1795	uio->uio_resid += cc;
1796	return (error);
1797
1798ovhiwat:
1799	ttstart(tp);
1800	s = spltty();
1801	/*
1802	 * This can only occur if FLUSHO is set in t_lflag,
1803	 * or if ttstart/oproc is synchronous (or very fast).
1804	 */
1805	if (tp->t_outq.c_cc <= hiwat) {
1806		splx(s);
1807		goto loop;
1808	}
1809	if (flag & IO_NDELAY) {
1810		splx(s);
1811		uio->uio_resid += cc;
1812		return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
1813	}
1814	SET(tp->t_state, TS_ASLEEP);
1815	error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1816	splx(s);
1817	if (error)
1818		goto out;
1819	goto loop;
1820}
1821
1822/*
1823 * Rubout one character from the rawq of tp
1824 * as cleanly as possible.
1825 */
1826void
1827ttyrub(c, tp)
1828	register int c;
1829	register struct tty *tp;
1830{
1831	register char *cp;
1832	register int savecol;
1833	int tabc, s;
1834
1835	if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
1836		return;
1837	CLR(tp->t_lflag, FLUSHO);
1838	if (ISSET(tp->t_lflag, ECHOE)) {
1839		if (tp->t_rocount == 0) {
1840			/*
1841			 * Screwed by ttwrite; retype
1842			 */
1843			ttyretype(tp);
1844			return;
1845		}
1846		if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
1847			ttyrubo(tp, 2);
1848		else {
1849			CLR(c, ~TTY_CHARMASK);
1850			switch (CCLASS(c)) {
1851			case ORDINARY:
1852				ttyrubo(tp, 1);
1853				break;
1854			case BACKSPACE:
1855			case CONTROL:
1856			case NEWLINE:
1857			case RETURN:
1858			case VTAB:
1859				if (ISSET(tp->t_lflag, ECHOCTL))
1860					ttyrubo(tp, 2);
1861				break;
1862			case TAB:
1863				if (tp->t_rocount < tp->t_rawq.c_cc) {
1864					ttyretype(tp);
1865					return;
1866				}
1867				s = spltty();
1868				savecol = tp->t_column;
1869				SET(tp->t_state, TS_CNTTB);
1870				SET(tp->t_lflag, FLUSHO);
1871				tp->t_column = tp->t_rocol;
1872				cp = tp->t_rawq.c_cf;
1873				if (cp)
1874					tabc = *cp;	/* XXX FIX NEXTC */
1875				for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
1876					ttyecho(tabc, tp);
1877				CLR(tp->t_lflag, FLUSHO);
1878				CLR(tp->t_state, TS_CNTTB);
1879				splx(s);
1880
1881				/* savecol will now be length of the tab. */
1882				savecol -= tp->t_column;
1883				tp->t_column += savecol;
1884				if (savecol > 8)
1885					savecol = 8;	/* overflow screw */
1886				while (--savecol >= 0)
1887					(void)ttyoutput('\b', tp);
1888				break;
1889			default:			/* XXX */
1890#define	PANICSTR	"ttyrub: would panic c = %d, val = %d\n"
1891				(void)printf(PANICSTR, c, CCLASS(c));
1892#ifdef notdef
1893				panic(PANICSTR, c, CCLASS(c));
1894#endif
1895			}
1896		}
1897	} else if (ISSET(tp->t_lflag, ECHOPRT)) {
1898		if (!ISSET(tp->t_state, TS_ERASE)) {
1899			SET(tp->t_state, TS_ERASE);
1900			(void)ttyoutput('\\', tp);
1901		}
1902		ttyecho(c, tp);
1903	} else
1904		ttyecho(tp->t_cc[VERASE], tp);
1905	--tp->t_rocount;
1906}
1907
1908/*
1909 * Back over cnt characters, erasing them.
1910 */
1911static void
1912ttyrubo(tp, cnt)
1913	register struct tty *tp;
1914	int cnt;
1915{
1916
1917	while (cnt-- > 0) {
1918		(void)ttyoutput('\b', tp);
1919		(void)ttyoutput(' ', tp);
1920		(void)ttyoutput('\b', tp);
1921	}
1922}
1923
1924/*
1925 * ttyretype --
1926 *	Reprint the rawq line.  Note, it is assumed that c_cc has already
1927 *	been checked.
1928 */
1929void
1930ttyretype(tp)
1931	register struct tty *tp;
1932{
1933	register char *cp;
1934	int s, c;
1935
1936	/* Echo the reprint character. */
1937	if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
1938		ttyecho(tp->t_cc[VREPRINT], tp);
1939
1940	(void)ttyoutput('\n', tp);
1941
1942	/*
1943	 * XXX
1944	 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
1945	 * BIT OF FIRST CHAR.
1946	 */
1947	s = spltty();
1948	for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
1949	    cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
1950		ttyecho(c, tp);
1951	for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
1952	    cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
1953		ttyecho(c, tp);
1954	CLR(tp->t_state, TS_ERASE);
1955	splx(s);
1956
1957	tp->t_rocount = tp->t_rawq.c_cc;
1958	tp->t_rocol = 0;
1959}
1960
1961/*
1962 * Echo a typed character to the terminal.
1963 */
1964static void
1965ttyecho(c, tp)
1966	register int c;
1967	register struct tty *tp;
1968{
1969
1970	if (!ISSET(tp->t_state, TS_CNTTB))
1971		CLR(tp->t_lflag, FLUSHO);
1972	if ((!ISSET(tp->t_lflag, ECHO) &&
1973	    (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) ||
1974	    ISSET(tp->t_lflag, EXTPROC))
1975		return;
1976	if (ISSET(tp->t_lflag, ECHOCTL) &&
1977	    ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
1978	    ISSET(c, TTY_CHARMASK) == 0177)) {
1979		(void)ttyoutput('^', tp);
1980		CLR(c, ~TTY_CHARMASK);
1981		if (c == 0177)
1982			c = '?';
1983		else
1984			c += 'A' - 1;
1985	}
1986	(void)ttyoutput(c, tp);
1987}
1988
1989/*
1990 * Wake up any readers on a tty.
1991 */
1992void
1993ttwakeup(tp)
1994	register struct tty *tp;
1995{
1996
1997	selwakeup(&tp->t_rsel);
1998	if (ISSET(tp->t_state, TS_ASYNC))
1999		pgsignal(tp->t_pgrp, SIGIO, 1);
2000	wakeup((caddr_t)&tp->t_rawq);
2001}
2002
2003/*
2004 * Look up a code for a specified speed in a conversion table;
2005 * used by drivers to map software speed values to hardware parameters.
2006 */
2007int
2008ttspeedtab(speed, table)
2009	int speed;
2010	register struct speedtab *table;
2011{
2012
2013	for ( ; table->sp_speed != -1; table++)
2014		if (table->sp_speed == speed)
2015			return (table->sp_code);
2016	return (-1);
2017}
2018
2019/*
2020 * Set tty hi and low water marks.
2021 *
2022 * Try to arrange the dynamics so there's about one second
2023 * from hi to low water.
2024 *
2025 */
2026void
2027ttsetwater(tp)
2028	struct tty *tp;
2029{
2030	register int cps, x;
2031
2032#define CLAMP(x, h, l)	((x) > h ? h : ((x) < l) ? l : (x))
2033
2034	cps = tp->t_ospeed / 10;
2035	tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2036	x += cps;
2037	x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2038	tp->t_hiwat = roundup(x, CBSIZE);
2039#undef	CLAMP
2040}
2041
2042/*
2043 * Report on state of foreground process group.
2044 */
2045void
2046ttyinfo(tp)
2047	register struct tty *tp;
2048{
2049	register struct proc *p, *pick;
2050	struct timeval utime, stime;
2051	int tmp;
2052
2053	if (ttycheckoutq(tp,0) == 0)
2054		return;
2055
2056	/* Print load average. */
2057	tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2058	ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2059
2060	if (tp->t_session == NULL)
2061		ttyprintf(tp, "not a controlling terminal\n");
2062	else if (tp->t_pgrp == NULL)
2063		ttyprintf(tp, "no foreground process group\n");
2064	else if ((p = tp->t_pgrp->pg_mem) == NULL)
2065		ttyprintf(tp, "empty foreground process group\n");
2066	else {
2067		/* Pick interesting process. */
2068		for (pick = NULL; p != NULL; p = p->p_pgrpnxt)
2069			if (proc_compare(pick, p))
2070				pick = p;
2071
2072		ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
2073		    pick->p_stat == SRUN ? "running" :
2074		    pick->p_wmesg ? pick->p_wmesg : "iowait");
2075
2076		calcru(pick, &utime, &stime, NULL);
2077
2078		/* Print user time. */
2079		ttyprintf(tp, "%d.%02du ",
2080		    utime.tv_sec, utime.tv_usec / 10000);
2081
2082		/* Print system time. */
2083		ttyprintf(tp, "%d.%02ds ",
2084		    stime.tv_sec, stime.tv_usec / 10000);
2085
2086#define	pgtok(a)	(((a) * NBPG) / 1024)
2087		/* Print percentage cpu, resident set size. */
2088		tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2089		ttyprintf(tp, "%d%% %dk\n",
2090		    tmp / 100,
2091		    pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 :
2092#ifdef pmap_resident_count
2093			pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap))
2094#else
2095			pgtok(pick->p_vmspace->vm_rssize)
2096#endif
2097			);
2098	}
2099	tp->t_rocount = 0;	/* so pending input will be retyped if BS */
2100}
2101
2102/*
2103 * Returns 1 if p2 is "better" than p1
2104 *
2105 * The algorithm for picking the "interesting" process is thus:
2106 *
2107 *	1) Only foreground processes are eligible - implied.
2108 *	2) Runnable processes are favored over anything else.  The runner
2109 *	   with the highest cpu utilization is picked (p_estcpu).  Ties are
2110 *	   broken by picking the highest pid.
2111 *	3) The sleeper with the shortest sleep time is next.  With ties,
2112 *	   we pick out just "short-term" sleepers (P_SINTR == 0).
2113 *	4) Further ties are broken by picking the highest pid.
2114 */
2115#define ISRUN(p)	(((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2116#define TESTAB(a, b)    ((a)<<1 | (b))
2117#define ONLYA   2
2118#define ONLYB   1
2119#define BOTH    3
2120
2121static int
2122proc_compare(p1, p2)
2123	register struct proc *p1, *p2;
2124{
2125
2126	if (p1 == NULL)
2127		return (1);
2128	/*
2129	 * see if at least one of them is runnable
2130	 */
2131	switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2132	case ONLYA:
2133		return (0);
2134	case ONLYB:
2135		return (1);
2136	case BOTH:
2137		/*
2138		 * tie - favor one with highest recent cpu utilization
2139		 */
2140		if (p2->p_estcpu > p1->p_estcpu)
2141			return (1);
2142		if (p1->p_estcpu > p2->p_estcpu)
2143			return (0);
2144		return (p2->p_pid > p1->p_pid);	/* tie - return highest pid */
2145	}
2146	/*
2147 	 * weed out zombies
2148	 */
2149	switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2150	case ONLYA:
2151		return (1);
2152	case ONLYB:
2153		return (0);
2154	case BOTH:
2155		return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
2156	}
2157	/*
2158	 * pick the one with the smallest sleep time
2159	 */
2160	if (p2->p_slptime > p1->p_slptime)
2161		return (0);
2162	if (p1->p_slptime > p2->p_slptime)
2163		return (1);
2164	/*
2165	 * favor one sleeping in a non-interruptible sleep
2166	 */
2167	if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)
2168		return (1);
2169	if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)
2170		return (0);
2171	return (p2->p_pid > p1->p_pid);		/* tie - return highest pid */
2172}
2173
2174/*
2175 * Output char to tty; console putchar style.
2176 */
2177int
2178tputchar(c, tp)
2179	int c;
2180	struct tty *tp;
2181{
2182	register int s;
2183
2184	s = spltty();
2185	if (ISSET(tp->t_state,
2186	    TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) {
2187		splx(s);
2188		return (-1);
2189	}
2190	if (c == '\n')
2191		(void)ttyoutput('\r', tp);
2192	(void)ttyoutput(c, tp);
2193	ttstart(tp);
2194	splx(s);
2195	return (0);
2196}
2197
2198/*
2199 * Sleep on chan, returning ERESTART if tty changed while we napped and
2200 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep.  If
2201 * the tty is revoked, restarting a pending call will redo validation done
2202 * at the start of the call.
2203 */
2204int
2205ttysleep(tp, chan, pri, wmesg, timo)
2206	struct tty *tp;
2207	void *chan;
2208	int pri, timo;
2209	char *wmesg;
2210{
2211	int error;
2212	short gen;
2213
2214	gen = tp->t_gen;
2215	error = tsleep(chan, pri, wmesg, timo);
2216	if (error)
2217		return (error);
2218	return (tp->t_gen == gen ? 0 : ERESTART);
2219}
2220
2221/*
2222 * XXX this is usable not useful or used.  Most tty drivers have
2223 * ifdefs for using ttymalloc() but assume a different interface.
2224 */
2225/*
2226 * Allocate a tty struct.  Clists in the struct will be allocated by
2227 * ttyopen().
2228 */
2229struct tty *
2230ttymalloc()
2231{
2232        struct tty *tp;
2233
2234        tp = malloc(sizeof *tp, M_TTYS, M_WAITOK);
2235        bzero(tp, sizeof *tp);
2236        return (tp);
2237}
2238
2239#if 0 /* XXX not yet usable: session leader holds a ref (see kern_exit.c). */
2240/*
2241 * Free a tty struct.  Clists in the struct should have been freed by
2242 * ttyclose().
2243 */
2244void
2245ttyfree(tp)
2246	struct tty *tp;
2247{
2248        free(tp, M_TTYS);
2249}
2250#endif /* 0 */
2251