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