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