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