xref: /csrg-svn/sys/kern/tty_pty.c (revision 52523)
1 /*
2  * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)tty_pty.c	7.24 (Berkeley) 02/15/92
8  */
9 
10 /*
11  * Pseudo-teletype Driver
12  * (Actually two drivers, requiring two entries in 'cdevsw')
13  */
14 #include "pty.h"
15 
16 #if NPTY > 0
17 #include "param.h"
18 #include "systm.h"
19 #include "ioctl.h"
20 #include "proc.h"
21 #include "tty.h"
22 #include "conf.h"
23 #include "file.h"
24 #include "uio.h"
25 #include "kernel.h"
26 #include "vnode.h"
27 
28 #if NPTY == 1
29 #undef NPTY
30 #define	NPTY	32		/* crude XXX */
31 #endif
32 
33 #define BUFSIZ 100		/* Chunk size iomoved to/from user */
34 
35 /*
36  * pts == /dev/tty[pqrs]?
37  * ptc == /dev/pty[pqrs]?
38  */
39 struct	tty pt_tty[NPTY];
40 struct	pt_ioctl {
41 	int	pt_flags;
42 	struct	selinfo pt_selr, pt_selw;
43 	u_char	pt_send;
44 	u_char	pt_ucntl;
45 } pt_ioctl[NPTY];
46 int	npty = NPTY;		/* for pstat -t */
47 
48 #define	PF_PKT		0x08		/* packet mode */
49 #define	PF_STOPPED	0x10		/* user told stopped */
50 #define	PF_REMOTE	0x20		/* remote and flow controlled input */
51 #define	PF_NOSTOP	0x40
52 #define PF_UCNTL	0x80		/* user control mode */
53 
54 void	ptsstop __P((struct tty *, int));
55 
56 /*ARGSUSED*/
57 ptsopen(dev, flag, devtype, p)
58 	dev_t dev;
59 	int flag, devtype;
60 	struct proc *p;
61 {
62 	register struct tty *tp;
63 	int error;
64 
65 #ifdef lint
66 	npty = npty;
67 #endif
68 	if (minor(dev) >= NPTY)
69 		return (ENXIO);
70 	tp = &pt_tty[minor(dev)];
71 	if ((tp->t_state & TS_ISOPEN) == 0) {
72 		tp->t_state |= TS_WOPEN;
73 		ttychars(tp);		/* Set up default chars */
74 		tp->t_iflag = TTYDEF_IFLAG;
75 		tp->t_oflag = TTYDEF_OFLAG;
76 		tp->t_lflag = TTYDEF_LFLAG;
77 		tp->t_cflag = TTYDEF_CFLAG;
78 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
79 		ttsetwater(tp);		/* would be done in xxparam() */
80 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
81 		return (EBUSY);
82 	if (tp->t_oproc)			/* Ctrlr still around. */
83 		tp->t_state |= TS_CARR_ON;
84 	while ((tp->t_state & TS_CARR_ON) == 0) {
85 		tp->t_state |= TS_WOPEN;
86 		if (flag&FNONBLOCK)
87 			break;
88 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
89 		    ttopen, 0))
90 			return (error);
91 	}
92 	error = (*linesw[tp->t_line].l_open)(dev, tp);
93 	ptcwakeup(tp, FREAD|FWRITE);
94 	return (error);
95 }
96 
97 ptsclose(dev, flag, mode, p)
98 	dev_t dev;
99 	int flag, mode;
100 	struct proc *p;
101 {
102 	register struct tty *tp;
103 
104 	tp = &pt_tty[minor(dev)];
105 	(*linesw[tp->t_line].l_close)(tp, flag);
106 	ttyclose(tp);
107 	ptcwakeup(tp, FREAD|FWRITE);
108 }
109 
110 ptsread(dev, uio, flag)
111 	dev_t dev;
112 	struct uio *uio;
113 	int flag;
114 {
115 	struct proc *p = curproc;
116 	register struct tty *tp = &pt_tty[minor(dev)];
117 	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
118 	int error = 0;
119 
120 again:
121 	if (pti->pt_flags & PF_REMOTE) {
122 		while (isbackground(p, tp)) {
123 			if ((p->p_sigignore & sigmask(SIGTTIN)) ||
124 			    (p->p_sigmask & sigmask(SIGTTIN)) ||
125 			    p->p_pgrp->pg_jobc == 0 ||
126 			    p->p_flag&SPPWAIT)
127 				return (EIO);
128 			pgsignal(p->p_pgrp, SIGTTIN, 1);
129 			if (error = ttysleep(tp, (caddr_t)&lbolt,
130 			    TTIPRI | PCATCH, ttybg, 0))
131 				return (error);
132 		}
133 		if (tp->t_canq.c_cc == 0) {
134 			if (flag & IO_NDELAY)
135 				return (EWOULDBLOCK);
136 			if (error = ttysleep(tp, (caddr_t)&tp->t_canq,
137 			    TTIPRI | PCATCH, ttyin, 0))
138 				return (error);
139 			goto again;
140 		}
141 		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
142 			if (ureadc(getc(&tp->t_canq), uio) < 0) {
143 				error = EFAULT;
144 				break;
145 			}
146 		if (tp->t_canq.c_cc == 1)
147 			(void) getc(&tp->t_canq);
148 		if (tp->t_canq.c_cc)
149 			return (error);
150 	} else
151 		if (tp->t_oproc)
152 			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
153 	ptcwakeup(tp, FWRITE);
154 	return (error);
155 }
156 
157 /*
158  * Write to pseudo-tty.
159  * Wakeups of controlling tty will happen
160  * indirectly, when tty driver calls ptsstart.
161  */
162 ptswrite(dev, uio, flag)
163 	dev_t dev;
164 	struct uio *uio;
165 {
166 	register struct tty *tp;
167 
168 	tp = &pt_tty[minor(dev)];
169 	if (tp->t_oproc == 0)
170 		return (EIO);
171 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
172 }
173 
174 /*
175  * Start output on pseudo-tty.
176  * Wake up process selecting or sleeping for input from controlling tty.
177  */
178 void
179 ptsstart(tp)
180 	struct tty *tp;
181 {
182 	register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
183 
184 	if (tp->t_state & TS_TTSTOP)
185 		return;
186 	if (pti->pt_flags & PF_STOPPED) {
187 		pti->pt_flags &= ~PF_STOPPED;
188 		pti->pt_send = TIOCPKT_START;
189 	}
190 	ptcwakeup(tp, FREAD);
191 }
192 
193 ptcwakeup(tp, flag)
194 	struct tty *tp;
195 	int flag;
196 {
197 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
198 
199 	if (flag & FREAD) {
200 		selwakeup(&pti->pt_selr);
201 		wakeup((caddr_t)&tp->t_outq.c_cf);
202 	}
203 	if (flag & FWRITE) {
204 		selwakeup(&pti->pt_selw);
205 		wakeup((caddr_t)&tp->t_rawq.c_cf);
206 	}
207 }
208 
209 /*ARGSUSED*/
210 #ifdef __STDC__
211 ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
212 #else
213 ptcopen(dev, flag, devtype, p)
214 	dev_t dev;
215 	int flag, devtype;
216 	struct proc *p;
217 #endif
218 {
219 	register struct tty *tp;
220 	struct pt_ioctl *pti;
221 
222 	if (minor(dev) >= NPTY)
223 		return (ENXIO);
224 	tp = &pt_tty[minor(dev)];
225 	if (tp->t_oproc)
226 		return (EIO);
227 	tp->t_oproc = ptsstart;
228 #ifdef sun4c
229 	tp->t_stop = ptsstop;
230 #endif
231 	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
232 	tp->t_lflag &= ~EXTPROC;
233 	pti = &pt_ioctl[minor(dev)];
234 	pti->pt_flags = 0;
235 	pti->pt_send = 0;
236 	pti->pt_ucntl = 0;
237 	return (0);
238 }
239 
240 ptcclose(dev)
241 	dev_t dev;
242 {
243 	register struct tty *tp;
244 
245 	tp = &pt_tty[minor(dev)];
246 	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
247 	tp->t_state &= ~TS_CARR_ON;
248 	tp->t_oproc = 0;		/* mark closed */
249 	tp->t_session = 0;
250 }
251 
252 ptcread(dev, uio, flag)
253 	dev_t dev;
254 	struct uio *uio;
255 	int flag;
256 {
257 	register struct tty *tp = &pt_tty[minor(dev)];
258 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
259 	char buf[BUFSIZ];
260 	int error = 0, cc;
261 
262 	/*
263 	 * We want to block until the slave
264 	 * is open, and there's something to read;
265 	 * but if we lost the slave or we're NBIO,
266 	 * then return the appropriate error instead.
267 	 */
268 	for (;;) {
269 		if (tp->t_state&TS_ISOPEN) {
270 			if (pti->pt_flags&PF_PKT && pti->pt_send) {
271 				error = ureadc((int)pti->pt_send, uio);
272 				if (error)
273 					return (error);
274 				if (pti->pt_send & TIOCPKT_IOCTL) {
275 					cc = MIN(uio->uio_resid,
276 						sizeof(tp->t_termios));
277 					uiomove(&tp->t_termios, cc, uio);
278 				}
279 				pti->pt_send = 0;
280 				return (0);
281 			}
282 			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
283 				error = ureadc((int)pti->pt_ucntl, uio);
284 				if (error)
285 					return (error);
286 				pti->pt_ucntl = 0;
287 				return (0);
288 			}
289 			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
290 				break;
291 		}
292 		if ((tp->t_state&TS_CARR_ON) == 0)
293 			return (0);	/* EOF */
294 		if (flag & IO_NDELAY)
295 			return (EWOULDBLOCK);
296 		if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
297 		    ttyin, 0))
298 			return (error);
299 	}
300 	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
301 		error = ureadc(0, uio);
302 	while (uio->uio_resid > 0 && error == 0) {
303 		cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
304 		if (cc <= 0)
305 			break;
306 		error = uiomove(buf, cc, uio);
307 	}
308 	if (tp->t_outq.c_cc <= tp->t_lowat) {
309 		if (tp->t_state&TS_ASLEEP) {
310 			tp->t_state &= ~TS_ASLEEP;
311 			wakeup((caddr_t)&tp->t_outq);
312 		}
313 		selwakeup(&tp->t_wsel);
314 	}
315 	return (error);
316 }
317 
318 void
319 ptsstop(tp, flush)
320 	register struct tty *tp;
321 	int flush;
322 {
323 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
324 	int flag;
325 
326 	/* note: FLUSHREAD and FLUSHWRITE already ok */
327 	if (flush == 0) {
328 		flush = TIOCPKT_STOP;
329 		pti->pt_flags |= PF_STOPPED;
330 	} else
331 		pti->pt_flags &= ~PF_STOPPED;
332 	pti->pt_send |= flush;
333 	/* change of perspective */
334 	flag = 0;
335 	if (flush & FREAD)
336 		flag |= FWRITE;
337 	if (flush & FWRITE)
338 		flag |= FREAD;
339 	ptcwakeup(tp, flag);
340 }
341 
342 ptcselect(dev, rw, p)
343 	dev_t dev;
344 	int rw;
345 	struct proc *p;
346 {
347 	register struct tty *tp = &pt_tty[minor(dev)];
348 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
349 	int s;
350 
351 	if ((tp->t_state&TS_CARR_ON) == 0)
352 		return (1);
353 	switch (rw) {
354 
355 	case FREAD:
356 		/*
357 		 * Need to block timeouts (ttrstart).
358 		 */
359 		s = spltty();
360 		if ((tp->t_state&TS_ISOPEN) &&
361 		     tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
362 			splx(s);
363 			return (1);
364 		}
365 		splx(s);
366 		/* FALLTHROUGH */
367 
368 	case 0:					/* exceptional */
369 		if ((tp->t_state&TS_ISOPEN) &&
370 		    (pti->pt_flags&PF_PKT && pti->pt_send ||
371 		     pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
372 			return (1);
373 		selrecord(p, &pti->pt_selr);
374 		break;
375 
376 
377 	case FWRITE:
378 		if (tp->t_state&TS_ISOPEN) {
379 			if (pti->pt_flags & PF_REMOTE) {
380 			    if (tp->t_canq.c_cc == 0)
381 				return (1);
382 			} else {
383 			    if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
384 				    return (1);
385 			    if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
386 				    return (1);
387 			}
388 		}
389 		selrecord(p, &pti->pt_selw);
390 		break;
391 
392 	}
393 	return (0);
394 }
395 
396 ptcwrite(dev, uio, flag)
397 	dev_t dev;
398 	register struct uio *uio;
399 {
400 	register struct tty *tp = &pt_tty[minor(dev)];
401 	register u_char *cp;
402 	register int cc = 0;
403 	u_char locbuf[BUFSIZ];
404 	int cnt = 0;
405 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
406 	int error = 0;
407 
408 again:
409 	if ((tp->t_state&TS_ISOPEN) == 0)
410 		goto block;
411 	if (pti->pt_flags & PF_REMOTE) {
412 		if (tp->t_canq.c_cc)
413 			goto block;
414 		while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
415 			if (cc == 0) {
416 				cc = min(uio->uio_resid, BUFSIZ);
417 				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
418 				cp = locbuf;
419 				error = uiomove((caddr_t)cp, cc, uio);
420 				if (error)
421 					return (error);
422 				/* check again for safety */
423 				if ((tp->t_state&TS_ISOPEN) == 0)
424 					return (EIO);
425 			}
426 			if (cc)
427 				(void) b_to_q((char *)cp, cc, &tp->t_canq);
428 			cc = 0;
429 		}
430 		(void) putc(0, &tp->t_canq);
431 		ttwakeup(tp);
432 		wakeup((caddr_t)&tp->t_canq);
433 		return (0);
434 	}
435 	while (uio->uio_resid > 0) {
436 		if (cc == 0) {
437 			cc = min(uio->uio_resid, BUFSIZ);
438 			cp = locbuf;
439 			error = uiomove((caddr_t)cp, cc, uio);
440 			if (error)
441 				return (error);
442 			/* check again for safety */
443 			if ((tp->t_state&TS_ISOPEN) == 0)
444 				return (EIO);
445 		}
446 		while (cc > 0) {
447 			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
448 			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
449 				wakeup((caddr_t)&tp->t_rawq);
450 				goto block;
451 			}
452 			(*linesw[tp->t_line].l_rint)(*cp++, tp);
453 			cnt++;
454 			cc--;
455 		}
456 		cc = 0;
457 	}
458 	return (0);
459 block:
460 	/*
461 	 * Come here to wait for slave to open, for space
462 	 * in outq, or space in rawq.
463 	 */
464 	if ((tp->t_state&TS_CARR_ON) == 0)
465 		return (EIO);
466 	if (flag & IO_NDELAY) {
467 		/* adjust for data copied in but not written */
468 		uio->uio_resid += cc;
469 		if (cnt == 0)
470 			return (EWOULDBLOCK);
471 		return (0);
472 	}
473 	if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
474 	    ttyout, 0)) {
475 		/* adjust for data copied in but not written */
476 		uio->uio_resid += cc;
477 		return (error);
478 	}
479 	goto again;
480 }
481 
482 /*ARGSUSED*/
483 ptyioctl(dev, cmd, data, flag, p)
484 	dev_t dev;
485 	int cmd;
486 	caddr_t data;
487 	int flag;
488 	struct proc *p;
489 {
490 	register struct tty *tp = &pt_tty[minor(dev)];
491 	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
492 	register u_char *cc = tp->t_cc;
493 	int stop, error;
494 
495 	/*
496 	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
497 	 * ttywflush(tp) will hang if there are characters in the outq.
498 	 */
499 	if (cmd == TIOCEXT) {
500 		/*
501 		 * When the EXTPROC bit is being toggled, we need
502 		 * to send an TIOCPKT_IOCTL if the packet driver
503 		 * is turned on.
504 		 */
505 		if (*(int *)data) {
506 			if (pti->pt_flags & PF_PKT) {
507 				pti->pt_send |= TIOCPKT_IOCTL;
508 				ptcwakeup(tp);
509 			}
510 			tp->t_lflag |= EXTPROC;
511 		} else {
512 			if ((tp->t_state & EXTPROC) &&
513 			    (pti->pt_flags & PF_PKT)) {
514 				pti->pt_send |= TIOCPKT_IOCTL;
515 				ptcwakeup(tp);
516 			}
517 			tp->t_lflag &= ~EXTPROC;
518 		}
519 		return(0);
520 	} else
521 	if (cdevsw[major(dev)].d_open == ptcopen)
522 		switch (cmd) {
523 
524 		case TIOCGPGRP:
525 			/*
526 			 * We aviod calling ttioctl on the controller since,
527 			 * in that case, tp must be the controlling terminal.
528 			 */
529 			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
530 			return (0);
531 
532 		case TIOCPKT:
533 			if (*(int *)data) {
534 				if (pti->pt_flags & PF_UCNTL)
535 					return (EINVAL);
536 				pti->pt_flags |= PF_PKT;
537 			} else
538 				pti->pt_flags &= ~PF_PKT;
539 			return (0);
540 
541 		case TIOCUCNTL:
542 			if (*(int *)data) {
543 				if (pti->pt_flags & PF_PKT)
544 					return (EINVAL);
545 				pti->pt_flags |= PF_UCNTL;
546 			} else
547 				pti->pt_flags &= ~PF_UCNTL;
548 			return (0);
549 
550 		case TIOCREMOTE:
551 			if (*(int *)data)
552 				pti->pt_flags |= PF_REMOTE;
553 			else
554 				pti->pt_flags &= ~PF_REMOTE;
555 			ttyflush(tp, FREAD|FWRITE);
556 			return (0);
557 
558 #ifdef COMPAT_43
559 		case TIOCSETP:
560 		case TIOCSETN:
561 #endif
562 		case TIOCSETD:
563 		case TIOCSETA:
564 		case TIOCSETAW:
565 		case TIOCSETAF:
566 			ndflush(&tp->t_outq, tp->t_outq.c_cc);
567 			break;
568 
569 		case TIOCSIG:
570 			if (*(unsigned int *)data >= NSIG)
571 				return(EINVAL);
572 			if ((tp->t_lflag&NOFLSH) == 0)
573 				ttyflush(tp, FREAD|FWRITE);
574 			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
575 			if ((*(unsigned int *)data == SIGINFO) &&
576 			    ((tp->t_lflag&NOKERNINFO) == 0))
577 				ttyinfo(tp);
578 			return(0);
579 		}
580 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
581 	if (error < 0)
582 		 error = ttioctl(tp, cmd, data, flag);
583 	if (error < 0) {
584 		if (pti->pt_flags & PF_UCNTL &&
585 		    (cmd & ~0xff) == UIOCCMD(0)) {
586 			if (cmd & 0xff) {
587 				pti->pt_ucntl = (u_char)cmd;
588 				ptcwakeup(tp, FREAD);
589 			}
590 			return (0);
591 		}
592 		error = ENOTTY;
593 	}
594 	/*
595 	 * If external processing and packet mode send ioctl packet.
596 	 */
597 	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
598 		switch(cmd) {
599 		case TIOCSETA:
600 		case TIOCSETAW:
601 		case TIOCSETAF:
602 #ifdef COMPAT_43
603 		case TIOCSETP:
604 		case TIOCSETN:
605 #endif
606 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
607 		case TIOCSETC:
608 		case TIOCSLTC:
609 		case TIOCLBIS:
610 		case TIOCLBIC:
611 		case TIOCLSET:
612 #endif
613 			pti->pt_send |= TIOCPKT_IOCTL;
614 		default:
615 			break;
616 		}
617 	}
618 	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
619 		&& CCEQ(cc[VSTART], CTRL('q'));
620 	if (pti->pt_flags & PF_NOSTOP) {
621 		if (stop) {
622 			pti->pt_send &= ~TIOCPKT_NOSTOP;
623 			pti->pt_send |= TIOCPKT_DOSTOP;
624 			pti->pt_flags &= ~PF_NOSTOP;
625 			ptcwakeup(tp, FREAD);
626 		}
627 	} else {
628 		if (!stop) {
629 			pti->pt_send &= ~TIOCPKT_DOSTOP;
630 			pti->pt_send |= TIOCPKT_NOSTOP;
631 			pti->pt_flags |= PF_NOSTOP;
632 			ptcwakeup(tp, FREAD);
633 		}
634 	}
635 	return (error);
636 }
637 #endif
638