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