xref: /csrg-svn/sys/kern/tty.c (revision 17598)
1*17598Sbloom /*	tty.c	6.13	84/12/31	*/
239Sbill 
39760Ssam #include "../machine/reg.h"
49760Ssam 
517095Sbloom #include "param.h"
617095Sbloom #include "systm.h"
717095Sbloom #include "dir.h"
817095Sbloom #include "user.h"
917095Sbloom #include "ioctl.h"
1017095Sbloom #include "tty.h"
1117095Sbloom #include "proc.h"
1217095Sbloom #include "inode.h"
1317095Sbloom #include "file.h"
1417095Sbloom #include "conf.h"
1517095Sbloom #include "buf.h"
1617095Sbloom #include "dk.h"
1717095Sbloom #include "uio.h"
1817095Sbloom #include "kernel.h"
1939Sbill 
207436Skre /*
217436Skre  * Table giving parity for characters and indicating
227436Skre  * character classes to tty driver.  In particular,
237436Skre  * if the low 6 bits are 0, then the character needs
247436Skre  * no special processing on output.
257436Skre  */
2639Sbill 
277436Skre char partab[] = {
287436Skre 	0001,0201,0201,0001,0201,0001,0001,0201,
297436Skre 	0202,0004,0003,0201,0005,0206,0201,0001,
307436Skre 	0201,0001,0001,0201,0001,0201,0201,0001,
317436Skre 	0001,0201,0201,0001,0201,0001,0001,0201,
327436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
337436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
347436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
357436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
367436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
377436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
387436Skre 	0000,0200,0200,0000,0200,0000,0000,0200,
397436Skre 	0200,0000,0000,0200,0000,0200,0200,0000,
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,0201,
447436Skre 
457436Skre 	/*
467436Skre 	 * 7 bit ascii ends with the last character above,
477436Skre 	 * but we contine through all 256 codes for the sake
487436Skre 	 * of the tty output routines which use special vax
497436Skre 	 * instructions which need a 256 character trt table.
507436Skre 	 */
517436Skre 
527436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
537436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
547436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
557436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
567436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
577436Skre 	0007,0007,0007,0007,0007,0007,0007,0007,
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 };
697436Skre 
70146Sbill /*
7139Sbill  * Input mapping table-- if an entry is non-zero, when the
7239Sbill  * corresponding character is typed preceded by "\" the escape
7339Sbill  * sequence is replaced by the table value.  Mostly used for
7439Sbill  * upper-case only terminals.
7539Sbill  */
7639Sbill char	maptab[] ={
7739Sbill 	000,000,000,000,000,000,000,000,
7839Sbill 	000,000,000,000,000,000,000,000,
7939Sbill 	000,000,000,000,000,000,000,000,
8039Sbill 	000,000,000,000,000,000,000,000,
8139Sbill 	000,'|',000,000,000,000,000,'`',
8239Sbill 	'{','}',000,000,000,000,000,000,
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,000,000,
8839Sbill 	000,000,000,000,000,000,'~',000,
8939Sbill 	000,'A','B','C','D','E','F','G',
9039Sbill 	'H','I','J','K','L','M','N','O',
9139Sbill 	'P','Q','R','S','T','U','V','W',
9239Sbill 	'X','Y','Z',000,000,000,000,000,
9339Sbill };
9439Sbill 
95925Sbill short	tthiwat[16] =
968954Sroot    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
97925Sbill short	ttlowat[16] =
98925Sbill    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99925Sbill 
1009578Ssam struct	ttychars ttydefaults = {
1019578Ssam 	CERASE,	CKILL,	CINTR,	CQUIT,	CSTART,	CSTOP,	CEOF,
1029578Ssam 	CBRK,	CSUSP,	CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
1039578Ssam };
10439Sbill 
10539Sbill ttychars(tp)
1069578Ssam 	struct tty *tp;
10739Sbill {
108174Sbill 
1099578Ssam 	tp->t_chars = ttydefaults;
11039Sbill }
11139Sbill 
11239Sbill /*
113903Sbill  * Wait for output to drain, then flush input waiting.
11439Sbill  */
11512752Ssam ttywflush(tp)
1165408Swnj 	register struct tty *tp;
11739Sbill {
11839Sbill 
11912752Ssam 	ttywait(tp);
12012752Ssam 	ttyflush(tp, FREAD);
12112752Ssam }
12212752Ssam 
12312752Ssam ttywait(tp)
12412752Ssam 	register struct tty *tp;
12512752Ssam {
12617545Skarels 	register int s = spltty();
12712752Ssam 
12813809Ssam 	while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
12913809Ssam 	    tp->t_state&TS_CARR_ON && tp->t_oproc) {	/* kludge for pty */
130903Sbill 		(*tp->t_oproc)(tp);
1315408Swnj 		tp->t_state |= TS_ASLEEP;
132903Sbill 		sleep((caddr_t)&tp->t_outq, TTOPRI);
133903Sbill 	}
1349859Ssam 	splx(s);
13539Sbill }
13639Sbill 
13739Sbill /*
1389578Ssam  * Flush all TTY queues
13939Sbill  */
14012752Ssam ttyflush(tp, rw)
1417625Ssam 	register struct tty *tp;
14239Sbill {
143903Sbill 	register s;
144903Sbill 
14517545Skarels 	s = spltty();
146903Sbill 	if (rw & FREAD) {
147903Sbill 		while (getc(&tp->t_canq) >= 0)
148903Sbill 			;
149903Sbill 		wakeup((caddr_t)&tp->t_rawq);
150903Sbill 	}
151903Sbill 	if (rw & FWRITE) {
152903Sbill 		wakeup((caddr_t)&tp->t_outq);
1535408Swnj 		tp->t_state &= ~TS_TTSTOP;
1545426Swnj 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
155903Sbill 		while (getc(&tp->t_outq) >= 0)
156903Sbill 			;
157903Sbill 	}
158903Sbill 	if (rw & FREAD) {
159903Sbill 		while (getc(&tp->t_rawq) >= 0)
160903Sbill 			;
1619578Ssam 		tp->t_rocount = 0;
162903Sbill 		tp->t_rocol = 0;
1639578Ssam 		tp->t_state &= ~TS_LOCAL;
164903Sbill 	}
165903Sbill 	splx(s);
16639Sbill }
16739Sbill 
168903Sbill /*
169903Sbill  * Send stop character on input overflow.
170903Sbill  */
171903Sbill ttyblock(tp)
1727625Ssam 	register struct tty *tp;
17339Sbill {
174903Sbill 	register x;
1759578Ssam 
176903Sbill 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
177903Sbill 	if (tp->t_rawq.c_cc > TTYHOG) {
17812752Ssam 		ttyflush(tp, FREAD|FWRITE);
1795408Swnj 		tp->t_state &= ~TS_TBLOCK;
180903Sbill 	}
18115118Skarels 	/*
18215118Skarels 	 * Block further input iff:
18315118Skarels 	 * Current input > threshold AND input is available to user program
18415118Skarels 	 */
18516055Skarels 	if (x >= TTYHOG/2 &&
18616055Skarels 	    ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0))) {
18715118Skarels 		if (putc(tp->t_stopc, &tp->t_outq)==0) {
18815118Skarels 			tp->t_state |= TS_TBLOCK;
18915118Skarels 			ttstart(tp);
19015118Skarels 		}
191903Sbill 	}
19239Sbill }
19339Sbill 
19439Sbill /*
195903Sbill  * Restart typewriter output following a delay
196903Sbill  * timeout.
197903Sbill  * The name of the routine is passed to the timeout
198903Sbill  * subroutine and it is called during a clock interrupt.
199121Sbill  */
200903Sbill ttrstrt(tp)
2017625Ssam 	register struct tty *tp;
202121Sbill {
203121Sbill 
2049578Ssam 	if (tp == 0)
2059578Ssam 		panic("ttrstrt");
2065408Swnj 	tp->t_state &= ~TS_TIMEOUT;
207903Sbill 	ttstart(tp);
208121Sbill }
209121Sbill 
210121Sbill /*
211903Sbill  * Start output on the typewriter. It is used from the top half
212903Sbill  * after some characters have been put on the output queue,
213903Sbill  * from the interrupt routine to transmit the next
214903Sbill  * character, and after a timeout has finished.
21539Sbill  */
216903Sbill ttstart(tp)
2177625Ssam 	register struct tty *tp;
21839Sbill {
219903Sbill 	register s;
22039Sbill 
22117545Skarels 	s = spltty();
2229578Ssam 	if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
2235622Swnj 	    tp->t_oproc)		/* kludge for pty */
224903Sbill 		(*tp->t_oproc)(tp);
225903Sbill 	splx(s);
22639Sbill }
22739Sbill 
22839Sbill /*
229903Sbill  * Common code for tty ioctls.
23039Sbill  */
2311780Sbill /*ARGSUSED*/
2327625Ssam ttioctl(tp, com, data, flag)
2337625Ssam 	register struct tty *tp;
2347625Ssam 	caddr_t data;
23539Sbill {
2368520Sroot 	int dev = tp->t_dev;
23739Sbill 	extern int nldisp;
2388556Sroot 	int s;
23912752Ssam 	register int newflags;
24039Sbill 
241903Sbill 	/*
242903Sbill 	 * If the ioctl involves modification,
24317545Skarels 	 * hang if in the background.
244903Sbill 	 */
2457625Ssam 	switch (com) {
24639Sbill 
247915Sbill 	case TIOCSETD:
248915Sbill 	case TIOCSETP:
249915Sbill 	case TIOCSETN:
250903Sbill 	case TIOCFLUSH:
251903Sbill 	case TIOCSETC:
252903Sbill 	case TIOCSLTC:
253903Sbill 	case TIOCSPGRP:
254903Sbill 	case TIOCLBIS:
255903Sbill 	case TIOCLBIC:
256903Sbill 	case TIOCLSET:
2579325Ssam 	case TIOCSTI:
258*17598Sbloom 	case TIOCSWINSZ:
25915078Skarels #define bit(a) (1<<(a-1))
260903Sbill 		while (tp->t_line == NTTYDISC &&
261903Sbill 		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
262903Sbill 		   (u.u_procp->p_flag&SVFORK) == 0 &&
26315078Skarels 		   !(u.u_procp->p_sigignore & bit(SIGTTOU)) &&
26415078Skarels 		   !(u.u_procp->p_sigmask & bit(SIGTTOU))) {
265903Sbill 			gsignal(u.u_procp->p_pgrp, SIGTTOU);
266903Sbill 			sleep((caddr_t)&lbolt, TTOPRI);
267903Sbill 		}
268903Sbill 		break;
269903Sbill 	}
27015078Skarels #undef	bit
271903Sbill 
2729578Ssam 	/*
2739578Ssam 	 * Process the ioctl.
2749578Ssam 	 */
2757625Ssam 	switch (com) {
276903Sbill 
2778556Sroot 	/* get discipline number */
27839Sbill 	case TIOCGETD:
2797625Ssam 		*(int *)data = tp->t_line;
28039Sbill 		break;
28139Sbill 
2828556Sroot 	/* set line discipline */
2837625Ssam 	case TIOCSETD: {
2847625Ssam 		register int t = *(int *)data;
2859578Ssam 		int error = 0;
2867625Ssam 
28715078Skarels 		if ((unsigned) t >= nldisp)
28810851Ssam 			return (ENXIO);
28917545Skarels 		s = spltty();
29039Sbill 		if (tp->t_line)
29139Sbill 			(*linesw[tp->t_line].l_close)(tp);
29239Sbill 		if (t)
2938556Sroot 			error = (*linesw[t].l_open)(dev, tp);
2948556Sroot 		splx(s);
29510851Ssam 		if (error) {
29617545Skarels 			s = spltty();
29710851Ssam 			if (tp->t_line)
29810851Ssam 				(void) (*linesw[tp->t_line].l_open)(dev, tp);
29910851Ssam 			splx(s);
3008556Sroot 			return (error);
30110851Ssam 		}
3028556Sroot 		tp->t_line = t;
30339Sbill 		break;
3047625Ssam 	}
30539Sbill 
3068556Sroot 	/* prevent more opens on channel */
3075614Swnj 	case TIOCEXCL:
3085614Swnj 		tp->t_state |= TS_XCLUDE;
3095614Swnj 		break;
3105614Swnj 
3115614Swnj 	case TIOCNXCL:
3125614Swnj 		tp->t_state &= ~TS_XCLUDE;
3135614Swnj 		break;
3145614Swnj 
3158556Sroot 	/* hang up line on last close */
31639Sbill 	case TIOCHPCL:
3175408Swnj 		tp->t_state |= TS_HUPCLS;
31839Sbill 		break;
31939Sbill 
3203942Sbugs 	case TIOCFLUSH: {
3217625Ssam 		register int flags = *(int *)data;
3227625Ssam 
3237625Ssam 		if (flags == 0)
3243942Sbugs 			flags = FREAD|FWRITE;
3257625Ssam 		else
3267625Ssam 			flags &= FREAD|FWRITE;
32712752Ssam 		ttyflush(tp, flags);
32839Sbill 		break;
3293944Sbugs 	}
33039Sbill 
3318556Sroot 	/* return number of characters immediately available */
3327625Ssam 	case FIONREAD:
3337625Ssam 		*(off_t *)data = ttnread(tp);
334174Sbill 		break;
335174Sbill 
33613077Ssam 	case TIOCOUTQ:
33713077Ssam 		*(int *)data = tp->t_outq.c_cc;
33813077Ssam 		break;
33913077Ssam 
3408589Sroot 	case TIOCSTOP:
34117545Skarels 		s = spltty();
3429578Ssam 		if ((tp->t_state&TS_TTSTOP) == 0) {
3435573Swnj 			tp->t_state |= TS_TTSTOP;
3445573Swnj 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
3455573Swnj 		}
3467625Ssam 		splx(s);
3475573Swnj 		break;
3485573Swnj 
3498589Sroot 	case TIOCSTART:
35017545Skarels 		s = spltty();
3519578Ssam 		if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
3525573Swnj 			tp->t_state &= ~TS_TTSTOP;
3539578Ssam 			tp->t_flags &= ~FLUSHO;
3545573Swnj 			ttstart(tp);
3555573Swnj 		}
3567625Ssam 		splx(s);
3575573Swnj 		break;
3585573Swnj 
3599325Ssam 	/*
3609325Ssam 	 * Simulate typing of a character at the terminal.
3619325Ssam 	 */
3629325Ssam 	case TIOCSTI:
36317183Smckusick 		if (u.u_uid && (flag & FREAD) == 0)
36417183Smckusick 			return (EPERM);
3659325Ssam 		if (u.u_uid && u.u_ttyp != tp)
3669325Ssam 			return (EACCES);
3679578Ssam 		(*linesw[tp->t_line].l_rint)(*(char *)data, tp);
3689325Ssam 		break;
3699325Ssam 
37012752Ssam 	case TIOCSETP:
37112752Ssam 	case TIOCSETN: {
37212752Ssam 		register struct sgttyb *sg = (struct sgttyb *)data;
37312752Ssam 
37412752Ssam 		tp->t_erase = sg->sg_erase;
37512752Ssam 		tp->t_kill = sg->sg_kill;
37612752Ssam 		tp->t_ispeed = sg->sg_ispeed;
37712752Ssam 		tp->t_ospeed = sg->sg_ospeed;
37812752Ssam 		newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
37917545Skarels 		s = spltty();
38012752Ssam 		if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) {
38112752Ssam 			ttywait(tp);
38212752Ssam 			ttyflush(tp, FREAD);
38312752Ssam 		} else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) {
38412752Ssam 			if (newflags&CBREAK) {
38512752Ssam 				struct clist tq;
38612752Ssam 
38712752Ssam 				catq(&tp->t_rawq, &tp->t_canq);
38812752Ssam 				tq = tp->t_rawq;
38912752Ssam 				tp->t_rawq = tp->t_canq;
39012752Ssam 				tp->t_canq = tq;
39112752Ssam 			} else {
39212752Ssam 				tp->t_flags |= PENDIN;
39313801Ssam 				newflags |= PENDIN;
39412752Ssam 				ttwakeup(tp);
39512752Ssam 			}
39612752Ssam 		}
39712752Ssam 		tp->t_flags = newflags;
39812752Ssam 		if (tp->t_flags&RAW) {
39912752Ssam 			tp->t_state &= ~TS_TTSTOP;
40012752Ssam 			ttstart(tp);
40112752Ssam 		}
40212752Ssam 		splx(s);
40312752Ssam 		break;
40412752Ssam 	}
40512752Ssam 
40612752Ssam 	/* send current parameters to user */
40712752Ssam 	case TIOCGETP: {
40812752Ssam 		register struct sgttyb *sg = (struct sgttyb *)data;
40912752Ssam 
41012752Ssam 		sg->sg_ispeed = tp->t_ispeed;
41112752Ssam 		sg->sg_ospeed = tp->t_ospeed;
41212752Ssam 		sg->sg_erase = tp->t_erase;
41312752Ssam 		sg->sg_kill = tp->t_kill;
41412752Ssam 		sg->sg_flags = tp->t_flags;
41512752Ssam 		break;
41612752Ssam 	}
41712752Ssam 
41812752Ssam 	case FIONBIO:
41912752Ssam 		if (*(int *)data)
42012752Ssam 			tp->t_state |= TS_NBIO;
42112752Ssam 		else
42212752Ssam 			tp->t_state &= ~TS_NBIO;
42312752Ssam 		break;
42412752Ssam 
42512752Ssam 	case FIOASYNC:
42612752Ssam 		if (*(int *)data)
42712752Ssam 			tp->t_state |= TS_ASYNC;
42812752Ssam 		else
42912752Ssam 			tp->t_state &= ~TS_ASYNC;
43012752Ssam 		break;
43112752Ssam 
43213077Ssam 	case TIOCGETC:
43313077Ssam 		bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars));
43413077Ssam 		break;
43513077Ssam 
43613077Ssam 	case TIOCSETC:
43713077Ssam 		bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars));
43813077Ssam 		break;
43913077Ssam 
44012752Ssam 	/* set/get local special characters */
44112752Ssam 	case TIOCSLTC:
44212752Ssam 		bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars));
44312752Ssam 		break;
44412752Ssam 
44512752Ssam 	case TIOCGLTC:
44612752Ssam 		bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars));
44712752Ssam 		break;
44812752Ssam 
44912752Ssam 	/*
45012752Ssam 	 * Modify local mode word.
45112752Ssam 	 */
45212752Ssam 	case TIOCLBIS:
45312752Ssam 		tp->t_flags |= *(int *)data << 16;
45412752Ssam 		break;
45512752Ssam 
45612752Ssam 	case TIOCLBIC:
45712752Ssam 		tp->t_flags &= ~(*(int *)data << 16);
45812752Ssam 		break;
45912752Ssam 
46012752Ssam 	case TIOCLSET:
46112752Ssam 		tp->t_flags &= 0xffff;
46212752Ssam 		tp->t_flags |= *(int *)data << 16;
46312752Ssam 		break;
46412752Ssam 
46512752Ssam 	case TIOCLGET:
46615720Skarels 		*(int *)data = ((unsigned) tp->t_flags) >> 16;
46712752Ssam 		break;
46812752Ssam 
46917545Skarels 	/*
47017545Skarels 	 * Allow SPGRP only if tty is ours and is open for reading.
471*17598Sbloom 	 * Quick check: if we can find a process in the new pgrp,
472*17598Sbloom 	 * this user must own that process.
473*17598Sbloom 	 * SHOULD VERIFY THAT PGRP IS IN USE AND IS THIS USER'S.
47417545Skarels 	 */
47512752Ssam 	case TIOCSPGRP:
47617545Skarels 		{
47717545Skarels 		struct proc *p;
47817545Skarels 		int pgrp = *(int *)data;
47917545Skarels 
48017545Skarels 		if (u.u_uid && (flag & FREAD) == 0)
48117545Skarels 			return (EPERM);
48217545Skarels 		if (u.u_uid && u.u_ttyp != tp)
48317545Skarels 			return (EACCES);
484*17598Sbloom 		p = pfind(pgrp);
485*17598Sbloom 		if (p && p->p_pgrp == pgrp &&
486*17598Sbloom 		    p->p_uid != u.u_uid && u.u_uid && !inferior(p))
487*17598Sbloom 			return (EPERM);
48817545Skarels 		tp->t_pgrp = pgrp;
48912752Ssam 		break;
49017545Skarels 		}
49112752Ssam 
49212752Ssam 	case TIOCGPGRP:
49312752Ssam 		*(int *)data = tp->t_pgrp;
49412752Ssam 		break;
49512752Ssam 
496*17598Sbloom 	case TIOCSWINSZ:
497*17598Sbloom 		if (bcmp((caddr_t)&tp->t_winsize, data,
498*17598Sbloom 				sizeof(struct winsize))) {
499*17598Sbloom 			tp->t_winsize = *(struct winsize *)data;
500*17598Sbloom 			gsignal(tp->t_pgrp, SIGWINCH);
501*17598Sbloom 		}
502*17598Sbloom 		break;
503*17598Sbloom 
504*17598Sbloom 	case TIOCGWINSZ:
505*17598Sbloom 		*(struct winsize *)data = tp->t_winsize;
506*17598Sbloom 		break;
507*17598Sbloom 
50839Sbill 	default:
5098556Sroot 		return (-1);
51039Sbill 	}
5118556Sroot 	return (0);
51239Sbill }
5134484Swnj 
5144484Swnj ttnread(tp)
5154484Swnj 	struct tty *tp;
5164484Swnj {
5174484Swnj 	int nread = 0;
5184484Swnj 
5199578Ssam 	if (tp->t_flags & PENDIN)
5204484Swnj 		ttypend(tp);
5214484Swnj 	nread = tp->t_canq.c_cc;
5224484Swnj 	if (tp->t_flags & (RAW|CBREAK))
5234484Swnj 		nread += tp->t_rawq.c_cc;
5244484Swnj 	return (nread);
5254484Swnj }
5264484Swnj 
5275408Swnj ttselect(dev, rw)
5284484Swnj 	dev_t dev;
5295408Swnj 	int rw;
5304484Swnj {
5314484Swnj 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
5324484Swnj 	int nread;
53317545Skarels 	int s = spltty();
5344484Swnj 
5355408Swnj 	switch (rw) {
5364484Swnj 
5374484Swnj 	case FREAD:
5384484Swnj 		nread = ttnread(tp);
5394484Swnj 		if (nread > 0)
5405408Swnj 			goto win;
5414938Swnj 		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
5425408Swnj 			tp->t_state |= TS_RCOLL;
5434484Swnj 		else
5444484Swnj 			tp->t_rsel = u.u_procp;
5455408Swnj 		break;
5464484Swnj 
5475408Swnj 	case FWRITE:
5485408Swnj 		if (tp->t_outq.c_cc <= TTLOWAT(tp))
5495408Swnj 			goto win;
5505408Swnj 		if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
5515408Swnj 			tp->t_state |= TS_WCOLL;
5525408Swnj 		else
5535408Swnj 			tp->t_wsel = u.u_procp;
5545408Swnj 		break;
5554484Swnj 	}
5565408Swnj 	splx(s);
5575408Swnj 	return (0);
5585408Swnj win:
5595408Swnj 	splx(s);
5605408Swnj 	return (1);
5614484Swnj }
5627436Skre 
5637502Sroot /*
5649578Ssam  * Establish a process group for distribution of
5657502Sroot  * quits and interrupts from the tty.
5667502Sroot  */
5677502Sroot ttyopen(dev, tp)
5687625Ssam 	dev_t dev;
5697625Ssam 	register struct tty *tp;
5707502Sroot {
5717502Sroot 	register struct proc *pp;
5727502Sroot 
5737502Sroot 	pp = u.u_procp;
5747502Sroot 	tp->t_dev = dev;
5757625Ssam 	if (pp->p_pgrp == 0) {
5767502Sroot 		u.u_ttyp = tp;
5777502Sroot 		u.u_ttyd = dev;
5787502Sroot 		if (tp->t_pgrp == 0)
5797502Sroot 			tp->t_pgrp = pp->p_pid;
5807502Sroot 		pp->p_pgrp = tp->t_pgrp;
5817502Sroot 	}
5827502Sroot 	tp->t_state &= ~TS_WOPEN;
58317545Skarels 	if ((tp->t_state & TS_ISOPEN) == 0) {
58417545Skarels 		tp->t_state |= TS_ISOPEN;
585*17598Sbloom 		bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
58617545Skarels 		if (tp->t_line != NTTYDISC)
58717545Skarels 			ttywflush(tp);
58817545Skarels 	}
5898556Sroot 	return (0);
5907502Sroot }
5917502Sroot 
5927502Sroot /*
5937502Sroot  * clean tp on last close
5947502Sroot  */
5957502Sroot ttyclose(tp)
5967625Ssam 	register struct tty *tp;
5977502Sroot {
5987502Sroot 
5997502Sroot 	if (tp->t_line) {
60012752Ssam 		ttywflush(tp);
6017502Sroot 		tp->t_line = 0;
6027502Sroot 		return;
6037502Sroot 	}
6047502Sroot 	tp->t_pgrp = 0;
60512752Ssam 	ttywflush(tp);
6067502Sroot 	tp->t_state = 0;
6077502Sroot }
6087502Sroot 
6097502Sroot /*
6107502Sroot  * reinput pending characters after state switch
61117545Skarels  * call at spltty().
6127502Sroot  */
6137502Sroot ttypend(tp)
6147625Ssam 	register struct tty *tp;
6157502Sroot {
6167502Sroot 	struct clist tq;
6177502Sroot 	register c;
6187502Sroot 
6199578Ssam 	tp->t_flags &= ~PENDIN;
6209578Ssam 	tp->t_state |= TS_TYPEN;
6217502Sroot 	tq = tp->t_rawq;
6227502Sroot 	tp->t_rawq.c_cc = 0;
6237502Sroot 	tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
6247502Sroot 	while ((c = getc(&tq)) >= 0)
6257502Sroot 		ttyinput(c, tp);
6269578Ssam 	tp->t_state &= ~TS_TYPEN;
6277502Sroot }
6287502Sroot 
6297502Sroot /*
6309578Ssam  * Place a character on raw TTY input queue,
6319578Ssam  * putting in delimiters and waking up top
6329578Ssam  * half as needed.  Also echo if required.
6339578Ssam  * The arguments are the character and the
6349578Ssam  * appropriate tty structure.
6357502Sroot  */
6367502Sroot ttyinput(c, tp)
6377625Ssam 	register c;
6387625Ssam 	register struct tty *tp;
6397502Sroot {
6409578Ssam 	register int t_flags = tp->t_flags;
6417502Sroot 	int i;
6427502Sroot 
6439578Ssam 	/*
6449578Ssam 	 * If input is pending take it first.
6459578Ssam 	 */
6469578Ssam 	if (t_flags&PENDIN)
6477502Sroot 		ttypend(tp);
6487502Sroot 	tk_nin++;
6497502Sroot 	c &= 0377;
6509578Ssam 
6519578Ssam 	/*
6529578Ssam 	 * In tandem mode, check high water mark.
6539578Ssam 	 */
6547502Sroot 	if (t_flags&TANDEM)
6557502Sroot 		ttyblock(tp);
6569578Ssam 
6579578Ssam 	if (t_flags&RAW) {
6589578Ssam 		/*
6599578Ssam 		 * Raw mode, just put character
6609578Ssam 		 * in input q w/o interpretation.
6619578Ssam 		 */
6629578Ssam 		if (tp->t_rawq.c_cc > TTYHOG)
66312752Ssam 			ttyflush(tp, FREAD|FWRITE);
6649578Ssam 		else {
6659578Ssam 			if (putc(c, &tp->t_rawq) >= 0)
6669578Ssam 				ttwakeup(tp);
6679578Ssam 			ttyecho(c, tp);
6687502Sroot 		}
6699578Ssam 		goto endcase;
6709578Ssam 	}
6719578Ssam 
6729578Ssam 	/*
6739578Ssam 	 * Ignore any high bit added during
6749578Ssam 	 * previous ttyinput processing.
6759578Ssam 	 */
6769578Ssam 	if ((tp->t_state&TS_TYPEN) == 0)
6779578Ssam 		c &= 0177;
6789578Ssam 	/*
6799578Ssam 	 * Check for literal nexting very first
6809578Ssam 	 */
6819578Ssam 	if (tp->t_state&TS_LNCH) {
6829578Ssam 		c |= 0200;
6839578Ssam 		tp->t_state &= ~TS_LNCH;
6849578Ssam 	}
6859578Ssam 
6869578Ssam 	/*
6879578Ssam 	 * Scan for special characters.  This code
6889578Ssam 	 * is really just a big case statement with
6899578Ssam 	 * non-constant cases.  The bottom of the
6909578Ssam 	 * case statement is labeled ``endcase'', so goto
6919578Ssam 	 * it after a case match, or similar.
6929578Ssam 	 */
6939578Ssam 	if (tp->t_line == NTTYDISC) {
6949578Ssam 		if (c == tp->t_lnextc) {
6957502Sroot 			if (tp->t_flags&ECHO)
6967502Sroot 				ttyout("^\b", tp);
6979578Ssam 			tp->t_state |= TS_LNCH;
6989578Ssam 			goto endcase;
6999578Ssam 		}
7009578Ssam 		if (c == tp->t_flushc) {
7019578Ssam 			if (tp->t_flags&FLUSHO)
7029578Ssam 				tp->t_flags &= ~FLUSHO;
7037502Sroot 			else {
70412752Ssam 				ttyflush(tp, FWRITE);
7057502Sroot 				ttyecho(c, tp);
7069578Ssam 				if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
7077502Sroot 					ttyretype(tp);
7089578Ssam 				tp->t_flags |= FLUSHO;
7097502Sroot 			}
7109578Ssam 			goto startoutput;
7119578Ssam 		}
7129578Ssam 		if (c == tp->t_suspc) {
7139578Ssam 			if ((tp->t_flags&NOFLSH) == 0)
71412752Ssam 				ttyflush(tp, FREAD);
7159578Ssam 			ttyecho(c, tp);
7169578Ssam 			gsignal(tp->t_pgrp, SIGTSTP);
7179578Ssam 			goto endcase;
7189578Ssam 		}
7199578Ssam 	}
7209578Ssam 
7219578Ssam 	/*
7229578Ssam 	 * Handle start/stop characters.
7239578Ssam 	 */
7249578Ssam 	if (c == tp->t_stopc) {
7259578Ssam 		if ((tp->t_state&TS_TTSTOP) == 0) {
7269578Ssam 			tp->t_state |= TS_TTSTOP;
7279578Ssam 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
7287502Sroot 			return;
7299578Ssam 		}
7309578Ssam 		if (c != tp->t_startc)
7319578Ssam 			return;
7329578Ssam 		goto endcase;
7339578Ssam 	}
7349578Ssam 	if (c == tp->t_startc)
7359578Ssam 		goto restartoutput;
7369578Ssam 
7379578Ssam 	/*
7389578Ssam 	 * Look for interrupt/quit chars.
7399578Ssam 	 */
7409578Ssam 	if (c == tp->t_intrc || c == tp->t_quitc) {
7419578Ssam 		if ((tp->t_flags&NOFLSH) == 0)
74212752Ssam 			ttyflush(tp, FREAD|FWRITE);
7439578Ssam 		ttyecho(c, tp);
7449578Ssam 		gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
7459578Ssam 		goto endcase;
7469578Ssam 	}
7479578Ssam 
7489578Ssam 	/*
7499578Ssam 	 * Cbreak mode, don't process line editing
7509578Ssam 	 * characters; check high water mark for wakeup.
7519578Ssam 	 */
7529578Ssam 	if (t_flags&CBREAK) {
7539578Ssam 		if (tp->t_rawq.c_cc > TTYHOG) {
7547502Sroot 			if (tp->t_outq.c_cc < TTHIWAT(tp) &&
7557502Sroot 			    tp->t_line == NTTYDISC)
7567502Sroot 				(void) ttyoutput(CTRL(g), tp);
7577502Sroot 		} else if (putc(c, &tp->t_rawq) >= 0) {
7587502Sroot 			ttwakeup(tp);
7597502Sroot 			ttyecho(c, tp);
7607502Sroot 		}
7619578Ssam 		goto endcase;
7629578Ssam 	}
7639578Ssam 
7649578Ssam 	/*
7659578Ssam 	 * From here on down cooked mode character
7669578Ssam 	 * processing takes place.
7679578Ssam 	 */
7689578Ssam 	if ((tp->t_state&TS_QUOT) &&
7699578Ssam 	    (c == tp->t_erase || c == tp->t_kill)) {
7709578Ssam 		ttyrub(unputc(&tp->t_rawq), tp);
7719578Ssam 		c |= 0200;
7729578Ssam 	}
7739578Ssam 	if (c == tp->t_erase) {
7749578Ssam 		if (tp->t_rawq.c_cc)
7759578Ssam 			ttyrub(unputc(&tp->t_rawq), tp);
7769578Ssam 		goto endcase;
7779578Ssam 	}
7789578Ssam 	if (c == tp->t_kill) {
7799578Ssam 		if (tp->t_flags&CRTKIL &&
7809578Ssam 		    tp->t_rawq.c_cc == tp->t_rocount) {
7819578Ssam 			while (tp->t_rawq.c_cc)
7829578Ssam 				ttyrub(unputc(&tp->t_rawq), tp);
7839578Ssam 		} else {
7849578Ssam 			ttyecho(c, tp);
7859578Ssam 			ttyecho('\n', tp);
7869578Ssam 			while (getc(&tp->t_rawq) > 0)
7879578Ssam 				;
7889578Ssam 			tp->t_rocount = 0;
7899578Ssam 		}
7909578Ssam 		tp->t_state &= ~TS_LOCAL;
7919578Ssam 		goto endcase;
7929578Ssam 	}
7939578Ssam 
7949578Ssam 	/*
7959578Ssam 	 * New line discipline,
7969578Ssam 	 * check word erase/reprint line.
7979578Ssam 	 */
7989578Ssam 	if (tp->t_line == NTTYDISC) {
7999578Ssam 		if (c == tp->t_werasc) {
8009578Ssam 			if (tp->t_rawq.c_cc == 0)
8019578Ssam 				goto endcase;
8029578Ssam 			do {
8039578Ssam 				c = unputc(&tp->t_rawq);
8049578Ssam 				if (c != ' ' && c != '\t')
8059578Ssam 					goto erasenb;
8069578Ssam 				ttyrub(c, tp);
8079578Ssam 			} while (tp->t_rawq.c_cc);
8089578Ssam 			goto endcase;
8099578Ssam 	erasenb:
8109578Ssam 			do {
8119578Ssam 				ttyrub(c, tp);
8129578Ssam 				if (tp->t_rawq.c_cc == 0)
8139578Ssam 					goto endcase;
8149578Ssam 				c = unputc(&tp->t_rawq);
8159578Ssam 			} while (c != ' ' && c != '\t');
8169578Ssam 			(void) putc(c, &tp->t_rawq);
8179578Ssam 			goto endcase;
8189578Ssam 		}
8199578Ssam 		if (c == tp->t_rprntc) {
8209578Ssam 			ttyretype(tp);
8219578Ssam 			goto endcase;
8229578Ssam 		}
8239578Ssam 	}
8249578Ssam 
8259578Ssam 	/*
8269578Ssam 	 * Check for input buffer overflow
8279578Ssam 	 */
82810391Ssam 	if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
82910391Ssam 		if (tp->t_line == NTTYDISC)
83010391Ssam 			(void) ttyoutput(CTRL(g), tp);
8319578Ssam 		goto endcase;
83210391Ssam 	}
8339578Ssam 
8349578Ssam 	/*
8359578Ssam 	 * Put data char in q for user and
8369578Ssam 	 * wakeup on seeing a line delimiter.
8379578Ssam 	 */
8389578Ssam 	if (putc(c, &tp->t_rawq) >= 0) {
8399578Ssam 		if (ttbreakc(c, tp)) {
8409578Ssam 			tp->t_rocount = 0;
8419578Ssam 			catq(&tp->t_rawq, &tp->t_canq);
8427502Sroot 			ttwakeup(tp);
8439578Ssam 		} else if (tp->t_rocount++ == 0)
8449578Ssam 			tp->t_rocol = tp->t_col;
8459578Ssam 		tp->t_state &= ~TS_QUOT;
8469578Ssam 		if (c == '\\')
8479578Ssam 			tp->t_state |= TS_QUOT;
8489578Ssam 		if (tp->t_state&TS_ERASE) {
8499578Ssam 			tp->t_state &= ~TS_ERASE;
8509578Ssam 			(void) ttyoutput('/', tp);
8519578Ssam 		}
8529578Ssam 		i = tp->t_col;
8537502Sroot 		ttyecho(c, tp);
8549578Ssam 		if (c == tp->t_eofc && tp->t_flags&ECHO) {
8559578Ssam 			i = MIN(2, tp->t_col - i);
8569578Ssam 			while (i > 0) {
8579578Ssam 				(void) ttyoutput('\b', tp);
8589578Ssam 				i--;
8599578Ssam 			}
8609578Ssam 		}
8617502Sroot 	}
8629578Ssam 
8639578Ssam endcase:
8649578Ssam 	/*
8659578Ssam 	 * If DEC-style start/stop is enabled don't restart
8669578Ssam 	 * output until seeing the start character.
8679578Ssam 	 */
8689578Ssam 	if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
8699578Ssam 	    tp->t_startc != tp->t_stopc)
8707502Sroot 		return;
8719578Ssam 
8729578Ssam restartoutput:
8737502Sroot 	tp->t_state &= ~TS_TTSTOP;
8749578Ssam 	tp->t_flags &= ~FLUSHO;
8759578Ssam 
8769578Ssam startoutput:
8777502Sroot 	ttstart(tp);
8787502Sroot }
8797502Sroot 
8807502Sroot /*
8819578Ssam  * Put character on TTY output queue, adding delays,
8827502Sroot  * expanding tabs, and handling the CR/NL bit.
8839578Ssam  * This is called both from the top half for output,
8849578Ssam  * and from interrupt level for echoing.
8857502Sroot  * The arguments are the character and the tty structure.
8867502Sroot  * Returns < 0 if putc succeeds, otherwise returns char to resend
8877502Sroot  * Must be recursive.
8887502Sroot  */
8897502Sroot ttyoutput(c, tp)
8907502Sroot 	register c;
8917502Sroot 	register struct tty *tp;
8927502Sroot {
8937502Sroot 	register char *colp;
8947502Sroot 	register ctype;
8957502Sroot 
8969578Ssam 	if (tp->t_flags & (RAW|LITOUT)) {
8979578Ssam 		if (tp->t_flags&FLUSHO)
8987502Sroot 			return (-1);
8997502Sroot 		if (putc(c, &tp->t_outq))
9007625Ssam 			return (c);
9017502Sroot 		tk_nout++;
9027502Sroot 		return (-1);
9037502Sroot 	}
9049578Ssam 
9057502Sroot 	/*
9069578Ssam 	 * Ignore EOT in normal mode to avoid
9079578Ssam 	 * hanging up certain terminals.
9087502Sroot 	 */
9097502Sroot 	c &= 0177;
9109578Ssam 	if (c == CEOT && (tp->t_flags&CBREAK) == 0)
9117502Sroot 		return (-1);
9127502Sroot 	/*
9137502Sroot 	 * Turn tabs to spaces as required
9147502Sroot 	 */
9159578Ssam 	if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
9167502Sroot 		register int s;
9177502Sroot 
9187502Sroot 		c = 8 - (tp->t_col&7);
9199578Ssam 		if ((tp->t_flags&FLUSHO) == 0) {
92017545Skarels 			s = spltty();		/* don't interrupt tabs */
9217502Sroot 			c -= b_to_q("        ", c, &tp->t_outq);
9227502Sroot 			tk_nout += c;
9237502Sroot 			splx(s);
9247502Sroot 		}
9257502Sroot 		tp->t_col += c;
9267502Sroot 		return (c ? -1 : '\t');
9277502Sroot 	}
9287502Sroot 	tk_nout++;
9297502Sroot 	/*
9307502Sroot 	 * for upper-case-only terminals,
9317502Sroot 	 * generate escapes.
9327502Sroot 	 */
9337502Sroot 	if (tp->t_flags&LCASE) {
9347502Sroot 		colp = "({)}!|^~'`";
9357625Ssam 		while (*colp++)
9367625Ssam 			if (c == *colp++) {
9377502Sroot 				if (ttyoutput('\\', tp) >= 0)
9387502Sroot 					return (c);
9397502Sroot 				c = colp[-2];
9407502Sroot 				break;
9417502Sroot 			}
9429578Ssam 		if ('A' <= c && c <= 'Z') {
9437502Sroot 			if (ttyoutput('\\', tp) >= 0)
9447502Sroot 				return (c);
9459578Ssam 		} else if ('a' <= c && c <= 'z')
9467502Sroot 			c += 'A' - 'a';
9477502Sroot 	}
9489578Ssam 
9497502Sroot 	/*
9507502Sroot 	 * turn <nl> to <cr><lf> if desired.
9517502Sroot 	 */
9529578Ssam 	if (c == '\n' && tp->t_flags&CRMOD)
9537502Sroot 		if (ttyoutput('\r', tp) >= 0)
9547502Sroot 			return (c);
9559578Ssam 	if (c == '~' && tp->t_flags&TILDE)
9567502Sroot 		c = '`';
9579578Ssam 	if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
9587502Sroot 		return (c);
9597502Sroot 	/*
9607502Sroot 	 * Calculate delays.
9617502Sroot 	 * The numbers here represent clock ticks
9627502Sroot 	 * and are not necessarily optimal for all terminals.
9637502Sroot 	 * The delays are indicated by characters above 0200.
9647502Sroot 	 * In raw mode there are no delays and the
9657502Sroot 	 * transmission path is 8 bits wide.
9669578Ssam 	 *
9679578Ssam 	 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
9687502Sroot 	 */
9697502Sroot 	colp = &tp->t_col;
9707502Sroot 	ctype = partab[c];
9717502Sroot 	c = 0;
9727502Sroot 	switch (ctype&077) {
9737502Sroot 
9747502Sroot 	case ORDINARY:
9757502Sroot 		(*colp)++;
9767502Sroot 
9777502Sroot 	case CONTROL:
9787502Sroot 		break;
9797502Sroot 
9807502Sroot 	case BACKSPACE:
9817502Sroot 		if (*colp)
9827502Sroot 			(*colp)--;
9837502Sroot 		break;
9847502Sroot 
98513821Ssam 	/*
98613821Ssam 	 * This macro is close enough to the correct thing;
98713821Ssam 	 * it should be replaced by real user settable delays
98813821Ssam 	 * in any event...
98913821Ssam 	 */
99013821Ssam #define	mstohz(ms)	(((ms) * hz) >> 10)
9917502Sroot 	case NEWLINE:
9927502Sroot 		ctype = (tp->t_flags >> 8) & 03;
9937625Ssam 		if (ctype == 1) { /* tty 37 */
99412752Ssam 			if (*colp > 0)
99513863Ssam 				c = max((((unsigned)*colp) >> 4) + 3,
99613863Ssam 				    (unsigned)6);
9979578Ssam 		} else if (ctype == 2) /* vt05 */
99813821Ssam 			c = mstohz(100);
9997502Sroot 		*colp = 0;
10007502Sroot 		break;
10017502Sroot 
10027502Sroot 	case TAB:
10037502Sroot 		ctype = (tp->t_flags >> 10) & 03;
10047625Ssam 		if (ctype == 1) { /* tty 37 */
10057502Sroot 			c = 1 - (*colp | ~07);
10067625Ssam 			if (c < 5)
10077502Sroot 				c = 0;
10087502Sroot 		}
10097502Sroot 		*colp |= 07;
10107502Sroot 		(*colp)++;
10117502Sroot 		break;
10127502Sroot 
10137502Sroot 	case VTAB:
10149578Ssam 		if (tp->t_flags&VTDELAY) /* tty 37 */
10157502Sroot 			c = 0177;
10167502Sroot 		break;
10177502Sroot 
10187502Sroot 	case RETURN:
10197502Sroot 		ctype = (tp->t_flags >> 12) & 03;
10209578Ssam 		if (ctype == 1) /* tn 300 */
102113821Ssam 			c = mstohz(83);
10229578Ssam 		else if (ctype == 2) /* ti 700 */
102313821Ssam 			c = mstohz(166);
10249578Ssam 		else if (ctype == 3) { /* concept 100 */
10257502Sroot 			int i;
10269578Ssam 
10277502Sroot 			if ((i = *colp) >= 0)
10289578Ssam 				for (; i < 9; i++)
10297502Sroot 					(void) putc(0177, &tp->t_outq);
10307502Sroot 		}
10317502Sroot 		*colp = 0;
10327502Sroot 	}
10339578Ssam 	if (c && (tp->t_flags&FLUSHO) == 0)
10347502Sroot 		(void) putc(c|0200, &tp->t_outq);
10357502Sroot 	return (-1);
10367502Sroot }
103713821Ssam #undef mstohz
10387502Sroot 
10397502Sroot /*
10407502Sroot  * Called from device's read routine after it has
10417502Sroot  * calculated the tty-structure given as argument.
10427502Sroot  */
10437722Swnj ttread(tp, uio)
10447625Ssam 	register struct tty *tp;
10457722Swnj 	struct uio *uio;
10467502Sroot {
10477502Sroot 	register struct clist *qp;
10489578Ssam 	register c, t_flags;
10499859Ssam 	int s, first, error = 0;
10507502Sroot 
10517502Sroot 	if ((tp->t_state&TS_CARR_ON)==0)
10528520Sroot 		return (EIO);
10537502Sroot loop:
10549578Ssam 	/*
10559578Ssam 	 * Take any pending input first.
10569578Ssam 	 */
105717545Skarels 	s = spltty();
10589578Ssam 	if (tp->t_flags&PENDIN)
10597502Sroot 		ttypend(tp);
10609859Ssam 	splx(s);
10619578Ssam 
10629578Ssam 	/*
10639578Ssam 	 * Hang process if it's in the background.
10649578Ssam 	 */
106515141Skarels #define bit(a) (1<<(a-1))
10667502Sroot 	while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
106715141Skarels 		if ((u.u_procp->p_sigignore & bit(SIGTTIN)) ||
106815141Skarels 		   (u.u_procp->p_sigmask & bit(SIGTTIN)) ||
10697502Sroot /*
10707502Sroot 		    (u.u_procp->p_flag&SDETACH) ||
10717502Sroot */
10727502Sroot 		    u.u_procp->p_flag&SVFORK)
10738520Sroot 			return (EIO);
10747502Sroot 		gsignal(u.u_procp->p_pgrp, SIGTTIN);
10757502Sroot 		sleep((caddr_t)&lbolt, TTIPRI);
10767502Sroot 	}
10779578Ssam 	t_flags = tp->t_flags;
107815141Skarels #undef	bit
10799578Ssam 
10809578Ssam 	/*
10819578Ssam 	 * In raw mode take characters directly from the
10829578Ssam 	 * raw queue w/o processing.  Interlock against
10839578Ssam 	 * device interrupts when interrogating rawq.
10849578Ssam 	 */
10859578Ssam 	if (t_flags&RAW) {
108617545Skarels 		s = spltty();
10877502Sroot 		if (tp->t_rawq.c_cc <= 0) {
10889578Ssam 			if ((tp->t_state&TS_CARR_ON) == 0 ||
10897502Sroot 			    (tp->t_state&TS_NBIO)) {
10909859Ssam 				splx(s);
109115094Skarels 				return (EWOULDBLOCK);
10927502Sroot 			}
10937502Sroot 			sleep((caddr_t)&tp->t_rawq, TTIPRI);
10949859Ssam 			splx(s);
10957502Sroot 			goto loop;
10967502Sroot 		}
10979859Ssam 		splx(s);
109814938Smckusick  		while (!error && tp->t_rawq.c_cc && uio->uio_resid)
109914938Smckusick  			error = ureadc(getc(&tp->t_rawq), uio);
11009859Ssam 		goto checktandem;
11019578Ssam 	}
11029578Ssam 
11039578Ssam 	/*
11049578Ssam 	 * In cbreak mode use the rawq, otherwise
11059578Ssam 	 * take characters from the canonicalized q.
11069578Ssam 	 */
11079578Ssam 	qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
11089578Ssam 
11099578Ssam 	/*
11109578Ssam 	 * No input, sleep on rawq awaiting hardware
11119578Ssam 	 * receipt and notification.
11129578Ssam 	 */
111317545Skarels 	s = spltty();
11149578Ssam 	if (qp->c_cc <= 0) {
11159578Ssam 		if ((tp->t_state&TS_CARR_ON) == 0 ||
11169578Ssam 		    (tp->t_state&TS_NBIO)) {
11179859Ssam 			splx(s);
11189578Ssam 			return (EWOULDBLOCK);
11197502Sroot 		}
11209578Ssam 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
11219859Ssam 		splx(s);
11229578Ssam 		goto loop;
11239578Ssam 	}
11249859Ssam 	splx(s);
11259578Ssam 
11269578Ssam 	/*
11279578Ssam 	 * Input present, perform input mapping
11289578Ssam 	 * and processing (we're not in raw mode).
11299578Ssam 	 */
11309578Ssam 	first = 1;
11319578Ssam 	while ((c = getc(qp)) >= 0) {
11329578Ssam 		if (t_flags&CRMOD && c == '\r')
11339578Ssam 			c = '\n';
11349578Ssam 		/*
11359578Ssam 		 * Hack lower case simulation on
11369578Ssam 		 * upper case only terminals.
11379578Ssam 		 */
11389578Ssam 		if (t_flags&LCASE && c <= 0177)
11399578Ssam 			if (tp->t_state&TS_BKSL) {
11409578Ssam 				if (maptab[c])
11419578Ssam 					c = maptab[c];
11429578Ssam 				tp->t_state &= ~TS_BKSL;
11439578Ssam 			} else if (c >= 'A' && c <= 'Z')
11449578Ssam 				c += 'a' - 'A';
11459578Ssam 			else if (c == '\\') {
11469578Ssam 				tp->t_state |= TS_BKSL;
11479578Ssam 				continue;
11487502Sroot 			}
11499578Ssam 		/*
11509578Ssam 		 * Check for delayed suspend character.
11519578Ssam 		 */
11529578Ssam 		if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
11539578Ssam 			gsignal(tp->t_pgrp, SIGTSTP);
11549578Ssam 			if (first) {
11559578Ssam 				sleep((caddr_t)&lbolt, TTIPRI);
11569578Ssam 				goto loop;
11579578Ssam 			}
11589578Ssam 			break;
11597502Sroot 		}
11609578Ssam 		/*
11619578Ssam 		 * Interpret EOF only in cooked mode.
11629578Ssam 		 */
11639578Ssam 		if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
11649578Ssam 			break;
11659578Ssam 		/*
11669578Ssam 		 * Give user character.
11679578Ssam 		 */
116814938Smckusick  		error = ureadc(c & 0177, uio);
11699578Ssam 		if (error)
11709578Ssam 			break;
117114938Smckusick  		if (uio->uio_resid == 0)
11729578Ssam 			break;
11739578Ssam 		/*
11749578Ssam 		 * In cooked mode check for a "break character"
11759578Ssam 		 * marking the end of a "line of input".
11769578Ssam 		 */
11779578Ssam 		if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
11789578Ssam 			break;
11799578Ssam 		first = 0;
11807502Sroot 	}
11819578Ssam 	tp->t_state &= ~TS_BKSL;
11829578Ssam 
11839859Ssam checktandem:
11849578Ssam 	/*
11859578Ssam 	 * Look to unblock output now that (presumably)
11869578Ssam 	 * the input queue has gone down.
11879578Ssam 	 */
11889859Ssam 	if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
11899578Ssam 		if (putc(tp->t_startc, &tp->t_outq) == 0) {
11907502Sroot 			tp->t_state &= ~TS_TBLOCK;
11917502Sroot 			ttstart(tp);
11927502Sroot 		}
11938520Sroot 	return (error);
11947502Sroot }
11957502Sroot 
11967502Sroot /*
11977502Sroot  * Called from the device's write routine after it has
11987502Sroot  * calculated the tty-structure given as argument.
11997502Sroot  */
12007822Sroot ttwrite(tp, uio)
12017625Ssam 	register struct tty *tp;
12029578Ssam 	register struct uio *uio;
12037502Sroot {
12047502Sroot 	register char *cp;
12059578Ssam 	register int cc, ce, c;
12069578Ssam 	int i, hiwat, cnt, error, s;
12077502Sroot 	char obuf[OBUFSIZ];
12087502Sroot 
12099578Ssam 	if ((tp->t_state&TS_CARR_ON) == 0)
12108520Sroot 		return (EIO);
12119578Ssam 	hiwat = TTHIWAT(tp);
12129578Ssam 	cnt = uio->uio_resid;
12139578Ssam 	error = 0;
12147502Sroot loop:
12159578Ssam 	/*
12169578Ssam 	 * Hang the process if it's in the background.
12179578Ssam 	 */
121815141Skarels #define bit(a) (1<<(a-1))
12197502Sroot 	while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
12209578Ssam 	    (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
122115141Skarels 	    !(u.u_procp->p_sigignore & bit(SIGTTOU)) &&
122215141Skarels 	    !(u.u_procp->p_sigmask & bit(SIGTTOU))
12237502Sroot /*
12247502Sroot 					     &&
12257502Sroot 	    (u.u_procp->p_flag&SDETACH)==0) {
12267502Sroot */
12277502Sroot 	    ) {
12287502Sroot 		gsignal(u.u_procp->p_pgrp, SIGTTOU);
12297502Sroot 		sleep((caddr_t)&lbolt, TTIPRI);
12307502Sroot 	}
123115141Skarels #undef	bit
12329578Ssam 
12339578Ssam 	/*
12349578Ssam 	 * Process the user's data in at most OBUFSIZ
12359578Ssam 	 * chunks.  Perform lower case simulation and
12369578Ssam 	 * similar hacks.  Keep track of high water
12379578Ssam 	 * mark, sleep on overflow awaiting device aid
12389578Ssam 	 * in acquiring new space.
12399578Ssam 	 */
12407822Sroot 	while (uio->uio_resid > 0) {
12419578Ssam 		/*
12429578Ssam 		 * Grab a hunk of data from the user.
12439578Ssam 		 */
12447822Sroot 		cc = uio->uio_iov->iov_len;
12457822Sroot 		if (cc == 0) {
12467822Sroot 			uio->uio_iovcnt--;
12477822Sroot 			uio->uio_iov++;
12487822Sroot 			if (uio->uio_iovcnt < 0)
12497822Sroot 				panic("ttwrite");
12507822Sroot 			continue;
12517822Sroot 		}
12527822Sroot 		if (cc > OBUFSIZ)
12537822Sroot 			cc = OBUFSIZ;
12547502Sroot 		cp = obuf;
125512752Ssam 		error = uiomove(cp, cc, UIO_WRITE, uio);
12568520Sroot 		if (error)
12577502Sroot 			break;
12587502Sroot 		if (tp->t_outq.c_cc > hiwat)
12597502Sroot 			goto ovhiwat;
12609578Ssam 		if (tp->t_flags&FLUSHO)
12617502Sroot 			continue;
12629578Ssam 		/*
12639578Ssam 		 * If we're mapping lower case or kludging tildes,
12649578Ssam 		 * then we've got to look at each character, so
12659578Ssam 		 * just feed the stuff to ttyoutput...
12669578Ssam 		 */
12679578Ssam 		if (tp->t_flags & (LCASE|TILDE)) {
12689578Ssam 			while (cc > 0) {
12697502Sroot 				c = *cp++;
12707502Sroot 				tp->t_rocount = 0;
12717625Ssam 				while ((c = ttyoutput(c, tp)) >= 0) {
12727502Sroot 					/* out of clists, wait a bit */
12737502Sroot 					ttstart(tp);
12747502Sroot 					sleep((caddr_t)&lbolt, TTOPRI);
12757502Sroot 					tp->t_rocount = 0;
12767502Sroot 				}
12777502Sroot 				--cc;
12787502Sroot 				if (tp->t_outq.c_cc > hiwat)
12797502Sroot 					goto ovhiwat;
12807502Sroot 			}
12817502Sroot 			continue;
12827502Sroot 		}
12839578Ssam 		/*
12849578Ssam 		 * If nothing fancy need be done, grab those characters we
12859578Ssam 		 * can handle without any of ttyoutput's processing and
12869578Ssam 		 * just transfer them to the output q.  For those chars
12879578Ssam 		 * which require special processing (as indicated by the
12889578Ssam 		 * bits in partab), call ttyoutput.  After processing
12899578Ssam 		 * a hunk of data, look for FLUSHO so ^O's will take effect
12909578Ssam 		 * immediately.
12919578Ssam 		 */
12929578Ssam 		while (cc > 0) {
12939578Ssam 			if (tp->t_flags & (RAW|LITOUT))
12947502Sroot 				ce = cc;
12957502Sroot 			else {
129612752Ssam 				ce = cc - scanc((unsigned)cc, (caddr_t)cp,
129712752Ssam 				   (caddr_t)partab, 077);
12989578Ssam 				/*
12999578Ssam 				 * If ce is zero, then we're processing
13009578Ssam 				 * a special character through ttyoutput.
13019578Ssam 				 */
13029578Ssam 				if (ce == 0) {
13037502Sroot 					tp->t_rocount = 0;
13047502Sroot 					if (ttyoutput(*cp, tp) >= 0) {
13059578Ssam 						/* no c-lists, wait a bit */
13067502Sroot 						ttstart(tp);
13077502Sroot 						sleep((caddr_t)&lbolt, TTOPRI);
13087502Sroot 						continue;
13097502Sroot 					}
13109578Ssam 					cp++, cc--;
13119578Ssam 					if (tp->t_flags&FLUSHO ||
13129578Ssam 					    tp->t_outq.c_cc > hiwat)
13137502Sroot 						goto ovhiwat;
13149578Ssam 					continue;
13157502Sroot 				}
13167502Sroot 			}
13179578Ssam 			/*
13189578Ssam 			 * A bunch of normal characters have been found,
13199578Ssam 			 * transfer them en masse to the output queue and
13209578Ssam 			 * continue processing at the top of the loop.
13219578Ssam 			 * If there are any further characters in this
13229578Ssam 			 * <= OBUFSIZ chunk, the first should be a character
13239578Ssam 			 * requiring special handling by ttyoutput.
13249578Ssam 			 */
13257502Sroot 			tp->t_rocount = 0;
13269578Ssam 			i = b_to_q(cp, ce, &tp->t_outq);
13279578Ssam 			ce -= i;
13289578Ssam 			tp->t_col += ce;
13299578Ssam 			cp += ce, cc -= ce, tk_nout += ce;
13309578Ssam 			if (i > 0) {
13319578Ssam 				/* out of c-lists, wait a bit */
13327502Sroot 				ttstart(tp);
13337502Sroot 				sleep((caddr_t)&lbolt, TTOPRI);
13347502Sroot 			}
13359578Ssam 			if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
13367502Sroot 				goto ovhiwat;
13377502Sroot 		}
13387502Sroot 	}
13397502Sroot 	ttstart(tp);
13408520Sroot 	return (error);
13417502Sroot 
13427502Sroot ovhiwat:
134317545Skarels 	s = spltty();
13449578Ssam 	if (cc != 0) {
13459578Ssam 		uio->uio_iov->iov_base -= cc;
13469578Ssam 		uio->uio_iov->iov_len += cc;
13479578Ssam 		uio->uio_resid += cc;
13489578Ssam 		uio->uio_offset -= cc;
13499578Ssam 	}
13509578Ssam 	/*
13519578Ssam 	 * This can only occur if FLUSHO
13529578Ssam 	 * is also set in t_flags.
13539578Ssam 	 */
13547502Sroot 	if (tp->t_outq.c_cc <= hiwat) {
13559578Ssam 		splx(s);
13567502Sroot 		goto loop;
13577502Sroot 	}
13587502Sroot 	ttstart(tp);
13599578Ssam 	if (tp->t_state&TS_NBIO) {
136017545Skarels 		splx(s);
13617822Sroot 		if (uio->uio_resid == cnt)
13628520Sroot 			return (EWOULDBLOCK);
13638520Sroot 		return (0);
13647502Sroot 	}
13657502Sroot 	tp->t_state |= TS_ASLEEP;
13667502Sroot 	sleep((caddr_t)&tp->t_outq, TTOPRI);
13679578Ssam 	splx(s);
13687502Sroot 	goto loop;
13697502Sroot }
13707502Sroot 
13717502Sroot /*
13727502Sroot  * Rubout one character from the rawq of tp
13737502Sroot  * as cleanly as possible.
13747502Sroot  */
13757502Sroot ttyrub(c, tp)
13767625Ssam 	register c;
13777625Ssam 	register struct tty *tp;
13787502Sroot {
13797502Sroot 	register char *cp;
13807502Sroot 	register int savecol;
13817502Sroot 	int s;
13827502Sroot 	char *nextc();
13837502Sroot 
13849578Ssam 	if ((tp->t_flags&ECHO) == 0)
13857502Sroot 		return;
13869578Ssam 	tp->t_flags &= ~FLUSHO;
13877502Sroot 	c &= 0377;
13889578Ssam 	if (tp->t_flags&CRTBS) {
13897502Sroot 		if (tp->t_rocount == 0) {
13907502Sroot 			/*
13917502Sroot 			 * Screwed by ttwrite; retype
13927502Sroot 			 */
13937502Sroot 			ttyretype(tp);
13947502Sroot 			return;
13957502Sroot 		}
13969578Ssam 		if (c == ('\t'|0200) || c == ('\n'|0200))
13977502Sroot 			ttyrubo(tp, 2);
13989578Ssam 		else switch (partab[c&=0177]&0177) {
13997502Sroot 
14007502Sroot 		case ORDINARY:
14017502Sroot 			if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
14027502Sroot 				ttyrubo(tp, 2);
14037502Sroot 			else
14047502Sroot 				ttyrubo(tp, 1);
14057502Sroot 			break;
14067502Sroot 
14077502Sroot 		case VTAB:
14087502Sroot 		case BACKSPACE:
14097502Sroot 		case CONTROL:
14107502Sroot 		case RETURN:
14119578Ssam 			if (tp->t_flags&CTLECH)
14127502Sroot 				ttyrubo(tp, 2);
14137502Sroot 			break;
14147502Sroot 
14157502Sroot 		case TAB:
14167502Sroot 			if (tp->t_rocount < tp->t_rawq.c_cc) {
14177502Sroot 				ttyretype(tp);
14187502Sroot 				return;
14197502Sroot 			}
142017545Skarels 			s = spltty();
14217502Sroot 			savecol = tp->t_col;
14229578Ssam 			tp->t_state |= TS_CNTTB;
14239578Ssam 			tp->t_flags |= FLUSHO;
14247502Sroot 			tp->t_col = tp->t_rocol;
14259578Ssam 			cp = tp->t_rawq.c_cf;
14269578Ssam 			for (; cp; cp = nextc(&tp->t_rawq, cp))
14277502Sroot 				ttyecho(*cp, tp);
14289578Ssam 			tp->t_flags &= ~FLUSHO;
14299578Ssam 			tp->t_state &= ~TS_CNTTB;
14307502Sroot 			splx(s);
14317502Sroot 			/*
14327502Sroot 			 * savecol will now be length of the tab
14337502Sroot 			 */
14347502Sroot 			savecol -= tp->t_col;
14357502Sroot 			tp->t_col += savecol;
14367502Sroot 			if (savecol > 8)
14377502Sroot 				savecol = 8;		/* overflow screw */
14387502Sroot 			while (--savecol >= 0)
14397502Sroot 				(void) ttyoutput('\b', tp);
14407502Sroot 			break;
14417502Sroot 
14427502Sroot 		default:
14437502Sroot 			panic("ttyrub");
14447502Sroot 		}
14459578Ssam 	} else if (tp->t_flags&PRTERA) {
14469578Ssam 		if ((tp->t_state&TS_ERASE) == 0) {
14477502Sroot 			(void) ttyoutput('\\', tp);
14489578Ssam 			tp->t_state |= TS_ERASE;
14497502Sroot 		}
14507502Sroot 		ttyecho(c, tp);
14517502Sroot 	} else
14527502Sroot 		ttyecho(tp->t_erase, tp);
14537502Sroot 	tp->t_rocount--;
14547502Sroot }
14557502Sroot 
14567502Sroot /*
14577502Sroot  * Crt back over cnt chars perhaps
14587502Sroot  * erasing them.
14597502Sroot  */
14607502Sroot ttyrubo(tp, cnt)
14617625Ssam 	register struct tty *tp;
14627625Ssam 	int cnt;
14637502Sroot {
14649578Ssam 	register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
14657502Sroot 
14667502Sroot 	while (--cnt >= 0)
14679578Ssam 		ttyout(rubostring, tp);
14687502Sroot }
14697502Sroot 
14707502Sroot /*
14717502Sroot  * Reprint the rawq line.
14727502Sroot  * We assume c_cc has already been checked.
14737502Sroot  */
14747502Sroot ttyretype(tp)
14757625Ssam 	register struct tty *tp;
14767502Sroot {
14777502Sroot 	register char *cp;
14787502Sroot 	char *nextc();
14797502Sroot 	int s;
14807502Sroot 
14819578Ssam 	if (tp->t_rprntc != 0377)
14829578Ssam 		ttyecho(tp->t_rprntc, tp);
14837502Sroot 	(void) ttyoutput('\n', tp);
148417545Skarels 	s = spltty();
14857502Sroot 	for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
14867502Sroot 		ttyecho(*cp, tp);
14877502Sroot 	for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
14887502Sroot 		ttyecho(*cp, tp);
14899578Ssam 	tp->t_state &= ~TS_ERASE;
14907502Sroot 	splx(s);
14917502Sroot 	tp->t_rocount = tp->t_rawq.c_cc;
14927502Sroot 	tp->t_rocol = 0;
14937502Sroot }
14947502Sroot 
14957502Sroot /*
14967502Sroot  * Echo a typed character to the terminal
14977502Sroot  */
14987502Sroot ttyecho(c, tp)
14997625Ssam 	register c;
15007625Ssam 	register struct tty *tp;
15017502Sroot {
15027502Sroot 
15039578Ssam 	if ((tp->t_state&TS_CNTTB) == 0)
15049578Ssam 		tp->t_flags &= ~FLUSHO;
15057502Sroot 	if ((tp->t_flags&ECHO) == 0)
15067502Sroot 		return;
15077502Sroot 	c &= 0377;
15087502Sroot 	if (tp->t_flags&RAW) {
15097502Sroot 		(void) ttyoutput(c, tp);
15107502Sroot 		return;
15117502Sroot 	}
15127502Sroot 	if (c == '\r' && tp->t_flags&CRMOD)
15137502Sroot 		c = '\n';
15149578Ssam 	if (tp->t_flags&CTLECH) {
15157502Sroot 		if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
15167502Sroot 			(void) ttyoutput('^', tp);
15177502Sroot 			c &= 0177;
15187502Sroot 			if (c == 0177)
15197502Sroot 				c = '?';
15207502Sroot 			else if (tp->t_flags&LCASE)
15217502Sroot 				c += 'a' - 1;
15227502Sroot 			else
15237502Sroot 				c += 'A' - 1;
15247502Sroot 		}
15257502Sroot 	}
15267502Sroot 	if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
15277502Sroot 		c += 'a' - 'A';
15289578Ssam 	(void) ttyoutput(c&0177, tp);
15297502Sroot }
15307502Sroot 
15317502Sroot /*
15327502Sroot  * Is c a break char for tp?
15337502Sroot  */
15347502Sroot ttbreakc(c, tp)
15357625Ssam 	register c;
15367625Ssam 	register struct tty *tp;
15377502Sroot {
15389578Ssam 	return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
15397502Sroot 		c == '\r' && (tp->t_flags&CRMOD));
15407502Sroot }
15417502Sroot 
15427502Sroot /*
15437502Sroot  * send string cp to tp
15447502Sroot  */
15457502Sroot ttyout(cp, tp)
15467625Ssam 	register char *cp;
15477625Ssam 	register struct tty *tp;
15487502Sroot {
15497502Sroot 	register char c;
15507502Sroot 
15517502Sroot 	while (c = *cp++)
15527502Sroot 		(void) ttyoutput(c, tp);
15537502Sroot }
15547502Sroot 
15557502Sroot ttwakeup(tp)
15567502Sroot 	struct tty *tp;
15577502Sroot {
15587502Sroot 
15597502Sroot 	if (tp->t_rsel) {
15607502Sroot 		selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
15617502Sroot 		tp->t_state &= ~TS_RCOLL;
15627502Sroot 		tp->t_rsel = 0;
15637502Sroot 	}
156412752Ssam 	if (tp->t_state & TS_ASYNC)
156512752Ssam 		gsignal(tp->t_pgrp, SIGIO);
15667502Sroot 	wakeup((caddr_t)&tp->t_rawq);
15677502Sroot }
15687502Sroot 
156913533Ssam #if !defined(vax)
15709578Ssam scanc(size, cp, table, mask)
15719578Ssam 	register int size;
15729578Ssam 	register char *cp, table[];
15739578Ssam 	register int mask;
15747502Sroot {
15759578Ssam 	register int i = 0;
15767502Sroot 
15779578Ssam 	while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
15789578Ssam 		i++;
157915100Skarels 	return (size - i);
15807502Sroot }
15819578Ssam #endif
1582