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