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