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