xref: /csrg-svn/sys/kern/tty.c (revision 15094)
1 /*	tty.c	6.4	83/09/25	*/
2 
3 #include "../machine/reg.h"
4 
5 #include "../h/param.h"
6 #include "../h/systm.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/ioctl.h"
10 #include "../h/tty.h"
11 #include "../h/proc.h"
12 #include "../h/inode.h"
13 #include "../h/file.h"
14 #include "../h/conf.h"
15 #include "../h/buf.h"
16 #include "../h/dk.h"
17 #include "../h/uio.h"
18 #include "../h/kernel.h"
19 
20 /*
21  * Table giving parity for characters and indicating
22  * character classes to tty driver.  In particular,
23  * if the low 6 bits are 0, then the character needs
24  * no special processing on output.
25  */
26 
27 char partab[] = {
28 	0001,0201,0201,0001,0201,0001,0001,0201,
29 	0202,0004,0003,0201,0005,0206,0201,0001,
30 	0201,0001,0001,0201,0001,0201,0201,0001,
31 	0001,0201,0201,0001,0201,0001,0001,0201,
32 	0200,0000,0000,0200,0000,0200,0200,0000,
33 	0000,0200,0200,0000,0200,0000,0000,0200,
34 	0000,0200,0200,0000,0200,0000,0000,0200,
35 	0200,0000,0000,0200,0000,0200,0200,0000,
36 	0200,0000,0000,0200,0000,0200,0200,0000,
37 	0000,0200,0200,0000,0200,0000,0000,0200,
38 	0000,0200,0200,0000,0200,0000,0000,0200,
39 	0200,0000,0000,0200,0000,0200,0200,0000,
40 	0000,0200,0200,0000,0200,0000,0000,0200,
41 	0200,0000,0000,0200,0000,0200,0200,0000,
42 	0200,0000,0000,0200,0000,0200,0200,0000,
43 	0000,0200,0200,0000,0200,0000,0000,0201,
44 
45 	/*
46 	 * 7 bit ascii ends with the last character above,
47 	 * but we contine through all 256 codes for the sake
48 	 * of the tty output routines which use special vax
49 	 * instructions which need a 256 character trt table.
50 	 */
51 
52 	0007,0007,0007,0007,0007,0007,0007,0007,
53 	0007,0007,0007,0007,0007,0007,0007,0007,
54 	0007,0007,0007,0007,0007,0007,0007,0007,
55 	0007,0007,0007,0007,0007,0007,0007,0007,
56 	0007,0007,0007,0007,0007,0007,0007,0007,
57 	0007,0007,0007,0007,0007,0007,0007,0007,
58 	0007,0007,0007,0007,0007,0007,0007,0007,
59 	0007,0007,0007,0007,0007,0007,0007,0007,
60 	0007,0007,0007,0007,0007,0007,0007,0007,
61 	0007,0007,0007,0007,0007,0007,0007,0007,
62 	0007,0007,0007,0007,0007,0007,0007,0007,
63 	0007,0007,0007,0007,0007,0007,0007,0007,
64 	0007,0007,0007,0007,0007,0007,0007,0007,
65 	0007,0007,0007,0007,0007,0007,0007,0007,
66 	0007,0007,0007,0007,0007,0007,0007,0007,
67 	0007,0007,0007,0007,0007,0007,0007,0007
68 };
69 
70 /*
71  * Input mapping table-- if an entry is non-zero, when the
72  * corresponding character is typed preceded by "\" the escape
73  * sequence is replaced by the table value.  Mostly used for
74  * upper-case only terminals.
75  */
76 char	maptab[] ={
77 	000,000,000,000,000,000,000,000,
78 	000,000,000,000,000,000,000,000,
79 	000,000,000,000,000,000,000,000,
80 	000,000,000,000,000,000,000,000,
81 	000,'|',000,000,000,000,000,'`',
82 	'{','}',000,000,000,000,000,000,
83 	000,000,000,000,000,000,000,000,
84 	000,000,000,000,000,000,000,000,
85 	000,000,000,000,000,000,000,000,
86 	000,000,000,000,000,000,000,000,
87 	000,000,000,000,000,000,000,000,
88 	000,000,000,000,000,000,'~',000,
89 	000,'A','B','C','D','E','F','G',
90 	'H','I','J','K','L','M','N','O',
91 	'P','Q','R','S','T','U','V','W',
92 	'X','Y','Z',000,000,000,000,000,
93 };
94 
95 short	tthiwat[16] =
96    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000 };
97 short	ttlowat[16] =
98    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99 
100 struct	ttychars ttydefaults = {
101 	CERASE,	CKILL,	CINTR,	CQUIT,	CSTART,	CSTOP,	CEOF,
102 	CBRK,	CSUSP,	CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
103 };
104 
105 ttychars(tp)
106 	struct tty *tp;
107 {
108 
109 	tp->t_chars = ttydefaults;
110 }
111 
112 /*
113  * Wait for output to drain, then flush input waiting.
114  */
115 ttywflush(tp)
116 	register struct tty *tp;
117 {
118 
119 	ttywait(tp);
120 	ttyflush(tp, FREAD);
121 }
122 
123 ttywait(tp)
124 	register struct tty *tp;
125 {
126 	register int s = spl5();
127 
128 	while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
129 	    tp->t_state&TS_CARR_ON && tp->t_oproc) {	/* kludge for pty */
130 		(*tp->t_oproc)(tp);
131 		tp->t_state |= TS_ASLEEP;
132 		sleep((caddr_t)&tp->t_outq, TTOPRI);
133 	}
134 	splx(s);
135 }
136 
137 /*
138  * Flush all TTY queues
139  */
140 ttyflush(tp, rw)
141 	register struct tty *tp;
142 {
143 	register s;
144 
145 	s = spl6();
146 	if (rw & FREAD) {
147 		while (getc(&tp->t_canq) >= 0)
148 			;
149 		wakeup((caddr_t)&tp->t_rawq);
150 	}
151 	if (rw & FWRITE) {
152 		wakeup((caddr_t)&tp->t_outq);
153 		tp->t_state &= ~TS_TTSTOP;
154 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
155 		while (getc(&tp->t_outq) >= 0)
156 			;
157 	}
158 	if (rw & FREAD) {
159 		while (getc(&tp->t_rawq) >= 0)
160 			;
161 		tp->t_delct = 0;
162 		tp->t_rocount = 0;
163 		tp->t_rocol = 0;
164 		tp->t_state &= ~TS_LOCAL;
165 	}
166 	splx(s);
167 }
168 
169 /*
170  * Send stop character on input overflow.
171  */
172 ttyblock(tp)
173 	register struct tty *tp;
174 {
175 	register x;
176 
177 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
178 	if (tp->t_rawq.c_cc > TTYHOG) {
179 		ttyflush(tp, FREAD|FWRITE);
180 		tp->t_state &= ~TS_TBLOCK;
181 	}
182 	if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) {
183 		tp->t_state |= TS_TBLOCK;
184 		ttstart(tp);
185 	}
186 }
187 
188 /*
189  * Restart typewriter output following a delay
190  * timeout.
191  * The name of the routine is passed to the timeout
192  * subroutine and it is called during a clock interrupt.
193  */
194 ttrstrt(tp)
195 	register struct tty *tp;
196 {
197 
198 	if (tp == 0)
199 		panic("ttrstrt");
200 	tp->t_state &= ~TS_TIMEOUT;
201 	ttstart(tp);
202 }
203 
204 /*
205  * Start output on the typewriter. It is used from the top half
206  * after some characters have been put on the output queue,
207  * from the interrupt routine to transmit the next
208  * character, and after a timeout has finished.
209  */
210 ttstart(tp)
211 	register struct tty *tp;
212 {
213 	register s;
214 
215 	s = spl5();
216 	if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
217 	    tp->t_oproc)		/* kludge for pty */
218 		(*tp->t_oproc)(tp);
219 	splx(s);
220 }
221 
222 /*
223  * Common code for tty ioctls.
224  */
225 /*ARGSUSED*/
226 ttioctl(tp, com, data, flag)
227 	register struct tty *tp;
228 	caddr_t data;
229 {
230 	int dev = tp->t_dev;
231 	extern int nldisp;
232 	int s;
233 	register int newflags;
234 
235 	/*
236 	 * If the ioctl involves modification,
237 	 * insist on being able to write the device,
238 	 * and hang if in the background.
239 	 */
240 	switch (com) {
241 
242 	case TIOCSETD:
243 	case TIOCSETP:
244 	case TIOCSETN:
245 	case TIOCFLUSH:
246 	case TIOCSETC:
247 	case TIOCSLTC:
248 	case TIOCSPGRP:
249 	case TIOCLBIS:
250 	case TIOCLBIC:
251 	case TIOCLSET:
252 	case TIOCSTI:
253 #define bit(a) (1<<(a-1))
254 		while (tp->t_line == NTTYDISC &&
255 		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
256 		   (u.u_procp->p_flag&SVFORK) == 0 &&
257 		   !(u.u_procp->p_sigignore & bit(SIGTTOU)) &&
258 		   !(u.u_procp->p_sigmask & bit(SIGTTOU))) {
259 			gsignal(u.u_procp->p_pgrp, SIGTTOU);
260 			sleep((caddr_t)&lbolt, TTOPRI);
261 		}
262 		break;
263 	}
264 #undef	bit
265 
266 	/*
267 	 * Process the ioctl.
268 	 */
269 	switch (com) {
270 
271 	/* get discipline number */
272 	case TIOCGETD:
273 		*(int *)data = tp->t_line;
274 		break;
275 
276 	/* set line discipline */
277 	case TIOCSETD: {
278 		register int t = *(int *)data;
279 		int error = 0;
280 
281 		if ((unsigned) t >= nldisp)
282 			return (ENXIO);
283 		s = spl5();
284 		if (tp->t_line)
285 			(*linesw[tp->t_line].l_close)(tp);
286 		if (t)
287 			error = (*linesw[t].l_open)(dev, tp);
288 		splx(s);
289 		if (error) {
290 			s = spl5();
291 			if (tp->t_line)
292 				(void) (*linesw[tp->t_line].l_open)(dev, tp);
293 			splx(s);
294 			return (error);
295 		}
296 		tp->t_line = t;
297 		break;
298 	}
299 
300 	/* prevent more opens on channel */
301 	case TIOCEXCL:
302 		tp->t_state |= TS_XCLUDE;
303 		break;
304 
305 	case TIOCNXCL:
306 		tp->t_state &= ~TS_XCLUDE;
307 		break;
308 
309 	/* hang up line on last close */
310 	case TIOCHPCL:
311 		tp->t_state |= TS_HUPCLS;
312 		break;
313 
314 	case TIOCFLUSH: {
315 		register int flags = *(int *)data;
316 
317 		if (flags == 0)
318 			flags = FREAD|FWRITE;
319 		else
320 			flags &= FREAD|FWRITE;
321 		ttyflush(tp, flags);
322 		break;
323 	}
324 
325 	/* return number of characters immediately available */
326 	case FIONREAD:
327 		*(off_t *)data = ttnread(tp);
328 		break;
329 
330 	case TIOCOUTQ:
331 		*(int *)data = tp->t_outq.c_cc;
332 		break;
333 
334 	case TIOCSTOP:
335 		s = spl5();
336 		if ((tp->t_state&TS_TTSTOP) == 0) {
337 			tp->t_state |= TS_TTSTOP;
338 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
339 		}
340 		splx(s);
341 		break;
342 
343 	case TIOCSTART:
344 		s = spl5();
345 		if ((tp->t_state&TS_TTSTOP) || (tp->t_flags&FLUSHO)) {
346 			tp->t_state &= ~TS_TTSTOP;
347 			tp->t_flags &= ~FLUSHO;
348 			ttstart(tp);
349 		}
350 		splx(s);
351 		break;
352 
353 	/*
354 	 * Simulate typing of a character at the terminal.
355 	 */
356 	case TIOCSTI:
357 		if (u.u_uid && u.u_ttyp != tp)
358 			return (EACCES);
359 		(*linesw[tp->t_line].l_rint)(*(char *)data, tp);
360 		break;
361 
362 	case TIOCSETP:
363 	case TIOCSETN: {
364 		register struct sgttyb *sg = (struct sgttyb *)data;
365 
366 		tp->t_erase = sg->sg_erase;
367 		tp->t_kill = sg->sg_kill;
368 		tp->t_ispeed = sg->sg_ispeed;
369 		tp->t_ospeed = sg->sg_ospeed;
370 		newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
371 		s = spl5();
372 		if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) {
373 			ttywait(tp);
374 			ttyflush(tp, FREAD);
375 		} else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) {
376 			if (newflags&CBREAK) {
377 				struct clist tq;
378 
379 				catq(&tp->t_rawq, &tp->t_canq);
380 				tq = tp->t_rawq;
381 				tp->t_rawq = tp->t_canq;
382 				tp->t_canq = tq;
383 			} else {
384 				tp->t_flags |= PENDIN;
385 				newflags |= PENDIN;
386 				ttwakeup(tp);
387 			}
388 		}
389 		tp->t_flags = newflags;
390 		if (tp->t_flags&RAW) {
391 			tp->t_state &= ~TS_TTSTOP;
392 			ttstart(tp);
393 		}
394 		splx(s);
395 		break;
396 	}
397 
398 	/* send current parameters to user */
399 	case TIOCGETP: {
400 		register struct sgttyb *sg = (struct sgttyb *)data;
401 
402 		sg->sg_ispeed = tp->t_ispeed;
403 		sg->sg_ospeed = tp->t_ospeed;
404 		sg->sg_erase = tp->t_erase;
405 		sg->sg_kill = tp->t_kill;
406 		sg->sg_flags = tp->t_flags;
407 		break;
408 	}
409 
410 	case FIONBIO:
411 		if (*(int *)data)
412 			tp->t_state |= TS_NBIO;
413 		else
414 			tp->t_state &= ~TS_NBIO;
415 		break;
416 
417 	case FIOASYNC:
418 		if (*(int *)data)
419 			tp->t_state |= TS_ASYNC;
420 		else
421 			tp->t_state &= ~TS_ASYNC;
422 		break;
423 
424 	case TIOCGETC:
425 		bcopy((caddr_t)&tp->t_intrc, data, sizeof (struct tchars));
426 		break;
427 
428 	case TIOCSETC:
429 		bcopy(data, (caddr_t)&tp->t_intrc, sizeof (struct tchars));
430 		break;
431 
432 	/* set/get local special characters */
433 	case TIOCSLTC:
434 		bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars));
435 		break;
436 
437 	case TIOCGLTC:
438 		bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars));
439 		break;
440 
441 	/*
442 	 * Modify local mode word.
443 	 */
444 	case TIOCLBIS:
445 		tp->t_flags |= *(int *)data << 16;
446 		break;
447 
448 	case TIOCLBIC:
449 		tp->t_flags &= ~(*(int *)data << 16);
450 		break;
451 
452 	case TIOCLSET:
453 		tp->t_flags &= 0xffff;
454 		tp->t_flags |= *(int *)data << 16;
455 		break;
456 
457 	case TIOCLGET:
458 		*(int *)data = tp->t_flags >> 16;
459 		break;
460 
461 	/* should allow SPGRP and GPGRP only if tty open for reading */
462 	case TIOCSPGRP:
463 		tp->t_pgrp = *(int *)data;
464 		break;
465 
466 	case TIOCGPGRP:
467 		*(int *)data = tp->t_pgrp;
468 		break;
469 
470 	default:
471 		return (-1);
472 	}
473 	return (0);
474 }
475 
476 ttnread(tp)
477 	struct tty *tp;
478 {
479 	int nread = 0;
480 
481 	if (tp->t_flags & PENDIN)
482 		ttypend(tp);
483 	nread = tp->t_canq.c_cc;
484 	if (tp->t_flags & (RAW|CBREAK))
485 		nread += tp->t_rawq.c_cc;
486 	return (nread);
487 }
488 
489 ttselect(dev, rw)
490 	dev_t dev;
491 	int rw;
492 {
493 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
494 	int nread;
495 	int s = spl5();
496 
497 	switch (rw) {
498 
499 	case FREAD:
500 		nread = ttnread(tp);
501 		if (nread > 0)
502 			goto win;
503 		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
504 			tp->t_state |= TS_RCOLL;
505 		else
506 			tp->t_rsel = u.u_procp;
507 		break;
508 
509 	case FWRITE:
510 		if (tp->t_outq.c_cc <= TTLOWAT(tp))
511 			goto win;
512 		if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
513 			tp->t_state |= TS_WCOLL;
514 		else
515 			tp->t_wsel = u.u_procp;
516 		break;
517 	}
518 	splx(s);
519 	return (0);
520 win:
521 	splx(s);
522 	return (1);
523 }
524 
525 /*
526  * Establish a process group for distribution of
527  * quits and interrupts from the tty.
528  */
529 ttyopen(dev, tp)
530 	dev_t dev;
531 	register struct tty *tp;
532 {
533 	register struct proc *pp;
534 
535 	pp = u.u_procp;
536 	tp->t_dev = dev;
537 	if (pp->p_pgrp == 0) {
538 		u.u_ttyp = tp;
539 		u.u_ttyd = dev;
540 		if (tp->t_pgrp == 0)
541 			tp->t_pgrp = pp->p_pid;
542 		pp->p_pgrp = tp->t_pgrp;
543 	}
544 	tp->t_state &= ~TS_WOPEN;
545 	tp->t_state |= TS_ISOPEN;
546 	if (tp->t_line != NTTYDISC)
547 		ttywflush(tp);
548 	return (0);
549 }
550 
551 /*
552  * clean tp on last close
553  */
554 ttyclose(tp)
555 	register struct tty *tp;
556 {
557 
558 	if (tp->t_line) {
559 		ttywflush(tp);
560 		tp->t_line = 0;
561 		return;
562 	}
563 	tp->t_pgrp = 0;
564 	ttywflush(tp);
565 	tp->t_state = 0;
566 }
567 
568 /*
569  * reinput pending characters after state switch
570  * call at spl5().
571  */
572 ttypend(tp)
573 	register struct tty *tp;
574 {
575 	struct clist tq;
576 	register c;
577 
578 	tp->t_flags &= ~PENDIN;
579 	tp->t_state |= TS_TYPEN;
580 	tq = tp->t_rawq;
581 	tp->t_rawq.c_cc = 0;
582 	tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
583 	while ((c = getc(&tq)) >= 0)
584 		ttyinput(c, tp);
585 	tp->t_state &= ~TS_TYPEN;
586 }
587 
588 /*
589  * Place a character on raw TTY input queue,
590  * putting in delimiters and waking up top
591  * half as needed.  Also echo if required.
592  * The arguments are the character and the
593  * appropriate tty structure.
594  */
595 ttyinput(c, tp)
596 	register c;
597 	register struct tty *tp;
598 {
599 	register int t_flags = tp->t_flags;
600 	int i;
601 
602 	/*
603 	 * If input is pending take it first.
604 	 */
605 	if (t_flags&PENDIN)
606 		ttypend(tp);
607 	tk_nin++;
608 	c &= 0377;
609 
610 	/*
611 	 * In tandem mode, check high water mark.
612 	 */
613 	if (t_flags&TANDEM)
614 		ttyblock(tp);
615 
616 	if (t_flags&RAW) {
617 		/*
618 		 * Raw mode, just put character
619 		 * in input q w/o interpretation.
620 		 */
621 		if (tp->t_rawq.c_cc > TTYHOG)
622 			ttyflush(tp, FREAD|FWRITE);
623 		else {
624 			if (putc(c, &tp->t_rawq) >= 0)
625 				ttwakeup(tp);
626 			ttyecho(c, tp);
627 		}
628 		goto endcase;
629 	}
630 
631 	/*
632 	 * Ignore any high bit added during
633 	 * previous ttyinput processing.
634 	 */
635 	if ((tp->t_state&TS_TYPEN) == 0)
636 		c &= 0177;
637 	/*
638 	 * Check for literal nexting very first
639 	 */
640 	if (tp->t_state&TS_LNCH) {
641 		c |= 0200;
642 		tp->t_state &= ~TS_LNCH;
643 	}
644 
645 	/*
646 	 * Scan for special characters.  This code
647 	 * is really just a big case statement with
648 	 * non-constant cases.  The bottom of the
649 	 * case statement is labeled ``endcase'', so goto
650 	 * it after a case match, or similar.
651 	 */
652 	if (tp->t_line == NTTYDISC) {
653 		if (c == tp->t_lnextc) {
654 			if (tp->t_flags&ECHO)
655 				ttyout("^\b", tp);
656 			tp->t_state |= TS_LNCH;
657 			goto endcase;
658 		}
659 		if (c == tp->t_flushc) {
660 			if (tp->t_flags&FLUSHO)
661 				tp->t_flags &= ~FLUSHO;
662 			else {
663 				ttyflush(tp, FWRITE);
664 				ttyecho(c, tp);
665 				if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
666 					ttyretype(tp);
667 				tp->t_flags |= FLUSHO;
668 			}
669 			goto startoutput;
670 		}
671 		if (c == tp->t_suspc) {
672 			if ((tp->t_flags&NOFLSH) == 0)
673 				ttyflush(tp, FREAD);
674 			ttyecho(c, tp);
675 			gsignal(tp->t_pgrp, SIGTSTP);
676 			goto endcase;
677 		}
678 	}
679 
680 	/*
681 	 * Handle start/stop characters.
682 	 */
683 	if (c == tp->t_stopc) {
684 		if ((tp->t_state&TS_TTSTOP) == 0) {
685 			tp->t_state |= TS_TTSTOP;
686 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
687 			return;
688 		}
689 		if (c != tp->t_startc)
690 			return;
691 		goto endcase;
692 	}
693 	if (c == tp->t_startc)
694 		goto restartoutput;
695 
696 	/*
697 	 * Look for interrupt/quit chars.
698 	 */
699 	if (c == tp->t_intrc || c == tp->t_quitc) {
700 		if ((tp->t_flags&NOFLSH) == 0)
701 			ttyflush(tp, FREAD|FWRITE);
702 		ttyecho(c, tp);
703 		gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
704 		goto endcase;
705 	}
706 
707 	/*
708 	 * Cbreak mode, don't process line editing
709 	 * characters; check high water mark for wakeup.
710 	 */
711 	if (t_flags&CBREAK) {
712 		if (tp->t_rawq.c_cc > TTYHOG) {
713 			if (tp->t_outq.c_cc < TTHIWAT(tp) &&
714 			    tp->t_line == NTTYDISC)
715 				(void) ttyoutput(CTRL(g), tp);
716 		} else if (putc(c, &tp->t_rawq) >= 0) {
717 			ttwakeup(tp);
718 			ttyecho(c, tp);
719 		}
720 		goto endcase;
721 	}
722 
723 	/*
724 	 * From here on down cooked mode character
725 	 * processing takes place.
726 	 */
727 	if ((tp->t_state&TS_QUOT) &&
728 	    (c == tp->t_erase || c == tp->t_kill)) {
729 		ttyrub(unputc(&tp->t_rawq), tp);
730 		c |= 0200;
731 	}
732 	if (c == tp->t_erase) {
733 		if (tp->t_rawq.c_cc)
734 			ttyrub(unputc(&tp->t_rawq), tp);
735 		goto endcase;
736 	}
737 	if (c == tp->t_kill) {
738 		if (tp->t_flags&CRTKIL &&
739 		    tp->t_rawq.c_cc == tp->t_rocount) {
740 			while (tp->t_rawq.c_cc)
741 				ttyrub(unputc(&tp->t_rawq), tp);
742 		} else {
743 			ttyecho(c, tp);
744 			ttyecho('\n', tp);
745 			while (getc(&tp->t_rawq) > 0)
746 				;
747 			tp->t_rocount = 0;
748 		}
749 		tp->t_state &= ~TS_LOCAL;
750 		goto endcase;
751 	}
752 
753 	/*
754 	 * New line discipline,
755 	 * check word erase/reprint line.
756 	 */
757 	if (tp->t_line == NTTYDISC) {
758 		if (c == tp->t_werasc) {
759 			if (tp->t_rawq.c_cc == 0)
760 				goto endcase;
761 			do {
762 				c = unputc(&tp->t_rawq);
763 				if (c != ' ' && c != '\t')
764 					goto erasenb;
765 				ttyrub(c, tp);
766 			} while (tp->t_rawq.c_cc);
767 			goto endcase;
768 	erasenb:
769 			do {
770 				ttyrub(c, tp);
771 				if (tp->t_rawq.c_cc == 0)
772 					goto endcase;
773 				c = unputc(&tp->t_rawq);
774 			} while (c != ' ' && c != '\t');
775 			(void) putc(c, &tp->t_rawq);
776 			goto endcase;
777 		}
778 		if (c == tp->t_rprntc) {
779 			ttyretype(tp);
780 			goto endcase;
781 		}
782 	}
783 
784 	/*
785 	 * Check for input buffer overflow
786 	 */
787 	if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
788 		if (tp->t_line == NTTYDISC)
789 			(void) ttyoutput(CTRL(g), tp);
790 		goto endcase;
791 	}
792 
793 	/*
794 	 * Put data char in q for user and
795 	 * wakeup on seeing a line delimiter.
796 	 */
797 	if (putc(c, &tp->t_rawq) >= 0) {
798 		if (ttbreakc(c, tp)) {
799 			tp->t_rocount = 0;
800 			catq(&tp->t_rawq, &tp->t_canq);
801 			ttwakeup(tp);
802 		} else if (tp->t_rocount++ == 0)
803 			tp->t_rocol = tp->t_col;
804 		tp->t_state &= ~TS_QUOT;
805 		if (c == '\\')
806 			tp->t_state |= TS_QUOT;
807 		if (tp->t_state&TS_ERASE) {
808 			tp->t_state &= ~TS_ERASE;
809 			(void) ttyoutput('/', tp);
810 		}
811 		i = tp->t_col;
812 		ttyecho(c, tp);
813 		if (c == tp->t_eofc && tp->t_flags&ECHO) {
814 			i = MIN(2, tp->t_col - i);
815 			while (i > 0) {
816 				(void) ttyoutput('\b', tp);
817 				i--;
818 			}
819 		}
820 	}
821 
822 endcase:
823 	/*
824 	 * If DEC-style start/stop is enabled don't restart
825 	 * output until seeing the start character.
826 	 */
827 	if (tp->t_flags&DECCTQ && tp->t_state&TS_TTSTOP &&
828 	    tp->t_startc != tp->t_stopc)
829 		return;
830 
831 restartoutput:
832 	tp->t_state &= ~TS_TTSTOP;
833 	tp->t_flags &= ~FLUSHO;
834 
835 startoutput:
836 	ttstart(tp);
837 }
838 
839 /*
840  * Put character on TTY output queue, adding delays,
841  * expanding tabs, and handling the CR/NL bit.
842  * This is called both from the top half for output,
843  * and from interrupt level for echoing.
844  * The arguments are the character and the tty structure.
845  * Returns < 0 if putc succeeds, otherwise returns char to resend
846  * Must be recursive.
847  */
848 ttyoutput(c, tp)
849 	register c;
850 	register struct tty *tp;
851 {
852 	register char *colp;
853 	register ctype;
854 
855 	if (tp->t_flags & (RAW|LITOUT)) {
856 		if (tp->t_flags&FLUSHO)
857 			return (-1);
858 		if (putc(c, &tp->t_outq))
859 			return (c);
860 		tk_nout++;
861 		return (-1);
862 	}
863 
864 	/*
865 	 * Ignore EOT in normal mode to avoid
866 	 * hanging up certain terminals.
867 	 */
868 	c &= 0177;
869 	if (c == CEOT && (tp->t_flags&CBREAK) == 0)
870 		return (-1);
871 	/*
872 	 * Turn tabs to spaces as required
873 	 */
874 	if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
875 		register int s;
876 
877 		c = 8 - (tp->t_col&7);
878 		if ((tp->t_flags&FLUSHO) == 0) {
879 			s = spl5();		/* don't interrupt tabs */
880 			c -= b_to_q("        ", c, &tp->t_outq);
881 			tk_nout += c;
882 			splx(s);
883 		}
884 		tp->t_col += c;
885 		return (c ? -1 : '\t');
886 	}
887 	tk_nout++;
888 	/*
889 	 * for upper-case-only terminals,
890 	 * generate escapes.
891 	 */
892 	if (tp->t_flags&LCASE) {
893 		colp = "({)}!|^~'`";
894 		while (*colp++)
895 			if (c == *colp++) {
896 				if (ttyoutput('\\', tp) >= 0)
897 					return (c);
898 				c = colp[-2];
899 				break;
900 			}
901 		if ('A' <= c && c <= 'Z') {
902 			if (ttyoutput('\\', tp) >= 0)
903 				return (c);
904 		} else if ('a' <= c && c <= 'z')
905 			c += 'A' - 'a';
906 	}
907 
908 	/*
909 	 * turn <nl> to <cr><lf> if desired.
910 	 */
911 	if (c == '\n' && tp->t_flags&CRMOD)
912 		if (ttyoutput('\r', tp) >= 0)
913 			return (c);
914 	if (c == '~' && tp->t_flags&TILDE)
915 		c = '`';
916 	if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
917 		return (c);
918 	/*
919 	 * Calculate delays.
920 	 * The numbers here represent clock ticks
921 	 * and are not necessarily optimal for all terminals.
922 	 * The delays are indicated by characters above 0200.
923 	 * In raw mode there are no delays and the
924 	 * transmission path is 8 bits wide.
925 	 *
926 	 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
927 	 */
928 	colp = &tp->t_col;
929 	ctype = partab[c];
930 	c = 0;
931 	switch (ctype&077) {
932 
933 	case ORDINARY:
934 		(*colp)++;
935 
936 	case CONTROL:
937 		break;
938 
939 	case BACKSPACE:
940 		if (*colp)
941 			(*colp)--;
942 		break;
943 
944 	/*
945 	 * This macro is close enough to the correct thing;
946 	 * it should be replaced by real user settable delays
947 	 * in any event...
948 	 */
949 #define	mstohz(ms)	(((ms) * hz) >> 10)
950 	case NEWLINE:
951 		ctype = (tp->t_flags >> 8) & 03;
952 		if (ctype == 1) { /* tty 37 */
953 			if (*colp > 0)
954 				c = max((((unsigned)*colp) >> 4) + 3,
955 				    (unsigned)6);
956 		} else if (ctype == 2) /* vt05 */
957 			c = mstohz(100);
958 		*colp = 0;
959 		break;
960 
961 	case TAB:
962 		ctype = (tp->t_flags >> 10) & 03;
963 		if (ctype == 1) { /* tty 37 */
964 			c = 1 - (*colp | ~07);
965 			if (c < 5)
966 				c = 0;
967 		}
968 		*colp |= 07;
969 		(*colp)++;
970 		break;
971 
972 	case VTAB:
973 		if (tp->t_flags&VTDELAY) /* tty 37 */
974 			c = 0177;
975 		break;
976 
977 	case RETURN:
978 		ctype = (tp->t_flags >> 12) & 03;
979 		if (ctype == 1) /* tn 300 */
980 			c = mstohz(83);
981 		else if (ctype == 2) /* ti 700 */
982 			c = mstohz(166);
983 		else if (ctype == 3) { /* concept 100 */
984 			int i;
985 
986 			if ((i = *colp) >= 0)
987 				for (; i < 9; i++)
988 					(void) putc(0177, &tp->t_outq);
989 		}
990 		*colp = 0;
991 	}
992 	if (c && (tp->t_flags&FLUSHO) == 0)
993 		(void) putc(c|0200, &tp->t_outq);
994 	return (-1);
995 }
996 #undef mstohz
997 
998 /*
999  * Called from device's read routine after it has
1000  * calculated the tty-structure given as argument.
1001  */
1002 ttread(tp, uio)
1003 	register struct tty *tp;
1004 	struct uio *uio;
1005 {
1006 	register struct clist *qp;
1007 	register c, t_flags;
1008 	int s, first, error = 0;
1009 
1010 	if ((tp->t_state&TS_CARR_ON)==0)
1011 		return (EIO);
1012 loop:
1013 	/*
1014 	 * Take any pending input first.
1015 	 */
1016 	s = spl5();
1017 	if (tp->t_flags&PENDIN)
1018 		ttypend(tp);
1019 	splx(s);
1020 
1021 	/*
1022 	 * Hang process if it's in the background.
1023 	 */
1024 	while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
1025 		if (u.u_signal[SIGTTIN] == SIG_IGN ||
1026 		    u.u_signal[SIGTTIN] == SIG_HOLD ||
1027 /*
1028 		    (u.u_procp->p_flag&SDETACH) ||
1029 */
1030 		    u.u_procp->p_flag&SVFORK)
1031 			return (EIO);
1032 		gsignal(u.u_procp->p_pgrp, SIGTTIN);
1033 		sleep((caddr_t)&lbolt, TTIPRI);
1034 	}
1035 	t_flags = tp->t_flags;
1036 
1037 	/*
1038 	 * In raw mode take characters directly from the
1039 	 * raw queue w/o processing.  Interlock against
1040 	 * device interrupts when interrogating rawq.
1041 	 */
1042 	if (t_flags&RAW) {
1043 		s = spl5();
1044 		if (tp->t_rawq.c_cc <= 0) {
1045 			if ((tp->t_state&TS_CARR_ON) == 0 ||
1046 			    (tp->t_state&TS_NBIO)) {
1047 				splx(s);
1048 				return (EWOULDBLOCK);
1049 			}
1050 			sleep((caddr_t)&tp->t_rawq, TTIPRI);
1051 			splx(s);
1052 			goto loop;
1053 		}
1054 		splx(s);
1055  		while (!error && tp->t_rawq.c_cc && uio->uio_resid)
1056  			error = ureadc(getc(&tp->t_rawq), uio);
1057 		goto checktandem;
1058 	}
1059 
1060 	/*
1061 	 * In cbreak mode use the rawq, otherwise
1062 	 * take characters from the canonicalized q.
1063 	 */
1064 	qp = t_flags&CBREAK ? &tp->t_rawq : &tp->t_canq;
1065 
1066 	/*
1067 	 * No input, sleep on rawq awaiting hardware
1068 	 * receipt and notification.
1069 	 */
1070 	s = spl5();
1071 	if (qp->c_cc <= 0) {
1072 		if ((tp->t_state&TS_CARR_ON) == 0 ||
1073 		    (tp->t_state&TS_NBIO)) {
1074 			splx(s);
1075 			return (EWOULDBLOCK);
1076 		}
1077 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
1078 		splx(s);
1079 		goto loop;
1080 	}
1081 	splx(s);
1082 
1083 	/*
1084 	 * Input present, perform input mapping
1085 	 * and processing (we're not in raw mode).
1086 	 */
1087 	first = 1;
1088 	while ((c = getc(qp)) >= 0) {
1089 		if (t_flags&CRMOD && c == '\r')
1090 			c = '\n';
1091 		/*
1092 		 * Hack lower case simulation on
1093 		 * upper case only terminals.
1094 		 */
1095 		if (t_flags&LCASE && c <= 0177)
1096 			if (tp->t_state&TS_BKSL) {
1097 				if (maptab[c])
1098 					c = maptab[c];
1099 				tp->t_state &= ~TS_BKSL;
1100 			} else if (c >= 'A' && c <= 'Z')
1101 				c += 'a' - 'A';
1102 			else if (c == '\\') {
1103 				tp->t_state |= TS_BKSL;
1104 				continue;
1105 			}
1106 		/*
1107 		 * Check for delayed suspend character.
1108 		 */
1109 		if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
1110 			gsignal(tp->t_pgrp, SIGTSTP);
1111 			if (first) {
1112 				sleep((caddr_t)&lbolt, TTIPRI);
1113 				goto loop;
1114 			}
1115 			break;
1116 		}
1117 		/*
1118 		 * Interpret EOF only in cooked mode.
1119 		 */
1120 		if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
1121 			break;
1122 		/*
1123 		 * Give user character.
1124 		 */
1125  		error = ureadc(c & 0177, uio);
1126 		if (error)
1127 			break;
1128  		if (uio->uio_resid == 0)
1129 			break;
1130 		/*
1131 		 * In cooked mode check for a "break character"
1132 		 * marking the end of a "line of input".
1133 		 */
1134 		if ((t_flags&CBREAK) == 0 && ttbreakc(c, tp))
1135 			break;
1136 		first = 0;
1137 	}
1138 	tp->t_state &= ~TS_BKSL;
1139 
1140 checktandem:
1141 	/*
1142 	 * Look to unblock output now that (presumably)
1143 	 * the input queue has gone down.
1144 	 */
1145 	if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5)
1146 		if (putc(tp->t_startc, &tp->t_outq) == 0) {
1147 			tp->t_state &= ~TS_TBLOCK;
1148 			ttstart(tp);
1149 		}
1150 	return (error);
1151 }
1152 
1153 /*
1154  * Called from the device's write routine after it has
1155  * calculated the tty-structure given as argument.
1156  */
1157 ttwrite(tp, uio)
1158 	register struct tty *tp;
1159 	register struct uio *uio;
1160 {
1161 	register char *cp;
1162 	register int cc, ce, c;
1163 	int i, hiwat, cnt, error, s;
1164 	char obuf[OBUFSIZ];
1165 
1166 	if ((tp->t_state&TS_CARR_ON) == 0)
1167 		return (EIO);
1168 	hiwat = TTHIWAT(tp);
1169 	cnt = uio->uio_resid;
1170 	error = 0;
1171 loop:
1172 	/*
1173 	 * Hang the process if it's in the background.
1174 	 */
1175 	while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
1176 	    (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
1177 	    u.u_signal[SIGTTOU] != SIG_IGN &&
1178 	    u.u_signal[SIGTTOU] != SIG_HOLD
1179 /*
1180 					     &&
1181 	    (u.u_procp->p_flag&SDETACH)==0) {
1182 */
1183 	    ) {
1184 		gsignal(u.u_procp->p_pgrp, SIGTTOU);
1185 		sleep((caddr_t)&lbolt, TTIPRI);
1186 	}
1187 
1188 	/*
1189 	 * Process the user's data in at most OBUFSIZ
1190 	 * chunks.  Perform lower case simulation and
1191 	 * similar hacks.  Keep track of high water
1192 	 * mark, sleep on overflow awaiting device aid
1193 	 * in acquiring new space.
1194 	 */
1195 	while (uio->uio_resid > 0) {
1196 		/*
1197 		 * Grab a hunk of data from the user.
1198 		 */
1199 		cc = uio->uio_iov->iov_len;
1200 		if (cc == 0) {
1201 			uio->uio_iovcnt--;
1202 			uio->uio_iov++;
1203 			if (uio->uio_iovcnt < 0)
1204 				panic("ttwrite");
1205 			continue;
1206 		}
1207 		if (cc > OBUFSIZ)
1208 			cc = OBUFSIZ;
1209 		cp = obuf;
1210 		error = uiomove(cp, cc, UIO_WRITE, uio);
1211 		if (error)
1212 			break;
1213 		if (tp->t_outq.c_cc > hiwat)
1214 			goto ovhiwat;
1215 		if (tp->t_flags&FLUSHO)
1216 			continue;
1217 		/*
1218 		 * If we're mapping lower case or kludging tildes,
1219 		 * then we've got to look at each character, so
1220 		 * just feed the stuff to ttyoutput...
1221 		 */
1222 		if (tp->t_flags & (LCASE|TILDE)) {
1223 			while (cc > 0) {
1224 				c = *cp++;
1225 				tp->t_rocount = 0;
1226 				while ((c = ttyoutput(c, tp)) >= 0) {
1227 					/* out of clists, wait a bit */
1228 					ttstart(tp);
1229 					sleep((caddr_t)&lbolt, TTOPRI);
1230 					tp->t_rocount = 0;
1231 				}
1232 				--cc;
1233 				if (tp->t_outq.c_cc > hiwat)
1234 					goto ovhiwat;
1235 			}
1236 			continue;
1237 		}
1238 		/*
1239 		 * If nothing fancy need be done, grab those characters we
1240 		 * can handle without any of ttyoutput's processing and
1241 		 * just transfer them to the output q.  For those chars
1242 		 * which require special processing (as indicated by the
1243 		 * bits in partab), call ttyoutput.  After processing
1244 		 * a hunk of data, look for FLUSHO so ^O's will take effect
1245 		 * immediately.
1246 		 */
1247 		while (cc > 0) {
1248 			if (tp->t_flags & (RAW|LITOUT))
1249 				ce = cc;
1250 			else {
1251 				ce = cc - scanc((unsigned)cc, (caddr_t)cp,
1252 				   (caddr_t)partab, 077);
1253 				/*
1254 				 * If ce is zero, then we're processing
1255 				 * a special character through ttyoutput.
1256 				 */
1257 				if (ce == 0) {
1258 					tp->t_rocount = 0;
1259 					if (ttyoutput(*cp, tp) >= 0) {
1260 						/* no c-lists, wait a bit */
1261 						ttstart(tp);
1262 						sleep((caddr_t)&lbolt, TTOPRI);
1263 						continue;
1264 					}
1265 					cp++, cc--;
1266 					if (tp->t_flags&FLUSHO ||
1267 					    tp->t_outq.c_cc > hiwat)
1268 						goto ovhiwat;
1269 					continue;
1270 				}
1271 			}
1272 			/*
1273 			 * A bunch of normal characters have been found,
1274 			 * transfer them en masse to the output queue and
1275 			 * continue processing at the top of the loop.
1276 			 * If there are any further characters in this
1277 			 * <= OBUFSIZ chunk, the first should be a character
1278 			 * requiring special handling by ttyoutput.
1279 			 */
1280 			tp->t_rocount = 0;
1281 			i = b_to_q(cp, ce, &tp->t_outq);
1282 			ce -= i;
1283 			tp->t_col += ce;
1284 			cp += ce, cc -= ce, tk_nout += ce;
1285 			if (i > 0) {
1286 				/* out of c-lists, wait a bit */
1287 				ttstart(tp);
1288 				sleep((caddr_t)&lbolt, TTOPRI);
1289 			}
1290 			if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat)
1291 				goto ovhiwat;
1292 		}
1293 	}
1294 	ttstart(tp);
1295 	return (error);
1296 
1297 ovhiwat:
1298 	s = spl5();
1299 	if (cc != 0) {
1300 		uio->uio_iov->iov_base -= cc;
1301 		uio->uio_iov->iov_len += cc;
1302 		uio->uio_resid += cc;
1303 		uio->uio_offset -= cc;
1304 	}
1305 	/*
1306 	 * This can only occur if FLUSHO
1307 	 * is also set in t_flags.
1308 	 */
1309 	if (tp->t_outq.c_cc <= hiwat) {
1310 		splx(s);
1311 		goto loop;
1312 	}
1313 	ttstart(tp);
1314 	if (tp->t_state&TS_NBIO) {
1315 		if (uio->uio_resid == cnt)
1316 			return (EWOULDBLOCK);
1317 		return (0);
1318 	}
1319 	tp->t_state |= TS_ASLEEP;
1320 	sleep((caddr_t)&tp->t_outq, TTOPRI);
1321 	splx(s);
1322 	goto loop;
1323 }
1324 
1325 /*
1326  * Rubout one character from the rawq of tp
1327  * as cleanly as possible.
1328  */
1329 ttyrub(c, tp)
1330 	register c;
1331 	register struct tty *tp;
1332 {
1333 	register char *cp;
1334 	register int savecol;
1335 	int s;
1336 	char *nextc();
1337 
1338 	if ((tp->t_flags&ECHO) == 0)
1339 		return;
1340 	tp->t_flags &= ~FLUSHO;
1341 	c &= 0377;
1342 	if (tp->t_flags&CRTBS) {
1343 		if (tp->t_rocount == 0) {
1344 			/*
1345 			 * Screwed by ttwrite; retype
1346 			 */
1347 			ttyretype(tp);
1348 			return;
1349 		}
1350 		if (c == ('\t'|0200) || c == ('\n'|0200))
1351 			ttyrubo(tp, 2);
1352 		else switch (partab[c&=0177]&0177) {
1353 
1354 		case ORDINARY:
1355 			if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1356 				ttyrubo(tp, 2);
1357 			else
1358 				ttyrubo(tp, 1);
1359 			break;
1360 
1361 		case VTAB:
1362 		case BACKSPACE:
1363 		case CONTROL:
1364 		case RETURN:
1365 			if (tp->t_flags&CTLECH)
1366 				ttyrubo(tp, 2);
1367 			break;
1368 
1369 		case TAB:
1370 			if (tp->t_rocount < tp->t_rawq.c_cc) {
1371 				ttyretype(tp);
1372 				return;
1373 			}
1374 			s = spl5();
1375 			savecol = tp->t_col;
1376 			tp->t_state |= TS_CNTTB;
1377 			tp->t_flags |= FLUSHO;
1378 			tp->t_col = tp->t_rocol;
1379 			cp = tp->t_rawq.c_cf;
1380 			for (; cp; cp = nextc(&tp->t_rawq, cp))
1381 				ttyecho(*cp, tp);
1382 			tp->t_flags &= ~FLUSHO;
1383 			tp->t_state &= ~TS_CNTTB;
1384 			splx(s);
1385 			/*
1386 			 * savecol will now be length of the tab
1387 			 */
1388 			savecol -= tp->t_col;
1389 			tp->t_col += savecol;
1390 			if (savecol > 8)
1391 				savecol = 8;		/* overflow screw */
1392 			while (--savecol >= 0)
1393 				(void) ttyoutput('\b', tp);
1394 			break;
1395 
1396 		default:
1397 			panic("ttyrub");
1398 		}
1399 	} else if (tp->t_flags&PRTERA) {
1400 		if ((tp->t_state&TS_ERASE) == 0) {
1401 			(void) ttyoutput('\\', tp);
1402 			tp->t_state |= TS_ERASE;
1403 		}
1404 		ttyecho(c, tp);
1405 	} else
1406 		ttyecho(tp->t_erase, tp);
1407 	tp->t_rocount--;
1408 }
1409 
1410 /*
1411  * Crt back over cnt chars perhaps
1412  * erasing them.
1413  */
1414 ttyrubo(tp, cnt)
1415 	register struct tty *tp;
1416 	int cnt;
1417 {
1418 	register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
1419 
1420 	while (--cnt >= 0)
1421 		ttyout(rubostring, tp);
1422 }
1423 
1424 /*
1425  * Reprint the rawq line.
1426  * We assume c_cc has already been checked.
1427  */
1428 ttyretype(tp)
1429 	register struct tty *tp;
1430 {
1431 	register char *cp;
1432 	char *nextc();
1433 	int s;
1434 
1435 	if (tp->t_rprntc != 0377)
1436 		ttyecho(tp->t_rprntc, tp);
1437 	(void) ttyoutput('\n', tp);
1438 	s = spl5();
1439 	for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1440 		ttyecho(*cp, tp);
1441 	for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1442 		ttyecho(*cp, tp);
1443 	tp->t_state &= ~TS_ERASE;
1444 	splx(s);
1445 	tp->t_rocount = tp->t_rawq.c_cc;
1446 	tp->t_rocol = 0;
1447 }
1448 
1449 /*
1450  * Echo a typed character to the terminal
1451  */
1452 ttyecho(c, tp)
1453 	register c;
1454 	register struct tty *tp;
1455 {
1456 
1457 	if ((tp->t_state&TS_CNTTB) == 0)
1458 		tp->t_flags &= ~FLUSHO;
1459 	if ((tp->t_flags&ECHO) == 0)
1460 		return;
1461 	c &= 0377;
1462 	if (tp->t_flags&RAW) {
1463 		(void) ttyoutput(c, tp);
1464 		return;
1465 	}
1466 	if (c == '\r' && tp->t_flags&CRMOD)
1467 		c = '\n';
1468 	if (tp->t_flags&CTLECH) {
1469 		if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1470 			(void) ttyoutput('^', tp);
1471 			c &= 0177;
1472 			if (c == 0177)
1473 				c = '?';
1474 			else if (tp->t_flags&LCASE)
1475 				c += 'a' - 1;
1476 			else
1477 				c += 'A' - 1;
1478 		}
1479 	}
1480 	if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1481 		c += 'a' - 'A';
1482 	(void) ttyoutput(c&0177, tp);
1483 }
1484 
1485 /*
1486  * Is c a break char for tp?
1487  */
1488 ttbreakc(c, tp)
1489 	register c;
1490 	register struct tty *tp;
1491 {
1492 	return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
1493 		c == '\r' && (tp->t_flags&CRMOD));
1494 }
1495 
1496 /*
1497  * send string cp to tp
1498  */
1499 ttyout(cp, tp)
1500 	register char *cp;
1501 	register struct tty *tp;
1502 {
1503 	register char c;
1504 
1505 	while (c = *cp++)
1506 		(void) ttyoutput(c, tp);
1507 }
1508 
1509 ttwakeup(tp)
1510 	struct tty *tp;
1511 {
1512 
1513 	if (tp->t_rsel) {
1514 		selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1515 		tp->t_state &= ~TS_RCOLL;
1516 		tp->t_rsel = 0;
1517 	}
1518 	if (tp->t_state & TS_ASYNC)
1519 		gsignal(tp->t_pgrp, SIGIO);
1520 	wakeup((caddr_t)&tp->t_rawq);
1521 }
1522 
1523 #if !defined(vax)
1524 scanc(size, cp, table, mask)
1525 	register int size;
1526 	register char *cp, table[];
1527 	register int mask;
1528 {
1529 	register int i = 0;
1530 
1531 	while ((table[*(u_char *)(cp + i)]&mask) == 0 && i < size)
1532 		i++;
1533 	return (i);
1534 }
1535 #endif
1536