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