pty.c revision 154833
1178173Simp/*-
2178173Simp * Copyright (c) 1982, 1986, 1989, 1993
3178173Simp *	The Regents of the University of California.  All rights reserved.
4182738Sobrien *
5182738Sobrien * Redistribution and use in source and binary forms, with or without
6178173Simp * 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 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	@(#)tty_pty.c	8.4 (Berkeley) 2/20/95
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/kern/tty_pty.c 154833 2006-01-26 01:30:34Z cognet $");
34
35/*
36 * Pseudo-teletype Driver
37 * (Actually two drivers, requiring two entries in 'cdevsw')
38 */
39#include "opt_compat.h"
40#include "opt_tty.h"
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/sx.h>
46#if defined(COMPAT_43TTY)
47#include <sys/ioctl_compat.h>
48#endif
49#include <sys/proc.h>
50#include <sys/tty.h>
51#include <sys/conf.h>
52#include <sys/fcntl.h>
53#include <sys/poll.h>
54#include <sys/kernel.h>
55#include <sys/uio.h>
56#include <sys/signalvar.h>
57#include <sys/malloc.h>
58
59static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
60
61static void ptsstart(struct tty *tp);
62static void ptsstop(struct tty *tp, int rw);
63static void ptcwakeup(struct tty *tp, int flag);
64static struct cdev *ptyinit(struct cdev *cdev, struct thread *td);
65
66static	d_open_t	ptsopen;
67static	d_close_t	ptsclose;
68static	d_read_t	ptsread;
69static	d_write_t	ptswrite;
70static	d_ioctl_t	ptsioctl;
71static	d_open_t	ptcopen;
72static	d_close_t	ptcclose;
73static	d_read_t	ptcread;
74static	d_ioctl_t	ptcioctl;
75static	d_write_t	ptcwrite;
76static	d_poll_t	ptcpoll;
77
78static struct cdevsw pts_cdevsw = {
79	.d_version =	D_VERSION,
80	.d_open =	ptsopen,
81	.d_close =	ptsclose,
82	.d_read =	ptsread,
83	.d_write =	ptswrite,
84	.d_ioctl =	ptsioctl,
85	.d_name =	"pts",
86	.d_flags =	D_TTY | D_NEEDGIANT,
87};
88
89static struct cdevsw ptc_cdevsw = {
90	.d_version =	D_VERSION,
91	.d_open =	ptcopen,
92	.d_close =	ptcclose,
93	.d_read =	ptcread,
94	.d_write =	ptcwrite,
95	.d_ioctl =	ptcioctl,
96	.d_poll =	ptcpoll,
97	.d_name =	"ptc",
98	.d_flags =	D_TTY | D_NEEDGIANT,
99};
100
101#define BUFSIZ 100		/* Chunk size iomoved to/from user */
102
103struct	ptsc {
104	int	pt_flags;
105	struct	selinfo pt_selr, pt_selw;
106	u_char	pt_send;
107	u_char	pt_ucntl;
108	struct tty *pt_tty;
109	struct cdev *devs, *devc;
110	int	pt_devs_open, pt_devc_open;
111	struct	prison *pt_prison;
112};
113
114#define	PF_PKT		0x08		/* packet mode */
115#define	PF_STOPPED	0x10		/* user told stopped */
116#define	PF_NOSTOP	0x40
117#define PF_UCNTL	0x80		/* user control mode */
118
119#define	TSA_PTC_READ(tp)	((void *)&(tp)->t_outq.c_cf)
120#define	TSA_PTC_WRITE(tp)	((void *)&(tp)->t_rawq.c_cl)
121#define	TSA_PTS_READ(tp)	((void *)&(tp)->t_canq)
122
123static char *names = "pqrsPQRS";
124/*
125 * This function creates and initializes a pts/ptc pair
126 *
127 * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
128 * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
129 *
130 * XXX: define and add mapping of upper minor bits to allow more
131 *      than 256 ptys.
132 */
133static struct cdev *
134ptyinit(struct cdev *devc, struct thread *td)
135{
136	struct ptsc *pt;
137	int n;
138
139	n = minor(devc);
140	/* For now we only map the lower 8 bits of the minor */
141	if (n & ~0xff)
142		return (NULL);
143
144	devc->si_flags &= ~SI_CHEAPCLONE;
145
146	/*
147	 * Initially do not create a slave endpoint.
148	 */
149	pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
150	pt->devc = devc;
151
152	pt->pt_tty = ttyalloc();
153	pt->pt_tty->t_sc = pt;
154	devc->si_drv1 = pt;
155	devc->si_tty = pt->pt_tty;
156	return (devc);
157}
158
159static void
160pty_create_slave(struct ucred *cred, struct ptsc *pt, int n)
161{
162
163	pt->devs = make_dev_cred(&pts_cdevsw, n, cred, UID_ROOT, GID_WHEEL,
164	    0666, "tty%c%r", names[n / 32], n % 32);
165	pt->devs->si_drv1 = pt;
166	pt->devs->si_tty = pt->pt_tty;
167	pt->pt_tty->t_dev = pt->devs;
168}
169
170static void
171pty_destroy_slave(struct ptsc *pt)
172{
173
174	pt->pt_tty->t_dev = NULL;
175	destroy_dev(pt->devs);
176	pt->devs = NULL;
177}
178
179static void
180pty_maybe_destroy_slave(struct ptsc *pt)
181{
182
183	if (pt->pt_devc_open == 0 && pt->pt_devs_open == 0)
184		pty_destroy_slave(pt);
185}
186
187/*ARGSUSED*/
188static	int
189ptsopen(struct cdev *dev, int flag, int devtype, struct thread *td)
190{
191	struct tty *tp;
192	int error;
193	struct ptsc *pt;
194
195	if (!dev->si_drv1)
196		return(ENXIO);
197	pt = dev->si_drv1;
198	tp = dev->si_tty;
199	if ((tp->t_state & TS_ISOPEN) == 0) {
200		ttyinitmode(tp, 1, 0);
201	} else if (tp->t_state & TS_XCLUDE && suser(td))
202		return (EBUSY);
203	else if (pt->pt_prison != td->td_ucred->cr_prison)
204		return (EBUSY);
205	if (tp->t_oproc)			/* Ctrlr still around. */
206		(void)ttyld_modem(tp, 1);
207	while ((tp->t_state & TS_CARR_ON) == 0) {
208		if (flag&FNONBLOCK)
209			break;
210		error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
211				 "ptsopn", 0);
212		if (error)
213			return (error);
214	}
215	error = ttyld_open(tp, dev);
216	if (error == 0) {
217		ptcwakeup(tp, FREAD|FWRITE);
218		pt->pt_devs_open = 1;
219	} else
220		pty_maybe_destroy_slave(pt);
221	return (error);
222}
223
224static	int
225ptsclose(struct cdev *dev, int flag, int mode, struct thread *td)
226{
227	struct ptsc *pti;
228	struct tty *tp;
229	int err;
230
231	tp = dev->si_tty;
232	pti = dev->si_drv1;
233
234	KASSERT(dev == pti->devs, ("ptsclose: dev != pti->devs"));
235
236	err = ttyld_close(tp, flag);
237	(void) tty_close(tp);
238
239	pti->pt_devs_open = 0;
240	pty_maybe_destroy_slave(pti);
241
242	return (err);
243}
244
245static	int
246ptsread(struct cdev *dev, struct uio *uio, int flag)
247{
248	struct tty *tp = dev->si_tty;
249	int error = 0;
250
251	if (tp->t_oproc)
252		error = ttyld_read(tp, uio, flag);
253	ptcwakeup(tp, FWRITE);
254	return (error);
255}
256
257/*
258 * Write to pseudo-tty.
259 * Wakeups of controlling tty will happen
260 * indirectly, when tty driver calls ptsstart.
261 */
262static	int
263ptswrite(struct cdev *dev, struct uio *uio, int flag)
264{
265	struct tty *tp;
266
267	tp = dev->si_tty;
268	if (tp->t_oproc == 0)
269		return (EIO);
270	return (ttyld_write(tp, uio, flag));
271}
272
273/*
274 * Start output on pseudo-tty.
275 * Wake up process selecting or sleeping for input from controlling tty.
276 */
277static void
278ptsstart(struct tty *tp)
279{
280	struct ptsc *pt = tp->t_sc;
281
282	if (tp->t_state & TS_TTSTOP)
283		return;
284	if (pt->pt_flags & PF_STOPPED) {
285		pt->pt_flags &= ~PF_STOPPED;
286		pt->pt_send = TIOCPKT_START;
287	}
288	ptcwakeup(tp, FREAD);
289}
290
291static void
292ptcwakeup(struct tty *tp, int flag)
293{
294	struct ptsc *pt = tp->t_sc;
295
296	if (flag & FREAD) {
297		selwakeuppri(&pt->pt_selr, TTIPRI);
298		wakeup(TSA_PTC_READ(tp));
299	}
300	if (flag & FWRITE) {
301		selwakeuppri(&pt->pt_selw, TTOPRI);
302		wakeup(TSA_PTC_WRITE(tp));
303	}
304}
305
306static	int
307ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td)
308{
309	struct tty *tp;
310	struct ptsc *pt;
311
312	if (!dev->si_drv1)
313		ptyinit(dev, td);
314	if (!dev->si_drv1)
315		return(ENXIO);
316	tp = dev->si_tty;
317	if (tp->t_oproc)
318		return (EIO);
319	tp->t_timeout = -1;
320	tp->t_oproc = ptsstart;
321	tp->t_stop = ptsstop;
322	(void)ttyld_modem(tp, 1);
323	tp->t_lflag &= ~EXTPROC;
324	pt = dev->si_drv1;
325	pt->pt_prison = td->td_ucred->cr_prison;
326	pt->pt_flags = 0;
327	pt->pt_send = 0;
328	pt->pt_ucntl = 0;
329
330	pty_create_slave(td->td_ucred, pt, minor(dev));
331	pt->pt_devc_open = 1;
332
333	return (0);
334}
335
336static	int
337ptcclose(struct cdev *dev, int flags, int fmt, struct thread *td)
338{
339	struct ptsc *pti = dev->si_drv1;
340	struct tty *tp;
341
342	tp = dev->si_tty;
343	(void)ttyld_modem(tp, 0);
344
345	/*
346	 * XXX MDMBUF makes no sense for ptys but would inhibit the above
347	 * l_modem().  CLOCAL makes sense but isn't supported.   Special
348	 * l_modem()s that ignore carrier drop make no sense for ptys but
349	 * may be in use because other parts of the line discipline make
350	 * sense for ptys.  Recover by doing everything that a normal
351	 * ttymodem() would have done except for sending a SIGHUP.
352	 */
353	if (tp->t_state & TS_ISOPEN) {
354		tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
355		tp->t_state |= TS_ZOMBIE;
356		ttyflush(tp, FREAD | FWRITE);
357	}
358
359	tp->t_oproc = 0;		/* mark closed */
360	pti->pt_devc_open = 0;
361	pty_maybe_destroy_slave(pti);
362	return (0);
363}
364
365static	int
366ptcread(struct cdev *dev, struct uio *uio, int flag)
367{
368	struct tty *tp = dev->si_tty;
369	struct ptsc *pt = dev->si_drv1;
370	char buf[BUFSIZ];
371	int error = 0, cc;
372
373	/*
374	 * We want to block until the slave
375	 * is open, and there's something to read;
376	 * but if we lost the slave or we're NBIO,
377	 * then return the appropriate error instead.
378	 */
379	for (;;) {
380		if (tp->t_state&TS_ISOPEN) {
381			if (pt->pt_flags&PF_PKT && pt->pt_send) {
382				error = ureadc((int)pt->pt_send, uio);
383				if (error)
384					return (error);
385				if (pt->pt_send & TIOCPKT_IOCTL) {
386					cc = min(uio->uio_resid,
387						sizeof(tp->t_termios));
388					uiomove(&tp->t_termios, cc, uio);
389				}
390				pt->pt_send = 0;
391				return (0);
392			}
393			if (pt->pt_flags&PF_UCNTL && pt->pt_ucntl) {
394				error = ureadc((int)pt->pt_ucntl, uio);
395				if (error)
396					return (error);
397				pt->pt_ucntl = 0;
398				return (0);
399			}
400			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
401				break;
402		}
403		if ((tp->t_state & TS_CONNECTED) == 0)
404			return (0);	/* EOF */
405		if (flag & O_NONBLOCK)
406			return (EWOULDBLOCK);
407		error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
408		if (error)
409			return (error);
410	}
411	if (pt->pt_flags & (PF_PKT|PF_UCNTL))
412		error = ureadc(0, uio);
413	while (uio->uio_resid > 0 && error == 0) {
414		cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
415		if (cc <= 0)
416			break;
417		error = uiomove(buf, cc, uio);
418	}
419	ttwwakeup(tp);
420	return (error);
421}
422
423static	void
424ptsstop(struct tty *tp, int flush)
425{
426	struct ptsc *pt = tp->t_sc;
427	int flag;
428
429	/* note: FLUSHREAD and FLUSHWRITE already ok */
430	if (flush == 0) {
431		flush = TIOCPKT_STOP;
432		pt->pt_flags |= PF_STOPPED;
433	} else
434		pt->pt_flags &= ~PF_STOPPED;
435	pt->pt_send |= flush;
436	/* change of perspective */
437	flag = 0;
438	if (flush & FREAD)
439		flag |= FWRITE;
440	if (flush & FWRITE)
441		flag |= FREAD;
442	ptcwakeup(tp, flag);
443}
444
445static	int
446ptcpoll(struct cdev *dev, int events, struct thread *td)
447{
448	struct tty *tp = dev->si_tty;
449	struct ptsc *pt = dev->si_drv1;
450	int revents = 0;
451	int s;
452
453	if ((tp->t_state & TS_CONNECTED) == 0)
454		return (events &
455		   (POLLHUP | POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM));
456
457	/*
458	 * Need to block timeouts (ttrstart).
459	 */
460	s = spltty();
461
462	if (events & (POLLIN | POLLRDNORM))
463		if ((tp->t_state & TS_ISOPEN) &&
464		    ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
465		     ((pt->pt_flags & PF_PKT) && pt->pt_send) ||
466		     ((pt->pt_flags & PF_UCNTL) && pt->pt_ucntl)))
467			revents |= events & (POLLIN | POLLRDNORM);
468
469	if (events & (POLLOUT | POLLWRNORM))
470		if (tp->t_state & TS_ISOPEN &&
471		    (((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
472		      (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)))))
473			revents |= events & (POLLOUT | POLLWRNORM);
474
475	if (events & POLLHUP)
476		if ((tp->t_state & TS_CARR_ON) == 0)
477			revents |= POLLHUP;
478
479	if (revents == 0) {
480		if (events & (POLLIN | POLLRDNORM))
481			selrecord(td, &pt->pt_selr);
482
483		if (events & (POLLOUT | POLLWRNORM))
484			selrecord(td, &pt->pt_selw);
485	}
486	splx(s);
487
488	return (revents);
489}
490
491static	int
492ptcwrite(struct cdev *dev, struct uio *uio, int flag)
493{
494	struct tty *tp = dev->si_tty;
495	u_char *cp = 0;
496	int cc = 0;
497	u_char locbuf[BUFSIZ];
498	int cnt = 0;
499	int error = 0;
500
501again:
502	if ((tp->t_state&TS_ISOPEN) == 0)
503		goto block;
504	while (uio->uio_resid > 0 || cc > 0) {
505		if (cc == 0) {
506			cc = min(uio->uio_resid, BUFSIZ);
507			cp = locbuf;
508			error = uiomove(cp, cc, uio);
509			if (error)
510				return (error);
511			/* check again for safety */
512			if ((tp->t_state & TS_ISOPEN) == 0) {
513				/* adjust for data copied in but not written */
514				uio->uio_resid += cc;
515				return (EIO);
516			}
517		}
518		while (cc > 0) {
519			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
520			   (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) {
521				wakeup(TSA_HUP_OR_INPUT(tp));
522				goto block;
523			}
524			ttyld_rint(tp, *cp++);
525			cnt++;
526			cc--;
527		}
528		cc = 0;
529	}
530	return (0);
531block:
532	/*
533	 * Come here to wait for slave to open, for space
534	 * in outq, or space in rawq, or an empty canq.
535	 */
536	if ((tp->t_state & TS_CONNECTED) == 0) {
537		/* adjust for data copied in but not written */
538		uio->uio_resid += cc;
539		return (EIO);
540	}
541	if (flag & O_NONBLOCK) {
542		/* adjust for data copied in but not written */
543		uio->uio_resid += cc;
544		if (cnt == 0)
545			return (EWOULDBLOCK);
546		return (0);
547	}
548	error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
549	if (error) {
550		/* adjust for data copied in but not written */
551		uio->uio_resid += cc;
552		return (error);
553	}
554	goto again;
555}
556
557/*ARGSUSED*/
558static	int
559ptcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
560{
561	struct tty *tp = dev->si_tty;
562	struct ptsc *pt = dev->si_drv1;
563
564	switch (cmd) {
565
566	case TIOCGPGRP:
567		/*
568		 * We avoid calling ttioctl on the controller since,
569		 * in that case, tp must be the controlling terminal.
570		 */
571		*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
572		return (0);
573
574	case TIOCPKT:
575		if (*(int *)data) {
576			if (pt->pt_flags & PF_UCNTL)
577				return (EINVAL);
578			pt->pt_flags |= PF_PKT;
579		} else
580			pt->pt_flags &= ~PF_PKT;
581		return (0);
582
583	case TIOCUCNTL:
584		if (*(int *)data) {
585			if (pt->pt_flags & PF_PKT)
586				return (EINVAL);
587			pt->pt_flags |= PF_UCNTL;
588		} else
589			pt->pt_flags &= ~PF_UCNTL;
590		return (0);
591	}
592
593	/*
594	 * The rest of the ioctls shouldn't be called until
595	 * the slave is open.
596	 */
597	if ((tp->t_state & TS_ISOPEN) == 0)
598		return (EAGAIN);
599
600	switch (cmd) {
601#ifdef COMPAT_43TTY
602	case TIOCSETP:
603	case TIOCSETN:
604#endif
605	case TIOCSETD:
606	case TIOCSETA:
607	case TIOCSETAW:
608	case TIOCSETAF:
609		/*
610		 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
611		 * ttywflush(tp) will hang if there are characters in
612		 * the outq.
613		 */
614		ndflush(&tp->t_outq, tp->t_outq.c_cc);
615		break;
616
617	case TIOCSIG:
618		if (*(unsigned int *)data >= NSIG ||
619		    *(unsigned int *)data == 0)
620			return(EINVAL);
621		if ((tp->t_lflag&NOFLSH) == 0)
622			ttyflush(tp, FREAD|FWRITE);
623		if (tp->t_pgrp != NULL) {
624			PGRP_LOCK(tp->t_pgrp);
625			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
626			PGRP_UNLOCK(tp->t_pgrp);
627		}
628		if ((*(unsigned int *)data == SIGINFO) &&
629		    ((tp->t_lflag&NOKERNINFO) == 0))
630			ttyinfo(tp);
631		return(0);
632	}
633
634	return (ptsioctl(dev, cmd, data, flag, td));
635}
636
637/*ARGSUSED*/
638static	int
639ptsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
640{
641	struct tty *tp = dev->si_tty;
642	struct ptsc *pt = dev->si_drv1;
643	u_char *cc = tp->t_cc;
644	int stop, error;
645
646	if (cmd == TIOCEXT) {
647		/*
648		 * When the EXTPROC bit is being toggled, we need
649		 * to send an TIOCPKT_IOCTL if the packet driver
650		 * is turned on.
651		 */
652		if (*(int *)data) {
653			if (pt->pt_flags & PF_PKT) {
654				pt->pt_send |= TIOCPKT_IOCTL;
655				ptcwakeup(tp, FREAD);
656			}
657			tp->t_lflag |= EXTPROC;
658		} else {
659			if ((tp->t_lflag & EXTPROC) &&
660			    (pt->pt_flags & PF_PKT)) {
661				pt->pt_send |= TIOCPKT_IOCTL;
662				ptcwakeup(tp, FREAD);
663			}
664			tp->t_lflag &= ~EXTPROC;
665		}
666		return(0);
667	}
668	error = ttyioctl(dev, cmd, data, flag, td);
669	if (error == ENOTTY) {
670		if (pt->pt_flags & PF_UCNTL &&
671		    (cmd & ~0xff) == UIOCCMD(0)) {
672			if (cmd & 0xff) {
673				pt->pt_ucntl = (u_char)cmd;
674				ptcwakeup(tp, FREAD);
675			}
676			return (0);
677		}
678		error = ENOTTY;
679	}
680	/*
681	 * If external processing and packet mode send ioctl packet.
682	 */
683	if ((tp->t_lflag&EXTPROC) && (pt->pt_flags & PF_PKT)) {
684		switch(cmd) {
685		case TIOCSETA:
686		case TIOCSETAW:
687		case TIOCSETAF:
688#ifdef COMPAT_43TTY
689		case TIOCSETP:
690		case TIOCSETN:
691		case TIOCSETC:
692		case TIOCSLTC:
693		case TIOCLBIS:
694		case TIOCLBIC:
695		case TIOCLSET:
696#endif
697			pt->pt_send |= TIOCPKT_IOCTL;
698			ptcwakeup(tp, FREAD);
699			break;
700		default:
701			break;
702		}
703	}
704	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
705		&& CCEQ(cc[VSTART], CTRL('q'));
706	if (pt->pt_flags & PF_NOSTOP) {
707		if (stop) {
708			pt->pt_send &= ~TIOCPKT_NOSTOP;
709			pt->pt_send |= TIOCPKT_DOSTOP;
710			pt->pt_flags &= ~PF_NOSTOP;
711			ptcwakeup(tp, FREAD);
712		}
713	} else {
714		if (!stop) {
715			pt->pt_send &= ~TIOCPKT_DOSTOP;
716			pt->pt_send |= TIOCPKT_NOSTOP;
717			pt->pt_flags |= PF_NOSTOP;
718			ptcwakeup(tp, FREAD);
719		}
720	}
721	return (error);
722}
723
724static void
725pty_clone(void *arg, struct ucred *cr, char *name, int namelen,
726    struct cdev **dev)
727{
728	int u;
729
730	if (*dev != NULL)
731		return;
732	if (bcmp(name, "pty", 3) != 0)
733		return;
734	if (name[5] != '\0')
735		return;
736	switch (name[3]) {
737	case 'p': u =   0; break;
738	case 'q': u =  32; break;
739	case 'r': u =  64; break;
740	case 's': u =  96; break;
741	case 'P': u = 128; break;
742	case 'Q': u = 160; break;
743	case 'R': u = 192; break;
744	case 'S': u = 224; break;
745	default: return;
746	}
747	if (name[4] >= '0' && name[4] <= '9')
748		u += name[4] - '0';
749	else if (name[4] >= 'a' && name[4] <= 'v')
750		u += name[4] - 'a' + 10;
751	else
752		return;
753	*dev = make_dev_cred(&ptc_cdevsw, u, cr,
754	    UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[u / 32], u % 32);
755	dev_ref(*dev);
756	(*dev)->si_flags |= SI_CHEAPCLONE;
757	return;
758}
759
760static void
761ptc_drvinit(void *unused)
762{
763
764	EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
765}
766
767SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,ptc_drvinit,NULL)
768