xref: /original-bsd/sys/kern/tty_pty.c (revision d24fe13c)
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.25 (Berkeley) 03/14/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 	int flag;
166 {
167 	register struct tty *tp;
168 
169 	tp = &pt_tty[minor(dev)];
170 	if (tp->t_oproc == 0)
171 		return (EIO);
172 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
173 }
174 
175 /*
176  * Start output on pseudo-tty.
177  * Wake up process selecting or sleeping for input from controlling tty.
178  */
179 void
180 ptsstart(tp)
181 	struct tty *tp;
182 {
183 	register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
184 
185 	if (tp->t_state & TS_TTSTOP)
186 		return;
187 	if (pti->pt_flags & PF_STOPPED) {
188 		pti->pt_flags &= ~PF_STOPPED;
189 		pti->pt_send = TIOCPKT_START;
190 	}
191 	ptcwakeup(tp, FREAD);
192 }
193 
194 ptcwakeup(tp, flag)
195 	struct tty *tp;
196 	int flag;
197 {
198 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
199 
200 	if (flag & FREAD) {
201 		selwakeup(&pti->pt_selr);
202 		wakeup((caddr_t)&tp->t_outq.c_cf);
203 	}
204 	if (flag & FWRITE) {
205 		selwakeup(&pti->pt_selw);
206 		wakeup((caddr_t)&tp->t_rawq.c_cf);
207 	}
208 }
209 
210 /*ARGSUSED*/
211 #ifdef __STDC__
212 ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
213 #else
214 ptcopen(dev, flag, devtype, p)
215 	dev_t dev;
216 	int flag, devtype;
217 	struct proc *p;
218 #endif
219 {
220 	register struct tty *tp;
221 	struct pt_ioctl *pti;
222 
223 	if (minor(dev) >= NPTY)
224 		return (ENXIO);
225 	tp = &pt_tty[minor(dev)];
226 	if (tp->t_oproc)
227 		return (EIO);
228 	tp->t_oproc = ptsstart;
229 #ifdef sun4c
230 	tp->t_stop = ptsstop;
231 #endif
232 	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
233 	tp->t_lflag &= ~EXTPROC;
234 	pti = &pt_ioctl[minor(dev)];
235 	pti->pt_flags = 0;
236 	pti->pt_send = 0;
237 	pti->pt_ucntl = 0;
238 	return (0);
239 }
240 
241 ptcclose(dev)
242 	dev_t dev;
243 {
244 	register struct tty *tp;
245 
246 	tp = &pt_tty[minor(dev)];
247 	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
248 	tp->t_state &= ~TS_CARR_ON;
249 	tp->t_oproc = 0;		/* mark closed */
250 	tp->t_session = 0;
251 }
252 
253 ptcread(dev, uio, flag)
254 	dev_t dev;
255 	struct uio *uio;
256 	int flag;
257 {
258 	register struct tty *tp = &pt_tty[minor(dev)];
259 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
260 	char buf[BUFSIZ];
261 	int error = 0, cc;
262 
263 	/*
264 	 * We want to block until the slave
265 	 * is open, and there's something to read;
266 	 * but if we lost the slave or we're NBIO,
267 	 * then return the appropriate error instead.
268 	 */
269 	for (;;) {
270 		if (tp->t_state&TS_ISOPEN) {
271 			if (pti->pt_flags&PF_PKT && pti->pt_send) {
272 				error = ureadc((int)pti->pt_send, uio);
273 				if (error)
274 					return (error);
275 				if (pti->pt_send & TIOCPKT_IOCTL) {
276 					cc = MIN(uio->uio_resid,
277 						sizeof(tp->t_termios));
278 					uiomove(&tp->t_termios, cc, uio);
279 				}
280 				pti->pt_send = 0;
281 				return (0);
282 			}
283 			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
284 				error = ureadc((int)pti->pt_ucntl, uio);
285 				if (error)
286 					return (error);
287 				pti->pt_ucntl = 0;
288 				return (0);
289 			}
290 			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
291 				break;
292 		}
293 		if ((tp->t_state&TS_CARR_ON) == 0)
294 			return (0);	/* EOF */
295 		if (flag & IO_NDELAY)
296 			return (EWOULDBLOCK);
297 		if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
298 		    ttyin, 0))
299 			return (error);
300 	}
301 	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
302 		error = ureadc(0, uio);
303 	while (uio->uio_resid > 0 && error == 0) {
304 		cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ));
305 		if (cc <= 0)
306 			break;
307 		error = uiomove(buf, cc, uio);
308 	}
309 	if (tp->t_outq.c_cc <= tp->t_lowat) {
310 		if (tp->t_state&TS_ASLEEP) {
311 			tp->t_state &= ~TS_ASLEEP;
312 			wakeup((caddr_t)&tp->t_outq);
313 		}
314 		selwakeup(&tp->t_wsel);
315 	}
316 	return (error);
317 }
318 
319 void
320 ptsstop(tp, flush)
321 	register struct tty *tp;
322 	int flush;
323 {
324 	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
325 	int flag;
326 
327 	/* note: FLUSHREAD and FLUSHWRITE already ok */
328 	if (flush == 0) {
329 		flush = TIOCPKT_STOP;
330 		pti->pt_flags |= PF_STOPPED;
331 	} else
332 		pti->pt_flags &= ~PF_STOPPED;
333 	pti->pt_send |= flush;
334 	/* change of perspective */
335 	flag = 0;
336 	if (flush & FREAD)
337 		flag |= FWRITE;
338 	if (flush & FWRITE)
339 		flag |= FREAD;
340 	ptcwakeup(tp, flag);
341 }
342 
343 ptcselect(dev, rw, p)
344 	dev_t dev;
345 	int rw;
346 	struct proc *p;
347 {
348 	register struct tty *tp = &pt_tty[minor(dev)];
349 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
350 	int s;
351 
352 	if ((tp->t_state&TS_CARR_ON) == 0)
353 		return (1);
354 	switch (rw) {
355 
356 	case FREAD:
357 		/*
358 		 * Need to block timeouts (ttrstart).
359 		 */
360 		s = spltty();
361 		if ((tp->t_state&TS_ISOPEN) &&
362 		     tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
363 			splx(s);
364 			return (1);
365 		}
366 		splx(s);
367 		/* FALLTHROUGH */
368 
369 	case 0:					/* exceptional */
370 		if ((tp->t_state&TS_ISOPEN) &&
371 		    (pti->pt_flags&PF_PKT && pti->pt_send ||
372 		     pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
373 			return (1);
374 		selrecord(p, &pti->pt_selr);
375 		break;
376 
377 
378 	case FWRITE:
379 		if (tp->t_state&TS_ISOPEN) {
380 			if (pti->pt_flags & PF_REMOTE) {
381 			    if (tp->t_canq.c_cc == 0)
382 				return (1);
383 			} else {
384 			    if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
385 				    return (1);
386 			    if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
387 				    return (1);
388 			}
389 		}
390 		selrecord(p, &pti->pt_selw);
391 		break;
392 
393 	}
394 	return (0);
395 }
396 
397 ptcwrite(dev, uio, flag)
398 	dev_t dev;
399 	register struct uio *uio;
400 	int flag;
401 {
402 	register struct tty *tp = &pt_tty[minor(dev)];
403 	register u_char *cp;
404 	register int cc = 0;
405 	u_char locbuf[BUFSIZ];
406 	int cnt = 0;
407 	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
408 	int error = 0;
409 
410 again:
411 	if ((tp->t_state&TS_ISOPEN) == 0)
412 		goto block;
413 	if (pti->pt_flags & PF_REMOTE) {
414 		if (tp->t_canq.c_cc)
415 			goto block;
416 		while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
417 			if (cc == 0) {
418 				cc = min(uio->uio_resid, BUFSIZ);
419 				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
420 				cp = locbuf;
421 				error = uiomove((caddr_t)cp, cc, uio);
422 				if (error)
423 					return (error);
424 				/* check again for safety */
425 				if ((tp->t_state&TS_ISOPEN) == 0)
426 					return (EIO);
427 			}
428 			if (cc)
429 				(void) b_to_q((char *)cp, cc, &tp->t_canq);
430 			cc = 0;
431 		}
432 		(void) putc(0, &tp->t_canq);
433 		ttwakeup(tp);
434 		wakeup((caddr_t)&tp->t_canq);
435 		return (0);
436 	}
437 	while (uio->uio_resid > 0) {
438 		if (cc == 0) {
439 			cc = min(uio->uio_resid, BUFSIZ);
440 			cp = locbuf;
441 			error = uiomove((caddr_t)cp, cc, uio);
442 			if (error)
443 				return (error);
444 			/* check again for safety */
445 			if ((tp->t_state&TS_ISOPEN) == 0)
446 				return (EIO);
447 		}
448 		while (cc > 0) {
449 			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
450 			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
451 				wakeup((caddr_t)&tp->t_rawq);
452 				goto block;
453 			}
454 			(*linesw[tp->t_line].l_rint)(*cp++, tp);
455 			cnt++;
456 			cc--;
457 		}
458 		cc = 0;
459 	}
460 	return (0);
461 block:
462 	/*
463 	 * Come here to wait for slave to open, for space
464 	 * in outq, or space in rawq.
465 	 */
466 	if ((tp->t_state&TS_CARR_ON) == 0)
467 		return (EIO);
468 	if (flag & IO_NDELAY) {
469 		/* adjust for data copied in but not written */
470 		uio->uio_resid += cc;
471 		if (cnt == 0)
472 			return (EWOULDBLOCK);
473 		return (0);
474 	}
475 	if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
476 	    ttyout, 0)) {
477 		/* adjust for data copied in but not written */
478 		uio->uio_resid += cc;
479 		return (error);
480 	}
481 	goto again;
482 }
483 
484 /*ARGSUSED*/
485 ptyioctl(dev, cmd, data, flag, p)
486 	dev_t dev;
487 	int cmd;
488 	caddr_t data;
489 	int flag;
490 	struct proc *p;
491 {
492 	register struct tty *tp = &pt_tty[minor(dev)];
493 	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
494 	register u_char *cc = tp->t_cc;
495 	int stop, error;
496 
497 	/*
498 	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
499 	 * ttywflush(tp) will hang if there are characters in the outq.
500 	 */
501 	if (cmd == TIOCEXT) {
502 		/*
503 		 * When the EXTPROC bit is being toggled, we need
504 		 * to send an TIOCPKT_IOCTL if the packet driver
505 		 * is turned on.
506 		 */
507 		if (*(int *)data) {
508 			if (pti->pt_flags & PF_PKT) {
509 				pti->pt_send |= TIOCPKT_IOCTL;
510 				ptcwakeup(tp);
511 			}
512 			tp->t_lflag |= EXTPROC;
513 		} else {
514 			if ((tp->t_state & EXTPROC) &&
515 			    (pti->pt_flags & PF_PKT)) {
516 				pti->pt_send |= TIOCPKT_IOCTL;
517 				ptcwakeup(tp);
518 			}
519 			tp->t_lflag &= ~EXTPROC;
520 		}
521 		return(0);
522 	} else
523 	if (cdevsw[major(dev)].d_open == ptcopen)
524 		switch (cmd) {
525 
526 		case TIOCGPGRP:
527 			/*
528 			 * We aviod calling ttioctl on the controller since,
529 			 * in that case, tp must be the controlling terminal.
530 			 */
531 			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
532 			return (0);
533 
534 		case TIOCPKT:
535 			if (*(int *)data) {
536 				if (pti->pt_flags & PF_UCNTL)
537 					return (EINVAL);
538 				pti->pt_flags |= PF_PKT;
539 			} else
540 				pti->pt_flags &= ~PF_PKT;
541 			return (0);
542 
543 		case TIOCUCNTL:
544 			if (*(int *)data) {
545 				if (pti->pt_flags & PF_PKT)
546 					return (EINVAL);
547 				pti->pt_flags |= PF_UCNTL;
548 			} else
549 				pti->pt_flags &= ~PF_UCNTL;
550 			return (0);
551 
552 		case TIOCREMOTE:
553 			if (*(int *)data)
554 				pti->pt_flags |= PF_REMOTE;
555 			else
556 				pti->pt_flags &= ~PF_REMOTE;
557 			ttyflush(tp, FREAD|FWRITE);
558 			return (0);
559 
560 #ifdef COMPAT_43
561 		case TIOCSETP:
562 		case TIOCSETN:
563 #endif
564 		case TIOCSETD:
565 		case TIOCSETA:
566 		case TIOCSETAW:
567 		case TIOCSETAF:
568 			ndflush(&tp->t_outq, tp->t_outq.c_cc);
569 			break;
570 
571 		case TIOCSIG:
572 			if (*(unsigned int *)data >= NSIG)
573 				return(EINVAL);
574 			if ((tp->t_lflag&NOFLSH) == 0)
575 				ttyflush(tp, FREAD|FWRITE);
576 			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
577 			if ((*(unsigned int *)data == SIGINFO) &&
578 			    ((tp->t_lflag&NOKERNINFO) == 0))
579 				ttyinfo(tp);
580 			return(0);
581 		}
582 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
583 	if (error < 0)
584 		 error = ttioctl(tp, cmd, data, flag);
585 	if (error < 0) {
586 		if (pti->pt_flags & PF_UCNTL &&
587 		    (cmd & ~0xff) == UIOCCMD(0)) {
588 			if (cmd & 0xff) {
589 				pti->pt_ucntl = (u_char)cmd;
590 				ptcwakeup(tp, FREAD);
591 			}
592 			return (0);
593 		}
594 		error = ENOTTY;
595 	}
596 	/*
597 	 * If external processing and packet mode send ioctl packet.
598 	 */
599 	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
600 		switch(cmd) {
601 		case TIOCSETA:
602 		case TIOCSETAW:
603 		case TIOCSETAF:
604 #ifdef COMPAT_43
605 		case TIOCSETP:
606 		case TIOCSETN:
607 #endif
608 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
609 		case TIOCSETC:
610 		case TIOCSLTC:
611 		case TIOCLBIS:
612 		case TIOCLBIC:
613 		case TIOCLSET:
614 #endif
615 			pti->pt_send |= TIOCPKT_IOCTL;
616 		default:
617 			break;
618 		}
619 	}
620 	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
621 		&& CCEQ(cc[VSTART], CTRL('q'));
622 	if (pti->pt_flags & PF_NOSTOP) {
623 		if (stop) {
624 			pti->pt_send &= ~TIOCPKT_NOSTOP;
625 			pti->pt_send |= TIOCPKT_DOSTOP;
626 			pti->pt_flags &= ~PF_NOSTOP;
627 			ptcwakeup(tp, FREAD);
628 		}
629 	} else {
630 		if (!stop) {
631 			pti->pt_send &= ~TIOCPKT_DOSTOP;
632 			pti->pt_send |= TIOCPKT_NOSTOP;
633 			pti->pt_flags |= PF_NOSTOP;
634 			ptcwakeup(tp, FREAD);
635 		}
636 	}
637 	return (error);
638 }
639 #endif
640