pty.c revision 69781
1226031Sstas/*
2226031Sstas * Copyright (c) 1982, 1986, 1989, 1993
3226031Sstas *	The Regents of the University of California.  All rights reserved.
4226031Sstas *
5226031Sstas * Redistribution and use in source and binary forms, with or without
6226031Sstas * modification, are permitted provided that the following conditions
7226031Sstas * are met:
8226031Sstas * 1. Redistributions of source code must retain the above copyright
9226031Sstas *    notice, this list of conditions and the following disclaimer.
10226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
11226031Sstas *    notice, this list of conditions and the following disclaimer in the
12226031Sstas *    documentation and/or other materials provided with the distribution.
13226031Sstas * 3. All advertising materials mentioning features or use of this software
14226031Sstas *    must display the following acknowledgement:
15226031Sstas *	This product includes software developed by the University of
16226031Sstas *	California, Berkeley and its contributors.
17226031Sstas * 4. Neither the name of the University nor the names of its contributors
18226031Sstas *    may be used to endorse or promote products derived from this software
19226031Sstas *    without specific prior written permission.
20226031Sstas *
21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31226031Sstas * SUCH DAMAGE.
32226031Sstas *
33226031Sstas *	@(#)tty_pty.c	8.4 (Berkeley) 2/20/95
34226031Sstas * $FreeBSD: head/sys/kern/tty_pty.c 69781 2000-12-08 21:51:06Z dwmalone $
35226031Sstas */
36226031Sstas
37226031Sstas/*
38226031Sstas * Pseudo-teletype Driver
39226031Sstas * (Actually two drivers, requiring two entries in 'cdevsw')
40226031Sstas */
41226031Sstas#include "opt_compat.h"
42226031Sstas#include <sys/param.h>
43226031Sstas#include <sys/systm.h>
44226031Sstas#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
45226031Sstas#include <sys/ioctl_compat.h>
46226031Sstas#endif
47226031Sstas#include <sys/proc.h>
48226031Sstas#include <sys/tty.h>
49226031Sstas#include <sys/conf.h>
50226031Sstas#include <sys/fcntl.h>
51226031Sstas#include <sys/poll.h>
52226031Sstas#include <sys/kernel.h>
53226031Sstas#include <sys/vnode.h>
54226031Sstas#include <sys/signalvar.h>
55226031Sstas#include <sys/malloc.h>
56226031Sstas
57226031Sstasstatic MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
58226031Sstas
59226031Sstasstatic void ptsstart __P((struct tty *tp));
60226031Sstasstatic void ptsstop __P((struct tty *tp, int rw));
61226031Sstasstatic void ptcwakeup __P((struct tty *tp, int flag));
62226031Sstasstatic dev_t ptyinit __P((int n));
63226031Sstas
64226031Sstasstatic	d_open_t	ptsopen;
65226031Sstasstatic	d_close_t	ptsclose;
66226031Sstasstatic	d_read_t	ptsread;
67226031Sstasstatic	d_write_t	ptswrite;
68226031Sstasstatic	d_ioctl_t	ptyioctl;
69226031Sstasstatic	d_open_t	ptcopen;
70226031Sstasstatic	d_close_t	ptcclose;
71226031Sstasstatic	d_read_t	ptcread;
72226031Sstasstatic	d_write_t	ptcwrite;
73226031Sstasstatic	d_poll_t	ptcpoll;
74226031Sstas
75226031Sstas#define	CDEV_MAJOR_S	5
76226031Sstasstatic struct cdevsw pts_cdevsw = {
77226031Sstas	/* open */	ptsopen,
78226031Sstas	/* close */	ptsclose,
79226031Sstas	/* read */	ptsread,
80226031Sstas	/* write */	ptswrite,
81226031Sstas	/* ioctl */	ptyioctl,
82226031Sstas	/* poll */	ttypoll,
83226031Sstas	/* mmap */	nommap,
84226031Sstas	/* strategy */	nostrategy,
85226031Sstas	/* name */	"pts",
86226031Sstas	/* maj */	CDEV_MAJOR_S,
87226031Sstas	/* dump */	nodump,
88226031Sstas	/* psize */	nopsize,
89226031Sstas	/* flags */	D_TTY,
90226031Sstas	/* bmaj */	-1
91226031Sstas};
92226031Sstas
93226031Sstas#define	CDEV_MAJOR_C	6
94226031Sstasstatic struct cdevsw ptc_cdevsw = {
95226031Sstas	/* open */	ptcopen,
96226031Sstas	/* close */	ptcclose,
97226031Sstas	/* read */	ptcread,
98226031Sstas	/* write */	ptcwrite,
99226031Sstas	/* ioctl */	ptyioctl,
100226031Sstas	/* poll */	ptcpoll,
101226031Sstas	/* mmap */	nommap,
102226031Sstas	/* strategy */	nostrategy,
103226031Sstas	/* name */	"ptc",
104226031Sstas	/* maj */	CDEV_MAJOR_C,
105226031Sstas	/* dump */	nodump,
106226031Sstas	/* psize */	nopsize,
107226031Sstas	/* flags */	D_TTY,
108226031Sstas	/* bmaj */	-1
109226031Sstas};
110226031Sstas
111226031Sstas#define BUFSIZ 100		/* Chunk size iomoved to/from user */
112226031Sstas
113226031Sstasstruct	pt_ioctl {
114226031Sstas	int	pt_flags;
115226031Sstas	struct	selinfo pt_selr, pt_selw;
116226031Sstas	u_char	pt_send;
117226031Sstas	u_char	pt_ucntl;
118226031Sstas	struct tty pt_tty;
119226031Sstas	dev_t	devs, devc;
120226031Sstas	struct	prison *pt_prison;
121226031Sstas};
122226031Sstas
123226031Sstas#define	PF_PKT		0x08		/* packet mode */
124226031Sstas#define	PF_STOPPED	0x10		/* user told stopped */
125226031Sstas#define	PF_REMOTE	0x20		/* remote and flow controlled input */
126226031Sstas#define	PF_NOSTOP	0x40
127226031Sstas#define PF_UCNTL	0x80		/* user control mode */
128226031Sstas
129226031Sstas/*
130226031Sstas * This function creates and initializes a pts/ptc pair
131226031Sstas *
132226031Sstas * pts == /dev/tty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
133226031Sstas * ptc == /dev/pty[pqrsPQRS][0123456789abcdefghijklmnopqrstuv]
134226031Sstas *
135226031Sstas * XXX: define and add mapping of upper minor bits to allow more
136226031Sstas *      than 256 ptys.
137226031Sstas */
138226031Sstasstatic dev_t
139226031Sstasptyinit(n)
140226031Sstas	int n;
141226031Sstas{
142226031Sstas	dev_t devs, devc;
143226031Sstas	char *names = "pqrsPQRS";
144226031Sstas	struct pt_ioctl *pt;
145226031Sstas
146226031Sstas	/* For now we only map the lower 8 bits of the minor */
147226031Sstas	if (n & ~0xff)
148226031Sstas		return (NODEV);
149226031Sstas
150226031Sstas	pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO);
151226031Sstas	pt->devs = devs = make_dev(&pts_cdevsw, n,
152226031Sstas	    UID_ROOT, GID_WHEEL, 0666, "tty%c%r", names[n / 32], n % 32);
153226031Sstas	pt->devc = devc = make_dev(&ptc_cdevsw, n,
154226031Sstas	    UID_ROOT, GID_WHEEL, 0666, "pty%c%r", names[n / 32], n % 32);
155226031Sstas
156226031Sstas	devs->si_drv1 = devc->si_drv1 = pt;
157226031Sstas	devs->si_tty = devc->si_tty = &pt->pt_tty;
158226031Sstas	ttyregister(&pt->pt_tty);
159226031Sstas	return (devc);
160226031Sstas}
161226031Sstas
162226031Sstas/*ARGSUSED*/
163226031Sstasstatic	int
164226031Sstasptsopen(dev, flag, devtype, p)
165226031Sstas	dev_t dev;
166226031Sstas	int flag, devtype;
167226031Sstas	struct proc *p;
168226031Sstas{
169226031Sstas	register struct tty *tp;
170226031Sstas	int error;
171226031Sstas	struct pt_ioctl *pti;
172226031Sstas
173226031Sstas	if (!dev->si_drv1)
174226031Sstas		ptyinit(minor(dev));
175226031Sstas	if (!dev->si_drv1)
176226031Sstas		return(ENXIO);
177226031Sstas	pti = dev->si_drv1;
178226031Sstas	tp = dev->si_tty;
179226031Sstas	if ((tp->t_state & TS_ISOPEN) == 0) {
180226031Sstas		ttychars(tp);		/* Set up default chars */
181226031Sstas		tp->t_iflag = TTYDEF_IFLAG;
182226031Sstas		tp->t_oflag = TTYDEF_OFLAG;
183226031Sstas		tp->t_lflag = TTYDEF_LFLAG;
184226031Sstas		tp->t_cflag = TTYDEF_CFLAG;
185226031Sstas		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
186226031Sstas	} else if (tp->t_state & TS_XCLUDE && suser(p)) {
187226031Sstas		return (EBUSY);
188226031Sstas	} else if (pti->pt_prison != p->p_prison) {
189226031Sstas		return (EBUSY);
190226031Sstas	}
191226031Sstas	if (tp->t_oproc)			/* Ctrlr still around. */
192226031Sstas		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
193226031Sstas	while ((tp->t_state & TS_CARR_ON) == 0) {
194226031Sstas		if (flag&FNONBLOCK)
195226031Sstas			break;
196226031Sstas		error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
197226031Sstas				 "ptsopn", 0);
198226031Sstas		if (error)
199226031Sstas			return (error);
200226031Sstas	}
201226031Sstas	error = (*linesw[tp->t_line].l_open)(dev, tp);
202226031Sstas	if (error == 0)
203226031Sstas		ptcwakeup(tp, FREAD|FWRITE);
204226031Sstas	return (error);
205226031Sstas}
206226031Sstas
207226031Sstasstatic	int
208226031Sstasptsclose(dev, flag, mode, p)
209226031Sstas	dev_t dev;
210226031Sstas	int flag, mode;
211226031Sstas	struct proc *p;
212226031Sstas{
213226031Sstas	register struct tty *tp;
214226031Sstas	int err;
215226031Sstas
216226031Sstas	tp = dev->si_tty;
217226031Sstas	err = (*linesw[tp->t_line].l_close)(tp, flag);
218226031Sstas	ptsstop(tp, FREAD|FWRITE);
219226031Sstas	(void) ttyclose(tp);
220226031Sstas	return (err);
221226031Sstas}
222226031Sstas
223226031Sstasstatic	int
224226031Sstasptsread(dev, uio, flag)
225226031Sstas	dev_t dev;
226226031Sstas	struct uio *uio;
227226031Sstas	int flag;
228226031Sstas{
229226031Sstas	struct proc *p = curproc;
230226031Sstas	register struct tty *tp = dev->si_tty;
231226031Sstas	register struct pt_ioctl *pti = dev->si_drv1;
232226031Sstas	int error = 0;
233226031Sstas
234226031Sstasagain:
235226031Sstas	if (pti->pt_flags & PF_REMOTE) {
236226031Sstas		while (isbackground(p, tp)) {
237234027Sstas			if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
238226031Sstas			    SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
239226031Sstas			    p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
240				return (EIO);
241			pgsignal(p->p_pgrp, SIGTTIN, 1);
242			error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
243					 0);
244			if (error)
245				return (error);
246		}
247		if (tp->t_canq.c_cc == 0) {
248			if (flag & IO_NDELAY)
249				return (EWOULDBLOCK);
250			error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
251					 "ptsin", 0);
252			if (error)
253				return (error);
254			goto again;
255		}
256		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
257			if (ureadc(getc(&tp->t_canq), uio) < 0) {
258				error = EFAULT;
259				break;
260			}
261		if (tp->t_canq.c_cc == 1)
262			(void) getc(&tp->t_canq);
263		if (tp->t_canq.c_cc)
264			return (error);
265	} else
266		if (tp->t_oproc)
267			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
268	ptcwakeup(tp, FWRITE);
269	return (error);
270}
271
272/*
273 * Write to pseudo-tty.
274 * Wakeups of controlling tty will happen
275 * indirectly, when tty driver calls ptsstart.
276 */
277static	int
278ptswrite(dev, uio, flag)
279	dev_t dev;
280	struct uio *uio;
281	int flag;
282{
283	register struct tty *tp;
284
285	tp = dev->si_tty;
286	if (tp->t_oproc == 0)
287		return (EIO);
288	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
289}
290
291/*
292 * Start output on pseudo-tty.
293 * Wake up process selecting or sleeping for input from controlling tty.
294 */
295static void
296ptsstart(tp)
297	struct tty *tp;
298{
299	register struct pt_ioctl *pti = tp->t_dev->si_drv1;
300
301	if (tp->t_state & TS_TTSTOP)
302		return;
303	if (pti->pt_flags & PF_STOPPED) {
304		pti->pt_flags &= ~PF_STOPPED;
305		pti->pt_send = TIOCPKT_START;
306	}
307	ptcwakeup(tp, FREAD);
308}
309
310static void
311ptcwakeup(tp, flag)
312	struct tty *tp;
313	int flag;
314{
315	struct pt_ioctl *pti = tp->t_dev->si_drv1;
316
317	if (flag & FREAD) {
318		selwakeup(&pti->pt_selr);
319		wakeup(TSA_PTC_READ(tp));
320	}
321	if (flag & FWRITE) {
322		selwakeup(&pti->pt_selw);
323		wakeup(TSA_PTC_WRITE(tp));
324	}
325}
326
327static	int
328ptcopen(dev, flag, devtype, p)
329	dev_t dev;
330	int flag, devtype;
331	struct proc *p;
332{
333	register struct tty *tp;
334	struct pt_ioctl *pti;
335
336	if (!dev->si_drv1)
337		ptyinit(minor(dev));
338	if (!dev->si_drv1)
339		return(ENXIO);
340	tp = dev->si_tty;
341	if (tp->t_oproc)
342		return (EIO);
343	tp->t_timeout = -1;
344	tp->t_oproc = ptsstart;
345	tp->t_stop = ptsstop;
346	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
347	tp->t_lflag &= ~EXTPROC;
348	pti = dev->si_drv1;
349	pti->pt_prison = p->p_prison;
350	pti->pt_flags = 0;
351	pti->pt_send = 0;
352	pti->pt_ucntl = 0;
353	return (0);
354}
355
356static	int
357ptcclose(dev, flags, fmt, p)
358	dev_t dev;
359	int flags;
360	int fmt;
361	struct proc *p;
362{
363	register struct tty *tp;
364
365	tp = dev->si_tty;
366	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
367
368	/*
369	 * XXX MDMBUF makes no sense for ptys but would inhibit the above
370	 * l_modem().  CLOCAL makes sense but isn't supported.   Special
371	 * l_modem()s that ignore carrier drop make no sense for ptys but
372	 * may be in use because other parts of the line discipline make
373	 * sense for ptys.  Recover by doing everything that a normal
374	 * ttymodem() would have done except for sending a SIGHUP.
375	 */
376	if (tp->t_state & TS_ISOPEN) {
377		tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
378		tp->t_state |= TS_ZOMBIE;
379		ttyflush(tp, FREAD | FWRITE);
380	}
381
382	tp->t_oproc = 0;		/* mark closed */
383	return (0);
384}
385
386static	int
387ptcread(dev, uio, flag)
388	dev_t dev;
389	struct uio *uio;
390	int flag;
391{
392	register struct tty *tp = dev->si_tty;
393	struct pt_ioctl *pti = dev->si_drv1;
394	char buf[BUFSIZ];
395	int error = 0, cc;
396
397	/*
398	 * We want to block until the slave
399	 * is open, and there's something to read;
400	 * but if we lost the slave or we're NBIO,
401	 * then return the appropriate error instead.
402	 */
403	for (;;) {
404		if (tp->t_state&TS_ISOPEN) {
405			if (pti->pt_flags&PF_PKT && pti->pt_send) {
406				error = ureadc((int)pti->pt_send, uio);
407				if (error)
408					return (error);
409				if (pti->pt_send & TIOCPKT_IOCTL) {
410					cc = min(uio->uio_resid,
411						sizeof(tp->t_termios));
412					uiomove((caddr_t)&tp->t_termios, cc,
413						uio);
414				}
415				pti->pt_send = 0;
416				return (0);
417			}
418			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
419				error = ureadc((int)pti->pt_ucntl, uio);
420				if (error)
421					return (error);
422				pti->pt_ucntl = 0;
423				return (0);
424			}
425			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
426				break;
427		}
428		if ((tp->t_state & TS_CONNECTED) == 0)
429			return (0);	/* EOF */
430		if (flag & IO_NDELAY)
431			return (EWOULDBLOCK);
432		error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
433		if (error)
434			return (error);
435	}
436	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
437		error = ureadc(0, uio);
438	while (uio->uio_resid > 0 && error == 0) {
439		cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
440		if (cc <= 0)
441			break;
442		error = uiomove(buf, cc, uio);
443	}
444	ttwwakeup(tp);
445	return (error);
446}
447
448static	void
449ptsstop(tp, flush)
450	register struct tty *tp;
451	int flush;
452{
453	struct pt_ioctl *pti = tp->t_dev->si_drv1;
454	int flag;
455
456	/* note: FLUSHREAD and FLUSHWRITE already ok */
457	if (flush == 0) {
458		flush = TIOCPKT_STOP;
459		pti->pt_flags |= PF_STOPPED;
460	} else
461		pti->pt_flags &= ~PF_STOPPED;
462	pti->pt_send |= flush;
463	/* change of perspective */
464	flag = 0;
465	if (flush & FREAD)
466		flag |= FWRITE;
467	if (flush & FWRITE)
468		flag |= FREAD;
469	ptcwakeup(tp, flag);
470}
471
472static	int
473ptcpoll(dev, events, p)
474	dev_t dev;
475	int events;
476	struct proc *p;
477{
478	register struct tty *tp = dev->si_tty;
479	struct pt_ioctl *pti = dev->si_drv1;
480	int revents = 0;
481	int s;
482
483	if ((tp->t_state & TS_CONNECTED) == 0)
484		return (seltrue(dev, events, p) | POLLHUP);
485
486	/*
487	 * Need to block timeouts (ttrstart).
488	 */
489	s = spltty();
490
491	if (events & (POLLIN | POLLRDNORM))
492		if ((tp->t_state & TS_ISOPEN) &&
493		    ((tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) ||
494		     ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
495		     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
496			revents |= events & (POLLIN | POLLRDNORM);
497
498	if (events & (POLLOUT | POLLWRNORM))
499		if (tp->t_state & TS_ISOPEN &&
500		    ((pti->pt_flags & PF_REMOTE) ?
501		     (tp->t_canq.c_cc == 0) :
502		     ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG - 2) ||
503		      (tp->t_canq.c_cc == 0 && (tp->t_iflag & ICANON)))))
504			revents |= events & (POLLOUT | POLLWRNORM);
505
506	if (events & POLLHUP)
507		if ((tp->t_state & TS_CARR_ON) == 0)
508			revents |= POLLHUP;
509
510	if (revents == 0) {
511		if (events & (POLLIN | POLLRDNORM))
512			selrecord(p, &pti->pt_selr);
513
514		if (events & (POLLOUT | POLLWRNORM))
515			selrecord(p, &pti->pt_selw);
516	}
517	splx(s);
518
519	return (revents);
520}
521
522static	int
523ptcwrite(dev, uio, flag)
524	dev_t dev;
525	register struct uio *uio;
526	int flag;
527{
528	register struct tty *tp = dev->si_tty;
529	register u_char *cp = 0;
530	register int cc = 0;
531	u_char locbuf[BUFSIZ];
532	int cnt = 0;
533	struct pt_ioctl *pti = dev->si_drv1;
534	int error = 0;
535
536again:
537	if ((tp->t_state&TS_ISOPEN) == 0)
538		goto block;
539	if (pti->pt_flags & PF_REMOTE) {
540		if (tp->t_canq.c_cc)
541			goto block;
542		while ((uio->uio_resid > 0 || cc > 0) &&
543		       tp->t_canq.c_cc < TTYHOG - 1) {
544			if (cc == 0) {
545				cc = min(uio->uio_resid, BUFSIZ);
546				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
547				cp = locbuf;
548				error = uiomove((caddr_t)cp, cc, uio);
549				if (error)
550					return (error);
551				/* check again for safety */
552				if ((tp->t_state & TS_ISOPEN) == 0) {
553					/* adjust as usual */
554					uio->uio_resid += cc;
555					return (EIO);
556				}
557			}
558			if (cc > 0) {
559				cc = b_to_q((char *)cp, cc, &tp->t_canq);
560				/*
561				 * XXX we don't guarantee that the canq size
562				 * is >= TTYHOG, so the above b_to_q() may
563				 * leave some bytes uncopied.  However, space
564				 * is guaranteed for the null terminator if
565				 * we don't fail here since (TTYHOG - 1) is
566				 * not a multiple of CBSIZE.
567				 */
568				if (cc > 0)
569					break;
570			}
571		}
572		/* adjust for data copied in but not written */
573		uio->uio_resid += cc;
574		(void) putc(0, &tp->t_canq);
575		ttwakeup(tp);
576		wakeup(TSA_PTS_READ(tp));
577		return (0);
578	}
579	while (uio->uio_resid > 0 || cc > 0) {
580		if (cc == 0) {
581			cc = min(uio->uio_resid, BUFSIZ);
582			cp = locbuf;
583			error = uiomove((caddr_t)cp, cc, uio);
584			if (error)
585				return (error);
586			/* check again for safety */
587			if ((tp->t_state & TS_ISOPEN) == 0) {
588				/* adjust for data copied in but not written */
589				uio->uio_resid += cc;
590				return (EIO);
591			}
592		}
593		while (cc > 0) {
594			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
595			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
596				wakeup(TSA_HUP_OR_INPUT(tp));
597				goto block;
598			}
599			(*linesw[tp->t_line].l_rint)(*cp++, tp);
600			cnt++;
601			cc--;
602		}
603		cc = 0;
604	}
605	return (0);
606block:
607	/*
608	 * Come here to wait for slave to open, for space
609	 * in outq, or space in rawq, or an empty canq.
610	 */
611	if ((tp->t_state & TS_CONNECTED) == 0) {
612		/* adjust for data copied in but not written */
613		uio->uio_resid += cc;
614		return (EIO);
615	}
616	if (flag & IO_NDELAY) {
617		/* adjust for data copied in but not written */
618		uio->uio_resid += cc;
619		if (cnt == 0)
620			return (EWOULDBLOCK);
621		return (0);
622	}
623	error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
624	if (error) {
625		/* adjust for data copied in but not written */
626		uio->uio_resid += cc;
627		return (error);
628	}
629	goto again;
630}
631
632/*ARGSUSED*/
633static	int
634ptyioctl(dev, cmd, data, flag, p)
635	dev_t dev;
636	u_long cmd;
637	caddr_t data;
638	int flag;
639	struct proc *p;
640{
641	register struct tty *tp = dev->si_tty;
642	register struct pt_ioctl *pti = dev->si_drv1;
643	register u_char *cc = tp->t_cc;
644	int stop, error;
645
646	if (devsw(dev)->d_open == ptcopen) {
647		switch (cmd) {
648
649		case TIOCGPGRP:
650			/*
651			 * We avoid calling ttioctl on the controller since,
652			 * in that case, tp must be the controlling terminal.
653			 */
654			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
655			return (0);
656
657		case TIOCPKT:
658			if (*(int *)data) {
659				if (pti->pt_flags & PF_UCNTL)
660					return (EINVAL);
661				pti->pt_flags |= PF_PKT;
662			} else
663				pti->pt_flags &= ~PF_PKT;
664			return (0);
665
666		case TIOCUCNTL:
667			if (*(int *)data) {
668				if (pti->pt_flags & PF_PKT)
669					return (EINVAL);
670				pti->pt_flags |= PF_UCNTL;
671			} else
672				pti->pt_flags &= ~PF_UCNTL;
673			return (0);
674
675		case TIOCREMOTE:
676			if (*(int *)data)
677				pti->pt_flags |= PF_REMOTE;
678			else
679				pti->pt_flags &= ~PF_REMOTE;
680			ttyflush(tp, FREAD|FWRITE);
681			return (0);
682		}
683
684		/*
685		 * The rest of the ioctls shouldn't be called until
686		 * the slave is open.
687		 */
688		if ((tp->t_state & TS_ISOPEN) == 0)
689			return (EAGAIN);
690
691		switch (cmd) {
692#ifdef COMPAT_43
693		case TIOCSETP:
694		case TIOCSETN:
695#endif
696		case TIOCSETD:
697		case TIOCSETA:
698		case TIOCSETAW:
699		case TIOCSETAF:
700			/*
701			 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
702			 * ttywflush(tp) will hang if there are characters in
703			 * the outq.
704			 */
705			ndflush(&tp->t_outq, tp->t_outq.c_cc);
706			break;
707
708		case TIOCSIG:
709			if (*(unsigned int *)data >= NSIG ||
710			    *(unsigned int *)data == 0)
711				return(EINVAL);
712			if ((tp->t_lflag&NOFLSH) == 0)
713				ttyflush(tp, FREAD|FWRITE);
714			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
715			if ((*(unsigned int *)data == SIGINFO) &&
716			    ((tp->t_lflag&NOKERNINFO) == 0))
717				ttyinfo(tp);
718			return(0);
719		}
720	}
721	if (cmd == TIOCEXT) {
722		/*
723		 * When the EXTPROC bit is being toggled, we need
724		 * to send an TIOCPKT_IOCTL if the packet driver
725		 * is turned on.
726		 */
727		if (*(int *)data) {
728			if (pti->pt_flags & PF_PKT) {
729				pti->pt_send |= TIOCPKT_IOCTL;
730				ptcwakeup(tp, FREAD);
731			}
732			tp->t_lflag |= EXTPROC;
733		} else {
734			if ((tp->t_lflag & EXTPROC) &&
735			    (pti->pt_flags & PF_PKT)) {
736				pti->pt_send |= TIOCPKT_IOCTL;
737				ptcwakeup(tp, FREAD);
738			}
739			tp->t_lflag &= ~EXTPROC;
740		}
741		return(0);
742	}
743	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
744	if (error == ENOIOCTL)
745		 error = ttioctl(tp, cmd, data, flag);
746	if (error == ENOIOCTL) {
747		if (pti->pt_flags & PF_UCNTL &&
748		    (cmd & ~0xff) == UIOCCMD(0)) {
749			if (cmd & 0xff) {
750				pti->pt_ucntl = (u_char)cmd;
751				ptcwakeup(tp, FREAD);
752			}
753			return (0);
754		}
755		error = ENOTTY;
756	}
757	/*
758	 * If external processing and packet mode send ioctl packet.
759	 */
760	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
761		switch(cmd) {
762		case TIOCSETA:
763		case TIOCSETAW:
764		case TIOCSETAF:
765#ifdef COMPAT_43
766		case TIOCSETP:
767		case TIOCSETN:
768#endif
769#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
770		case TIOCSETC:
771		case TIOCSLTC:
772		case TIOCLBIS:
773		case TIOCLBIC:
774		case TIOCLSET:
775#endif
776			pti->pt_send |= TIOCPKT_IOCTL;
777			ptcwakeup(tp, FREAD);
778		default:
779			break;
780		}
781	}
782	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
783		&& CCEQ(cc[VSTART], CTRL('q'));
784	if (pti->pt_flags & PF_NOSTOP) {
785		if (stop) {
786			pti->pt_send &= ~TIOCPKT_NOSTOP;
787			pti->pt_send |= TIOCPKT_DOSTOP;
788			pti->pt_flags &= ~PF_NOSTOP;
789			ptcwakeup(tp, FREAD);
790		}
791	} else {
792		if (!stop) {
793			pti->pt_send &= ~TIOCPKT_DOSTOP;
794			pti->pt_send |= TIOCPKT_NOSTOP;
795			pti->pt_flags |= PF_NOSTOP;
796			ptcwakeup(tp, FREAD);
797		}
798	}
799	return (error);
800}
801
802
803static void ptc_drvinit __P((void *unused));
804
805static void pty_clone __P((void *arg, char *name, int namelen, dev_t *dev));
806
807static void
808pty_clone(arg, name, namelen, dev)
809	void *arg;
810	char *name;
811	int namelen;
812	dev_t *dev;
813{
814	int u;
815
816	if (*dev != NODEV)
817		return;
818	if (bcmp(name, "pty", 3) != 0)
819		return;
820	if (name[5] != '\0')
821		return;
822	switch (name[3]) {
823	case 'p': u =   0; break;
824	case 'q': u =  32; break;
825	case 'r': u =  64; break;
826	case 's': u =  96; break;
827	case 'P': u = 128; break;
828	case 'Q': u = 160; break;
829	case 'R': u = 192; break;
830	case 'S': u = 224; break;
831	default: return;
832	}
833	if (name[4] >= '0' && name[4] <= '9')
834		u += name[4] - '0';
835	else if (name[4] >= 'a' && name[4] <= 'v')
836		u += name[4] - 'a' + 10;
837	else
838		return;
839	*dev = ptyinit(u);
840	return;
841}
842
843static void
844ptc_drvinit(unused)
845	void *unused;
846{
847	EVENTHANDLER_REGISTER(dev_clone, pty_clone, 0, 1000);
848	cdevsw_add(&pts_cdevsw);
849	cdevsw_add(&ptc_cdevsw);
850}
851
852SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR_C,ptc_drvinit,NULL)
853