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