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