xref: /csrg-svn/sys/kern/tty.c (revision 24273)
123387Smckusick /*
223387Smckusick  * Copyright (c) 1982 Regents of the University of California.
323387Smckusick  * All rights reserved.  The Berkeley software License Agreement
423387Smckusick  * specifies the terms and conditions for redistribution.
523387Smckusick  *
6*24273Slepreau  *	@(#)tty.c	6.20 (Berkeley) 08/13/85
723387Smckusick  */
839Sbill 
99760Ssam #include "../machine/reg.h"
109760Ssam 
1117095Sbloom #include "param.h"
1217095Sbloom #include "systm.h"
1317095Sbloom #include "dir.h"
1417095Sbloom #include "user.h"
1517095Sbloom #include "ioctl.h"
1617095Sbloom #include "tty.h"
1717095Sbloom #include "proc.h"
1817095Sbloom #include "inode.h"
1917095Sbloom #include "file.h"
2017095Sbloom #include "conf.h"
2117095Sbloom #include "buf.h"
2217095Sbloom #include "dk.h"
2317095Sbloom #include "uio.h"
2417095Sbloom #include "kernel.h"
2539Sbill 
267436Skre /*
277436Skre  * Table giving parity for characters and indicating
287436Skre  * character classes to tty driver.  In particular,
297436Skre  * if the low 6 bits are 0, then the character needs
307436Skre  * no special processing on output.
317436Skre  */
3239Sbill 
337436Skre char partab[] = {
347436Skre 	0001,0201,0201,0001,0201,0001,0001,0201,
357436Skre 	0202,0004,0003,0201,0005,0206,0201,0001,
367436Skre 	0201,0001,0001,0201,0001,0201,0201,0001,
377436Skre 	0001,0201,0201,0001,0201,0001,0001,0201,
387436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
397436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
407436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
417436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
427436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
437436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
447436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
457436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
467436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
477436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
487436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
497436Skre 	0000,0200,0200,0000,0200,0000,0000,0201,
507436Skre 
517436Skre 	/*
527436Skre 	 * 7 bit ascii ends with the last character above,
537436Skre 	 * but we contine through all 256 codes for the sake
547436Skre 	 * of the tty output routines which use special vax
557436Skre 	 * instructions which need a 256 character trt table.
567436Skre 	 */
577436Skre 
587436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
597436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
607436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
617436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
627436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
637436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
647436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
657436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
667436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
677436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
687436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
697436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
707436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
717436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
727436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
737436Skre 	0007,0007,0007,0007,0007,0007,0007,0007
747436Skre };
757436Skre 
76146Sbill /*
7739Sbill  * Input mapping table-- if an entry is non-zero, when the
7839Sbill  * corresponding character is typed preceded by "\" the escape
7939Sbill  * sequence is replaced by the table value.  Mostly used for
8039Sbill  * upper-case only terminals.
8139Sbill  */
8239Sbill char	maptab[] ={
8339Sbill 	000,000,000,000,000,000,000,000,
8439Sbill 	000,000,000,000,000,000,000,000,
8539Sbill 	000,000,000,000,000,000,000,000,
8639Sbill 	000,000,000,000,000,000,000,000,
8739Sbill 	000,'|',000,000,000,000,000,'`',
8839Sbill 	'{','}',000,000,000,000,000,000,
8939Sbill 	000,000,000,000,000,000,000,000,
9039Sbill 	000,000,000,000,000,000,000,000,
9139Sbill 	000,000,000,000,000,000,000,000,
9239Sbill 	000,000,000,000,000,000,000,000,
9339Sbill 	000,000,000,000,000,000,000,000,
9439Sbill 	000,000,000,000,000,000,'~',000,
9539Sbill 	000,'A','B','C','D','E','F','G',
9639Sbill 	'H','I','J','K','L','M','N','O',
9739Sbill 	'P','Q','R','S','T','U','V','W',
9839Sbill 	'X','Y','Z',000,000,000,000,000,
9939Sbill };
10039Sbill 
101925Sbill short	tthiwat[16] =
1028954Sroot    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
103925Sbill short	ttlowat[16] =
104925Sbill    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
105925Sbill 
1069578Ssam struct	ttychars ttydefaults = {
1079578Ssam 	CERASE,	CKILL,	CINTR,	CQUIT,	CSTART,	CSTOP,	CEOF,
1089578Ssam 	CBRK,	CSUSP,	CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
1099578Ssam };
11039Sbill 
11139Sbill ttychars(tp)
1129578Ssam 	struct tty *tp;
11339Sbill {
114174Sbill 
1159578Ssam 	tp->t_chars = ttydefaults;
11639Sbill }
11739Sbill 
11839Sbill /*
119903Sbill  * Wait for output to drain, then flush input waiting.
12039Sbill  */
12112752Ssam ttywflush(tp)
1225408Swnj 	register struct tty *tp;
12339Sbill {
12439Sbill 
12512752Ssam 	ttywait(tp);
12612752Ssam 	ttyflush(tp, FREAD);
12712752Ssam }
12812752Ssam 
12912752Ssam ttywait(tp)
13012752Ssam 	register struct tty *tp;
13112752Ssam {
13217545Skarels 	register int s = spltty();
13312752Ssam 
13413809Ssam 	while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
13513809Ssam 	    tp->t_state&TS_CARR_ON && tp->t_oproc) {	/* kludge for pty */
136903Sbill 		(*tp->t_oproc)(tp);
1375408Swnj 		tp->t_state |= TS_ASLEEP;
138903Sbill 		sleep((caddr_t)&tp->t_outq, TTOPRI);
139903Sbill 	}
1409859Ssam 	splx(s);
14139Sbill }
14239Sbill 
14339Sbill /*
1449578Ssam  * Flush all TTY queues
14539Sbill  */
14612752Ssam ttyflush(tp, rw)
1477625Ssam 	register struct tty *tp;
14839Sbill {
149903Sbill 	register s;
150903Sbill 
15117545Skarels 	s = spltty();
152903Sbill 	if (rw & FREAD) {
153903Sbill 		while (getc(&tp->t_canq) >= 0)
154903Sbill 			;
155903Sbill 		wakeup((caddr_t)&tp->t_rawq);
156903Sbill 	}
157903Sbill 	if (rw & FWRITE) {
158903Sbill 		wakeup((caddr_t)&tp->t_outq);
1595408Swnj 		tp->t_state &= ~TS_TTSTOP;
1605426Swnj 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
161903Sbill 		while (getc(&tp->t_outq) >= 0)
162903Sbill 			;
163903Sbill 	}
164903Sbill 	if (rw & FREAD) {
165903Sbill 		while (getc(&tp->t_rawq) >= 0)
166903Sbill 			;
1679578Ssam 		tp->t_rocount = 0;
168903Sbill 		tp->t_rocol = 0;
1699578Ssam 		tp->t_state &= ~TS_LOCAL;
170903Sbill 	}
171903Sbill 	splx(s);
17239Sbill }
17339Sbill 
174903Sbill /*
175903Sbill  * Send stop character on input overflow.
176903Sbill  */
177903Sbill ttyblock(tp)
1787625Ssam 	register struct tty *tp;
17939Sbill {
180903Sbill 	register x;
1819578Ssam 
182903Sbill 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
183903Sbill 	if (tp->t_rawq.c_cc > TTYHOG) {
18412752Ssam 		ttyflush(tp, FREAD|FWRITE);
1855408Swnj 		tp->t_state &= ~TS_TBLOCK;
186903Sbill 	}
18715118Skarels 	/*
18815118Skarels 	 * Block further input iff:
18915118Skarels 	 * Current input > threshold AND input is available to user program
19015118Skarels 	 */
19116055Skarels 	if (x >= TTYHOG/2 &&
19216055Skarels 	    ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0))) {
19315118Skarels 		if (putc(tp->t_stopc, &tp->t_outq)==0) {
19415118Skarels 			tp->t_state |= TS_TBLOCK;
19515118Skarels 			ttstart(tp);
19615118Skarels 		}
197903Sbill 	}
19839Sbill }
19939Sbill 
20039Sbill /*
201903Sbill  * Restart typewriter output following a delay
202903Sbill  * timeout.
203903Sbill  * The name of the routine is passed to the timeout
204903Sbill  * subroutine and it is called during a clock interrupt.
205121Sbill  */
206903Sbill ttrstrt(tp)
2077625Ssam 	register struct tty *tp;
208121Sbill {
209121Sbill 
2109578Ssam 	if (tp == 0)
2119578Ssam 		panic("ttrstrt");
2125408Swnj 	tp->t_state &= ~TS_TIMEOUT;
213903Sbill 	ttstart(tp);
214121Sbill }
215121Sbill 
216121Sbill /*
217903Sbill  * Start output on the typewriter. It is used from the top half
218903Sbill  * after some characters have been put on the output queue,
219903Sbill  * from the interrupt routine to transmit the next
220903Sbill  * character, and after a timeout has finished.
22139Sbill  */
222903Sbill ttstart(tp)
2237625Ssam 	register struct tty *tp;
22439Sbill {
225903Sbill 	register s;
22639Sbill 
22717545Skarels 	s = spltty();
2289578Ssam 	if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
2295622Swnj 	    tp->t_oproc)		/* kludge for pty */
230903Sbill 		(*tp->t_oproc)(tp);
231903Sbill 	splx(s);
23239Sbill }
23339Sbill 
23439Sbill /*
235903Sbill  * Common code for tty ioctls.
23639Sbill  */
2371780Sbill /*ARGSUSED*/
2387625Ssam ttioctl(tp, com, data, flag)
2397625Ssam 	register struct tty *tp;
2407625Ssam 	caddr_t data;
24139Sbill {
2428520Sroot 	int dev = tp->t_dev;
24339Sbill 	extern int nldisp;
2448556Sroot 	int s;
24512752Ssam 	register int newflags;
24639Sbill 
247903Sbill 	/*
248903Sbill 	 * If the ioctl involves modification,
24917545Skarels 	 * hang if in the background.
250903Sbill 	 */
2517625Ssam 	switch (com) {
25239Sbill 
253915Sbill 	case TIOCSETD:
254915Sbill 	case TIOCSETP:
255915Sbill 	case TIOCSETN:
256903Sbill 	case TIOCFLUSH:
257903Sbill 	case TIOCSETC:
258903Sbill 	case TIOCSLTC:
259903Sbill 	case TIOCSPGRP:
260903Sbill 	case TIOCLBIS:
261903Sbill 	case TIOCLBIC:
262903Sbill 	case TIOCLSET:
2639325Ssam 	case TIOCSTI:
26417598Sbloom 	case TIOCSWINSZ:
26515078Skarels #define bit(a) (1<<(a-1))
266903Sbill 		while (tp->t_line == NTTYDISC &&
267903Sbill 		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
268903Sbill 		   (u.u_procp->p_flag&SVFORK) == 0 &&
26915078Skarels 		   !(u.u_procp->p_sigignore & bit(SIGTTOU)) &&
27015078Skarels 		   !(u.u_procp->p_sigmask & bit(SIGTTOU))) {
271903Sbill 			gsignal(u.u_procp->p_pgrp, SIGTTOU);
272903Sbill 			sleep((caddr_t)&lbolt, TTOPRI);
273903Sbill 		}
274903Sbill 		break;
275903Sbill 	}
27615078Skarels #undef	bit
277903Sbill 
2789578Ssam 	/*
2799578Ssam 	 * Process the ioctl.
2809578Ssam 	 */
2817625Ssam 	switch (com) {
282903Sbill 
2838556Sroot 	/* get discipline number */
28439Sbill 	case TIOCGETD:
2857625Ssam 		*(int *)data = tp->t_line;
28639Sbill 		break;
28739Sbill 
2888556Sroot 	/* set line discipline */
2897625Ssam 	case TIOCSETD: {
2907625Ssam 		register int t = *(int *)data;
2919578Ssam 		int error = 0;
2927625Ssam 
29315078Skarels 		if ((unsigned) t >= nldisp)
29410851Ssam 			return (ENXIO);
29517545Skarels 		s = spltty();
29639Sbill 		if (tp->t_line)
29739Sbill 			(*linesw[tp->t_line].l_close)(tp);
29839Sbill 		if (t)
2998556Sroot 			error = (*linesw[t].l_open)(dev, tp);
30010851Ssam 		if (error) {
30110851Ssam 			if (tp->t_line)
30210851Ssam 				(void) (*linesw[tp->t_line].l_open)(dev, tp);
30310851Ssam 			splx(s);
3048556Sroot 			return (error);
30510851Ssam 		}
3068556Sroot 		tp->t_line = t;
30718650Sbloom 		splx(s);
30839Sbill 		break;
3097625Ssam 	}
31039Sbill 
3118556Sroot 	/* prevent more opens on channel */
3125614Swnj 	case TIOCEXCL:
3135614Swnj 		tp->t_state |= TS_XCLUDE;
3145614Swnj 		break;
3155614Swnj 
3165614Swnj 	case TIOCNXCL:
3175614Swnj 		tp->t_state &= ~TS_XCLUDE;
3185614Swnj 		break;
3195614Swnj 
3208556Sroot 	/* hang up line on last close */
32139Sbill 	case TIOCHPCL:
3225408Swnj 		tp->t_state |= TS_HUPCLS;
32339Sbill 		break;
32439Sbill 
3253942Sbugs 	case TIOCFLUSH: {
3267625Ssam 		register int flags = *(int *)data;
3277625Ssam 
3287625Ssam 		if (flags == 0)
3293942Sbugs 			flags = FREAD|FWRITE;
3307625Ssam 		else
3317625Ssam 			flags &= FREAD|FWRITE;
33212752Ssam 		ttyflush(tp, flags);
33339Sbill 		break;
3343944Sbugs 	}
33539Sbill 
3368556Sroot 	/* return number of characters immediately available */
3377625Ssam 	case FIONREAD:
3387625Ssam 		*(off_t *)data = ttnread(tp);
339174Sbill 		break;
340174Sbill 
34113077Ssam 	case TIOCOUTQ:
34213077Ssam 		*(int *)data = tp->t_outq.c_cc;
34313077Ssam 		break;
34413077Ssam 
3458589Sroot 	case TIOCSTOP:
34617545Skarels 		s = spltty();
3479578Ssam 		if ((tp->t_state&TS_TTSTOP) == 0) {
3485573Swnj 			tp->t_state |= TS_TTSTOP;
3495573Swnj 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
3505573Swnj 		}
3517625Ssam 		splx(s);
3525573Swnj 		break;
3535573Swnj 
3548589Sroot 	case TIOCSTART:
35517545Skarels 		s = spltty();
3569578Ssam 		if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
3575573Swnj 			tp->t_state &= ~TS_TTSTOP;
3589578Ssam 			tp->t_flags &= ~FLUSHO;
3595573Swnj 			ttstart(tp);
3605573Swnj 		}
3617625Ssam 		splx(s);
3625573Swnj 		break;
3635573Swnj 
3649325Ssam 	/*
3659325Ssam 	 * Simulate typing of a character at the terminal.
3669325Ssam 	 */
3679325Ssam 	case TIOCSTI:
36817183Smckusick 		if (u.u_uid && (flag & FREAD) == 0)
36917183Smckusick 			return (EPERM);
3709325Ssam 		if (u.u_uid && u.u_ttyp != tp)
3719325Ssam 			return (EACCES);
3729578Ssam 		(*linesw[tp->t_line].l_rint)(*(char *)data, tp);
3739325Ssam 		break;
3749325Ssam 
37512752Ssam 	case TIOCSETP:
37612752Ssam 	case TIOCSETN: {
37712752Ssam 		register struct sgttyb *sg = (struct sgttyb *)data;
37812752Ssam 
37912752Ssam 		tp->t_erase = sg->sg_erase;
38012752Ssam 		tp->t_kill = sg->sg_kill;
38112752Ssam 		tp->t_ispeed = sg->sg_ispeed;
38212752Ssam 		tp->t_ospeed = sg->sg_ospeed;
38312752Ssam 		newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
38417545Skarels 		s = spltty();
38512752Ssam 		if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) {
38612752Ssam 			ttywait(tp);
38712752Ssam 			ttyflush(tp, FREAD);
38812752Ssam 		} else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) {
38912752Ssam 			if (newflags&CBREAK) {
39012752Ssam 				struct clist tq;
39112752Ssam 
39212752Ssam 				catq(&tp->t_rawq, &tp->t_canq);
39312752Ssam 				tq = tp->t_rawq;
39412752Ssam 				tp->t_rawq = tp->t_canq;
39512752Ssam 				tp->t_canq = tq;
39612752Ssam 			} else {
39712752Ssam 				tp->t_flags |= PENDIN;
39813801Ssam 				newflags |= PENDIN;
39912752Ssam 				ttwakeup(tp);
40012752Ssam 			}
40112752Ssam 		}
40212752Ssam 		tp->t_flags = newflags;
40312752Ssam 		if (tp->t_flags&RAW) {
40412752Ssam 			tp->t_state &= ~TS_TTSTOP;
40512752Ssam 			ttstart(tp);
40612752Ssam 		}
40712752Ssam 		splx(s);
40812752Ssam 		break;
40912752Ssam 	}
41012752Ssam 
41112752Ssam 	/* send current parameters to user */
41212752Ssam 	case TIOCGETP: {
41312752Ssam 		register struct sgttyb *sg = (struct sgttyb *)data;
41412752Ssam 
41512752Ssam 		sg->sg_ispeed = tp->t_ispeed;
41612752Ssam 		sg->sg_ospeed = tp->t_ospeed;
41712752Ssam 		sg->sg_erase = tp->t_erase;
41812752Ssam 		sg->sg_kill = tp->t_kill;
41912752Ssam 		sg->sg_flags = tp->t_flags;
42012752Ssam 		break;
42112752Ssam 	}
42212752Ssam 
42312752Ssam 	case FIONBIO:
42412752Ssam 		if (*(int *)data)
42512752Ssam 			tp->t_state |= TS_NBIO;
42612752Ssam 		else
42712752Ssam 			tp->t_state &= ~TS_NBIO;
42812752Ssam 		break;
42912752Ssam 
43012752Ssam 	case FIOASYNC:
43112752Ssam 		if (*(int *)data)
43212752Ssam 			tp->t_state |= TS_ASYNC;
43312752Ssam 		else
43412752Ssam 			tp->t_state &= ~TS_ASYNC;
43512752Ssam 		break;
43612752Ssam 
43713077Ssam 	case TIOCGETC:
43813077Ssam 		bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars));
43913077Ssam 		break;
44013077Ssam 
44113077Ssam 	case TIOCSETC:
44213077Ssam 		bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars));
44313077Ssam 		break;
44413077Ssam 
44512752Ssam 	/* set/get local special characters */
44612752Ssam 	case TIOCSLTC:
44712752Ssam 		bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars));
44812752Ssam 		break;
44912752Ssam 
45012752Ssam 	case TIOCGLTC:
45112752Ssam 		bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars));
45212752Ssam 		break;
45312752Ssam 
45412752Ssam 	/*
45512752Ssam 	 * Modify local mode word.
45612752Ssam 	 */
45712752Ssam 	case TIOCLBIS:
45812752Ssam 		tp->t_flags |= *(int *)data << 16;
45912752Ssam 		break;
46012752Ssam 
46112752Ssam 	case TIOCLBIC:
46212752Ssam 		tp->t_flags &= ~(*(int *)data << 16);
46312752Ssam 		break;
46412752Ssam 
46512752Ssam 	case TIOCLSET:
46612752Ssam 		tp->t_flags &= 0xffff;
46712752Ssam 		tp->t_flags |= *(int *)data << 16;
46812752Ssam 		break;
46912752Ssam 
47012752Ssam 	case TIOCLGET:
47115720Skarels 		*(int *)data = ((unsigned) tp->t_flags) >> 16;
47212752Ssam 		break;
47312752Ssam 
47417545Skarels 	/*
47517932Skarels 	 * Allow SPGRP only if tty is open for reading.
47617598Sbloom 	 * Quick check: if we can find a process in the new pgrp,
47717598Sbloom 	 * this user must own that process.
47817598Sbloom 	 * SHOULD VERIFY THAT PGRP IS IN USE AND IS THIS USER'S.
47917545Skarels 	 */
48018650Sbloom 	case TIOCSPGRP: {
48117545Skarels 		struct proc *p;
48217545Skarels 		int pgrp = *(int *)data;
48317545Skarels 
48417545Skarels 		if (u.u_uid && (flag & FREAD) == 0)
48517545Skarels 			return (EPERM);
48617598Sbloom 		p = pfind(pgrp);
48717598Sbloom 		if (p && p->p_pgrp == pgrp &&
48817598Sbloom 		    p->p_uid != u.u_uid && u.u_uid && !inferior(p))
48917598Sbloom 			return (EPERM);
49017545Skarels 		tp->t_pgrp = pgrp;
49112752Ssam 		break;
49218650Sbloom 	}
49312752Ssam 
49412752Ssam 	case TIOCGPGRP:
49512752Ssam 		*(int *)data = tp->t_pgrp;
49612752Ssam 		break;
49712752Ssam 
49817598Sbloom 	case TIOCSWINSZ:
49918650Sbloom 		if (bcmp((caddr_t)&tp->t_winsize, data,
50018650Sbloom 		    sizeof (struct winsize))) {
50117598Sbloom 			tp->t_winsize = *(struct winsize *)data;
50217598Sbloom 			gsignal(tp->t_pgrp, SIGWINCH);
50317598Sbloom 		}
50417598Sbloom 		break;
50517598Sbloom 
50617598Sbloom 	case TIOCGWINSZ:
50717598Sbloom 		*(struct winsize *)data = tp->t_winsize;
50817598Sbloom 		break;
50917598Sbloom 
51039Sbill 	default:
5118556Sroot 		return (-1);
51239Sbill 	}
5138556Sroot 	return (0);
51439Sbill }
5154484Swnj 
5164484Swnj ttnread(tp)
5174484Swnj 	struct tty *tp;
5184484Swnj {
5194484Swnj 	int nread = 0;
5204484Swnj 
5219578Ssam 	if (tp->t_flags & PENDIN)
5224484Swnj 		ttypend(tp);
5234484Swnj 	nread = tp->t_canq.c_cc;
5244484Swnj 	if (tp->t_flags & (RAW|CBREAK))
5254484Swnj 		nread += tp->t_rawq.c_cc;
5264484Swnj 	return (nread);
5274484Swnj }
5284484Swnj 
5295408Swnj ttselect(dev, rw)
5304484Swnj 	dev_t dev;
5315408Swnj 	int rw;
5324484Swnj {
5334484Swnj 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
5344484Swnj 	int nread;
53517545Skarels 	int s = spltty();
5364484Swnj 
5375408Swnj 	switch (rw) {
5384484Swnj 
5394484Swnj 	case FREAD:
5404484Swnj 		nread = ttnread(tp);
54121776Sbloom 		if ((nread > 0) || ((tp->t_state & TS_CARR_ON) == 0))
5425408Swnj 			goto win;
5434938Swnj 		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
5445408Swnj 			tp->t_state |= TS_RCOLL;
5454484Swnj 		else
5464484Swnj 			tp->t_rsel = u.u_procp;
5475408Swnj 		break;
5484484Swnj 
5495408Swnj 	case FWRITE:
5505408Swnj 		if (tp->t_outq.c_cc <= TTLOWAT(tp))
5515408Swnj 			goto win;
5525408Swnj 		if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
5535408Swnj 			tp->t_state |= TS_WCOLL;
5545408Swnj 		else
5555408Swnj 			tp->t_wsel = u.u_procp;
5565408Swnj 		break;
5574484Swnj 	}
5585408Swnj 	splx(s);
5595408Swnj 	return (0);
5605408Swnj win:
5615408Swnj 	splx(s);
5625408Swnj 	return (1);
5634484Swnj }
5647436Skre 
5657502Sroot /*
5669578Ssam  * Establish a process group for distribution of
5677502Sroot  * quits and interrupts from the tty.
5687502Sroot  */
5697502Sroot ttyopen(dev, tp)
5707625Ssam 	dev_t dev;
5717625Ssam 	register struct tty *tp;
5727502Sroot {
5737502Sroot 	register struct proc *pp;
5747502Sroot 
5757502Sroot 	pp = u.u_procp;
5767502Sroot 	tp->t_dev = dev;
5777625Ssam 	if (pp->p_pgrp == 0) {
5787502Sroot 		u.u_ttyp = tp;
5797502Sroot 		u.u_ttyd = dev;
5807502Sroot 		if (tp->t_pgrp == 0)
5817502Sroot 			tp->t_pgrp = pp->p_pid;
5827502Sroot 		pp->p_pgrp = tp->t_pgrp;
5837502Sroot 	}
5847502Sroot 	tp->t_state &= ~TS_WOPEN;
58517545Skarels 	if ((tp->t_state & TS_ISOPEN) == 0) {
58617545Skarels 		tp->t_state |= TS_ISOPEN;
58717598Sbloom 		bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
58817545Skarels 		if (tp->t_line != NTTYDISC)
58917545Skarels 			ttywflush(tp);
59017545Skarels 	}
5918556Sroot 	return (0);
5927502Sroot }
5937502Sroot 
5947502Sroot /*
5957502Sroot  * clean tp on last close
5967502Sroot  */
5977502Sroot ttyclose(tp)
5987625Ssam 	register struct tty *tp;
5997502Sroot {
6007502Sroot 
6017502Sroot 	if (tp->t_line) {
60212752Ssam 		ttywflush(tp);
6037502Sroot 		tp->t_line = 0;
6047502Sroot 		return;
6057502Sroot 	}
6067502Sroot 	tp->t_pgrp = 0;
60712752Ssam 	ttywflush(tp);
6087502Sroot 	tp->t_state = 0;
6097502Sroot }
6107502Sroot 
6117502Sroot /*
6127502Sroot  * reinput pending characters after state switch
61317545Skarels  * call at spltty().
6147502Sroot  */
6157502Sroot ttypend(tp)
6167625Ssam 	register struct tty *tp;
6177502Sroot {
6187502Sroot 	struct clist tq;
6197502Sroot 	register c;
6207502Sroot 
6219578Ssam 	tp->t_flags &= ~PENDIN;
6229578Ssam 	tp->t_state |= TS_TYPEN;
6237502Sroot 	tq = tp->t_rawq;
6247502Sroot 	tp->t_rawq.c_cc = 0;
6257502Sroot 	tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
6267502Sroot 	while ((c = getc(&tq)) >= 0)
6277502Sroot 		ttyinput(c, tp);
6289578Ssam 	tp->t_state &= ~TS_TYPEN;
6297502Sroot }
6307502Sroot 
6317502Sroot /*
6329578Ssam  * Place a character on raw TTY input queue,
6339578Ssam  * putting in delimiters and waking up top
6349578Ssam  * half as needed.  Also echo if required.
6359578Ssam  * The arguments are the character and the
6369578Ssam  * appropriate tty structure.
6377502Sroot  */
6387502Sroot ttyinput(c, tp)
6397625Ssam 	register c;
6407625Ssam 	register struct tty *tp;
6417502Sroot {
6429578Ssam 	register int t_flags = tp->t_flags;
6437502Sroot 	int i;
6447502Sroot 
6459578Ssam 	/*
6469578Ssam 	 * If input is pending take it first.
6479578Ssam 	 */
6489578Ssam 	if (t_flags&PENDIN)
6497502Sroot 		ttypend(tp);
6507502Sroot 	tk_nin++;
6517502Sroot 	c &= 0377;
6529578Ssam 
6539578Ssam 	/*
6549578Ssam 	 * In tandem mode, check high water mark.
6559578Ssam 	 */
6567502Sroot 	if (t_flags&TANDEM)
6577502Sroot 		ttyblock(tp);
6589578Ssam 
6599578Ssam 	if (t_flags&RAW) {
6609578Ssam 		/*
6619578Ssam 		 * Raw mode, just put character
6629578Ssam 		 * in input q w/o interpretation.
6639578Ssam 		 */
6649578Ssam 		if (tp->t_rawq.c_cc > TTYHOG)
66512752Ssam 			ttyflush(tp, FREAD|FWRITE);
6669578Ssam 		else {
6679578Ssam 			if (putc(c, &tp->t_rawq) >= 0)
6689578Ssam 				ttwakeup(tp);
6699578Ssam 			ttyecho(c, tp);
6707502Sroot 		}
6719578Ssam 		goto endcase;
6729578Ssam 	}
6739578Ssam 
6749578Ssam 	/*
6759578Ssam 	 * Ignore any high bit added during
6769578Ssam 	 * previous ttyinput processing.
6779578Ssam 	 */
678*24273Slepreau 	if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0)
6799578Ssam 		c &= 0177;
6809578Ssam 	/*
6819578Ssam 	 * Check for literal nexting very first
6829578Ssam 	 */
6839578Ssam 	if (tp->t_state&TS_LNCH) {
6849578Ssam 		c |= 0200;
6859578Ssam 		tp->t_state &= ~TS_LNCH;
6869578Ssam 	}
6879578Ssam 
6889578Ssam 	/*
6899578Ssam 	 * Scan for special characters.  This code
6909578Ssam 	 * is really just a big case statement with
6919578Ssam 	 * non-constant cases.  The bottom of the
6929578Ssam 	 * case statement is labeled ``endcase'', so goto
6939578Ssam 	 * it after a case match, or similar.
6949578Ssam 	 */
6959578Ssam 	if (tp->t_line == NTTYDISC) {
6969578Ssam 		if (c == tp->t_lnextc) {
69721776Sbloom 			if (t_flags&ECHO)
6987502Sroot 				ttyout("^\b", tp);
6999578Ssam 			tp->t_state |= TS_LNCH;
7009578Ssam 			goto endcase;
7019578Ssam 		}
7029578Ssam 		if (c == tp->t_flushc) {
70321776Sbloom 			if (t_flags&FLUSHO)
7049578Ssam 				tp->t_flags &= ~FLUSHO;
7057502Sroot 			else {
70612752Ssam 				ttyflush(tp, FWRITE);
7077502Sroot 				ttyecho(c, tp);
7089578Ssam 				if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
7097502Sroot 					ttyretype(tp);
7109578Ssam 				tp->t_flags |= FLUSHO;
7117502Sroot 			}
7129578Ssam 			goto startoutput;
7139578Ssam 		}
7149578Ssam 		if (c == tp->t_suspc) {
71521776Sbloom 			if ((t_flags&NOFLSH) == 0)
71612752Ssam 				ttyflush(tp, FREAD);
7179578Ssam 			ttyecho(c, tp);
7189578Ssam 			gsignal(tp->t_pgrp, SIGTSTP);
7199578Ssam 			goto endcase;
7209578Ssam 		}
7219578Ssam 	}
7229578Ssam 
7239578Ssam 	/*
7249578Ssam 	 * Handle start/stop characters.
7259578Ssam 	 */
7269578Ssam 	if (c == tp->t_stopc) {
7279578Ssam 		if ((tp->t_state&TS_TTSTOP) == 0) {
7289578Ssam 			tp->t_state |= TS_TTSTOP;
7299578Ssam 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
7307502Sroot 			return;
7319578Ssam 		}
7329578Ssam 		if (c != tp->t_startc)
7339578Ssam 			return;
7349578Ssam 		goto endcase;
7359578Ssam 	}
7369578Ssam 	if (c == tp->t_startc)
7379578Ssam 		goto restartoutput;
7389578Ssam 
7399578Ssam 	/*
7409578Ssam 	 * Look for interrupt/quit chars.
7419578Ssam 	 */
7429578Ssam 	if (c == tp->t_intrc || c == tp->t_quitc) {
74321776Sbloom 		if ((t_flags&NOFLSH) == 0)
74412752Ssam 			ttyflush(tp, FREAD|FWRITE);
7459578Ssam 		ttyecho(c, tp);
7469578Ssam 		gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
7479578Ssam 		goto endcase;
7489578Ssam 	}
7499578Ssam 
75023165Sbloom 	if (tp->t_flags & LCASE && c <= 0177) {
75123165Sbloom 		if (tp->t_state&TS_BKSL) {
75223165Sbloom 			ttyrub(unputc(&tp->t_rawq), tp);
75323165Sbloom 			if (maptab[c])
75423165Sbloom 				c = maptab[c];
75523165Sbloom 			c |= 0200;
75623165Sbloom 			tp->t_state &= ~(TS_BKSL|TS_QUOT);
75723165Sbloom 		} else if (c >= 'A' && c <= 'Z')
75823165Sbloom 			c += 'a' - 'A';
75923165Sbloom 		else if (c == '\\')
76023165Sbloom 			tp->t_state |= TS_BKSL;
76123165Sbloom 	}
76223165Sbloom 
7639578Ssam 	/*
7649578Ssam 	 * Cbreak mode, don't process line editing
7659578Ssam 	 * characters; check high water mark for wakeup.
7669578Ssam 	 */
7679578Ssam 	if (t_flags&CBREAK) {
7689578Ssam 		if (tp->t_rawq.c_cc > TTYHOG) {
7697502Sroot 			if (tp->t_outq.c_cc < TTHIWAT(tp) &&
7707502Sroot 			    tp->t_line == NTTYDISC)
7717502Sroot 				(void) ttyoutput(CTRL(g), tp);
7727502Sroot 		} else if (putc(c, &tp->t_rawq) >= 0) {
7737502Sroot 			ttwakeup(tp);
7747502Sroot 			ttyecho(c, tp);
7757502Sroot 		}
7769578Ssam 		goto endcase;
7779578Ssam 	}
7789578Ssam 
7799578Ssam 	/*
7809578Ssam 	 * From here on down cooked mode character
7819578Ssam 	 * processing takes place.
7829578Ssam 	 */
7839578Ssam 	if ((tp->t_state&TS_QUOT) &&
7849578Ssam 	    (c == tp->t_erase || c == tp->t_kill)) {
7859578Ssam 		ttyrub(unputc(&tp->t_rawq), tp);
7869578Ssam 		c |= 0200;
7879578Ssam 	}
7889578Ssam 	if (c == tp->t_erase) {
7899578Ssam 		if (tp->t_rawq.c_cc)
7909578Ssam 			ttyrub(unputc(&tp->t_rawq), tp);
7919578Ssam 		goto endcase;
7929578Ssam 	}
7939578Ssam 	if (c == tp->t_kill) {
79421776Sbloom 		if (t_flags&CRTKIL &&
7959578Ssam 		    tp->t_rawq.c_cc == tp->t_rocount) {
7969578Ssam 			while (tp->t_rawq.c_cc)
7979578Ssam 				ttyrub(unputc(&tp->t_rawq), tp);
7989578Ssam 		} else {
7999578Ssam 			ttyecho(c, tp);
8009578Ssam 			ttyecho('\n', tp);
8019578Ssam 			while (getc(&tp->t_rawq) > 0)
8029578Ssam 				;
8039578Ssam 			tp->t_rocount = 0;
8049578Ssam 		}
8059578Ssam 		tp->t_state &= ~TS_LOCAL;
8069578Ssam 		goto endcase;
8079578Ssam 	}
8089578Ssam 
8099578Ssam 	/*
8109578Ssam 	 * New line discipline,
8119578Ssam 	 * check word erase/reprint line.
8129578Ssam 	 */
8139578Ssam 	if (tp->t_line == NTTYDISC) {
8149578Ssam 		if (c == tp->t_werasc) {
8159578Ssam 			if (tp->t_rawq.c_cc == 0)
8169578Ssam 				goto endcase;
8179578Ssam 			do {
8189578Ssam 				c = unputc(&tp->t_rawq);
8199578Ssam 				if (c != ' ' && c != '\t')
8209578Ssam 					goto erasenb;
8219578Ssam 				ttyrub(c, tp);
8229578Ssam 			} while (tp->t_rawq.c_cc);
8239578Ssam 			goto endcase;
8249578Ssam 	erasenb:
8259578Ssam 			do {
8269578Ssam 				ttyrub(c, tp);
8279578Ssam 				if (tp->t_rawq.c_cc == 0)
8289578Ssam 					goto endcase;
8299578Ssam 				c = unputc(&tp->t_rawq);
8309578Ssam 			} while (c != ' ' && c != '\t');
8319578Ssam 			(void) putc(c, &tp->t_rawq);
8329578Ssam 			goto endcase;
8339578Ssam 		}
8349578Ssam 		if (c == tp->t_rprntc) {
8359578Ssam 			ttyretype(tp);
8369578Ssam 			goto endcase;
8379578Ssam 		}
8389578Ssam 	}
8399578Ssam 
8409578Ssam 	/*
8419578Ssam 	 * Check for input buffer overflow
8429578Ssam 	 */
84310391Ssam 	if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
84410391Ssam 		if (tp->t_line == NTTYDISC)
84510391Ssam 			(void) ttyoutput(CTRL(g), tp);
8469578Ssam 		goto endcase;
84710391Ssam 	}
8489578Ssam 
8499578Ssam 	/*
8509578Ssam 	 * Put data char in q for user and
8519578Ssam 	 * wakeup on seeing a line delimiter.
8529578Ssam 	 */
8539578Ssam 	if (putc(c, &tp->t_rawq) >= 0) {
8549578Ssam 		if (ttbreakc(c, tp)) {
8559578Ssam 			tp->t_rocount = 0;
8569578Ssam 			catq(&tp->t_rawq, &tp->t_canq);
8577502Sroot 			ttwakeup(tp);
8589578Ssam 		} else if (tp->t_rocount++ == 0)
8599578Ssam 			tp->t_rocol = tp->t_col;
8609578Ssam 		tp->t_state &= ~TS_QUOT;
8619578Ssam 		if (c == '\\')
8629578Ssam 			tp->t_state |= TS_QUOT;
8639578Ssam 		if (tp->t_state&TS_ERASE) {
8649578Ssam 			tp->t_state &= ~TS_ERASE;
8659578Ssam 			(void) ttyoutput('/', tp);
8669578Ssam 		}
8679578Ssam 		i = tp->t_col;
8687502Sroot 		ttyecho(c, tp);
86921776Sbloom 		if (c == tp->t_eofc && t_flags&ECHO) {
8709578Ssam 			i = MIN(2, tp->t_col - i);
8719578Ssam 			while (i > 0) {
8729578Ssam 				(void) ttyoutput('\b', tp);
8739578Ssam 				i--;
8749578Ssam 			}
8759578Ssam 		}
8767502Sroot 	}
8779578Ssam endcase:
8789578Ssam 	/*
8799578Ssam 	 * If DEC-style start/stop is enabled don't restart
8809578Ssam 	 * output until seeing the start character.
8819578Ssam 	 */
88221776Sbloom 	if (t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
8839578Ssam 	    tp->t_startc != tp->t_stopc)
8847502Sroot 		return;
8859578Ssam restartoutput:
8867502Sroot 	tp->t_state &= ~TS_TTSTOP;
8879578Ssam 	tp->t_flags &= ~FLUSHO;
8889578Ssam startoutput:
8897502Sroot 	ttstart(tp);
8907502Sroot }
8917502Sroot 
8927502Sroot /*
8939578Ssam  * Put character on TTY output queue, adding delays,
8947502Sroot  * expanding tabs, and handling the CR/NL bit.
8959578Ssam  * This is called both from the top half for output,
8969578Ssam  * and from interrupt level for echoing.
8977502Sroot  * The arguments are the character and the tty structure.
8987502Sroot  * Returns < 0 if putc succeeds, otherwise returns char to resend
8997502Sroot  * Must be recursive.
9007502Sroot  */
9017502Sroot ttyoutput(c, tp)
9027502Sroot 	register c;
9037502Sroot 	register struct tty *tp;
9047502Sroot {
9057502Sroot 	register char *colp;
9067502Sroot 	register ctype;
9077502Sroot 
9089578Ssam 	if (tp->t_flags & (RAW|LITOUT)) {
9099578Ssam 		if (tp->t_flags&FLUSHO)
9107502Sroot 			return (-1);
9117502Sroot 		if (putc(c, &tp->t_outq))
9127625Ssam 			return (c);
9137502Sroot 		tk_nout++;
9147502Sroot 		return (-1);
9157502Sroot 	}
9169578Ssam 
9177502Sroot 	/*
9189578Ssam 	 * Ignore EOT in normal mode to avoid
9199578Ssam 	 * hanging up certain terminals.
9207502Sroot 	 */
9217502Sroot 	c &= 0177;
9229578Ssam 	if (c == CEOT && (tp->t_flags&CBREAK) == 0)
9237502Sroot 		return (-1);
9247502Sroot 	/*
9257502Sroot 	 * Turn tabs to spaces as required
9267502Sroot 	 */
9279578Ssam 	if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
9287502Sroot 		register int s;
9297502Sroot 
9307502Sroot 		c = 8 - (tp->t_col&7);
9319578Ssam 		if ((tp->t_flags&FLUSHO) == 0) {
93217545Skarels 			s = spltty();		/* don't interrupt tabs */
9337502Sroot 			c -= b_to_q("        ", c, &tp->t_outq);
9347502Sroot 			tk_nout += c;
9357502Sroot 			splx(s);
9367502Sroot 		}
9377502Sroot 		tp->t_col += c;
9387502Sroot 		return (c ? -1 : '\t');
9397502Sroot 	}
9407502Sroot 	tk_nout++;
9417502Sroot 	/*
9427502Sroot 	 * for upper-case-only terminals,
9437502Sroot 	 * generate escapes.
9447502Sroot 	 */
9457502Sroot 	if (tp->t_flags&LCASE) {
9467502Sroot 		colp = "({)}!|^~'`";
9477625Ssam 		while (*colp++)
9487625Ssam 			if (c == *colp++) {
9497502Sroot 				if (ttyoutput('\\', tp) >= 0)
9507502Sroot 					return (c);
9517502Sroot 				c = colp[-2];
9527502Sroot 				break;
9537502Sroot 			}
9549578Ssam 		if ('A' <= c && c <= 'Z') {
9557502Sroot 			if (ttyoutput('\\', tp) >= 0)
9567502Sroot 				return (c);
9579578Ssam 		} else if ('a' <= c && c <= 'z')
9587502Sroot 			c += 'A' - 'a';
9597502Sroot 	}
9609578Ssam 
9617502Sroot 	/*
9627502Sroot 	 * turn <nl> to <cr><lf> if desired.
9637502Sroot 	 */
9649578Ssam 	if (c == '\n' && tp->t_flags&CRMOD)
9657502Sroot 		if (ttyoutput('\r', tp) >= 0)
9667502Sroot 			return (c);
9679578Ssam 	if (c == '~' && tp->t_flags&TILDE)
9687502Sroot 		c = '`';
9699578Ssam 	if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
9707502Sroot 		return (c);
9717502Sroot 	/*
9727502Sroot 	 * Calculate delays.
9737502Sroot 	 * The numbers here represent clock ticks
9747502Sroot 	 * and are not necessarily optimal for all terminals.
9757502Sroot 	 * The delays are indicated by characters above 0200.
9767502Sroot 	 * In raw mode there are no delays and the
9777502Sroot 	 * transmission path is 8 bits wide.
9789578Ssam 	 *
9799578Ssam 	 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
9807502Sroot 	 */
9817502Sroot 	colp = &tp->t_col;
9827502Sroot 	ctype = partab[c];
9837502Sroot 	c = 0;
9847502Sroot 	switch (ctype&077) {
9857502Sroot 
9867502Sroot 	case ORDINARY:
9877502Sroot 		(*colp)++;
9887502Sroot 
9897502Sroot 	case CONTROL:
9907502Sroot 		break;
9917502Sroot 
9927502Sroot 	case BACKSPACE:
9937502Sroot 		if (*colp)
9947502Sroot 			(*colp)--;
9957502Sroot 		break;
9967502Sroot 
99713821Ssam 	/*
99813821Ssam 	 * This macro is close enough to the correct thing;
99913821Ssam 	 * it should be replaced by real user settable delays
100013821Ssam 	 * in any event...
100113821Ssam 	 */
100213821Ssam #define	mstohz(ms)	(((ms) * hz) >> 10)
10037502Sroot 	case NEWLINE:
10047502Sroot 		ctype = (tp->t_flags >> 8) & 03;
10057625Ssam 		if (ctype == 1) { /* tty 37 */
100612752Ssam 			if (*colp > 0)
100713863Ssam 				c = max((((unsigned)*colp) >> 4) + 3,
100813863Ssam 				    (unsigned)6);
10099578Ssam 		} else if (ctype == 2) /* vt05 */
101013821Ssam 			c = mstohz(100);
10117502Sroot 		*colp = 0;
10127502Sroot 		break;
10137502Sroot 
10147502Sroot 	case TAB:
10157502Sroot 		ctype = (tp->t_flags >> 10) & 03;
10167625Ssam 		if (ctype == 1) { /* tty 37 */
10177502Sroot 			c = 1 - (*colp | ~07);
10187625Ssam 			if (c < 5)
10197502Sroot 				c = 0;
10207502Sroot 		}
10217502Sroot 		*colp |= 07;
10227502Sroot 		(*colp)++;
10237502Sroot 		break;
10247502Sroot 
10257502Sroot 	case VTAB:
10269578Ssam 		if (tp->t_flags&VTDELAY) /* tty 37 */
10277502Sroot 			c = 0177;
10287502Sroot 		break;
10297502Sroot 
10307502Sroot 	case RETURN:
10317502Sroot 		ctype = (tp->t_flags >> 12) & 03;
10329578Ssam 		if (ctype == 1) /* tn 300 */
103313821Ssam 			c = mstohz(83);
10349578Ssam 		else if (ctype == 2) /* ti 700 */
103513821Ssam 			c = mstohz(166);
10369578Ssam 		else if (ctype == 3) { /* concept 100 */
10377502Sroot 			int i;
10389578Ssam 
10397502Sroot 			if ((i = *colp) >= 0)
10409578Ssam 				for (; i < 9; i++)
10417502Sroot 					(void) putc(0177, &tp->t_outq);
10427502Sroot 		}
10437502Sroot 		*colp = 0;
10447502Sroot 	}
10459578Ssam 	if (c && (tp->t_flags&FLUSHO) == 0)
10467502Sroot 		(void) putc(c|0200, &tp->t_outq);
10477502Sroot 	return (-1);
10487502Sroot }
104913821Ssam #undef mstohz
10507502Sroot 
10517502Sroot /*
10527502Sroot  * Called from device's read routine after it has
10537502Sroot  * calculated the tty-structure given as argument.
10547502Sroot  */
10557722Swnj ttread(tp, uio)
10567625Ssam 	register struct tty *tp;
10577722Swnj 	struct uio *uio;
10587502Sroot {
10597502Sroot 	register struct clist *qp;
10609578Ssam 	register c, t_flags;
10619859Ssam 	int s, first, error = 0;
10627502Sroot 
10637502Sroot loop:
10649578Ssam 	/*
10659578Ssam 	 * Take any pending input first.
10669578Ssam 	 */
106717545Skarels 	s = spltty();
10689578Ssam 	if (tp->t_flags&PENDIN)
10697502Sroot 		ttypend(tp);
10709859Ssam 	splx(s);
10719578Ssam 
107223165Sbloom 	if ((tp->t_state&TS_CARR_ON)==0)
107323165Sbloom 		return (EIO);
107423165Sbloom 
10759578Ssam 	/*
10769578Ssam 	 * Hang process if it's in the background.
10779578Ssam 	 */
107815141Skarels #define bit(a) (1<<(a-1))
107923165Sbloom 	if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
108015141Skarels 		if ((u.u_procp->p_sigignore & bit(SIGTTIN)) ||
108115141Skarels 		   (u.u_procp->p_sigmask & bit(SIGTTIN)) ||
10827502Sroot 		    u.u_procp->p_flag&SVFORK)
10838520Sroot 			return (EIO);
10847502Sroot 		gsignal(u.u_procp->p_pgrp, SIGTTIN);
10857502Sroot 		sleep((caddr_t)&lbolt, TTIPRI);
108623165Sbloom 		goto loop;
10877502Sroot 	}
10889578Ssam 	t_flags = tp->t_flags;
108915141Skarels #undef	bit
10909578Ssam 
10919578Ssam 	/*
10929578Ssam 	 * In raw mode take characters directly from the
10939578Ssam 	 * raw queue w/o processing.  Interlock against
10949578Ssam 	 * device interrupts when interrogating rawq.
10959578Ssam 	 */
10969578Ssam 	if (t_flags&RAW) {
109717545Skarels 		s = spltty();
10987502Sroot 		if (tp->t_rawq.c_cc <= 0) {
10999578Ssam 			if ((tp->t_state&TS_CARR_ON) == 0 ||
11007502Sroot 			    (tp->t_state&TS_NBIO)) {
11019859Ssam 				splx(s);
110215094Skarels 				return (EWOULDBLOCK);
11037502Sroot 			}
11047502Sroot 			sleep((caddr_t)&tp->t_rawq, TTIPRI);
11059859Ssam 			splx(s);
11067502Sroot 			goto loop;
11077502Sroot 		}
11089859Ssam 		splx(s);
110914938Smckusick  		while (!error && tp->t_rawq.c_cc && uio->uio_resid)
111014938Smckusick  			error = ureadc(getc(&tp->t_rawq), uio);
11119859Ssam 		goto checktandem;
11129578Ssam 	}
11139578Ssam 
11149578Ssam 	/*
11159578Ssam 	 * In cbreak mode use the rawq, otherwise
11169578Ssam 	 * take characters from the canonicalized q.
11179578Ssam 	 */
11189578Ssam 	qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
11199578Ssam 
11209578Ssam 	/*
11219578Ssam 	 * No input, sleep on rawq awaiting hardware
11229578Ssam 	 * receipt and notification.
11239578Ssam 	 */
112417545Skarels 	s = spltty();
11259578Ssam 	if (qp->c_cc <= 0) {
11269578Ssam 		if ((tp->t_state&TS_CARR_ON) == 0 ||
11279578Ssam 		    (tp->t_state&TS_NBIO)) {
11289859Ssam 			splx(s);
11299578Ssam 			return (EWOULDBLOCK);
11307502Sroot 		}
11319578Ssam 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
11329859Ssam 		splx(s);
11339578Ssam 		goto loop;
11349578Ssam 	}
11359859Ssam 	splx(s);
11369578Ssam 
11379578Ssam 	/*
11389578Ssam 	 * Input present, perform input mapping
11399578Ssam 	 * and processing (we're not in raw mode).
11409578Ssam 	 */
11419578Ssam 	first = 1;
11429578Ssam 	while ((c = getc(qp)) >= 0) {
11439578Ssam 		if (t_flags&CRMOD && c == '\r')
11449578Ssam 			c = '\n';
11459578Ssam 		/*
11469578Ssam 		 * Check for delayed suspend character.
11479578Ssam 		 */
11489578Ssam 		if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
11499578Ssam 			gsignal(tp->t_pgrp, SIGTSTP);
11509578Ssam 			if (first) {
11519578Ssam 				sleep((caddr_t)&lbolt, TTIPRI);
11529578Ssam 				goto loop;
11539578Ssam 			}
11549578Ssam 			break;
11557502Sroot 		}
11569578Ssam 		/*
11579578Ssam 		 * Interpret EOF only in cooked mode.
11589578Ssam 		 */
11599578Ssam 		if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
11609578Ssam 			break;
11619578Ssam 		/*
11629578Ssam 		 * Give user character.
11639578Ssam 		 */
1164*24273Slepreau  		error = ureadc(t_flags&PASS8 ? c : c & 0177, uio);
11659578Ssam 		if (error)
11669578Ssam 			break;
116714938Smckusick  		if (uio->uio_resid == 0)
11689578Ssam 			break;
11699578Ssam 		/*
11709578Ssam 		 * In cooked mode check for a "break character"
11719578Ssam 		 * marking the end of a "line of input".
11729578Ssam 		 */
11739578Ssam 		if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
11749578Ssam 			break;
11759578Ssam 		first = 0;
11767502Sroot 	}
11779578Ssam 
11789859Ssam checktandem:
11799578Ssam 	/*
11809578Ssam 	 * Look to unblock output now that (presumably)
11819578Ssam 	 * the input queue has gone down.
11829578Ssam 	 */
11839859Ssam 	if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
11849578Ssam 		if (putc(tp->t_startc, &tp->t_outq) == 0) {
11857502Sroot 			tp->t_state &= ~TS_TBLOCK;
11867502Sroot 			ttstart(tp);
11877502Sroot 		}
11888520Sroot 	return (error);
11897502Sroot }
11907502Sroot 
11917502Sroot /*
11927502Sroot  * Called from the device's write routine after it has
11937502Sroot  * calculated the tty-structure given as argument.
11947502Sroot  */
11957822Sroot ttwrite(tp, uio)
11967625Ssam 	register struct tty *tp;
11979578Ssam 	register struct uio *uio;
11987502Sroot {
11997502Sroot 	register char *cp;
12009578Ssam 	register int cc, ce, c;
12019578Ssam 	int i, hiwat, cnt, error, s;
12027502Sroot 	char obuf[OBUFSIZ];
12037502Sroot 
12049578Ssam 	hiwat = TTHIWAT(tp);
12059578Ssam 	cnt = uio->uio_resid;
12069578Ssam 	error = 0;
12077502Sroot loop:
120821776Sbloom 	if ((tp->t_state&TS_CARR_ON) == 0)
120921776Sbloom 		return (EIO);
12109578Ssam 	/*
12119578Ssam 	 * Hang the process if it's in the background.
12129578Ssam 	 */
121315141Skarels #define bit(a) (1<<(a-1))
121421776Sbloom 	if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
12159578Ssam 	    (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
121615141Skarels 	    !(u.u_procp->p_sigignore & bit(SIGTTOU)) &&
121721776Sbloom 	    !(u.u_procp->p_sigmask & bit(SIGTTOU))) {
12187502Sroot 		gsignal(u.u_procp->p_pgrp, SIGTTOU);
12197502Sroot 		sleep((caddr_t)&lbolt, TTIPRI);
122021776Sbloom 		goto loop;
12217502Sroot 	}
122215141Skarels #undef	bit
12239578Ssam 
12249578Ssam 	/*
12259578Ssam 	 * Process the user's data in at most OBUFSIZ
12269578Ssam 	 * chunks.  Perform lower case simulation and
12279578Ssam 	 * similar hacks.  Keep track of high water
12289578Ssam 	 * mark, sleep on overflow awaiting device aid
12299578Ssam 	 * in acquiring new space.
12309578Ssam 	 */
12317822Sroot 	while (uio->uio_resid > 0) {
12329578Ssam 		/*
12339578Ssam 		 * Grab a hunk of data from the user.
12349578Ssam 		 */
12357822Sroot 		cc = uio->uio_iov->iov_len;
12367822Sroot 		if (cc == 0) {
12377822Sroot 			uio->uio_iovcnt--;
12387822Sroot 			uio->uio_iov++;
123921776Sbloom 			if (uio->uio_iovcnt <= 0)
12407822Sroot 				panic("ttwrite");
12417822Sroot 			continue;
12427822Sroot 		}
12437822Sroot 		if (cc > OBUFSIZ)
12447822Sroot 			cc = OBUFSIZ;
12457502Sroot 		cp = obuf;
124612752Ssam 		error = uiomove(cp, cc, UIO_WRITE, uio);
12478520Sroot 		if (error)
12487502Sroot 			break;
12497502Sroot 		if (tp->t_outq.c_cc > hiwat)
12507502Sroot 			goto ovhiwat;
12519578Ssam 		if (tp->t_flags&FLUSHO)
12527502Sroot 			continue;
12539578Ssam 		/*
12549578Ssam 		 * If we're mapping lower case or kludging tildes,
12559578Ssam 		 * then we've got to look at each character, so
12569578Ssam 		 * just feed the stuff to ttyoutput...
12579578Ssam 		 */
12589578Ssam 		if (tp->t_flags & (LCASE|TILDE)) {
12599578Ssam 			while (cc > 0) {
12607502Sroot 				c = *cp++;
12617502Sroot 				tp->t_rocount = 0;
12627625Ssam 				while ((c = ttyoutput(c, tp)) >= 0) {
12637502Sroot 					/* out of clists, wait a bit */
12647502Sroot 					ttstart(tp);
12657502Sroot 					sleep((caddr_t)&lbolt, TTOPRI);
12667502Sroot 					tp->t_rocount = 0;
126721776Sbloom 					if (cc != 0) {
126821776Sbloom 						uio->uio_iov->iov_base -= cc;
126921776Sbloom 						uio->uio_iov->iov_len += cc;
127021776Sbloom 						uio->uio_resid += cc;
127121776Sbloom 						uio->uio_offset -= cc;
127221776Sbloom 					}
127321776Sbloom 					goto loop;
12747502Sroot 				}
12757502Sroot 				--cc;
12767502Sroot 				if (tp->t_outq.c_cc > hiwat)
12777502Sroot 					goto ovhiwat;
12787502Sroot 			}
12797502Sroot 			continue;
12807502Sroot 		}
12819578Ssam 		/*
12829578Ssam 		 * If nothing fancy need be done, grab those characters we
12839578Ssam 		 * can handle without any of ttyoutput's processing and
12849578Ssam 		 * just transfer them to the output q.  For those chars
12859578Ssam 		 * which require special processing (as indicated by the
12869578Ssam 		 * bits in partab), call ttyoutput.  After processing
12879578Ssam 		 * a hunk of data, look for FLUSHO so ^O's will take effect
12889578Ssam 		 * immediately.
12899578Ssam 		 */
12909578Ssam 		while (cc > 0) {
12919578Ssam 			if (tp->t_flags & (RAW|LITOUT))
12927502Sroot 				ce = cc;
12937502Sroot 			else {
129412752Ssam 				ce = cc - scanc((unsigned)cc, (caddr_t)cp,
129512752Ssam 				   (caddr_t)partab, 077);
12969578Ssam 				/*
12979578Ssam 				 * If ce is zero, then we're processing
12989578Ssam 				 * a special character through ttyoutput.
12999578Ssam 				 */
13009578Ssam 				if (ce == 0) {
13017502Sroot 					tp->t_rocount = 0;
13027502Sroot 					if (ttyoutput(*cp, tp) >= 0) {
130321776Sbloom 					    /* no c-lists, wait a bit */
130421776Sbloom 					    ttstart(tp);
130521776Sbloom 					    sleep((caddr_t)&lbolt, TTOPRI);
130621776Sbloom 					    if (cc != 0) {
130721776Sbloom 					        uio->uio_iov->iov_base -= cc;
130821776Sbloom 					        uio->uio_iov->iov_len += cc;
130921776Sbloom 					        uio->uio_resid += cc;
131021776Sbloom 						uio->uio_offset -= cc;
131121776Sbloom 					    }
131221776Sbloom 					    goto loop;
13137502Sroot 					}
13149578Ssam 					cp++, cc--;
13159578Ssam 					if (tp->t_flags&FLUSHO ||
13169578Ssam 					    tp->t_outq.c_cc > hiwat)
13177502Sroot 						goto ovhiwat;
13189578Ssam 					continue;
13197502Sroot 				}
13207502Sroot 			}
13219578Ssam 			/*
13229578Ssam 			 * A bunch of normal characters have been found,
13239578Ssam 			 * transfer them en masse to the output queue and
13249578Ssam 			 * continue processing at the top of the loop.
13259578Ssam 			 * If there are any further characters in this
13269578Ssam 			 * <= OBUFSIZ chunk, the first should be a character
13279578Ssam 			 * requiring special handling by ttyoutput.
13289578Ssam 			 */
13297502Sroot 			tp->t_rocount = 0;
13309578Ssam 			i = b_to_q(cp, ce, &tp->t_outq);
13319578Ssam 			ce -= i;
13329578Ssam 			tp->t_col += ce;
13339578Ssam 			cp += ce, cc -= ce, tk_nout += ce;
13349578Ssam 			if (i > 0) {
13359578Ssam 				/* out of c-lists, wait a bit */
13367502Sroot 				ttstart(tp);
13377502Sroot 				sleep((caddr_t)&lbolt, TTOPRI);
133821776Sbloom 				uio->uio_iov->iov_base -= cc;
133921776Sbloom 				uio->uio_iov->iov_len += cc;
134021776Sbloom 				uio->uio_resid += cc;
134121776Sbloom 				uio->uio_offset -= cc;
134221776Sbloom 				goto loop;
13437502Sroot 			}
13449578Ssam 			if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
13457502Sroot 				goto ovhiwat;
13467502Sroot 		}
13477502Sroot 	}
13487502Sroot 	ttstart(tp);
13498520Sroot 	return (error);
13507502Sroot 
13517502Sroot ovhiwat:
135217545Skarels 	s = spltty();
13539578Ssam 	if (cc != 0) {
13549578Ssam 		uio->uio_iov->iov_base -= cc;
13559578Ssam 		uio->uio_iov->iov_len += cc;
13569578Ssam 		uio->uio_resid += cc;
13579578Ssam 		uio->uio_offset -= cc;
13589578Ssam 	}
13599578Ssam 	/*
13609578Ssam 	 * This can only occur if FLUSHO
13619578Ssam 	 * is also set in t_flags.
13629578Ssam 	 */
13637502Sroot 	if (tp->t_outq.c_cc <= hiwat) {
13649578Ssam 		splx(s);
13657502Sroot 		goto loop;
13667502Sroot 	}
13677502Sroot 	ttstart(tp);
13689578Ssam 	if (tp->t_state&TS_NBIO) {
136917545Skarels 		splx(s);
13707822Sroot 		if (uio->uio_resid == cnt)
13718520Sroot 			return (EWOULDBLOCK);
13728520Sroot 		return (0);
13737502Sroot 	}
13747502Sroot 	tp->t_state |= TS_ASLEEP;
13757502Sroot 	sleep((caddr_t)&tp->t_outq, TTOPRI);
13769578Ssam 	splx(s);
13777502Sroot 	goto loop;
13787502Sroot }
13797502Sroot 
13807502Sroot /*
13817502Sroot  * Rubout one character from the rawq of tp
13827502Sroot  * as cleanly as possible.
13837502Sroot  */
13847502Sroot ttyrub(c, tp)
13857625Ssam 	register c;
13867625Ssam 	register struct tty *tp;
13877502Sroot {
13887502Sroot 	register char *cp;
13897502Sroot 	register int savecol;
13907502Sroot 	int s;
13917502Sroot 	char *nextc();
13927502Sroot 
13939578Ssam 	if ((tp->t_flags&ECHO) == 0)
13947502Sroot 		return;
13959578Ssam 	tp->t_flags &= ~FLUSHO;
13967502Sroot 	c &= 0377;
13979578Ssam 	if (tp->t_flags&CRTBS) {
13987502Sroot 		if (tp->t_rocount == 0) {
13997502Sroot 			/*
14007502Sroot 			 * Screwed by ttwrite; retype
14017502Sroot 			 */
14027502Sroot 			ttyretype(tp);
14037502Sroot 			return;
14047502Sroot 		}
14059578Ssam 		if (c == ('\t'|0200) || c == ('\n'|0200))
14067502Sroot 			ttyrubo(tp, 2);
14079578Ssam 		else switch (partab[c&=0177]&0177) {
14087502Sroot 
14097502Sroot 		case ORDINARY:
14107502Sroot 			if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
14117502Sroot 				ttyrubo(tp, 2);
14127502Sroot 			else
14137502Sroot 				ttyrubo(tp, 1);
14147502Sroot 			break;
14157502Sroot 
14167502Sroot 		case VTAB:
14177502Sroot 		case BACKSPACE:
14187502Sroot 		case CONTROL:
14197502Sroot 		case RETURN:
14209578Ssam 			if (tp->t_flags&CTLECH)
14217502Sroot 				ttyrubo(tp, 2);
14227502Sroot 			break;
14237502Sroot 
14247502Sroot 		case TAB:
14257502Sroot 			if (tp->t_rocount < tp->t_rawq.c_cc) {
14267502Sroot 				ttyretype(tp);
14277502Sroot 				return;
14287502Sroot 			}
142917545Skarels 			s = spltty();
14307502Sroot 			savecol = tp->t_col;
14319578Ssam 			tp->t_state |= TS_CNTTB;
14329578Ssam 			tp->t_flags |= FLUSHO;
14337502Sroot 			tp->t_col = tp->t_rocol;
14349578Ssam 			cp = tp->t_rawq.c_cf;
14359578Ssam 			for (; cp; cp = nextc(&tp->t_rawq, cp))
14367502Sroot 				ttyecho(*cp, tp);
14379578Ssam 			tp->t_flags &= ~FLUSHO;
14389578Ssam 			tp->t_state &= ~TS_CNTTB;
14397502Sroot 			splx(s);
14407502Sroot 			/*
14417502Sroot 			 * savecol will now be length of the tab
14427502Sroot 			 */
14437502Sroot 			savecol -= tp->t_col;
14447502Sroot 			tp->t_col += savecol;
14457502Sroot 			if (savecol > 8)
14467502Sroot 				savecol = 8;		/* overflow screw */
14477502Sroot 			while (--savecol >= 0)
14487502Sroot 				(void) ttyoutput('\b', tp);
14497502Sroot 			break;
14507502Sroot 
14517502Sroot 		default:
14527502Sroot 			panic("ttyrub");
14537502Sroot 		}
14549578Ssam 	} else if (tp->t_flags&PRTERA) {
14559578Ssam 		if ((tp->t_state&TS_ERASE) == 0) {
14567502Sroot 			(void) ttyoutput('\\', tp);
14579578Ssam 			tp->t_state |= TS_ERASE;
14587502Sroot 		}
14597502Sroot 		ttyecho(c, tp);
14607502Sroot 	} else
14617502Sroot 		ttyecho(tp->t_erase, tp);
14627502Sroot 	tp->t_rocount--;
14637502Sroot }
14647502Sroot 
14657502Sroot /*
14667502Sroot  * Crt back over cnt chars perhaps
14677502Sroot  * erasing them.
14687502Sroot  */
14697502Sroot ttyrubo(tp, cnt)
14707625Ssam 	register struct tty *tp;
14717625Ssam 	int cnt;
14727502Sroot {
14739578Ssam 	register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
14747502Sroot 
14757502Sroot 	while (--cnt >= 0)
14769578Ssam 		ttyout(rubostring, tp);
14777502Sroot }
14787502Sroot 
14797502Sroot /*
14807502Sroot  * Reprint the rawq line.
14817502Sroot  * We assume c_cc has already been checked.
14827502Sroot  */
14837502Sroot ttyretype(tp)
14847625Ssam 	register struct tty *tp;
14857502Sroot {
14867502Sroot 	register char *cp;
14877502Sroot 	char *nextc();
14887502Sroot 	int s;
14897502Sroot 
14909578Ssam 	if (tp->t_rprntc != 0377)
14919578Ssam 		ttyecho(tp->t_rprntc, tp);
14927502Sroot 	(void) ttyoutput('\n', tp);
149317545Skarels 	s = spltty();
14947502Sroot 	for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
14957502Sroot 		ttyecho(*cp, tp);
14967502Sroot 	for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
14977502Sroot 		ttyecho(*cp, tp);
14989578Ssam 	tp->t_state &= ~TS_ERASE;
14997502Sroot 	splx(s);
15007502Sroot 	tp->t_rocount = tp->t_rawq.c_cc;
15017502Sroot 	tp->t_rocol = 0;
15027502Sroot }
15037502Sroot 
15047502Sroot /*
15057502Sroot  * Echo a typed character to the terminal
15067502Sroot  */
15077502Sroot ttyecho(c, tp)
15087625Ssam 	register c;
15097625Ssam 	register struct tty *tp;
15107502Sroot {
15117502Sroot 
15129578Ssam 	if ((tp->t_state&TS_CNTTB) == 0)
15139578Ssam 		tp->t_flags &= ~FLUSHO;
15147502Sroot 	if ((tp->t_flags&ECHO) == 0)
15157502Sroot 		return;
15167502Sroot 	c &= 0377;
15177502Sroot 	if (tp->t_flags&RAW) {
15187502Sroot 		(void) ttyoutput(c, tp);
15197502Sroot 		return;
15207502Sroot 	}
15217502Sroot 	if (c == '\r' && tp->t_flags&CRMOD)
15227502Sroot 		c = '\n';
15239578Ssam 	if (tp->t_flags&CTLECH) {
15247502Sroot 		if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
15257502Sroot 			(void) ttyoutput('^', tp);
15267502Sroot 			c &= 0177;
15277502Sroot 			if (c == 0177)
15287502Sroot 				c = '?';
15297502Sroot 			else if (tp->t_flags&LCASE)
15307502Sroot 				c += 'a' - 1;
15317502Sroot 			else
15327502Sroot 				c += 'A' - 1;
15337502Sroot 		}
15347502Sroot 	}
15359578Ssam 	(void) ttyoutput(c&0177, tp);
15367502Sroot }
15377502Sroot 
15387502Sroot /*
15397502Sroot  * Is c a break char for tp?
15407502Sroot  */
15417502Sroot ttbreakc(c, tp)
15427625Ssam 	register c;
15437625Ssam 	register struct tty *tp;
15447502Sroot {
15459578Ssam 	return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
15467502Sroot 		c == '\r' && (tp->t_flags&CRMOD));
15477502Sroot }
15487502Sroot 
15497502Sroot /*
15507502Sroot  * send string cp to tp
15517502Sroot  */
15527502Sroot ttyout(cp, tp)
15537625Ssam 	register char *cp;
15547625Ssam 	register struct tty *tp;
15557502Sroot {
15567502Sroot 	register char c;
15577502Sroot 
15587502Sroot 	while (c = *cp++)
15597502Sroot 		(void) ttyoutput(c, tp);
15607502Sroot }
15617502Sroot 
15627502Sroot ttwakeup(tp)
15637502Sroot 	struct tty *tp;
15647502Sroot {
15657502Sroot 
15667502Sroot 	if (tp->t_rsel) {
15677502Sroot 		selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
15687502Sroot 		tp->t_state &= ~TS_RCOLL;
15697502Sroot 		tp->t_rsel = 0;
15707502Sroot 	}
157112752Ssam 	if (tp->t_state & TS_ASYNC)
157212752Ssam 		gsignal(tp->t_pgrp, SIGIO);
15737502Sroot 	wakeup((caddr_t)&tp->t_rawq);
15747502Sroot }
1575