xref: /csrg-svn/sys/kern/tty.c (revision 7625)
1 /*	tty.c	4.25	82/08/01	*/
2 
3 /*
4  * TTY subroutines common to more than one line discipline
5  */
6 #include "../h/param.h"
7 #include "../h/systm.h"
8 #include "../h/dir.h"
9 #include "../h/user.h"
10 #include "../h/tty.h"
11 #include "../h/proc.h"
12 #include "../h/inode.h"
13 #include "../h/file.h"
14 #include "../h/reg.h"
15 #include "../h/conf.h"
16 #include "../h/buf.h"
17 #include "../h/dk.h"
18 
19 /*
20  * Table giving parity for characters and indicating
21  * character classes to tty driver.  In particular,
22  * if the low 6 bits are 0, then the character needs
23  * no special processing on output.
24  */
25 
26 char partab[] = {
27 	0001,0201,0201,0001,0201,0001,0001,0201,
28 	0202,0004,0003,0201,0005,0206,0201,0001,
29 	0201,0001,0001,0201,0001,0201,0201,0001,
30 	0001,0201,0201,0001,0201,0001,0001,0201,
31 	0200,0000,0000,0200,0000,0200,0200,0000,
32 	0000,0200,0200,0000,0200,0000,0000,0200,
33 	0000,0200,0200,0000,0200,0000,0000,0200,
34 	0200,0000,0000,0200,0000,0200,0200,0000,
35 	0200,0000,0000,0200,0000,0200,0200,0000,
36 	0000,0200,0200,0000,0200,0000,0000,0200,
37 	0000,0200,0200,0000,0200,0000,0000,0200,
38 	0200,0000,0000,0200,0000,0200,0200,0000,
39 	0000,0200,0200,0000,0200,0000,0000,0200,
40 	0200,0000,0000,0200,0000,0200,0200,0000,
41 	0200,0000,0000,0200,0000,0200,0200,0000,
42 	0000,0200,0200,0000,0200,0000,0000,0201,
43 
44 	/*
45 	 * 7 bit ascii ends with the last character above,
46 	 * but we contine through all 256 codes for the sake
47 	 * of the tty output routines which use special vax
48 	 * instructions which need a 256 character trt table.
49 	 */
50 
51 	0007,0007,0007,0007,0007,0007,0007,0007,
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 };
68 
69 /*
70  * Input mapping table-- if an entry is non-zero, when the
71  * corresponding character is typed preceded by "\" the escape
72  * sequence is replaced by the table value.  Mostly used for
73  * upper-case only terminals.
74  */
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,650,650 };
97 short	ttlowat[16] =
98    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99 
100 #define	OBUFSIZ	100
101 
102 /*
103  * set default control characters.
104  */
105 ttychars(tp)
106 	register struct tty *tp;
107 {
108 
109 	tun.t_intrc = CINTR;
110 	tun.t_quitc = CQUIT;
111 	tun.t_startc = CSTART;
112 	tun.t_stopc = CSTOP;
113 	tun.t_eofc = CEOT;
114 	tun.t_brkc = CBRK;
115 	tp->t_erase = CERASE;
116 	tp->t_kill = CKILL;
117 /* begin local */
118 	tlun.t_suspc = CTRL(z);
119 	tlun.t_dsuspc = CTRL(y);
120 	tlun.t_rprntc = CTRL(r);
121 	tlun.t_flushc = CTRL(o);
122 	tlun.t_werasc = CTRL(w);
123 	tlun.t_lnextc = CTRL(v);
124 	tp->t_local = 0;
125 	tp->t_lstate = 0;
126 /* end local */
127 }
128 
129 /*
130  * Wait for output to drain, then flush input waiting.
131  */
132 wflushtty(tp)
133 	register struct tty *tp;
134 {
135 
136 	(void) spl5();
137 	while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
138 	    && tp->t_oproc) {		/* kludge for pty */
139 		(*tp->t_oproc)(tp);
140 		tp->t_state |= TS_ASLEEP;
141 		sleep((caddr_t)&tp->t_outq, TTOPRI);
142 	}
143 	flushtty(tp, FREAD);
144 	(void) spl0();
145 }
146 
147 /*
148  * flush all TTY queues
149  */
150 flushtty(tp, rw)
151 	register struct tty *tp;
152 {
153 	register s;
154 
155 	s = spl6();
156 	if (rw & FREAD) {
157 		while (getc(&tp->t_canq) >= 0)
158 			;
159 		wakeup((caddr_t)&tp->t_rawq);
160 	}
161 	if (rw & FWRITE) {
162 		wakeup((caddr_t)&tp->t_outq);
163 		tp->t_state &= ~TS_TTSTOP;
164 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
165 		while (getc(&tp->t_outq) >= 0)
166 			;
167 	}
168 	if (rw & FREAD) {
169 		while (getc(&tp->t_rawq) >= 0)
170 			;
171 		tp->t_delct = 0;
172 		tp->t_rocount = 0;		/* local */
173 		tp->t_rocol = 0;
174 		tp->t_lstate = 0;
175 	}
176 	splx(s);
177 }
178 
179 /*
180  * Send stop character on input overflow.
181  */
182 ttyblock(tp)
183 	register struct tty *tp;
184 {
185 	register x;
186 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
187 	if (tp->t_rawq.c_cc > TTYHOG) {
188 		flushtty(tp, FREAD|FWRITE);
189 		tp->t_state &= ~TS_TBLOCK;
190 	}
191 	if (x >= TTYHOG/2) {
192 		if (putc(tun.t_stopc, &tp->t_outq)==0) {
193 			tp->t_state |= TS_TBLOCK;
194 			tp->t_char++;
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 		printf("ttrstrt: arg was 0!\n");
212 		return;
213 	}
214 	tp->t_state &= ~TS_TIMEOUT;
215 	ttstart(tp);
216 }
217 
218 /*
219  * Start output on the typewriter. It is used from the top half
220  * after some characters have been put on the output queue,
221  * from the interrupt routine to transmit the next
222  * character, and after a timeout has finished.
223  */
224 ttstart(tp)
225 	register struct tty *tp;
226 {
227 	register s;
228 
229 	s = spl5();
230 	if ((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
231 	    tp->t_oproc)		/* kludge for pty */
232 		(*tp->t_oproc)(tp);
233 	splx(s);
234 }
235 
236 /*
237  * Common code for tty ioctls.
238  */
239 /*ARGSUSED*/
240 ttioctl(tp, com, data, flag)
241 	register struct tty *tp;
242 	caddr_t data;
243 {
244 	int dev;
245 	extern int nldisp;
246 
247 	/*
248 	 * This is especially so that isatty() will
249 	 * fail when carrier is gone.
250 	 */
251 	if ((tp->t_state&TS_CARR_ON) == 0) {
252 		u.u_error = EBADF;
253 		return (1);
254 	}
255 
256 	dev = tp->t_dev;
257 	/*
258 	 * If the ioctl involves modification,
259 	 * insist on being able to write the device,
260 	 * and hang if in the background.
261 	 */
262 	switch (com) {
263 
264 	case TIOCSETD:
265 	case TIOCSETP:
266 	case TIOCSETN:
267 	case TIOCFLUSH:
268 	case TIOCSETC:
269 	case TIOCSLTC:
270 	case TIOCSPGRP:
271 	case TIOCLBIS:
272 	case TIOCLBIC:
273 	case TIOCLSET:
274 /* this is reasonable, but impractical...
275 		if ((flag & FWRITE) == 0) {
276 			u.u_error = EBADF;
277 			return (1);
278 		}
279  */
280 		while (tp->t_line == NTTYDISC &&
281 		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
282 		   (u.u_procp->p_flag&SVFORK) == 0 &&
283 		   u.u_signal[SIGTTOU] != SIG_IGN &&
284 		   u.u_signal[SIGTTOU] != SIG_HOLD
285 /*
286 						   &&
287 		   (u.u_procp->p_flag&SDETACH)==0) {
288 */
289 		   ) {
290 			gsignal(u.u_procp->p_pgrp, SIGTTOU);
291 			sleep((caddr_t)&lbolt, TTOPRI);
292 		}
293 		break;
294 	}
295 
296 	/*
297 	 * Process the ioctl.
298 	 */
299 	switch (com) {
300 
301 	/*
302 	 * Get discipline number
303 	 */
304 	case TIOCGETD:
305 		*(int *)data = tp->t_line;
306 		break;
307 
308 	/*
309 	 * Set line discipline
310 	 */
311 	case TIOCSETD: {
312 		register int t = *(int *)data;
313 
314 		if (t >= nldisp) {
315 			u.u_error = ENXIO;
316 			break;
317 		}
318 		(void) spl5();
319 		if (tp->t_line)
320 			(*linesw[tp->t_line].l_close)(tp);
321 		if (t)
322 			(*linesw[t].l_open)(dev, tp);
323 		if (u.u_error==0)
324 			tp->t_line = t;
325 		(void) spl0();
326 		break;
327 	}
328 
329 	/*
330 	 * Prevent more opens on channel
331 	 */
332 	case TIOCEXCL:
333 		tp->t_state |= TS_XCLUDE;
334 		break;
335 
336 	case TIOCNXCL:
337 		tp->t_state &= ~TS_XCLUDE;
338 		break;
339 
340 	/*
341 	 * Set new parameters
342 	 */
343 	case TIOCSETP:
344 	case TIOCSETN: {
345 		register struct sgttyb *sg = (struct sgttyb *)data;
346 		struct clist tq;
347 
348 		(void) spl5();
349 		if (tp->t_flags&RAW || sg->sg_flags&RAW || com == TIOCSETP)
350 			wflushtty(tp);
351 		else if ((tp->t_flags&CBREAK) != (sg->sg_flags&CBREAK)) {
352 			if (sg->sg_flags & CBREAK) {
353 				catq(&tp->t_rawq, &tp->t_canq);
354 				tq = tp->t_rawq;
355 				tp->t_rawq = tp->t_canq;
356 				tp->t_canq = tq;
357 			} else {
358 				tp->t_local |= LPENDIN;
359 				ttwakeup(tp);
360 			}
361 		}
362 		tp->t_ispeed = sg->sg_ispeed;
363 		tp->t_ospeed = sg->sg_ospeed;
364 		tp->t_erase = sg->sg_erase;
365 		tp->t_kill = sg->sg_kill;
366 		tp->t_flags = sg->sg_flags;
367 		if (tp->t_flags & RAW) {
368 			tp->t_state &= ~TS_TTSTOP;
369 			ttstart(tp);
370 		}
371 		(void) spl0();
372 		break;
373 	}
374 
375 	/*
376 	 * Send current parameters to user
377 	 */
378 	case TIOCGETP: {
379 		register struct sgttyb *sg = (struct sgttyb *)data;
380 
381 		sg->sg_ispeed = tp->t_ispeed;
382 		sg->sg_ospeed = tp->t_ospeed;
383 		sg->sg_erase = tp->t_erase;
384 		sg->sg_kill = tp->t_kill;
385 		sg->sg_flags = tp->t_flags;
386 		break;
387 	}
388 
389 	/*
390 	 * Hang up line on last close
391 	 */
392 	case TIOCHPCL:
393 		tp->t_state |= TS_HUPCLS;
394 		break;
395 
396 	case TIOCFLUSH: {
397 		register int flags = *(int *)data;
398 
399 		if (flags == 0)
400 			flags = FREAD|FWRITE;
401 		else
402 			flags &= FREAD|FWRITE;
403 		flushtty(tp, flags);
404 		break;
405 	}
406 
407 	case FIONBIO:
408 		if (*(int *)data)
409 			tp->t_state |= TS_NBIO;
410 		else
411 			tp->t_state &= ~TS_NBIO;
412 		break;
413 
414 	case FIOASYNC:
415 		if (*(int *)data)
416 			tp->t_state |= TS_ASYNC;
417 		else
418 			tp->t_state &= ~TS_ASYNC;
419 		break;
420 
421 	/*
422 	 * Set and fetch special characters
423 	 */
424 	case TIOCSETC:
425 		bcopy(data, (caddr_t)&tun, sizeof (struct tchars));
426 		break;
427 
428 	case TIOCGETC:
429 		bcopy((caddr_t)&tun, data, sizeof (struct tchars));
430 		break;
431 
432 /* local ioctls */
433 	/*
434 	 * Set/get local special characters.
435 	 */
436 	case TIOCSLTC:
437 		bcopy(data, (caddr_t)&tlun, sizeof (struct ltchars));
438 		break;
439 
440 	case TIOCGLTC:
441 		bcopy((caddr_t)&tlun, data, sizeof (struct ltchars));
442 		break;
443 
444 	/*
445 	 * Return number of characters immediately available.
446 	 */
447 	case FIONREAD:
448 		*(off_t *)data = ttnread(tp);
449 		break;
450 
451 	/*
452 	 * Should allow SPGRP and GPGRP only if tty open for reading.
453 	 */
454 	case TIOCSPGRP:
455 		tp->t_pgrp = *(int *)data;
456 		break;
457 
458 	case TIOCGPGRP:
459 		*(int *)data = tp->t_pgrp;
460 		break;
461 
462 	/*
463 	 * Modify local mode word.
464 	 */
465 	case TIOCLBIS:
466 		tp->t_local |= *(int *)data;
467 		break;
468 
469 	case TIOCLBIC:
470 		tp->t_local &= ~(*(int *)data);
471 		break;
472 
473 	case TIOCLSET:
474 		tp->t_local = *(int *)data;
475 		break;
476 
477 	case TIOCLGET:
478 		*(int *)data = tp->t_local;
479 		break;
480 
481 	case TIOCSTOP: {
482 		int s = spl5();
483 
484 		if ((tp->t_state & TS_TTSTOP) == 0) {
485 			tp->t_state |= TS_TTSTOP;
486 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
487 		}
488 		splx(s);
489 		break;
490 	}
491 
492 	case TIOCSTART: {
493 		int s = spl5();
494 
495 		if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
496 			tp->t_state &= ~TS_TTSTOP;
497 			tp->t_local &= ~LFLUSHO;
498 			ttstart(tp);
499 		}
500 		splx(s);
501 		break;
502 	}
503 
504 /* end of locals */
505 
506 	default:
507 		return (0);
508 	}
509 	return (1);
510 }
511 
512 ttnread(tp)
513 	struct tty *tp;
514 {
515 	int nread = 0;
516 
517 	if (tp->t_local & LPENDIN)
518 		ttypend(tp);
519 	nread = tp->t_canq.c_cc;
520 	if (tp->t_flags & (RAW|CBREAK))
521 		nread += tp->t_rawq.c_cc;
522 	return (nread);
523 }
524 
525 ttselect(dev, rw)
526 	dev_t dev;
527 	int rw;
528 {
529 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
530 	int nread;
531 	int s = spl5();
532 
533 	switch (rw) {
534 
535 	case FREAD:
536 		nread = ttnread(tp);
537 		if (nread > 0)
538 			goto win;
539 		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
540 			tp->t_state |= TS_RCOLL;
541 		else
542 			tp->t_rsel = u.u_procp;
543 		break;
544 
545 	case FWRITE:
546 		if (tp->t_outq.c_cc <= TTLOWAT(tp))
547 			goto win;
548 		if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
549 			tp->t_state |= TS_WCOLL;
550 		else
551 			tp->t_wsel = u.u_procp;
552 		break;
553 	}
554 	splx(s);
555 	return (0);
556 win:
557 	splx(s);
558 	return (1);
559 }
560 
561 #define	OBUFSIZ	100
562 
563 /*
564  * routine called on opens while tp->t_line == NTTYDISC
565  * establishes a process group for distribution of
566  * quits and interrupts from the tty.
567  * (actually, pp->p_pgrp can't be 0 when this routine
568  * is called since NTTYDISC is not the default discipline)
569  */
570 ttyopen(dev, tp)
571 	dev_t dev;
572 	register struct tty *tp;
573 {
574 	register struct proc *pp;
575 
576 	pp = u.u_procp;
577 	tp->t_dev = dev;
578 	if (pp->p_pgrp == 0) {
579 		u.u_ttyp = tp;
580 		u.u_ttyd = dev;
581 		if (tp->t_pgrp == 0)
582 			tp->t_pgrp = pp->p_pid;
583 		pp->p_pgrp = tp->t_pgrp;
584 	}
585 	tp->t_state &= ~TS_WOPEN;
586 	tp->t_state |= TS_ISOPEN;
587 	if (tp->t_line != NTTYDISC)
588 		wflushtty(tp);
589 }
590 
591 /*
592  * clean tp on last close
593  */
594 ttyclose(tp)
595 	register struct tty *tp;
596 {
597 
598 	if (tp->t_line) {
599 		wflushtty(tp);
600 		tp->t_line = 0;
601 		return;
602 	}
603 	tp->t_pgrp = 0;
604 	wflushtty(tp);
605 	tp->t_state = 0;
606 }
607 
608 /*
609  * reinput pending characters after state switch
610  * call at spl5().
611  */
612 ttypend(tp)
613 	register struct tty *tp;
614 {
615 	struct clist tq;
616 	register c;
617 
618 	tp->t_local &= ~LPENDIN;
619 	tp->t_lstate |= LSTYPEN;
620 	tq = tp->t_rawq;
621 	tp->t_rawq.c_cc = 0;
622 	tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
623 	while ((c = getc(&tq)) >= 0)
624 		ttyinput(c, tp);
625 	tp->t_lstate &= ~LSTYPEN;
626 }
627 
628 /*
629  * Place a character on raw TTY input queue, putting in delimiters
630  * and waking up top half as needed.
631  * Also echo if required.
632  * The arguments are the character and the appropriate
633  * tty structure.
634  */
635 ttyinput(c, tp)
636 	register c;
637 	register struct tty *tp;
638 {
639 	register int t_flags;
640 	int i;
641 
642 	if (tp->t_local&LPENDIN)
643 		ttypend(tp);
644 	tk_nin++;
645 	c &= 0377;
646 	t_flags = tp->t_flags;
647 	if (t_flags&TANDEM)
648 		ttyblock(tp);
649 	if ((t_flags&RAW)==0) {
650 		if ((tp->t_lstate&LSTYPEN) == 0)
651 			c &= 0177;
652 	/* check for literal nexting very first */
653 		if (tp->t_lstate&LSLNCH) {
654 			c |= 0200;
655 			tp->t_lstate &= ~LSLNCH;
656 		}
657 		if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) {
658 			if (tp->t_flags&ECHO)
659 				ttyout("^\b", tp);
660 			tp->t_lstate |= LSLNCH;
661 	/* check for output control functions */
662 		} else if (c==tun.t_stopc) {
663 			if ((tp->t_state&TS_TTSTOP)==0) {
664 				tp->t_state |= TS_TTSTOP;
665 				(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
666 				return;
667 			}
668 			if (c!=tun.t_startc)
669 				return;
670 		} else if (c==tun.t_startc) {
671 			tp->t_state &= ~TS_TTSTOP;
672 			tp->t_local &= ~LFLUSHO;
673 			ttstart(tp);
674 			return;
675 		} else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) {
676 			if (tp->t_local & LFLUSHO)
677 				tp->t_local &= ~LFLUSHO;
678 			else {
679 				flushtty(tp, FWRITE);
680 				ttyecho(c, tp);
681 				if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
682 					ttyretype(tp);
683 				tp->t_local |= LFLUSHO;
684 			}
685 			ttstart(tp);
686 			return;
687 		} else if (c==tun.t_intrc || c==tun.t_quitc ||
688 		    (tp->t_line == NTTYDISC && c==tlun.t_suspc)) {
689 			if ((tp->t_local & LNOFLSH) == 0)
690 				flushtty(tp,
691 				    c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
692 			ttyecho(c, tp);
693 			c = c==tun.t_intrc ? SIGINT :
694 				((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
695 			ttsignal(tp, c);
696 	/* check for buffer editing functions - cooked mode */
697 		} else if ((t_flags&CBREAK) == 0) {
698 			if ((tp->t_lstate&LSQUOT) &&
699 			    (c==tp->t_erase||c==tp->t_kill)) {
700 				ttyrub(unputc(&tp->t_rawq), tp);
701 				c |= 0200;
702 			}
703 			if (c==tp->t_erase) {
704 				if (tp->t_rawq.c_cc)
705 					ttyrub(unputc(&tp->t_rawq), tp);
706 			} else if (c==tp->t_kill) {
707 				if (tp->t_local&LCRTKIL &&
708 				    tp->t_rawq.c_cc == tp->t_rocount) {
709 					while (tp->t_rawq.c_cc)
710 						ttyrub(unputc(&tp->t_rawq), tp);
711 				} else {
712 					ttyecho(c, tp);
713 					ttyecho('\n', tp);
714 					while (getc(&tp->t_rawq) > 0)
715 						;
716 					tp->t_rocount = 0;
717 				}
718 				tp->t_lstate = 0;
719 			} else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) {
720 				if (tp->t_rawq.c_cc == 0)
721 					goto out;
722 				do {
723 					c = unputc(&tp->t_rawq);
724 					if (c != ' ' && c != '\t')
725 						goto erasenb;
726 					ttyrub(c, tp);
727 				} while (tp->t_rawq.c_cc);
728 				goto out;
729 			    erasenb:
730 				do {
731 					ttyrub(c, tp);
732 					if (tp->t_rawq.c_cc == 0)
733 						goto out;
734 					c = unputc(&tp->t_rawq);
735 				} while (c != ' ' && c != '\t');
736 				(void) putc(c, &tp->t_rawq);
737 			} else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) {
738 				ttyretype(tp);
739 	/* check for cooked mode input buffer overflow */
740 			} else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
741 				;
742 	/* put data char in q for user and wakeup if a break char */
743 			} else if (putc(c, &tp->t_rawq) >= 0) {
744 				if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG
745 				    && tp->t_line == NTTYDISC)
746 					(void) ttyoutput(CTRL(g), tp);
747 				if (!ttbreakc(c, tp)) {
748 					if (tp->t_rocount++ == 0)
749 						tp->t_rocol = tp->t_col;
750 				} else {
751 					tp->t_rocount = 0;
752 					catq(&tp->t_rawq, &tp->t_canq);
753 					/* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */
754 					ttwakeup(tp);
755 				}
756 				tp->t_lstate &= ~LSQUOT;
757 				if (c == '\\')
758 					tp->t_lstate |= LSQUOT;
759 				if (tp->t_lstate&LSERASE) {
760 					tp->t_lstate &= ~LSERASE;
761 					(void) ttyoutput('/', tp);
762 				}
763 				i = tp->t_col;
764 				ttyecho(c, tp);
765 				if (c==tun.t_eofc && tp->t_flags&ECHO) {
766 					i = MIN(2, tp->t_col - i);
767 					while (i > 0) {
768 						(void) ttyoutput('\b', tp);
769 						i--;
770 					}
771 				}
772 			}
773 	/* CBREAK mode */
774 		} else if (tp->t_rawq.c_cc > TTYHOG) {
775 			if (tp->t_outq.c_cc < TTHIWAT(tp) &&
776 			    tp->t_line == NTTYDISC)
777 				(void) ttyoutput(CTRL(g), tp);
778 		} else if (putc(c, &tp->t_rawq) >= 0) {
779 			ttwakeup(tp);
780 			ttyecho(c, tp);
781 		}
782 	/* RAW mode */
783 	} else if (tp->t_rawq.c_cc > TTYHOG)
784 		flushtty(tp, FREAD|FWRITE);
785 	else {
786 		if (putc(c, &tp->t_rawq) >= 0)
787 			ttwakeup(tp);
788 		ttyecho(c, tp);
789 	}
790 out:
791 	if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP &&
792 	    tun.t_startc != tun.t_stopc)
793 		return;
794 	tp->t_state &= ~TS_TTSTOP;
795 	tp->t_local &= ~LFLUSHO;
796 	ttstart(tp);
797 }
798 
799 /*
800  * put character on TTY output queue, adding delays,
801  * expanding tabs, and handling the CR/NL bit.
802  * It is called both from the top half for output, and from
803  * interrupt level for echoing.
804  * The arguments are the character and the tty structure.
805  * Returns < 0 if putc succeeds, otherwise returns char to resend
806  * Must be recursive.
807  */
808 ttyoutput(c, tp)
809 	register c;
810 	register struct tty *tp;
811 {
812 	register char *colp;
813 	register ctype;
814 
815 	if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
816 		if (tp->t_local&LFLUSHO)
817 			return (-1);
818 		if (putc(c, &tp->t_outq))
819 			return (c);
820 		tk_nout++;
821 		return (-1);
822 	}
823 	/*
824 	 * Ignore EOT in normal mode to avoid hanging up
825 	 * certain terminals.
826 	 */
827 	c &= 0177;
828 	if (c==CEOT && (tp->t_flags&CBREAK)==0)
829 		return (-1);
830 	/*
831 	 * Turn tabs to spaces as required
832 	 */
833 	if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
834 		register int s;
835 
836 		c = 8 - (tp->t_col&7);
837 		if ((tp->t_local&LFLUSHO) == 0) {
838 			s = spl5();		/* don't interrupt tabs */
839 			c -= b_to_q("        ", c, &tp->t_outq);
840 			tk_nout += c;
841 			splx(s);
842 		}
843 		tp->t_col += c;
844 		return (c ? -1 : '\t');
845 	}
846 	tk_nout++;
847 	/*
848 	 * for upper-case-only terminals,
849 	 * generate escapes.
850 	 */
851 	if (tp->t_flags&LCASE) {
852 		colp = "({)}!|^~'`";
853 		while (*colp++)
854 			if (c == *colp++) {
855 				if (ttyoutput('\\', tp) >= 0)
856 					return (c);
857 				c = colp[-2];
858 				break;
859 			}
860 		if ('A'<=c && c<='Z') {
861 			if (ttyoutput('\\', tp) >= 0)
862 				return (c);
863 		} else if ('a'<=c && c<='z')
864 			c += 'A' - 'a';
865 	}
866 	/*
867 	 * turn <nl> to <cr><lf> if desired.
868 	 */
869 	if (c=='\n' && tp->t_flags&CRMOD)
870 		if (ttyoutput('\r', tp) >= 0)
871 			return (c);
872 	if (c=='~' && tp->t_local&LTILDE)
873 		c = '`';
874 	if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
875 		return (c);
876 	/*
877 	 * Calculate delays.
878 	 * The numbers here represent clock ticks
879 	 * and are not necessarily optimal for all terminals.
880 	 * The delays are indicated by characters above 0200.
881 	 * In raw mode there are no delays and the
882 	 * transmission path is 8 bits wide.
883 	 */
884 	colp = &tp->t_col;
885 	ctype = partab[c];
886 	c = 0;
887 	switch (ctype&077) {
888 
889 	case ORDINARY:
890 		(*colp)++;
891 
892 	case CONTROL:
893 		break;
894 
895 	case BACKSPACE:
896 		if (*colp)
897 			(*colp)--;
898 		break;
899 
900 	case NEWLINE:
901 		ctype = (tp->t_flags >> 8) & 03;
902 		if (ctype == 1) { /* tty 37 */
903 			if (*colp)
904 				c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
905 		} else
906 		if (ctype == 2) { /* vt05 */
907 			c = 6;
908 		}
909 		*colp = 0;
910 		break;
911 
912 	case TAB:
913 		ctype = (tp->t_flags >> 10) & 03;
914 		if (ctype == 1) { /* tty 37 */
915 			c = 1 - (*colp | ~07);
916 			if (c < 5)
917 				c = 0;
918 		}
919 		*colp |= 07;
920 		(*colp)++;
921 		break;
922 
923 	case VTAB:
924 		if (tp->t_flags & VTDELAY) /* tty 37 */
925 			c = 0177;
926 		break;
927 
928 	case RETURN:
929 		ctype = (tp->t_flags >> 12) & 03;
930 		if (ctype == 1) { /* tn 300 */
931 			c = 5;
932 		} else if (ctype == 2) { /* ti 700 */
933 			c = 10;
934 		} else if (ctype == 3) { /* concept 100 */
935 			int i;
936 			if ((i = *colp) >= 0)
937 				for (; i<9; i++)
938 					(void) putc(0177, &tp->t_outq);
939 		}
940 		*colp = 0;
941 	}
942 	if (c && (tp->t_local&LFLUSHO) == 0)
943 		(void) putc(c|0200, &tp->t_outq);
944 	return (-1);
945 }
946 
947 /*
948  * Called from device's read routine after it has
949  * calculated the tty-structure given as argument.
950  */
951 ttread(tp)
952 	register struct tty *tp;
953 {
954 	register struct clist *qp;
955 	register c, first;
956 
957 	if ((tp->t_state&TS_CARR_ON)==0)
958 		return (0);
959 loop:
960 	(void) spl5();
961 	if (tp->t_local&LPENDIN)
962 		ttypend(tp);
963 	(void) spl0();
964 	while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
965 		if (u.u_signal[SIGTTIN] == SIG_IGN ||
966 		    u.u_signal[SIGTTIN] == SIG_HOLD ||
967 /*
968 		    (u.u_procp->p_flag&SDETACH) ||
969 */
970 		    u.u_procp->p_flag&SVFORK)
971 			return (0);
972 		gsignal(u.u_procp->p_pgrp, SIGTTIN);
973 		sleep((caddr_t)&lbolt, TTIPRI);
974 	}
975 	if (tp->t_flags&RAW) {
976 		(void) spl5();
977 		if (tp->t_rawq.c_cc <= 0) {
978 			if ((tp->t_state&TS_CARR_ON)==0 ||
979 			    (tp->t_state&TS_NBIO)) {
980 				(void) spl0();
981 				return (0);
982 			}
983 			sleep((caddr_t)&tp->t_rawq, TTIPRI);
984 			(void) spl0();
985 			goto loop;
986 		}
987 		(void) spl0();
988 		while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0)
989 			;
990 		return (0);
991 	} else {
992 		qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
993 		(void) spl5();
994 		if (qp->c_cc <= 0) {
995 			if ((tp->t_state&TS_CARR_ON)==0 ||
996 			    (tp->t_state&TS_NBIO)) {
997 				(void) spl0();
998 				return (0);
999 			}
1000 			sleep((caddr_t)&tp->t_rawq, TTIPRI);
1001 			(void) spl0();
1002 			goto loop;
1003 		}
1004 		(void) spl0();
1005 		first = 1;
1006 		while ((c = getc(qp)) >= 0) {
1007 			if (tp->t_flags&CRMOD && c == '\r')
1008 				c = '\n';
1009 			if (tp->t_flags&LCASE && c <= 0177)
1010 				if (tp->t_lstate&LSBKSL) {
1011 					if (maptab[c])
1012 						c = maptab[c];
1013 					tp->t_lstate &= ~LSBKSL;
1014 				} else if (c >= 'A' && c <= 'Z')
1015 					c += 'a' - 'A';
1016 				else if (c == '\\') {
1017 					tp->t_lstate |= LSBKSL;
1018 					continue;
1019 				}
1020 			if (c == tlun.t_dsuspc) {
1021 				ttsignal(tp, SIGTSTP);
1022 				if (first) {
1023 					sleep((caddr_t)&lbolt, TTIPRI);
1024 					goto loop;
1025 				}
1026 				break;
1027 			}
1028 			if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
1029 				break;
1030 			if (passc(c & 0177) < 0)
1031 				break;
1032 			if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp))
1033 				break;
1034 			first = 0;
1035 		}
1036 		tp->t_lstate &= ~LSBKSL;
1037 	}
1038 
1039 	if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
1040 		if (putc(tun.t_startc, &tp->t_outq)==0) {
1041 			tp->t_state &= ~TS_TBLOCK;
1042 			ttstart(tp);
1043 		}
1044 		tp->t_char = 0;
1045 	}
1046 
1047 	return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
1048 }
1049 
1050 /*
1051  * Called from the device's write routine after it has
1052  * calculated the tty-structure given as argument.
1053  */
1054 caddr_t
1055 ttwrite(tp)
1056 	register struct tty *tp;
1057 {
1058 #ifdef vax
1059 	/*
1060 	 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
1061 	 * AND MUST NOT BE CHANGED WITHOUT PATCHING
1062 	 * THE 'ASM' INLINES BELOW.  WATCH OUT.
1063 	 */
1064 #endif
1065 	register char *cp;
1066 	register int cc, ce;
1067 	register i;
1068 	char obuf[OBUFSIZ];
1069 	register c;
1070 	int hiwat = TTHIWAT(tp);
1071 	int cnt = u.u_count;
1072 
1073 	if ((tp->t_state&TS_CARR_ON)==0)
1074 		return (NULL);
1075 loop:
1076 	while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
1077 	    (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
1078 	    u.u_signal[SIGTTOU] != SIG_IGN &&
1079 	    u.u_signal[SIGTTOU] != SIG_HOLD
1080 /*
1081 					     &&
1082 	    (u.u_procp->p_flag&SDETACH)==0) {
1083 */
1084 	    ) {
1085 		gsignal(u.u_procp->p_pgrp, SIGTTOU);
1086 		sleep((caddr_t)&lbolt, TTIPRI);
1087 	}
1088 	while (u.u_count) {
1089 		cc = MIN(u.u_count, OBUFSIZ);
1090 		cp = obuf;
1091 		iomove(cp, (unsigned)cc, B_WRITE);
1092 		if (u.u_error)
1093 			break;
1094 		if (tp->t_outq.c_cc > hiwat)
1095 			goto ovhiwat;
1096 		if (tp->t_local&LFLUSHO)
1097 			continue;
1098 		if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
1099 			while (cc) {
1100 				c = *cp++;
1101 				tp->t_rocount = 0;
1102 				while ((c = ttyoutput(c, tp)) >= 0) {
1103 					/* out of clists, wait a bit */
1104 					ttstart(tp);
1105 					sleep((caddr_t)&lbolt, TTOPRI);
1106 					tp->t_rocount = 0;
1107 				}
1108 				--cc;
1109 				if (tp->t_outq.c_cc > hiwat)
1110 					goto ovhiwat;
1111 			}
1112 			continue;
1113 		}
1114 		while (cc) {
1115 			if (tp->t_flags&RAW || tp->t_local&LLITOUT)
1116 				ce = cc;
1117 			else {
1118 #ifdef vax
1119 				asm("	scanc	r9,(r10),_partab,$077");
1120 				asm("	subl3	r0,r9,r8");
1121 #else
1122 				ce=0;
1123 				while (((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
1124 					ce++;
1125 #endif
1126 				if (ce==0) {
1127 					tp->t_rocount = 0;
1128 					if (ttyoutput(*cp, tp) >= 0) {
1129 						ttstart(tp);
1130 						sleep((caddr_t)&lbolt, TTOPRI);
1131 						continue;
1132 					}
1133 					cp++;
1134 					cc--;
1135 					if (tp->t_outq.c_cc > hiwat)
1136 						goto ovhiwat;
1137 				}
1138 			}
1139 			tp->t_rocount = 0;
1140 			i=b_to_q(cp,ce,&tp->t_outq);
1141 			ce-=i;
1142 			tk_nout+=ce;
1143 			tp->t_col+=ce;
1144 			cp+=ce;
1145 			cc-=ce;
1146 			if (i) {
1147 				ttstart(tp);
1148 				sleep((caddr_t)&lbolt, TTOPRI);
1149 			}
1150 			if (ce || tp->t_outq.c_cc > hiwat)
1151 				goto ovhiwat;
1152 		}
1153 	}
1154 	ttstart(tp);
1155 	return (NULL);
1156 
1157 ovhiwat:
1158 	(void) spl5();
1159 	u.u_base -= cc;
1160 	u.u_offset -= cc;
1161 	u.u_count += cc;
1162 	if (tp->t_outq.c_cc <= hiwat) {
1163 		(void) spl0();
1164 		goto loop;
1165 	}
1166 	ttstart(tp);
1167 	if (tp->t_state & TS_NBIO) {
1168 		if (u.u_count == cnt)
1169 			u.u_error = EWOULDBLOCK;
1170 		return (NULL);
1171 	}
1172 	tp->t_state |= TS_ASLEEP;
1173 	sleep((caddr_t)&tp->t_outq, TTOPRI);
1174 	(void) spl0();
1175 	goto loop;
1176 }
1177 
1178 /*
1179  * Rubout one character from the rawq of tp
1180  * as cleanly as possible.
1181  */
1182 ttyrub(c, tp)
1183 	register c;
1184 	register struct tty *tp;
1185 {
1186 	register char *cp;
1187 	register int savecol;
1188 	int s;
1189 	char *nextc();
1190 
1191 	if ((tp->t_flags&ECHO)==0)
1192 		return;
1193 	tp->t_local &= ~LFLUSHO;
1194 	c &= 0377;
1195 	if (tp->t_local&LCRTBS) {
1196 		if (tp->t_rocount == 0) {
1197 			/*
1198 			 * Screwed by ttwrite; retype
1199 			 */
1200 			ttyretype(tp);
1201 			return;
1202 		}
1203 		if (c==('\t'|0200) || c==('\n'|0200))
1204 			ttyrubo(tp, 2);
1205 		else switch (partab[c&=0177] & 0177) {
1206 
1207 		case ORDINARY:
1208 			if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
1209 				ttyrubo(tp, 2);
1210 			else
1211 				ttyrubo(tp, 1);
1212 			break;
1213 
1214 		case VTAB:
1215 		case BACKSPACE:
1216 		case CONTROL:
1217 		case RETURN:
1218 			if (tp->t_local & LCTLECH)
1219 				ttyrubo(tp, 2);
1220 			break;
1221 
1222 		case TAB:
1223 			if (tp->t_rocount < tp->t_rawq.c_cc) {
1224 				ttyretype(tp);
1225 				return;
1226 			}
1227 			s = spl5();
1228 			savecol = tp->t_col;
1229 			tp->t_lstate |= LSCNTTB;
1230 			tp->t_local |= LFLUSHO;
1231 			tp->t_col = tp->t_rocol;
1232 			for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1233 				ttyecho(*cp, tp);
1234 			tp->t_local &= ~LFLUSHO;
1235 			tp->t_lstate &= ~LSCNTTB;
1236 			splx(s);
1237 			/*
1238 			 * savecol will now be length of the tab
1239 			 */
1240 			savecol -= tp->t_col;
1241 			tp->t_col += savecol;
1242 			if (savecol > 8)
1243 				savecol = 8;		/* overflow screw */
1244 			while (--savecol >= 0)
1245 				(void) ttyoutput('\b', tp);
1246 			break;
1247 
1248 		default:
1249 			panic("ttyrub");
1250 		}
1251 	} else if (tp->t_local&LPRTERA) {
1252 		if ((tp->t_lstate&LSERASE) == 0) {
1253 			(void) ttyoutput('\\', tp);
1254 			tp->t_lstate |= LSERASE;
1255 		}
1256 		ttyecho(c, tp);
1257 	} else
1258 		ttyecho(tp->t_erase, tp);
1259 	tp->t_rocount--;
1260 }
1261 
1262 /*
1263  * Crt back over cnt chars perhaps
1264  * erasing them.
1265  */
1266 ttyrubo(tp, cnt)
1267 	register struct tty *tp;
1268 	int cnt;
1269 {
1270 
1271 	while (--cnt >= 0)
1272 		ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
1273 }
1274 
1275 /*
1276  * Reprint the rawq line.
1277  * We assume c_cc has already been checked.
1278  */
1279 ttyretype(tp)
1280 	register struct tty *tp;
1281 {
1282 	register char *cp;
1283 	char *nextc();
1284 	int s;
1285 
1286 	if (tlun.t_rprntc != 0377)
1287 		ttyecho(tlun.t_rprntc, tp);
1288 	(void) ttyoutput('\n', tp);
1289 	s = spl5();
1290 	for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
1291 		ttyecho(*cp, tp);
1292 	for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
1293 		ttyecho(*cp, tp);
1294 	tp->t_lstate &= ~LSERASE;
1295 	splx(s);
1296 	tp->t_rocount = tp->t_rawq.c_cc;
1297 	tp->t_rocol = 0;
1298 }
1299 
1300 /*
1301  * Echo a typed character to the terminal
1302  */
1303 ttyecho(c, tp)
1304 	register c;
1305 	register struct tty *tp;
1306 {
1307 
1308 	if ((tp->t_lstate & LSCNTTB) == 0)
1309 		tp->t_local &= ~LFLUSHO;
1310 	if ((tp->t_flags&ECHO) == 0)
1311 		return;
1312 	c &= 0377;
1313 	if (tp->t_flags&RAW) {
1314 		(void) ttyoutput(c, tp);
1315 		return;
1316 	}
1317 	if (c == '\r' && tp->t_flags&CRMOD)
1318 		c = '\n';
1319 	if (tp->t_local&LCTLECH) {
1320 		if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
1321 			(void) ttyoutput('^', tp);
1322 			c &= 0177;
1323 			if (c == 0177)
1324 				c = '?';
1325 			else if (tp->t_flags&LCASE)
1326 				c += 'a' - 1;
1327 			else
1328 				c += 'A' - 1;
1329 		}
1330 	}
1331 	if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z'))
1332 		c += 'a' - 'A';
1333 	(void) ttyoutput(c & 0177, tp);
1334 }
1335 
1336 /*
1337  * Is c a break char for tp?
1338  */
1339 ttbreakc(c, tp)
1340 	register c;
1341 	register struct tty *tp;
1342 {
1343 	return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
1344 		c == '\r' && (tp->t_flags&CRMOD));
1345 }
1346 
1347 /*
1348  * send string cp to tp
1349  */
1350 ttyout(cp, tp)
1351 	register char *cp;
1352 	register struct tty *tp;
1353 {
1354 	register char c;
1355 
1356 	while (c = *cp++)
1357 		(void) ttyoutput(c, tp);
1358 }
1359 
1360 ttwakeup(tp)
1361 	struct tty *tp;
1362 {
1363 
1364 	if (tp->t_rsel) {
1365 		selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1366 		tp->t_state &= ~TS_RCOLL;
1367 		tp->t_rsel = 0;
1368 	}
1369 	wakeup((caddr_t)&tp->t_rawq);
1370 }
1371 
1372 ttsignal(tp, signo)
1373 	struct tty *tp;
1374 	int signo;
1375 {
1376 
1377 	gsignal(tp->t_pgrp, signo);
1378 }
1379