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