pty.c revision 78405
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)tty_pty.c	8.4 (Berkeley) 2/20/95
34 * $FreeBSD: head/sys/kern/tty_pty.c 78405 2001-06-18 09:22:30Z brian $
35 */
36
37/*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41#include "opt_compat.h"
42#include <sys/param.h>
43#include <sys/systm.h>
44#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
45#include <sys/ioctl_compat.h>
46#endif
47#include <sys/proc.h>
48#include <sys/tty.h>
49#include <sys/conf.h>
50#include <sys/fcntl.h>
51#include <sys/poll.h>
52#include <sys/kernel.h>
53#include <sys/vnode.h>
54#include <sys/signalvar.h>
55#include <sys/malloc.h>
56
57static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
58
59static void ptsstart __P((struct tty *tp));
60static void ptsstop __P((struct tty *tp, int rw));
61static void ptcwakeup __P((struct tty *tp, int flag));
62static dev_t ptyinit __P((dev_t cdev));
63
64static	d_open_t	ptsopen;
65static	d_close_t	ptsclose;
66static	d_read_t	ptsread;
67static	d_write_t	ptswrite;
68static	d_ioctl_t	ptyioctl;
69static	d_open_t	ptcopen;
70static	d_close_t	ptcclose;
71static	d_read_t	ptcread;
72static	d_write_t	ptcwrite;
73static	d_poll_t	ptcpoll;
74
75#define	CDEV_MAJOR_S	5
76static struct cdevsw pts_cdevsw = {
77	/* open */	ptsopen,
78	/* close */	ptsclose,
79	/* read */	ptsread,
80	/* write */	ptswrite,
81	/* ioctl */	ptyioctl,
82	/* poll */	ttypoll,
83	/* mmap */	nommap,
84	/* strategy */	nostrategy,
85	/* name */	"pts",
86	/* maj */	CDEV_MAJOR_S,
87	/* dump */	nodump,
88	/* psize */	nopsize,
89	/* flags */	D_TTY | D_KQFILTER,
90	/* kqfilter */	ttykqfilter,
91};
92
93#define	CDEV_MAJOR_C	6
94static struct cdevsw ptc_cdevsw = {
95	/* open */	ptcopen,
96	/* close */	ptcclose,
97	/* read */	ptcread,
98	/* write */	ptcwrite,
99	/* ioctl */	ptyioctl,
100	/* poll */	ptcpoll,
101	/* mmap */	nommap,
102	/* strategy */	nostrategy,
103	/* name */	"ptc",
104	/* maj */	CDEV_MAJOR_C,
105	/* dump */	nodump,
106	/* psize */	nopsize,
107	/* flags */	D_TTY | D_KQFILTER,
108	/* kqfilter */	ttykqfilter,
109};
110
111#define BUFSIZ 100		/* Chunk size iomoved to/from user */
112
113struct	pt_ioctl {
114	int	pt_flags;
115	struct	selinfo pt_selr, pt_selw;
116	u_char	pt_send;
117	u_char	pt_ucntl;
118	struct tty pt_tty;
119	dev_t	devs, devc;
120	struct	prison *pt_prison;
121};
122
123#define	PF_PKT		0x08		/* packet mode */
124#define	PF_STOPPED	0x10		/* user told stopped */
125#define	PF_REMOTE	0x20		/* remote and flow controlled input */
126#define	PF_NOSTOP	0x40
127#define PF_UCNTL	0x80		/* user control mode */
128
129static char *names = "pqrsPQRS";
130/*
131 * This function creates and initializes a pts/ptc pair
132 *
133 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
134 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
135 *
136 * XXX: define and add mapping of upper minor bits to allow more
137 *      than 256 ptys.
138 */
139static dev_t
140ptyinit(dev_t devc)
141{
142	dev_t devs;
143	struct pt_ioctl *pt;
144	int n;
145
146	n = minor(devc);
147	/* For now we only map the lower 8 bits of the minor */
148	if (n & ~0xff)
149		return (NODEV);
150
151	devc->si_flags &= ~SI_CHEAPCLONE;
152
153	pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
154	pt->devs = devs = make_dev(&pts_cdevsw, n,
155	    UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
156	pt->devc = devc;
157
158	devs->si_drv1 = devc->si_drv1 = pt;
159	devs->si_tty = devc->si_tty = &pt->pt_tty;
160	pt->pt_tty.t_dev = devs;
161	ttyregister(&pt->pt_tty);
162	return (devc);
163}
164
165/*ARGSUSED*/
166static	int
167ptsopen(dev, flag, devtype, p)
168	dev_t dev;
169	int flag, devtype;
170	struct proc *p;
171{
172	register struct tty *tp;
173	int error;
174	struct pt_ioctl *pti;
175
176	if (!dev->si_drv1)
177		return(ENXIO);
178	pti = dev->si_drv1;
179	tp = dev->si_tty;
180	if ((tp->t_state & TS_ISOPEN) == 0) {
181		ttychars(tp);		/* Set up default chars */
182		tp->t_iflag = TTYDEF_IFLAG;
183		tp->t_oflag = TTYDEF_OFLAG;
184		tp->t_lflag = TTYDEF_LFLAG;
185		tp->t_cflag = TTYDEF_CFLAG;
186		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
187	} else if (tp->t_state & TS_XCLUDE && suser(p)) {
188		return (EBUSY);
189	} else if (pti->pt_prison != p->p_ucred->cr_prison) {
190		return (EBUSY);
191	}
192	if (tp->t_oproc)			/* Ctrlr still around. */
193		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
194	while ((tp->t_state & TS_CARR_ON) == 0) {
195		if (flag&FNONBLOCK)
196			break;
197		error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
198				 "ptsopn", 0);
199		if (error)
200			return (error);
201	}
202	error = (*linesw[tp->t_line].l_open)(dev, tp);
203	if (error == 0)
204		ptcwakeup(tp, FREAD|FWRITE);
205	return (error);
206}
207
208static	int
209ptsclose(dev, flag, mode, p)
210	dev_t dev;
211	int flag, mode;
212	struct proc *p;
213{
214	register struct tty *tp;
215	int err;
216
217	tp = dev->si_tty;
218	err = (*linesw[tp->t_line].l_close)(tp, flag);
219	ptsstop(tp, FREAD|FWRITE);
220	(void) ttyclose(tp);
221	return (err);
222}
223
224static	int
225ptsread(dev, uio, flag)
226	dev_t dev;
227	struct uio *uio;
228	int flag;
229{
230	struct proc *p = curproc;
231	register struct tty *tp = dev->si_tty;
232	register struct pt_ioctl *pti = dev->si_drv1;
233	int error = 0;
234
235again:
236	if (pti->pt_flags & PF_REMOTE) {
237		while (isbackground(p, tp)) {
238			if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
239			    SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
240			    p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
241				return (EIO);
242			pgsignal(p->p_pgrp, SIGTTIN, 1);
243			error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
244					 0);
245			if (error)
246				return (error);
247		}
248		if (tp->t_canq.c_cc == 0) {
249			if (flag & IO_NDELAY)
250				return (EWOULDBLOCK);
251			error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
252					 "ptsin", 0);
253			if (error)
254				return (error);
255			goto again;
256		}
257		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
258			if (ureadc(getc(&tp->t_canq), uio) < 0) {
259				error = EFAULT;
260				break;
261			}
262		if (tp->t_canq.c_cc == 1)
263			(void) getc(&tp->t_canq);
264		if (tp->t_canq.c_cc)
265			return (error);
266	} else
267		if (tp->t_oproc)
268			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
269	ptcwakeup(tp, FWRITE);
270	return (error);
271}
272
273/*
274 * Write to pseudo-tty.
275 * Wakeups of controlling tty will happen
276 * indirectly, when tty driver calls ptsstart.
277 */
278static	int
279ptswrite(dev, uio, flag)
280	dev_t dev;
281	struct uio *uio;
282	int flag;
283{
284	register struct tty *tp;
285
286	tp = dev->si_tty;
287	if (tp->t_oproc == 0)
288		return (EIO);
289	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
290}
291
292/*
293 * Start output on pseudo-tty.
294 * Wake up process selecting or sleeping for input from controlling tty.
295 */
296static void
297ptsstart(tp)
298	struct tty *tp;
299{
300	register struct pt_ioctl *pti = tp->t_dev->si_drv1;
301
302	if (tp->t_state & TS_TTSTOP)
303		return;
304	if (pti->pt_flags & PF_STOPPED) {
305		pti->pt_flags &= ~PF_STOPPED;
306		pti->pt_send = TIOCPKT_START;
307	}
308	ptcwakeup(tp, FREAD);
309}
310
311static void
312ptcwakeup(tp, flag)
313	struct tty *tp;
314	int flag;
315{
316	struct pt_ioctl *pti = tp->t_dev->si_drv1;
317
318	if (flag & FREAD) {
319		selwakeup(&pti->pt_selr);
320		wakeup(TSA_PTC_READ(tp));
321	}
322	if (flag & FWRITE) {
323		selwakeup(&pti->pt_selw);
324		wakeup(TSA_PTC_WRITE(tp));
325	}
326}
327
328static	int
329ptcopen(dev, flag, devtype, p)
330	dev_t dev;
331	int flag, devtype;
332	struct proc *p;
333{
334	register struct tty *tp;
335	struct pt_ioctl *pti;
336
337	if (!dev->si_drv1)
338		ptyinit(dev);
339	if (!dev->si_drv1)
340		return(ENXIO);
341	tp = dev->si_tty;
342	if (tp->t_oproc)
343		return (EIO);
344	tp->t_timeout = -1;
345	tp->t_oproc = ptsstart;
346	tp->t_stop = ptsstop;
347	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
348	tp->t_lflag &= ~EXTPROC;
349	pti = dev->si_drv1;
350	pti->pt_prison = p->p_ucred->cr_prison;
351	pti->pt_flags = 0;
352	pti->pt_send = 0;
353	pti->pt_ucntl = 0;
354	return (0);
355}
356
357static	int
358ptcclose(dev, flags, fmt, p)
359	dev_t dev;
360	int flags;
361	int fmt;
362	struct proc *p;
363{
364	register struct tty *tp;
365
366	tp = dev->si_tty;
367	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
368
369	/*
370	 * XXX MDMBUF makes no sense for ptys but would inhibit the above
371	 * l_modem().  CLOCAL makes sense but isn't supported.   Special
372	 * l_modem()s that ignore carrier drop make no sense for ptys but
373	 * may be in use because other parts of the line discipline make
374	 * sense for ptys.  Recover by doing everything that a normal
375	 * ttymodem() would have done except for sending a SIGHUP.
376	 */
377	if (tp->t_state & TS_ISOPEN) {
378		tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
379		tp->t_state |= TS_ZOMBIE;
380		ttyflush(tp, FREAD | FWRITE);
381	}
382
383	tp->t_oproc = 0;		/* mark closed */
384	return (0);
385}
386
387static	int
388ptcread(dev, uio, flag)
389	dev_t dev;
390	struct uio *uio;
391	int flag;
392{
393	register struct tty *tp = dev->si_tty;
394	struct pt_ioctl *pti = dev->si_drv1;
395	char buf[BUFSIZ];
396	int error = 0, cc;
397
398	/*
399	 * We want to block until the slave
400	 * is open, and there's something to read;
401	 * but if we lost the slave or we're NBIO,
402	 * then return the appropriate error instead.
403	 */
404	for (;;) {
405		if (tp->t_state&TS_ISOPEN) {
406			if (pti->pt_flags&PF_PKT && pti->pt_send) {
407				error = ureadc((int)pti->pt_send, uio);
408				if (error)
409					return (error);
410				if (pti->pt_send & TIOCPKT_IOCTL) {
411					cc = min(uio->uio_resid,
412						sizeof(tp->t_termios));
413					uiomove((caddr_t)&tp->t_termios, cc,
414						uio);
415				}
416				pti->pt_send = 0;
417				return (0);
418			}
419			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
420				error = ureadc((int)pti->pt_ucntl, uio);
421				if (error)
422					return (error);
423				pti->pt_ucntl = 0;
424				return (0);
425			}
426			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
427				break;
428		}
429		if ((tp->t_state & TS_CONNECTED) == 0)
430			return (0);	/* EOF */
431		if (flag & IO_NDELAY)
432			return (EWOULDBLOCK);
433		error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
434		if (error)
435			return (error);
436	}
437	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
438		error = ureadc(0, uio);
439	while (uio->uio_resid > 0 && error == 0) {
440		cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
441		if (cc <= 0)
442			break;
443		error = uiomove(buf, cc, uio);
444	}
445	ttwwakeup(tp);
446	return (error);
447}
448
449static	void
450ptsstop(tp, flush)
451	register struct tty *tp;
452	int flush;
453{
454	struct pt_ioctl *pti = tp->t_dev->si_drv1;
455	int flag;
456
457	/* note: FLUSHREAD and FLUSHWRITE already ok */
458	if (flush == 0) {
459		flush = TIOCPKT_STOP;
460		pti->pt_flags |= PF_STOPPED;
461	} else
462		pti->pt_flags &= ~PF_STOPPED;
463	pti->pt_send |= flush;
464	/* change of perspective */
465	flag = 0;
466	if (flush & FREAD)
467		flag |= FWRITE;
468	if (flush & FWRITE)
469		flag |= FREAD;
470	ptcwakeup(tp, flag);
471}
472
473static	int
474ptcpoll(dev, events, p)
475	dev_t dev;
476	int events;
477	struct proc *p;
478{
479	register struct tty *tp = dev->si_tty;
480	struct pt_ioctl *pti = dev->si_drv1;
481	int revents = 0;
482	int s;
483
484	if ((tp->t_state & TS_CONNECTED) == 0)
485		return (seltrue(dev, events, p) | POLLHUP);
486
487	/*
488	 * Need to block timeouts (ttrstart).
489	 */
490	s = spltty();
491
492	if (events & (POLLIN | POLLRDNORM))
493		if ((tp->t_state & TS_ISOPEN) &&
494		    ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
495		     ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
496		     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
497			revents |= events & (POLLIN | POLLRDNORM);
498
499	if (events & (POLLOUT | POLLWRNORM))
500		if (tp->t_state & TS_ISOPEN &&
501		    ((pti->pt_flags & PF_REMOTE) ?
502		     (tp->t_canq.c_cc == 0) :
503		     ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
504		      (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON)))))
505			revents |= events & (POLLOUT | POLLWRNORM);
506
507	if (events & POLLHUP)
508		if ((tp->t_state & TS_CARR_ON) == 0)
509			revents |= POLLHUP;
510
511	if (revents == 0) {
512		if (events & (POLLIN | POLLRDNORM))
513			selrecord(p, &pti->pt_selr);
514
515		if (events & (POLLOUT | POLLWRNORM))
516			selrecord(p, &pti->pt_selw);
517	}
518	splx(s);
519
520	return (revents);
521}
522
523static	int
524ptcwrite(dev, uio, flag)
525	dev_t dev;
526	register struct uio *uio;
527	int flag;
528{
529	register struct tty *tp = dev->si_tty;
530	register u_char *cp = 0;
531	register int cc = 0;
532	u_char locbuf[BUFSIZ];
533	int cnt = 0;
534	struct pt_ioctl *pti = dev->si_drv1;
535	int error = 0;
536
537again:
538	if ((tp->t_state&TS_ISOPEN) == 0)
539		goto block;
540	if (pti->pt_flags & PF_REMOTE) {
541		if (tp->t_canq.c_cc)
542			goto block;
543		while ((uio->uio_resid > 0 || cc > 0) &&
544		       tp->t_canq.c_cc < TTYHOG - 1) {
545			if (cc == 0) {
546				cc = min(uio->uio_resid, BUFSIZ);
547				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
548				cp = locbuf;
549				error = uiomove((caddr_t)cp, cc, uio);
550				if (error)
551					return (error);
552				/* check again for safety */
553				if ((tp->t_state & TS_ISOPEN) == 0) {
554					/* adjust as usual */
555					uio->uio_resid += cc;
556					return (EIO);
557				}
558			}
559			if (cc > 0) {
560				cc = b_to_q((char *)cp, cc, &tp->t_canq);
561				/*
562				 * XXX we don't guarantee that the canq size
563				 * is >= TTYHOG, so the above b_to_q() may
564				 * leave some bytes uncopied.  However, space
565				 * is guaranteed for the null terminator if
566				 * we don't fail here since (TTYHOG - 1) is
567				 * not a multiple of CBSIZE.
568				 */
569				if (cc > 0)
570					break;
571			}
572		}
573		/* adjust for data copied in but not written */
574		uio->uio_resid += cc;
575		(void) putc(0, &tp->t_canq);
576		ttwakeup(tp);
577		wakeup(TSA_PTS_READ(tp));
578		return (0);
579	}
580	while (uio->uio_resid > 0 || cc > 0) {
581		if (cc == 0) {
582			cc = min(uio->uio_resid, BUFSIZ);
583			cp = locbuf;
584			error = uiomove((caddr_t)cp, cc, uio);
585			if (error)
586				return (error);
587			/* check again for safety */
588			if ((tp->t_state & TS_ISOPEN) == 0) {
589				/* adjust for data copied in but not written */
590				uio->uio_resid += cc;
591				return (EIO);
592			}
593		}
594		while (cc > 0) {
595			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
596			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
597				wakeup(TSA_HUP_OR_INPUT(tp));
598				goto block;
599			}
600			(*linesw[tp->t_line].l_rint)(*cp++, tp);
601			cnt++;
602			cc--;
603		}
604		cc = 0;
605	}
606	return (0);
607block:
608	/*
609	 * Come here to wait for slave to open, for space
610	 * in outq, or space in rawq, or an empty canq.
611	 */
612	if ((tp->t_state & TS_CONNECTED) == 0) {
613		/* adjust for data copied in but not written */
614		uio->uio_resid += cc;
615		return (EIO);
616	}
617	if (flag & IO_NDELAY) {
618		/* adjust for data copied in but not written */
619		uio->uio_resid += cc;
620		if (cnt == 0)
621			return (EWOULDBLOCK);
622		return (0);
623	}
624	error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
625	if (error) {
626		/* adjust for data copied in but not written */
627		uio->uio_resid += cc;
628		return (error);
629	}
630	goto again;
631}
632
633/*ARGSUSED*/
634static	int
635ptyioctl(dev, cmd, data, flag, p)
636	dev_t dev;
637	u_long cmd;
638	caddr_t data;
639	int flag;
640	struct proc *p;
641{
642	register struct tty *tp = dev->si_tty;
643	register struct pt_ioctl *pti = dev->si_drv1;
644	register u_char *cc = tp->t_cc;
645	int stop, error;
646
647	if (devsw(dev)->d_open == ptcopen) {
648		switch (cmd) {
649
650		case TIOCGPGRP:
651			/*
652			 * We avoid calling ttioctl on the controller since,
653			 * in that case, tp must be the controlling terminal.
654			 */
655			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
656			return (0);
657
658		case TIOCPKT:
659			if (*(int *)data) {
660				if (pti->pt_flags & PF_UCNTL)
661					return (EINVAL);
662				pti->pt_flags |= PF_PKT;
663			} else
664				pti->pt_flags &= ~PF_PKT;
665			return (0);
666
667		case TIOCUCNTL:
668			if (*(int *)data) {
669				if (pti->pt_flags & PF_PKT)
670					return (EINVAL);
671				pti->pt_flags |= PF_UCNTL;
672			} else
673				pti->pt_flags &= ~PF_UCNTL;
674			return (0);
675
676		case TIOCREMOTE:
677			if (*(int *)data)
678				pti->pt_flags |= PF_REMOTE;
679			else
680				pti->pt_flags &= ~PF_REMOTE;
681			ttyflush(tp, FREAD|FWRITE);
682			return (0);
683		}
684
685		/*
686		 * The rest of the ioctls shouldn't be called until
687		 * the slave is open.
688		 */
689		if ((tp->t_state & TS_ISOPEN) == 0)
690			return (EAGAIN);
691
692		switch (cmd) {
693#ifdef COMPAT_43
694		case TIOCSETP:
695		case TIOCSETN:
696#endif
697		case TIOCSETD:
698		case TIOCSETA:
699		case TIOCSETAW:
700		case TIOCSETAF:
701			/*
702			 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
703			 * ttywflush(tp) will hang if there are characters in
704			 * the outq.
705			 */
706			ndflush(&tp->t_outq, tp->t_outq.c_cc);
707			break;
708
709		case TIOCSIG:
710			if (*(unsigned int *)data >= NSIG ||
711			    *(unsigned int *)data == 0)
712				return(EINVAL);
713			if ((tp->t_lflag&NOFLSH) == 0)
714				ttyflush(tp, FREAD|FWRITE);
715			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
716			if ((*(unsigned int *)data == SIGINFO) &&
717			    ((tp->t_lflag&NOKERNINFO) == 0))
718				ttyinfo(tp);
719			return(0);
720		}
721	}
722	if (cmd == TIOCEXT) {
723		/*
724		 * When the EXTPROC bit is being toggled, we need
725		 * to send an TIOCPKT_IOCTL if the packet driver
726		 * is turned on.
727		 */
728		if (*(int *)data) {
729			if (pti->pt_flags & PF_PKT) {
730				pti->pt_send |= TIOCPKT_IOCTL;
731				ptcwakeup(tp, FREAD);
732			}
733			tp->t_lflag |= EXTPROC;
734		} else {
735			if ((tp->t_lflag & EXTPROC) &&
736			    (pti->pt_flags & PF_PKT)) {
737				pti->pt_send |= TIOCPKT_IOCTL;
738				ptcwakeup(tp, FREAD);
739			}
740			tp->t_lflag &= ~EXTPROC;
741		}
742		return(0);
743	}
744	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
745	if (error == ENOIOCTL)
746		 error = ttioctl(tp, cmd, data, flag);
747	if (error == ENOIOCTL) {
748		if (pti->pt_flags & PF_UCNTL &&
749		    (cmd & ~0xff) == UIOCCMD(0)) {
750			if (cmd & 0xff) {
751				pti->pt_ucntl = (u_char)cmd;
752				ptcwakeup(tp, FREAD);
753			}
754			return (0);
755		}
756		error = ENOTTY;
757	}
758	/*
759	 * If external processing and packet mode send ioctl packet.
760	 */
761	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
762		switch(cmd) {
763		case TIOCSETA:
764		case TIOCSETAW:
765		case TIOCSETAF:
766#ifdef COMPAT_43
767		case TIOCSETP:
768		case TIOCSETN:
769#endif
770#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
771		case TIOCSETC:
772		case TIOCSLTC:
773		case TIOCLBIS:
774		case TIOCLBIC:
775		case TIOCLSET:
776#endif
777			pti->pt_send |= TIOCPKT_IOCTL;
778			ptcwakeup(tp, FREAD);
779		default:
780			break;
781		}
782	}
783	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
784		&& CCEQ(cc[VSTART], CTRL('q'));
785	if (pti->pt_flags & PF_NOSTOP) {
786		if (stop) {
787			pti->pt_send &= ~TIOCPKT_NOSTOP;
788			pti->pt_send |= TIOCPKT_DOSTOP;
789			pti->pt_flags &= ~PF_NOSTOP;
790			ptcwakeup(tp, FREAD);
791		}
792	} else {
793		if (!stop) {
794			pti->pt_send &= ~TIOCPKT_DOSTOP;
795			pti->pt_send |= TIOCPKT_NOSTOP;
796			pti->pt_flags |= PF_NOSTOP;
797			ptcwakeup(tp, FREAD);
798		}
799	}
800	return (error);
801}
802
803
804static void ptc_drvinit __P((void *unused));
805
806static void pty_clone __P((void *arg, char *name, int namelen, dev_t *dev));
807
808static void
809pty_clone(arg, name, namelen, dev)
810	void *arg;
811	char *name;
812	int namelen;
813	dev_t *dev;
814{
815	int u;
816
817	if (*dev != NODEV)
818		return;
819	if (bcmp(name, "pty", 3) != 0)
820		return;
821	if (name[5] != '\0')
822		return;
823	switch (name[3]) {
824	case 'p': u =   0; break;
825	case 'q': u =  32; break;
826	case 'r': u =  64; break;
827	case 's': u =  96; break;
828	case 'P': u = 128; break;
829	case 'Q': u = 160; break;
830	case 'R': u = 192; break;
831	case 'S': u = 224; break;
832	default: return;
833	}
834	if (name[4] >= '0' && name[4] <= '9')
835		u += name[4] - '0';
836	else if (name[4] >= 'a' && name[4] <= 'v')
837		u += name[4] - 'a' + 10;
838	else
839		return;
840	*dev = make_dev(&ptc_cdevsw, u,
841	    UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
842	(*dev)->si_flags |= SI_CHEAPCLONE;
843	return;
844}
845
846static void
847ptc_drvinit(unused)
848	void *unused;
849{
850	EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
851	cdevsw_add(&pts_cdevsw);
852	cdevsw_add(&ptc_cdevsw);
853}
854
855SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
856