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