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