xref: /csrg-svn/sys/kern/tty.c (revision 7436)
1 /*	tty.c	4.23	82/07/15	*/
2 
3 /*
4  * TTY subroutines common to more than one line discipline
5  */
6 #include "../h/param.h"
7 #include "../h/systm.h"
8 #include "../h/dir.h"
9 #include "../h/user.h"
10 #include "../h/tty.h"
11 #include "../h/proc.h"
12 #include "../h/inode.h"
13 #include "../h/file.h"
14 #include "../h/reg.h"
15 #include "../h/conf.h"
16 #include "../h/buf.h"
17 #include "../h/dk.h"
18 
19 /*
20  * Table giving parity for characters and indicating
21  * character classes to tty driver.  In particular,
22  * if the low 6 bits are 0, then the character needs
23  * no special processing on output.
24  */
25 
26 char partab[] = {
27 	0001,0201,0201,0001,0201,0001,0001,0201,
28 	0202,0004,0003,0201,0005,0206,0201,0001,
29 	0201,0001,0001,0201,0001,0201,0201,0001,
30 	0001,0201,0201,0001,0201,0001,0001,0201,
31 	0200,0000,0000,0200,0000,0200,0200,0000,
32 	0000,0200,0200,0000,0200,0000,0000,0200,
33 	0000,0200,0200,0000,0200,0000,0000,0200,
34 	0200,0000,0000,0200,0000,0200,0200,0000,
35 	0200,0000,0000,0200,0000,0200,0200,0000,
36 	0000,0200,0200,0000,0200,0000,0000,0200,
37 	0000,0200,0200,0000,0200,0000,0000,0200,
38 	0200,0000,0000,0200,0000,0200,0200,0000,
39 	0000,0200,0200,0000,0200,0000,0000,0200,
40 	0200,0000,0000,0200,0000,0200,0200,0000,
41 	0200,0000,0000,0200,0000,0200,0200,0000,
42 	0000,0200,0200,0000,0200,0000,0000,0201,
43 
44 	/*
45 	 * 7 bit ascii ends with the last character above,
46 	 * but we contine through all 256 codes for the sake
47 	 * of the tty output routines which use special vax
48 	 * instructions which need a 256 character trt table.
49 	 */
50 
51 	0007,0007,0007,0007,0007,0007,0007,0007,
52 	0007,0007,0007,0007,0007,0007,0007,0007,
53 	0007,0007,0007,0007,0007,0007,0007,0007,
54 	0007,0007,0007,0007,0007,0007,0007,0007,
55 	0007,0007,0007,0007,0007,0007,0007,0007,
56 	0007,0007,0007,0007,0007,0007,0007,0007,
57 	0007,0007,0007,0007,0007,0007,0007,0007,
58 	0007,0007,0007,0007,0007,0007,0007,0007,
59 	0007,0007,0007,0007,0007,0007,0007,0007,
60 	0007,0007,0007,0007,0007,0007,0007,0007,
61 	0007,0007,0007,0007,0007,0007,0007,0007,
62 	0007,0007,0007,0007,0007,0007,0007,0007,
63 	0007,0007,0007,0007,0007,0007,0007,0007,
64 	0007,0007,0007,0007,0007,0007,0007,0007,
65 	0007,0007,0007,0007,0007,0007,0007,0007,
66 	0007,0007,0007,0007,0007,0007,0007,0007
67 };
68 
69 /*
70  * Input mapping table-- if an entry is non-zero, when the
71  * corresponding character is typed preceded by "\" the escape
72  * sequence is replaced by the table value.  Mostly used for
73  * upper-case only terminals.
74  */
75 
76 char	maptab[] ={
77 	000,000,000,000,000,000,000,000,
78 	000,000,000,000,000,000,000,000,
79 	000,000,000,000,000,000,000,000,
80 	000,000,000,000,000,000,000,000,
81 	000,'|',000,000,000,000,000,'`',
82 	'{','}',000,000,000,000,000,000,
83 	000,000,000,000,000,000,000,000,
84 	000,000,000,000,000,000,000,000,
85 	000,000,000,000,000,000,000,000,
86 	000,000,000,000,000,000,000,000,
87 	000,000,000,000,000,000,000,000,
88 	000,000,000,000,000,000,'~',000,
89 	000,'A','B','C','D','E','F','G',
90 	'H','I','J','K','L','M','N','O',
91 	'P','Q','R','S','T','U','V','W',
92 	'X','Y','Z',000,000,000,000,000,
93 };
94 
95 short	tthiwat[16] =
96    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
97 short	ttlowat[16] =
98    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
99 
100 #define	OBUFSIZ	100
101 
102 /*
103  * set default control characters.
104  */
105 ttychars(tp)
106 register struct tty *tp;
107 {
108 
109 	tun.t_intrc = CINTR;
110 	tun.t_quitc = CQUIT;
111 	tun.t_startc = CSTART;
112 	tun.t_stopc = CSTOP;
113 	tun.t_eofc = CEOT;
114 	tun.t_brkc = CBRK;
115 	tp->t_erase = CERASE;
116 	tp->t_kill = CKILL;
117 /* begin local */
118 	tlun.t_suspc = CTRL(z);
119 	tlun.t_dsuspc = CTRL(y);
120 	tlun.t_rprntc = CTRL(r);
121 	tlun.t_flushc = CTRL(o);
122 	tlun.t_werasc = CTRL(w);
123 	tlun.t_lnextc = CTRL(v);
124 	tp->t_local = 0;
125 	tp->t_lstate = 0;
126 /* end local */
127 }
128 
129 /*
130  * Wait for output to drain, then flush input waiting.
131  */
132 wflushtty(tp)
133 	register struct tty *tp;
134 {
135 
136 	(void) spl5();
137 	while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON
138 	    && tp->t_oproc) {		/* kludge for pty */
139 		(*tp->t_oproc)(tp);
140 		tp->t_state |= TS_ASLEEP;
141 		sleep((caddr_t)&tp->t_outq, TTOPRI);
142 	}
143 	flushtty(tp, FREAD);
144 	(void) spl0();
145 }
146 
147 /*
148  * flush all TTY queues
149  */
150 flushtty(tp, rw)
151 register struct tty *tp;
152 {
153 	register s;
154 
155 	s = spl6();
156 	if (rw & FREAD) {
157 		while (getc(&tp->t_canq) >= 0)
158 			;
159 		wakeup((caddr_t)&tp->t_rawq);
160 	}
161 	if (rw & FWRITE) {
162 		wakeup((caddr_t)&tp->t_outq);
163 		tp->t_state &= ~TS_TTSTOP;
164 		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
165 		while (getc(&tp->t_outq) >= 0)
166 			;
167 	}
168 	if (rw & FREAD) {
169 		while (getc(&tp->t_rawq) >= 0)
170 			;
171 		tp->t_delct = 0;
172 		tp->t_rocount = 0;		/* local */
173 		tp->t_rocol = 0;
174 		tp->t_lstate = 0;
175 	}
176 	splx(s);
177 }
178 
179 /*
180  * Send stop character on input overflow.
181  */
182 ttyblock(tp)
183 register struct tty *tp;
184 {
185 	register x;
186 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
187 	if (tp->t_rawq.c_cc > TTYHOG) {
188 		flushtty(tp, FREAD|FWRITE);
189 		tp->t_state &= ~TS_TBLOCK;
190 	}
191 	if (x >= TTYHOG/2) {
192 		if (putc(tun.t_stopc, &tp->t_outq)==0) {
193 			tp->t_state |= TS_TBLOCK;
194 			tp->t_char++;
195 			ttstart(tp);
196 		}
197 	}
198 }
199 
200 /*
201  * Restart typewriter output following a delay
202  * timeout.
203  * The name of the routine is passed to the timeout
204  * subroutine and it is called during a clock interrupt.
205  */
206 ttrstrt(tp)
207 register struct tty *tp;
208 {
209 
210 	if (tp == 0) {
211 		printf("ttrstrt: arg was 0!\n");
212 		return;
213 	}
214 	tp->t_state &= ~TS_TIMEOUT;
215 	ttstart(tp);
216 }
217 
218 /*
219  * Start output on the typewriter. It is used from the top half
220  * after some characters have been put on the output queue,
221  * from the interrupt routine to transmit the next
222  * character, and after a timeout has finished.
223  */
224 ttstart(tp)
225 register struct tty *tp;
226 {
227 	register s;
228 
229 	s = spl5();
230 	if((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
231 	    tp->t_oproc)		/* kludge for pty */
232 		(*tp->t_oproc)(tp);
233 	splx(s);
234 }
235 
236 /*
237  * Common code for tty ioctls.
238  */
239 /*ARGSUSED*/
240 ttioctl(tp, com, addr, flag)
241 register struct tty *tp;
242 caddr_t addr;
243 {
244 	int dev;
245 	unsigned t;
246 	struct sgttyb iocb;
247 	struct clist tq;
248 	extern int nldisp;
249 	register c;
250 	int temp;
251 
252 	/*
253 	 * This is especially so that isatty() will
254 	 * fail when carrier is gone.
255 	 */
256 	if ((tp->t_state&TS_CARR_ON) == 0) {
257 		u.u_error = EBADF;
258 		return (1);
259 	}
260 
261 	dev = tp->t_dev;
262 	/*
263 	 * If the ioctl involves modification,
264 	 * insist on being able to write the device,
265 	 * and hang if in the background.
266 	 */
267 	switch(com) {
268 
269 	case TIOCSETD:
270 	case TIOCSETP:
271 	case TIOCSETN:
272 	case TIOCFLUSH:
273 	case TIOCSETC:
274 	case TIOCSLTC:
275 	case TIOCSPGRP:
276 	case TIOCLBIS:
277 	case TIOCLBIC:
278 	case TIOCLSET:
279 	case TIOCSTI:
280 /* this is reasonable, but impractical...
281 		if ((flag & FWRITE) == 0) {
282 			u.u_error = EBADF;
283 			return (1);
284 		}
285  */
286 		while (tp->t_line == NTTYDISC &&
287 		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
288 		   (u.u_procp->p_flag&SVFORK) == 0 &&
289 		   u.u_signal[SIGTTOU] != SIG_IGN &&
290 		   u.u_signal[SIGTTOU] != SIG_HOLD
291 /*
292 						   &&
293 		   (u.u_procp->p_flag&SDETACH)==0) {
294 */
295 		   ) {
296 			gsignal(u.u_procp->p_pgrp, SIGTTOU);
297 			sleep((caddr_t)&lbolt, TTOPRI);
298 		}
299 		break;
300 	}
301 
302 	/*
303 	 * Process the ioctl.
304 	 */
305 	switch(com) {
306 
307 	/*
308 	 * Get discipline number
309 	 */
310 	case TIOCGETD:
311 		t = tp->t_line;
312 		if (copyout((caddr_t)&t, addr, sizeof(t)))
313 			u.u_error = EFAULT;
314 		break;
315 
316 	/*
317 	 * Set line discipline
318 	 */
319 	case TIOCSETD:
320 		if (copyin(addr, (caddr_t)&t, sizeof(t))) {
321 			u.u_error = EFAULT;
322 			break;
323 		}
324 		if (t >= nldisp) {
325 			u.u_error = ENXIO;
326 			break;
327 		}
328 		(void) spl5();
329 		if (tp->t_line)
330 			(*linesw[tp->t_line].l_close)(tp);
331 		if (t)
332 			(*linesw[t].l_open)(dev, tp, addr);
333 		if (u.u_error==0)
334 			tp->t_line = t;
335 		(void) spl0();
336 		break;
337 
338 	/*
339 	 * Prevent more opens on channel
340 	 */
341 	case TIOCEXCL:
342 		tp->t_state |= TS_XCLUDE;
343 		break;
344 
345 	case TIOCNXCL:
346 		tp->t_state &= ~TS_XCLUDE;
347 		break;
348 
349 	/*
350 	 * Set new parameters
351 	 */
352 	case TIOCSETP:
353 	case TIOCSETN:
354 		if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
355 			u.u_error = EFAULT;
356 			return(1);
357 		}
358 		(void) spl5();
359 		if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
360 		    com == TIOCSETP)
361 			wflushtty(tp);
362 		else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
363 			if (iocb.sg_flags & CBREAK) {
364 				catq(&tp->t_rawq, &tp->t_canq);
365 				tq = tp->t_rawq;
366 				tp->t_rawq = tp->t_canq;
367 				tp->t_canq = tq;
368 			} else {
369 				tp->t_local |= LPENDIN;
370 				ttwakeup(tp);
371 			}
372 		}
373 		tp->t_ispeed = iocb.sg_ispeed;
374 		tp->t_ospeed = iocb.sg_ospeed;
375 		tp->t_erase = iocb.sg_erase;
376 		tp->t_kill = iocb.sg_kill;
377 		tp->t_flags = iocb.sg_flags;
378 		if (tp->t_flags & RAW) {
379 			tp->t_state &= ~TS_TTSTOP;
380 			ttstart(tp);
381 		}
382 		(void) spl0();
383 		break;
384 
385 	/*
386 	 * Send current parameters to user
387 	 */
388 	case TIOCGETP:
389 		iocb.sg_ispeed = tp->t_ispeed;
390 		iocb.sg_ospeed = tp->t_ospeed;
391 		iocb.sg_erase = tp->t_erase;
392 		iocb.sg_kill = tp->t_kill;
393 		iocb.sg_flags = tp->t_flags;
394 		if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
395 			u.u_error = EFAULT;
396 		break;
397 
398 	/*
399 	 * Hang up line on last close
400 	 */
401 	case TIOCHPCL:
402 		tp->t_state |= TS_HUPCLS;
403 		break;
404 
405 	case TIOCFLUSH: {
406 		int flags;
407 		if (addr == 0)
408 			flags = FREAD|FWRITE;
409 		else if (copyin(addr, (caddr_t)&flags, sizeof (flags))) {
410 			u.u_error = EFAULT;
411 			return(1);
412 		}
413 		flushtty(tp, flags);
414 		break;
415 	}
416 
417 	case FIONBIO: {
418 		int nbio;
419 		if (copyin(addr, (caddr_t)&nbio, sizeof (nbio))) {
420 			u.u_error = EFAULT;
421 			return(1);
422 		}
423 		if (nbio)
424 			tp->t_state |= TS_NBIO;
425 		else
426 			tp->t_state &= ~TS_NBIO;
427 		break;
428 	}
429 
430 	case FIOASYNC: {
431 		int async;
432 		if (copyin(addr, (caddr_t)&async, sizeof (async))) {
433 			u.u_error = EFAULT;
434 			return(1);
435 		}
436 		if (async)
437 			tp->t_state |= TS_ASYNC;
438 		else
439 			tp->t_state &= ~TS_ASYNC;
440 		break;
441 	}
442 
443 	/*
444 	 * Set and fetch special characters
445 	 */
446 	case TIOCSETC:
447 		if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
448 			u.u_error = EFAULT;
449 		break;
450 
451 	case TIOCGETC:
452 		if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
453 			u.u_error = EFAULT;
454 		break;
455 
456 /* local ioctls */
457 	/*
458 	 * Set/get local special characters.
459 	 */
460 	case TIOCSLTC:
461 		if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
462 			u.u_error = EFAULT;
463 		break;
464 
465 	case TIOCGLTC:
466 		if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
467 			u.u_error = EFAULT;
468 		break;
469 
470 	/*
471 	 * Return number of characters immediately available.
472 	 */
473 	case FIONREAD: {
474 		off_t nread = ttnread(tp);
475 		if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
476 			u.u_error = EFAULT;
477 		break;
478 		}
479 
480 	/*
481 	 * Should allow SPGRP and GPGRP only if tty open for reading.
482 	 */
483 	case TIOCSPGRP:
484 		if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
485 			u.u_error = EFAULT;
486 		break;
487 
488 	case TIOCGPGRP:
489 		if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
490 			u.u_error = EFAULT;
491 		break;
492 
493 	/*
494 	 * Modify local mode word.
495 	 */
496 	case TIOCLBIS:
497 		if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
498 			u.u_error = EFAULT;
499 		else
500 			tp->t_local |= temp;
501 		break;
502 
503 	case TIOCLBIC:
504 		if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
505 			u.u_error = EFAULT;
506 		else
507 			tp->t_local &= ~temp;
508 		break;
509 
510 	case TIOCLSET:
511 		if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
512 			u.u_error = EFAULT;
513 		else
514 			tp->t_local = temp;
515 		break;
516 
517 	case TIOCLGET:
518 		if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
519 			u.u_error = EFAULT;
520 		break;
521 
522 	/*
523 	 * Return number of characters in
524 	 * the output.
525 	 */
526 	case TIOCOUTQ:
527 		if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
528 			u.u_error = EFAULT;
529 		break;
530 
531 	/*
532 	 * Simulate typing of a character at the terminal.
533 	 */
534 	case TIOCSTI:
535 		c = fubyte(addr);
536 		if (u.u_uid && u.u_ttyp != tp || c < 0)
537 			u.u_error = EFAULT;
538 		else
539 			(*linesw[tp->t_line].l_rint)(c, tp);
540 		break;
541 
542 	case TIOCSTOP:
543 		c = spl5();
544 		if ((tp->t_state & TS_TTSTOP) == 0) {
545 			tp->t_state |= TS_TTSTOP;
546 			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
547 		}
548 		splx(c);
549 		break;
550 
551 	case TIOCSTART:
552 		c = spl5();
553 		if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) {
554 			tp->t_state &= ~TS_TTSTOP;
555 			tp->t_local &= ~LFLUSHO;
556 			ttstart(tp);
557 		}
558 		splx(c);
559 		break;
560 
561 /* end of locals */
562 
563 	default:
564 		return(0);
565 	}
566 	return(1);
567 }
568 
569 ttnread(tp)
570 	struct tty *tp;
571 {
572 	int nread = 0;
573 
574 	if (tp->t_local & LPENDIN)
575 		ttypend(tp);
576 	nread = tp->t_canq.c_cc;
577 	if (tp->t_flags & (RAW|CBREAK))
578 		nread += tp->t_rawq.c_cc;
579 	return (nread);
580 }
581 
582 ttselect(dev, rw)
583 	dev_t dev;
584 	int rw;
585 {
586 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
587 	int nread;
588 	int s = spl5();
589 
590 	switch (rw) {
591 
592 	case FREAD:
593 		nread = ttnread(tp);
594 		if (nread > 0)
595 			goto win;
596 		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
597 			tp->t_state |= TS_RCOLL;
598 		else
599 			tp->t_rsel = u.u_procp;
600 		break;
601 
602 	case FWRITE:
603 		if (tp->t_outq.c_cc <= TTLOWAT(tp))
604 			goto win;
605 		if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
606 			tp->t_state |= TS_WCOLL;
607 		else
608 			tp->t_wsel = u.u_procp;
609 		break;
610 	}
611 	splx(s);
612 	return (0);
613 win:
614 	splx(s);
615 	return (1);
616 }
617 
618