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