pty.c revision 77176
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 77176 2001-05-25 13:23:42Z phk $
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	devc->si_flags &= ~SI_CHEAPCLONE;
147	n = minor(devc);
148	/* For now we only map the lower 8 bits of the minor */
149	if (n & ~0xff)
150		return (NODEV);
151
152	pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
153	pt->devs = devs = make_dev(&pts_cdevsw, n,
154	    UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
155	pt->devc = devc;
156
157	devs->si_drv1 = devc->si_drv1 = pt;
158	devs->si_tty = devc->si_tty = &pt->pt_tty;
159	ttyregister(&pt->pt_tty);
160	return (devc);
161}
162
163/*ARGSUSED*/
164static	int
165ptsopen(dev, flag, devtype, p)
166	dev_t dev;
167	int flag, devtype;
168	struct proc *p;
169{
170	register struct tty *tp;
171	int error;
172	struct pt_ioctl *pti;
173
174	if (!dev->si_drv1)
175		return(ENXIO);
176	pti = dev->si_drv1;
177	tp = dev->si_tty;
178	if ((tp->t_state & TS_ISOPEN) == 0) {
179		ttychars(tp);		/* Set up default chars */
180		tp->t_iflag = TTYDEF_IFLAG;
181		tp->t_oflag = TTYDEF_OFLAG;
182		tp->t_lflag = TTYDEF_LFLAG;
183		tp->t_cflag = TTYDEF_CFLAG;
184		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
185	} else if (tp->t_state & TS_XCLUDE && suser(p)) {
186		return (EBUSY);
187	} else if (pti->pt_prison != p->p_ucred->cr_prison) {
188		return (EBUSY);
189	}
190	if (tp->t_oproc)			/* Ctrlr still around. */
191		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
192	while ((tp->t_state & TS_CARR_ON) == 0) {
193		if (flag&FNONBLOCK)
194			break;
195		error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
196				 "ptsopn", 0);
197		if (error)
198			return (error);
199	}
200	error = (*linesw[tp->t_line].l_open)(dev, tp);
201	if (error == 0)
202		ptcwakeup(tp, FREAD|FWRITE);
203	return (error);
204}
205
206static	int
207ptsclose(dev, flag, mode, p)
208	dev_t dev;
209	int flag, mode;
210	struct proc *p;
211{
212	register struct tty *tp;
213	int err;
214
215	tp = dev->si_tty;
216	err = (*linesw[tp->t_line].l_close)(tp, flag);
217	ptsstop(tp, FREAD|FWRITE);
218	(void) ttyclose(tp);
219	return (err);
220}
221
222static	int
223ptsread(dev, uio, flag)
224	dev_t dev;
225	struct uio *uio;
226	int flag;
227{
228	struct proc *p = curproc;
229	register struct tty *tp = dev->si_tty;
230	register struct pt_ioctl *pti = dev->si_drv1;
231	int error = 0;
232
233again:
234	if (pti->pt_flags & PF_REMOTE) {
235		while (isbackground(p, tp)) {
236			if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
237			    SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
238			    p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
239				return (EIO);
240			pgsignal(p->p_pgrp, SIGTTIN, 1);
241			error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
242					 0);
243			if (error)
244				return (error);
245		}
246		if (tp->t_canq.c_cc == 0) {
247			if (flag & IO_NDELAY)
248				return (EWOULDBLOCK);
249			error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
250					 "ptsin", 0);
251			if (error)
252				return (error);
253			goto again;
254		}
255		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
256			if (ureadc(getc(&tp->t_canq), uio) < 0) {
257				error = EFAULT;
258				break;
259			}
260		if (tp->t_canq.c_cc == 1)
261			(void) getc(&tp->t_canq);
262		if (tp->t_canq.c_cc)
263			return (error);
264	} else
265		if (tp->t_oproc)
266			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
267	ptcwakeup(tp, FWRITE);
268	return (error);
269}
270
271/*
272 * Write to pseudo-tty.
273 * Wakeups of controlling tty will happen
274 * indirectly, when tty driver calls ptsstart.
275 */
276static	int
277ptswrite(dev, uio, flag)
278	dev_t dev;
279	struct uio *uio;
280	int flag;
281{
282	register struct tty *tp;
283
284	tp = dev->si_tty;
285	if (tp->t_oproc == 0)
286		return (EIO);
287	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
288}
289
290/*
291 * Start output on pseudo-tty.
292 * Wake up process selecting or sleeping for input from controlling tty.
293 */
294static void
295ptsstart(tp)
296	struct tty *tp;
297{
298	register struct pt_ioctl *pti = tp->t_dev->si_drv1;
299
300	if (tp->t_state & TS_TTSTOP)
301		return;
302	if (pti->pt_flags & PF_STOPPED) {
303		pti->pt_flags &= ~PF_STOPPED;
304		pti->pt_send = TIOCPKT_START;
305	}
306	ptcwakeup(tp, FREAD);
307}
308
309static void
310ptcwakeup(tp, flag)
311	struct tty *tp;
312	int flag;
313{
314	struct pt_ioctl *pti = tp->t_dev->si_drv1;
315
316	if (flag & FREAD) {
317		selwakeup(&pti->pt_selr);
318		wakeup(TSA_PTC_READ(tp));
319	}
320	if (flag & FWRITE) {
321		selwakeup(&pti->pt_selw);
322		wakeup(TSA_PTC_WRITE(tp));
323	}
324}
325
326static	int
327ptcopen(dev, flag, devtype, p)
328	dev_t dev;
329	int flag, devtype;
330	struct proc *p;
331{
332	register struct tty *tp;
333	struct pt_ioctl *pti;
334
335	if (!dev->si_drv1)
336		ptyinit(dev);
337	if (!dev->si_drv1)
338		return(ENXIO);
339	tp = dev->si_tty;
340	if (tp->t_oproc)
341		return (EIO);
342	tp->t_timeout = -1;
343	tp->t_oproc = ptsstart;
344	tp->t_stop = ptsstop;
345	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
346	tp->t_lflag &= ~EXTPROC;
347	pti = dev->si_drv1;
348	pti->pt_prison = p->p_ucred->cr_prison;
349	pti->pt_flags = 0;
350	pti->pt_send = 0;
351	pti->pt_ucntl = 0;
352	return (0);
353}
354
355static	int
356ptcclose(dev, flags, fmt, p)
357	dev_t dev;
358	int flags;
359	int fmt;
360	struct proc *p;
361{
362	register struct tty *tp;
363
364	tp = dev->si_tty;
365	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
366
367	/*
368	 * XXX MDMBUF makes no sense for ptys but would inhibit the above
369	 * l_modem().  CLOCAL makes sense but isn't supported.   Special
370	 * l_modem()s that ignore carrier drop make no sense for ptys but
371	 * may be in use because other parts of the line discipline make
372	 * sense for ptys.  Recover by doing everything that a normal
373	 * ttymodem() would have done except for sending a SIGHUP.
374	 */
375	if (tp->t_state & TS_ISOPEN) {
376		tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
377		tp->t_state |= TS_ZOMBIE;
378		ttyflush(tp, FREAD | FWRITE);
379	}
380
381	tp->t_oproc = 0;		/* mark closed */
382	return (0);
383}
384
385static	int
386ptcread(dev, uio, flag)
387	dev_t dev;
388	struct uio *uio;
389	int flag;
390{
391	register struct tty *tp = dev->si_tty;
392	struct pt_ioctl *pti = dev->si_drv1;
393	char buf[BUFSIZ];
394	int error = 0, cc;
395
396	/*
397	 * We want to block until the slave
398	 * is open, and there's something to read;
399	 * but if we lost the slave or we're NBIO,
400	 * then return the appropriate error instead.
401	 */
402	for (;;) {
403		if (tp->t_state&TS_ISOPEN) {
404			if (pti->pt_flags&PF_PKT && pti->pt_send) {
405				error = ureadc((int)pti->pt_send, uio);
406				if (error)
407					return (error);
408				if (pti->pt_send & TIOCPKT_IOCTL) {
409					cc = min(uio->uio_resid,
410						sizeof(tp->t_termios));
411					uiomove((caddr_t)&tp->t_termios, cc,
412						uio);
413				}
414				pti->pt_send = 0;
415				return (0);
416			}
417			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
418				error = ureadc((int)pti->pt_ucntl, uio);
419				if (error)
420					return (error);
421				pti->pt_ucntl = 0;
422				return (0);
423			}
424			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
425				break;
426		}
427		if ((tp->t_state & TS_CONNECTED) == 0)
428			return (0);	/* EOF */
429		if (flag & IO_NDELAY)
430			return (EWOULDBLOCK);
431		error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
432		if (error)
433			return (error);
434	}
435	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
436		error = ureadc(0, uio);
437	while (uio->uio_resid > 0 && error == 0) {
438		cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
439		if (cc <= 0)
440			break;
441		error = uiomove(buf, cc, uio);
442	}
443	ttwwakeup(tp);
444	return (error);
445}
446
447static	void
448ptsstop(tp, flush)
449	register struct tty *tp;
450	int flush;
451{
452	struct pt_ioctl *pti = tp->t_dev->si_drv1;
453	int flag;
454
455	/* note: FLUSHREAD and FLUSHWRITE already ok */
456	if (flush == 0) {
457		flush = TIOCPKT_STOP;
458		pti->pt_flags |= PF_STOPPED;
459	} else
460		pti->pt_flags &= ~PF_STOPPED;
461	pti->pt_send |= flush;
462	/* change of perspective */
463	flag = 0;
464	if (flush & FREAD)
465		flag |= FWRITE;
466	if (flush & FWRITE)
467		flag |= FREAD;
468	ptcwakeup(tp, flag);
469}
470
471static	int
472ptcpoll(dev, events, p)
473	dev_t dev;
474	int events;
475	struct proc *p;
476{
477	register struct tty *tp = dev->si_tty;
478	struct pt_ioctl *pti = dev->si_drv1;
479	int revents = 0;
480	int s;
481
482	if ((tp->t_state & TS_CONNECTED) == 0)
483		return (seltrue(dev, events, p) | POLLHUP);
484
485	/*
486	 * Need to block timeouts (ttrstart).
487	 */
488	s = spltty();
489
490	if (events & (POLLIN | POLLRDNORM))
491		if ((tp->t_state & TS_ISOPEN) &&
492		    ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
493		     ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
494		     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
495			revents |= events & (POLLIN | POLLRDNORM);
496
497	if (events & (POLLOUT | POLLWRNORM))
498		if (tp->t_state & TS_ISOPEN &&
499		    ((pti->pt_flags & PF_REMOTE) ?
500		     (tp->t_canq.c_cc == 0) :
501		     ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
502		      (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON)))))
503			revents |= events & (POLLOUT | POLLWRNORM);
504
505	if (events & POLLHUP)
506		if ((tp->t_state & TS_CARR_ON) == 0)
507			revents |= POLLHUP;
508
509	if (revents == 0) {
510		if (events & (POLLIN | POLLRDNORM))
511			selrecord(p, &pti->pt_selr);
512
513		if (events & (POLLOUT | POLLWRNORM))
514			selrecord(p, &pti->pt_selw);
515	}
516	splx(s);
517
518	return (revents);
519}
520
521static	int
522ptcwrite(dev, uio, flag)
523	dev_t dev;
524	register struct uio *uio;
525	int flag;
526{
527	register struct tty *tp = dev->si_tty;
528	register u_char *cp = 0;
529	register int cc = 0;
530	u_char locbuf[BUFSIZ];
531	int cnt = 0;
532	struct pt_ioctl *pti = dev->si_drv1;
533	int error = 0;
534
535again:
536	if ((tp->t_state&TS_ISOPEN) == 0)
537		goto block;
538	if (pti->pt_flags & PF_REMOTE) {
539		if (tp->t_canq.c_cc)
540			goto block;
541		while ((uio->uio_resid > 0 || cc > 0) &&
542		       tp->t_canq.c_cc < TTYHOG - 1) {
543			if (cc == 0) {
544				cc = min(uio->uio_resid, BUFSIZ);
545				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
546				cp = locbuf;
547				error = uiomove((caddr_t)cp, cc, uio);
548				if (error)
549					return (error);
550				/* check again for safety */
551				if ((tp->t_state & TS_ISOPEN) == 0) {
552					/* adjust as usual */
553					uio->uio_resid += cc;
554					return (EIO);
555				}
556			}
557			if (cc > 0) {
558				cc = b_to_q((char *)cp, cc, &tp->t_canq);
559				/*
560				 * XXX we don't guarantee that the canq size
561				 * is >= TTYHOG, so the above b_to_q() may
562				 * leave some bytes uncopied.  However, space
563				 * is guaranteed for the null terminator if
564				 * we don't fail here since (TTYHOG - 1) is
565				 * not a multiple of CBSIZE.
566				 */
567				if (cc > 0)
568					break;
569			}
570		}
571		/* adjust for data copied in but not written */
572		uio->uio_resid += cc;
573		(void) putc(0, &tp->t_canq);
574		ttwakeup(tp);
575		wakeup(TSA_PTS_READ(tp));
576		return (0);
577	}
578	while (uio->uio_resid > 0 || cc > 0) {
579		if (cc == 0) {
580			cc = min(uio->uio_resid, BUFSIZ);
581			cp = locbuf;
582			error = uiomove((caddr_t)cp, cc, uio);
583			if (error)
584				return (error);
585			/* check again for safety */
586			if ((tp->t_state & TS_ISOPEN) == 0) {
587				/* adjust for data copied in but not written */
588				uio->uio_resid += cc;
589				return (EIO);
590			}
591		}
592		while (cc > 0) {
593			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
594			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
595				wakeup(TSA_HUP_OR_INPUT(tp));
596				goto block;
597			}
598			(*linesw[tp->t_line].l_rint)(*cp++, tp);
599			cnt++;
600			cc--;
601		}
602		cc = 0;
603	}
604	return (0);
605block:
606	/*
607	 * Come here to wait for slave to open, for space
608	 * in outq, or space in rawq, or an empty canq.
609	 */
610	if ((tp->t_state & TS_CONNECTED) == 0) {
611		/* adjust for data copied in but not written */
612		uio->uio_resid += cc;
613		return (EIO);
614	}
615	if (flag & IO_NDELAY) {
616		/* adjust for data copied in but not written */
617		uio->uio_resid += cc;
618		if (cnt == 0)
619			return (EWOULDBLOCK);
620		return (0);
621	}
622	error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
623	if (error) {
624		/* adjust for data copied in but not written */
625		uio->uio_resid += cc;
626		return (error);
627	}
628	goto again;
629}
630
631/*ARGSUSED*/
632static	int
633ptyioctl(dev, cmd, data, flag, p)
634	dev_t dev;
635	u_long cmd;
636	caddr_t data;
637	int flag;
638	struct proc *p;
639{
640	register struct tty *tp = dev->si_tty;
641	register struct pt_ioctl *pti = dev->si_drv1;
642	register u_char *cc = tp->t_cc;
643	int stop, error;
644
645	if (devsw(dev)->d_open == ptcopen) {
646		switch (cmd) {
647
648		case TIOCGPGRP:
649			/*
650			 * We avoid calling ttioctl on the controller since,
651			 * in that case, tp must be the controlling terminal.
652			 */
653			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
654			return (0);
655
656		case TIOCPKT:
657			if (*(int *)data) {
658				if (pti->pt_flags & PF_UCNTL)
659					return (EINVAL);
660				pti->pt_flags |= PF_PKT;
661			} else
662				pti->pt_flags &= ~PF_PKT;
663			return (0);
664
665		case TIOCUCNTL:
666			if (*(int *)data) {
667				if (pti->pt_flags & PF_PKT)
668					return (EINVAL);
669				pti->pt_flags |= PF_UCNTL;
670			} else
671				pti->pt_flags &= ~PF_UCNTL;
672			return (0);
673
674		case TIOCREMOTE:
675			if (*(int *)data)
676				pti->pt_flags |= PF_REMOTE;
677			else
678				pti->pt_flags &= ~PF_REMOTE;
679			ttyflush(tp, FREAD|FWRITE);
680			return (0);
681		}
682
683		/*
684		 * The rest of the ioctls shouldn't be called until
685		 * the slave is open.
686		 */
687		if ((tp->t_state & TS_ISOPEN) == 0)
688			return (EAGAIN);
689
690		switch (cmd) {
691#ifdef COMPAT_43
692		case TIOCSETP:
693		case TIOCSETN:
694#endif
695		case TIOCSETD:
696		case TIOCSETA:
697		case TIOCSETAW:
698		case TIOCSETAF:
699			/*
700			 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
701			 * ttywflush(tp) will hang if there are characters in
702			 * the outq.
703			 */
704			ndflush(&tp->t_outq, tp->t_outq.c_cc);
705			break;
706
707		case TIOCSIG:
708			if (*(unsigned int *)data >= NSIG ||
709			    *(unsigned int *)data == 0)
710				return(EINVAL);
711			if ((tp->t_lflag&NOFLSH) == 0)
712				ttyflush(tp, FREAD|FWRITE);
713			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
714			if ((*(unsigned int *)data == SIGINFO) &&
715			    ((tp->t_lflag&NOKERNINFO) == 0))
716				ttyinfo(tp);
717			return(0);
718		}
719	}
720	if (cmd == TIOCEXT) {
721		/*
722		 * When the EXTPROC bit is being toggled, we need
723		 * to send an TIOCPKT_IOCTL if the packet driver
724		 * is turned on.
725		 */
726		if (*(int *)data) {
727			if (pti->pt_flags & PF_PKT) {
728				pti->pt_send |= TIOCPKT_IOCTL;
729				ptcwakeup(tp, FREAD);
730			}
731			tp->t_lflag |= EXTPROC;
732		} else {
733			if ((tp->t_lflag & EXTPROC) &&
734			    (pti->pt_flags & PF_PKT)) {
735				pti->pt_send |= TIOCPKT_IOCTL;
736				ptcwakeup(tp, FREAD);
737			}
738			tp->t_lflag &= ~EXTPROC;
739		}
740		return(0);
741	}
742	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
743	if (error == ENOIOCTL)
744		 error = ttioctl(tp, cmd, data, flag);
745	if (error == ENOIOCTL) {
746		if (pti->pt_flags & PF_UCNTL &&
747		    (cmd & ~0xff) == UIOCCMD(0)) {
748			if (cmd & 0xff) {
749				pti->pt_ucntl = (u_char)cmd;
750				ptcwakeup(tp, FREAD);
751			}
752			return (0);
753		}
754		error = ENOTTY;
755	}
756	/*
757	 * If external processing and packet mode send ioctl packet.
758	 */
759	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
760		switch(cmd) {
761		case TIOCSETA:
762		case TIOCSETAW:
763		case TIOCSETAF:
764#ifdef COMPAT_43
765		case TIOCSETP:
766		case TIOCSETN:
767#endif
768#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
769		case TIOCSETC:
770		case TIOCSLTC:
771		case TIOCLBIS:
772		case TIOCLBIC:
773		case TIOCLSET:
774#endif
775			pti->pt_send |= TIOCPKT_IOCTL;
776			ptcwakeup(tp, FREAD);
777		default:
778			break;
779		}
780	}
781	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
782		&& CCEQ(cc[VSTART], CTRL('q'));
783	if (pti->pt_flags & PF_NOSTOP) {
784		if (stop) {
785			pti->pt_send &= ~TIOCPKT_NOSTOP;
786			pti->pt_send |= TIOCPKT_DOSTOP;
787			pti->pt_flags &= ~PF_NOSTOP;
788			ptcwakeup(tp, FREAD);
789		}
790	} else {
791		if (!stop) {
792			pti->pt_send &= ~TIOCPKT_DOSTOP;
793			pti->pt_send |= TIOCPKT_NOSTOP;
794			pti->pt_flags |= PF_NOSTOP;
795			ptcwakeup(tp, FREAD);
796		}
797	}
798	return (error);
799}
800
801
802static void ptc_drvinit __P((void *unused));
803
804static void pty_clone __P((void *arg, char *name, int namelen, dev_t *dev));
805
806static void
807pty_clone(arg, name, namelen, dev)
808	void *arg;
809	char *name;
810	int namelen;
811	dev_t *dev;
812{
813	int u;
814
815	if (*dev != NODEV)
816		return;
817	if (bcmp(name, "pty", 3) != 0)
818		return;
819	if (name[5] != '\0')
820		return;
821	switch (name[3]) {
822	case 'p': u =   0; break;
823	case 'q': u =  32; break;
824	case 'r': u =  64; break;
825	case 's': u =  96; break;
826	case 'P': u = 128; break;
827	case 'Q': u = 160; break;
828	case 'R': u = 192; break;
829	case 'S': u = 224; break;
830	default: return;
831	}
832	if (name[4] >= '0' && name[4] <= '9')
833		u += name[4] - '0';
834	else if (name[4] >= 'a' && name[4] <= 'v')
835		u += name[4] - 'a' + 10;
836	else
837		return;
838	*dev = make_dev(&ptc_cdevsw, u,
839	    UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
840	(*dev)->si_flags |= SI_CHEAPCLONE;
841	return;
842}
843
844static void
845ptc_drvinit(unused)
846	void *unused;
847{
848	EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
849	cdevsw_add(&pts_cdevsw);
850	cdevsw_add(&ptc_cdevsw);
851}
852
853SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
854