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