pty.c revision 9824
167754Smsmith/*
267754Smsmith * Copyright (c) 1982, 1986, 1989, 1993
367754Smsmith *	The Regents of the University of California.  All rights reserved.
467754Smsmith *
567754Smsmith * Redistribution and use in source and binary forms, with or without
667754Smsmith * modification, are permitted provided that the following conditions
7217365Sjkim * are met:
8245582Sjkim * 1. Redistributions of source code must retain the above copyright
970243Smsmith *    notice, this list of conditions and the following disclaimer.
1067754Smsmith * 2. Redistributions in binary form must reproduce the above copyright
11217365Sjkim *    notice, this list of conditions and the following disclaimer in the
12217365Sjkim *    documentation and/or other materials provided with the distribution.
13217365Sjkim * 3. All advertising materials mentioning features or use of this software
14217365Sjkim *    must display the following acknowledgement:
15217365Sjkim *	This product includes software developed by the University of
16217365Sjkim *	California, Berkeley and its contributors.
17217365Sjkim * 4. Neither the name of the University nor the names of its contributors
18217365Sjkim *    may be used to endorse or promote products derived from this software
19217365Sjkim *    without specific prior written permission.
20217365Sjkim *
21217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22217365Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23217365Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24217365Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2567754Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2967754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30217365Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31217365Sjkim * SUCH DAMAGE.
32217365Sjkim *
33217365Sjkim *	@(#)tty_pty.c	8.2 (Berkeley) 9/23/93
34217365Sjkim * $Id: tty_pty.c,v 1.15 1995/07/22 16:45:08 bde Exp $
35217365Sjkim */
36217365Sjkim
37217365Sjkim/*
38217365Sjkim * Pseudo-teletype Driver
39217365Sjkim * (Actually two drivers, requiring two entries in 'cdevsw')
40217365Sjkim */
41217365Sjkim#include "pty.h"		/* XXX */
42217365Sjkim
4367754Smsmith#include <sys/param.h>
44193341Sjkim#include <sys/systm.h>
45193341Sjkim#include <sys/ioctl.h>
46193341Sjkim#include <sys/proc.h>
4767754Smsmith#include <sys/tty.h>
4877424Smsmith#include <sys/conf.h>
4991116Smsmith#include <sys/file.h>
5067754Smsmith#include <sys/uio.h>
51231844Sjkim#include <sys/kernel.h>
52231844Sjkim#include <sys/vnode.h>
53151937Sjkim#include <sys/signalvar.h>
5467754Smsmith
55151937Sjkim#if NPTY == 1
56151937Sjkim#undef NPTY
57151937Sjkim#define	NPTY	32		/* crude XXX */
58193267Sjkim#endif
59193267Sjkim
60151937Sjkim#define BUFSIZ 100		/* Chunk size iomoved to/from user */
61151937Sjkim
6267754Smsmith/*
6367754Smsmith * pts == /dev/tty[pqrs]?
64209746Sjkim * ptc == /dev/pty[pqrs]?
65193267Sjkim */
66209746Sjkimstruct	tty pt_tty[NPTY];	/* XXX */
67209746Sjkimstruct	pt_ioctl {
68209746Sjkim	int	pt_flags;
69209746Sjkim	struct	selinfo pt_selr, pt_selw;
70209746Sjkim	u_char	pt_send;
71209746Sjkim	u_char	pt_ucntl;
72209746Sjkim} pt_ioctl[NPTY];		/* XXX */
73209746Sjkimint	npty = NPTY;		/* for pstat -t */
74209746Sjkim
75209746Sjkim#define	PF_PKT		0x08		/* packet mode */
76209746Sjkim#define	PF_STOPPED	0x10		/* user told stopped */
77239340Sjkim#define	PF_REMOTE	0x20		/* remote and flow controlled input */
78209746Sjkim#define	PF_NOSTOP	0x40
79209746Sjkim#define PF_UCNTL	0x80		/* user control mode */
80209746Sjkim
81239340Sjkimvoid	ptsstop		__P((struct tty *, int));
82209746Sjkimvoid	ptcwakeup	__P((struct tty *, int));
83209746Sjkim
84209746Sjkim/*
85209746Sjkim * Establish n (or default if n is 1) ptys in the system.
86209746Sjkim *
87209746Sjkim * XXX cdevsw & pstat require the array `pty[]' to be an array
88209746Sjkim */
89193267Sjkimvoid
90209746Sjkimptyattach(n)
91193267Sjkim	int n;
92193267Sjkim{
93193267Sjkim#ifdef notyet
94209746Sjkim	char *mem;
95193267Sjkim	register u_long ntb;
96193267Sjkim#define	DEFAULT_NPTY	32
97193267Sjkim
98193267Sjkim	/* maybe should allow 0 => none? */
99209746Sjkim	if (n <= 1)
100209746Sjkim		n = DEFAULT_NPTY;
101209746Sjkim	ntb = n * sizeof(struct tty);
102193267Sjkim	mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
103193267Sjkim	    M_DEVBUF, M_WAITOK);
104193267Sjkim	pt_tty = (struct tty *)mem;
105193267Sjkim	mem = (char *)ALIGN(mem + ntb);
106209746Sjkim	pt_ioctl = (struct pt_ioctl *)mem;
107193267Sjkim	npty = n;
108193267Sjkim#endif
109209746Sjkim}
110209746Sjkim
111209746Sjkim/*ARGSUSED*/
112193267Sjkimint
113193267Sjkimptsopen(dev, flag, devtype, p)
114193267Sjkim	dev_t dev;
115193267Sjkim	int flag, devtype;
116193267Sjkim	struct proc *p;
117193267Sjkim{
118193267Sjkim	register struct tty *tp;
119193267Sjkim	int error;
120193267Sjkim
121193267Sjkim	if (minor(dev) >= npty)
122197104Sjkim		return (ENXIO);
123193267Sjkim	tp = &pt_tty[minor(dev)];
124193267Sjkim	if ((tp->t_state & TS_ISOPEN) == 0) {
125193267Sjkim		ttychars(tp);		/* Set up default chars */
126193267Sjkim		tp->t_iflag = TTYDEF_IFLAG;
127193267Sjkim		tp->t_oflag = TTYDEF_OFLAG;
128209746Sjkim		tp->t_lflag = TTYDEF_LFLAG;
129193267Sjkim		tp->t_cflag = TTYDEF_CFLAG;
130239340Sjkim		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
131209746Sjkim		ttsetwater(tp);		/* would be done in xxparam() */
132209746Sjkim	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
133209746Sjkim		return (EBUSY);
134193267Sjkim	if (tp->t_oproc)			/* Ctrlr still around. */
135209746Sjkim		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
136193267Sjkim	while ((tp->t_state & TS_CARR_ON) == 0) {
137209746Sjkim		if (flag&FNONBLOCK)
138209746Sjkim			break;
139209746Sjkim		error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
140209746Sjkim				 "ptsopn", 0);
141193267Sjkim		if (error)
142209746Sjkim			return (error);
143193267Sjkim	}
144209746Sjkim	error = (*linesw[tp->t_line].l_open)(dev, tp);
145250838Sjkim	if (error == 0)
146209746Sjkim		ptcwakeup(tp, FREAD|FWRITE);
147209746Sjkim	return (error);
148193267Sjkim}
149209746Sjkim
150250838Sjkimint
151209746Sjkimptsclose(dev, flag, mode, p)
152209746Sjkim	dev_t dev;
15367754Smsmith	int flag, mode;
154209746Sjkim	struct proc *p;
155250838Sjkim{
156245582Sjkim	register struct tty *tp;
157209746Sjkim	int err;
158114237Snjl
15967754Smsmith	tp = &pt_tty[minor(dev)];
160209746Sjkim	err = (*linesw[tp->t_line].l_close)(tp, flag);
16184491Smsmith	ptsstop(tp, FREAD|FWRITE);
162209746Sjkim	(void) ttyclose(tp);
163129684Snjl	return (err);
16467754Smsmith}
16567754Smsmith
16691116Smsmithint
16784491Smsmithptsread(dev, uio, flag)
16884491Smsmith	dev_t dev;
16967754Smsmith	struct uio *uio;
17067754Smsmith	int flag;
171128212Snjl{
17267754Smsmith	struct proc *p = curproc;
173138287Smarks	register struct tty *tp = &pt_tty[minor(dev)];
17467754Smsmith	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
175128212Snjl	int error = 0;
17667754Smsmith
17767754Smsmithagain:
17867754Smsmith	if (pti->pt_flags & PF_REMOTE) {
17999679Siwasaki		while (isbackground(p, tp)) {
18067754Smsmith			if ((p->p_sigignore & sigmask(SIGTTIN)) ||
181114237Snjl			    (p->p_sigmask & sigmask(SIGTTIN)) ||
18267754Smsmith			    p->p_pgrp->pg_jobc == 0 ||
183209746Sjkim			    p->p_flag & P_PPWAIT)
18499679Siwasaki				return (EIO);
185209746Sjkim			pgsignal(p->p_pgrp, SIGTTIN, 1);
18667754Smsmith			error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
18780062Smsmith					 0);
18891116Smsmith			if (error)
18983174Smsmith				return (error);
190209746Sjkim		}
19183174Smsmith		if (tp->t_canq.c_cc == 0) {
192209746Sjkim			if (flag & IO_NDELAY)
193209746Sjkim				return (EWOULDBLOCK);
194209746Sjkim			error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH,
195209746Sjkim					 "ptsin", 0);
196209746Sjkim			if (error)
197167802Sjkim				return (error);
19867754Smsmith			goto again;
19967754Smsmith		}
20067754Smsmith		while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
20167754Smsmith			if (ureadc(getc(&tp->t_canq), uio) < 0) {
202239340Sjkim				error = EFAULT;
203209746Sjkim				break;
204197104Sjkim			}
205209746Sjkim		if (tp->t_canq.c_cc == 1)
20699679Siwasaki			(void) getc(&tp->t_canq);
20799679Siwasaki		if (tp->t_canq.c_cc)
20867754Smsmith			return (error);
20967754Smsmith	} else
21067754Smsmith		if (tp->t_oproc)
21167754Smsmith			error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
21267754Smsmith	ptcwakeup(tp, FWRITE);
21367754Smsmith	return (error);
21467754Smsmith}
215128212Snjl
216128212Snjl/*
21767754Smsmith * Write to pseudo-tty.
218128212Snjl * Wakeups of controlling tty will happen
21967754Smsmith * indirectly, when tty driver calls ptsstart.
22067754Smsmith */
22167754Smsmithint
22267754Smsmithptswrite(dev, uio, flag)
22367754Smsmith	dev_t dev;
22499679Siwasaki	struct uio *uio;
22567754Smsmith	int flag;
226117521Snjl{
22767754Smsmith	register struct tty *tp;
22867754Smsmith
229114237Snjl	tp = &pt_tty[minor(dev)];
230209746Sjkim	if (tp->t_oproc == 0)
23191116Smsmith		return (EIO);
232209746Sjkim	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
23399679Siwasaki}
23467754Smsmith
23580062Smsmith/*
23691116Smsmith * Start output on pseudo-tty.
23783174Smsmith * Wake up process selecting or sleeping for input from controlling tty.
23883174Smsmith */
23967754Smsmithvoid
24067754Smsmithptsstart(tp)
24199679Siwasaki	struct tty *tp;
24267754Smsmith{
24367754Smsmith	register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
244114237Snjl
24567754Smsmith	if (tp->t_state & TS_TTSTOP)
246114237Snjl		return;
24767754Smsmith	if (pti->pt_flags & PF_STOPPED) {
24891116Smsmith		pti->pt_flags &= ~PF_STOPPED;
24991116Smsmith		pti->pt_send = TIOCPKT_START;
250239340Sjkim	}
25191116Smsmith	ptcwakeup(tp, FREAD);
252129684Snjl}
25391116Smsmith
254129684Snjlvoid
25599679Siwasakiptcwakeup(tp, flag)
256114237Snjl	struct tty *tp;
25767754Smsmith	int flag;
25867754Smsmith{
259129684Snjl	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
26091116Smsmith
261129684Snjl	if (flag & FREAD) {
26284491Smsmith		selwakeup(&pti->pt_selr);
263114237Snjl		wakeup(TSA_PTC_READ(tp));
26484491Smsmith	}
26584491Smsmith	if (flag & FWRITE) {
266129684Snjl		selwakeup(&pti->pt_selw);
26791116Smsmith		wakeup(TSA_PTC_WRITE(tp));
268197104Sjkim	}
26999679Siwasaki}
27099679Siwasaki
271202771Sjkimint
27299679Siwasakiptcopen(dev, flag, devtype, p)
27399679Siwasaki	dev_t dev;
274129684Snjl	int flag, devtype;
27567754Smsmith	struct proc *p;
276114237Snjl{
27767754Smsmith	register struct tty *tp;
278114237Snjl	struct pt_ioctl *pti;
279114237Snjl
280114237Snjl	if (minor(dev) >= npty)
281114237Snjl		return (ENXIO);
282202771Sjkim	tp = &pt_tty[minor(dev)];
283117521Snjl	if (tp->t_oproc)
284117521Snjl		return (EIO);
285117521Snjl	tp->t_oproc = ptsstart;
286117521Snjl#ifdef sun4c
287117521Snjl	tp->t_stop = ptsstop;
288117521Snjl#endif
289117521Snjl	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
290117521Snjl	tp->t_lflag &= ~EXTPROC;
291117521Snjl	pti = &pt_ioctl[minor(dev)];
292117521Snjl	pti->pt_flags = 0;
293117521Snjl	pti->pt_send = 0;
294117521Snjl	pti->pt_ucntl = 0;
295151937Sjkim	return (0);
296117521Snjl}
297117521Snjl
298117521Snjlint
299117521Snjlptcclose(dev)
300117521Snjl	dev_t dev;
301117521Snjl{
302193267Sjkim	register struct tty *tp;
303193267Sjkim
304117521Snjl	tp = &pt_tty[minor(dev)];
305117521Snjl	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
306117521Snjl
307117521Snjl	/*
308117521Snjl	 * XXX MDMBUF makes no sense for ptys but would inhibit the above
309117521Snjl	 * l_modem().  CLOCAL makes sense but isn't supported.   Special
310117521Snjl	 * l_modem()s that ignore carrier drop make no sense for ptys but
311117521Snjl	 * may be in use because other parts of the line discipline make
312117521Snjl	 * sense for ptys.  Recover by doing everything that a normal
313126372Snjl	 * ttymodem() would have done except for sending a SIGHUP.
314126372Snjl	 */
315197104Sjkim	tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
316117521Snjl	tp->t_state |= TS_ZOMBIE;
317117521Snjl	ttyflush(tp, FREAD | FWRITE);
318117521Snjl
319117521Snjl	tp->t_oproc = 0;		/* mark closed */
320117521Snjl	tp->t_session = 0;
321117521Snjl	return (0);
32299679Siwasaki}
32367754Smsmith
32484491Smsmithint
32591116Smsmithptcread(dev, uio, flag)
32684491Smsmith	dev_t dev;
32784491Smsmith	struct uio *uio;
328117521Snjl	int flag;
329117521Snjl{
330117521Snjl	register struct tty *tp = &pt_tty[minor(dev)];
331117521Snjl	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
332117521Snjl	char buf[BUFSIZ];
333117521Snjl	int error = 0, cc;
334117521Snjl
335151937Sjkim	/*
336117521Snjl	 * We want to block until the slave
337117521Snjl	 * is open, and there's something to read;
338117521Snjl	 * but if we lost the slave or we're NBIO,
339117521Snjl	 * then return the appropriate error instead.
340117521Snjl	 */
341117521Snjl	for (;;) {
342193267Sjkim		if (tp->t_state&TS_ISOPEN) {
343193267Sjkim			if (pti->pt_flags&PF_PKT && pti->pt_send) {
344117521Snjl				error = ureadc((int)pti->pt_send, uio);
345117521Snjl				if (error)
346117521Snjl					return (error);
347117521Snjl				if (pti->pt_send & TIOCPKT_IOCTL) {
348117521Snjl					cc = min(uio->uio_resid,
349117521Snjl						sizeof(tp->t_termios));
350117521Snjl					uiomove((caddr_t)&tp->t_termios, cc,
351117521Snjl						uio);
352117521Snjl				}
353128212Snjl				pti->pt_send = 0;
354126372Snjl				return (0);
355197104Sjkim			}
356117521Snjl			if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
357117521Snjl				error = ureadc((int)pti->pt_ucntl, uio);
358117521Snjl				if (error)
359117521Snjl					return (error);
360117521Snjl				pti->pt_ucntl = 0;
361117521Snjl				return (0);
362117521Snjl			}
363117521Snjl			if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
364117521Snjl				break;
365117521Snjl		}
366117521Snjl		if ((tp->t_state & TS_CONNECTED) == 0)
367117521Snjl			return (0);	/* EOF */
368129684Snjl		if (flag & IO_NDELAY)
369117521Snjl			return (EWOULDBLOCK);
370117521Snjl		error = tsleep(TSA_PTC_READ(tp), TTIPRI | PCATCH, "ptcin", 0);
371117521Snjl		if (error)
372117521Snjl			return (error);
373117521Snjl	}
374117521Snjl	if (pti->pt_flags & (PF_PKT|PF_UCNTL))
375151937Sjkim		error = ureadc(0, uio);
376151937Sjkim	while (uio->uio_resid > 0 && error == 0) {
377117521Snjl		cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
378117521Snjl		if (cc <= 0)
379117521Snjl			break;
380129684Snjl		error = uiomove(buf, cc, uio);
381129684Snjl	}
382117521Snjl	ttwwakeup(tp);
383193267Sjkim	return (error);
384193267Sjkim}
385117521Snjl
386117521Snjlvoid
387117521Snjlptsstop(tp, flush)
388117521Snjl	register struct tty *tp;
389117521Snjl	int flush;
390129684Snjl{
391117521Snjl	struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
392117521Snjl	int flag;
393117521Snjl
394117521Snjl	/* note: FLUSHREAD and FLUSHWRITE already ok */
395117521Snjl	if (flush == 0) {
396129684Snjl		flush = TIOCPKT_STOP;
397117521Snjl		pti->pt_flags |= PF_STOPPED;
398129684Snjl	} else
399117521Snjl		pti->pt_flags &= ~PF_STOPPED;
400117521Snjl	pti->pt_send |= flush;
401129684Snjl	/* change of perspective */
402117521Snjl	flag = 0;
403197104Sjkim	if (flush & FREAD)
404129684Snjl		flag |= FWRITE;
405117521Snjl	if (flush & FWRITE)
406117521Snjl		flag |= FREAD;
407117521Snjl	ptcwakeup(tp, flag);
408117521Snjl}
409117521Snjl
410117521Snjlint
411117521Snjlptcselect(dev, rw, p)
412117521Snjl	dev_t dev;
413117521Snjl	int rw;
414117521Snjl	struct proc *p;
415117521Snjl{
416117521Snjl	register struct tty *tp = &pt_tty[minor(dev)];
417129684Snjl	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
41884491Smsmith	int s;
419129684Snjl
420129684Snjl	if ((tp->t_state & TS_CONNECTED) == 0)
42184491Smsmith		return (1);
422128212Snjl	switch (rw) {
42384491Smsmith
424151937Sjkim	case FREAD:
425151937Sjkim		/*
42684491Smsmith		 * Need to block timeouts (ttrstart).
42784491Smsmith		 */
42884491Smsmith		s = spltty();
429151937Sjkim		if ((tp->t_state&TS_ISOPEN) &&
430129684Snjl		     tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
431129684Snjl			splx(s);
432193267Sjkim			return (1);
433193267Sjkim		}
43484491Smsmith		splx(s);
435129684Snjl		/* FALLTHROUGH */
43699679Siwasaki
43784491Smsmith	case 0:					/* exceptional */
43884491Smsmith		if ((tp->t_state&TS_ISOPEN) &&
439129684Snjl		    ((pti->pt_flags&PF_PKT && pti->pt_send) ||
44091116Smsmith		     (pti->pt_flags&PF_UCNTL && pti->pt_ucntl)))
441129684Snjl			return (1);
442129684Snjl		selrecord(p, &pti->pt_selr);
443129684Snjl		break;
444129684Snjl
445129684Snjl
446129684Snjl	case FWRITE:
44791116Smsmith		if (tp->t_state&TS_ISOPEN) {
448129684Snjl			if (pti->pt_flags & PF_REMOTE) {
449129684Snjl			    if (tp->t_canq.c_cc == 0)
450197104Sjkim				return (1);
451129684Snjl			} else {
452129684Snjl			    if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
453129684Snjl				    return (1);
454129684Snjl			    if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
455129684Snjl				    return (1);
456129684Snjl			}
457129684Snjl		}
458129684Snjl		selrecord(p, &pti->pt_selw);
459117521Snjl		break;
46084491Smsmith
46199679Siwasaki	}
462117521Snjl	return (0);
463117521Snjl}
464129684Snjl
465117521Snjlint
466151937Sjkimptcwrite(dev, uio, flag)
467117521Snjl	dev_t dev;
468117521Snjl	register struct uio *uio;
469117521Snjl	int flag;
470151937Sjkim{
471117521Snjl	register struct tty *tp = &pt_tty[minor(dev)];
472117521Snjl	register u_char *cp = 0;
473114237Snjl	register int cc = 0;
474129684Snjl	u_char locbuf[BUFSIZ];
475129684Snjl	int cnt = 0;
476151937Sjkim	struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
477117521Snjl	int error = 0;
478117521Snjl
479114237Snjlagain:
480117521Snjl	if ((tp->t_state&TS_ISOPEN) == 0)
481167802Sjkim		goto block;
482117521Snjl	if (pti->pt_flags & PF_REMOTE) {
483117521Snjl		if (tp->t_canq.c_cc)
484193267Sjkim			goto block;
485193267Sjkim		while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
486129684Snjl			if (cc == 0) {
487129684Snjl				cc = min(uio->uio_resid, BUFSIZ);
488117521Snjl				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
489117521Snjl				cp = locbuf;
490129684Snjl				error = uiomove((caddr_t)cp, cc, uio);
491129684Snjl				if (error)
492129684Snjl					return (error);
493129684Snjl				/* check again for safety */
494151937Sjkim				if ((tp->t_state&TS_ISOPEN) == 0)
495129684Snjl					return (EIO);
496129684Snjl			}
497129684Snjl			if (cc)
498151937Sjkim				(void) b_to_q((char *)cp, cc, &tp->t_canq);
499129684Snjl			cc = 0;
500129684Snjl		}
501126372Snjl		(void) putc(0, &tp->t_canq);
502129684Snjl		ttwakeup(tp);
503129684Snjl		wakeup(TSA_PTS_READ(tp));
504151937Sjkim		return (0);
505129684Snjl	}
506129684Snjl	while (uio->uio_resid > 0) {
507126372Snjl		if (cc == 0) {
508114237Snjl			cc = min(uio->uio_resid, BUFSIZ);
509167802Sjkim			cp = locbuf;
510128212Snjl			error = uiomove((caddr_t)cp, cc, uio);
511114237Snjl			if (error)
512193267Sjkim				return (error);
513129684Snjl			/* check again for safety */
51484491Smsmith			if ((tp->t_state&TS_ISOPEN) == 0)
51584491Smsmith				return (EIO);
51691116Smsmith		}
51784491Smsmith		while (cc > 0) {
51884491Smsmith			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
519129684Snjl			   (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
52084491Smsmith				wakeup(TSA_HUP_OR_INPUT(tp));
521151937Sjkim				goto block;
52284491Smsmith			}
523128212Snjl			(*linesw[tp->t_line].l_rint)(*cp++, tp);
52484491Smsmith			cnt++;
525151937Sjkim			cc--;
52684491Smsmith		}
52784491Smsmith		cc = 0;
52884491Smsmith	}
52999679Siwasaki	return (0);
530129684Snjlblock:
531151937Sjkim	/*
53284491Smsmith	 * Come here to wait for slave to open, for space
53399679Siwasaki	 * in outq, or space in rawq.
53484491Smsmith	 */
53584491Smsmith	if ((tp->t_state & TS_CONNECTED) == 0)
536167802Sjkim		return (EIO);
53791116Smsmith	if (flag & IO_NDELAY) {
53891116Smsmith		/* adjust for data copied in but not written */
539193267Sjkim		uio->uio_resid += cc;
540129684Snjl		if (cnt == 0)
54184491Smsmith			return (EWOULDBLOCK);
542129684Snjl		return (0);
543231844Sjkim	}
544	error = tsleep(TSA_PTC_WRITE(tp), TTOPRI | PCATCH, "ptcout", 0);
545	if (error) {
546		/* adjust for data copied in but not written */
547		uio->uio_resid += cc;
548		return (error);
549	}
550	goto again;
551}
552
553struct tty *
554ptydevtotty(dev)
555	dev_t		dev;
556{
557	if (minor(dev) >= npty)
558		return (NULL);
559
560	return &pt_tty[minor(dev)];
561}
562
563/*ARGSUSED*/
564int
565ptyioctl(dev, cmd, data, flag, p)
566	dev_t dev;
567	int cmd;
568	caddr_t data;
569	int flag;
570	struct proc *p;
571{
572	register struct tty *tp = &pt_tty[minor(dev)];
573	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
574	register u_char *cc = tp->t_cc;
575	int stop, error;
576
577	/*
578	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
579	 * ttywflush(tp) will hang if there are characters in the outq.
580	 */
581	if (cmd == TIOCEXT) {
582		/*
583		 * When the EXTPROC bit is being toggled, we need
584		 * to send an TIOCPKT_IOCTL if the packet driver
585		 * is turned on.
586		 */
587		if (*(int *)data) {
588			if (pti->pt_flags & PF_PKT) {
589				pti->pt_send |= TIOCPKT_IOCTL;
590				ptcwakeup(tp, FREAD);
591			}
592			tp->t_lflag |= EXTPROC;
593		} else {
594			if ((tp->t_state & EXTPROC) &&
595			    (pti->pt_flags & PF_PKT)) {
596				pti->pt_send |= TIOCPKT_IOCTL;
597				ptcwakeup(tp, FREAD);
598			}
599			tp->t_lflag &= ~EXTPROC;
600		}
601		return(0);
602	} else
603	if (cdevsw[major(dev)].d_open == ptcopen)
604		switch (cmd) {
605
606		case TIOCGPGRP:
607			/*
608			 * We aviod calling ttioctl on the controller since,
609			 * in that case, tp must be the controlling terminal.
610			 */
611			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
612			return (0);
613
614		case TIOCPKT:
615			if (*(int *)data) {
616				if (pti->pt_flags & PF_UCNTL)
617					return (EINVAL);
618				pti->pt_flags |= PF_PKT;
619			} else
620				pti->pt_flags &= ~PF_PKT;
621			return (0);
622
623		case TIOCUCNTL:
624			if (*(int *)data) {
625				if (pti->pt_flags & PF_PKT)
626					return (EINVAL);
627				pti->pt_flags |= PF_UCNTL;
628			} else
629				pti->pt_flags &= ~PF_UCNTL;
630			return (0);
631
632		case TIOCREMOTE:
633			if (*(int *)data)
634				pti->pt_flags |= PF_REMOTE;
635			else
636				pti->pt_flags &= ~PF_REMOTE;
637			ttyflush(tp, FREAD|FWRITE);
638			return (0);
639
640#ifdef COMPAT_43
641		case TIOCSETP:
642		case TIOCSETN:
643#endif
644		case TIOCSETD:
645		case TIOCSETA:
646		case TIOCSETAW:
647		case TIOCSETAF:
648			ndflush(&tp->t_outq, tp->t_outq.c_cc);
649			break;
650
651		case TIOCSIG:
652			if (*(unsigned int *)data >= NSIG)
653				return(EINVAL);
654			if ((tp->t_lflag&NOFLSH) == 0)
655				ttyflush(tp, FREAD|FWRITE);
656			pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
657			if ((*(unsigned int *)data == SIGINFO) &&
658			    ((tp->t_lflag&NOKERNINFO) == 0))
659				ttyinfo(tp);
660			return(0);
661		}
662	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
663	if (error < 0)
664		 error = ttioctl(tp, cmd, data, flag);
665	if (error < 0) {
666		if (pti->pt_flags & PF_UCNTL &&
667		    (cmd & ~0xff) == UIOCCMD(0)) {
668			if (cmd & 0xff) {
669				pti->pt_ucntl = (u_char)cmd;
670				ptcwakeup(tp, FREAD);
671			}
672			return (0);
673		}
674		error = ENOTTY;
675	}
676	/*
677	 * If external processing and packet mode send ioctl packet.
678	 */
679	if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
680		switch(cmd) {
681		case TIOCSETA:
682		case TIOCSETAW:
683		case TIOCSETAF:
684#ifdef COMPAT_43
685		case TIOCSETP:
686		case TIOCSETN:
687#endif
688#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
689		case TIOCSETC:
690		case TIOCSLTC:
691		case TIOCLBIS:
692		case TIOCLBIC:
693		case TIOCLSET:
694#endif
695			pti->pt_send |= TIOCPKT_IOCTL;
696			ptcwakeup(tp, FREAD);
697		default:
698			break;
699		}
700	}
701	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
702		&& CCEQ(cc[VSTART], CTRL('q'));
703	if (pti->pt_flags & PF_NOSTOP) {
704		if (stop) {
705			pti->pt_send &= ~TIOCPKT_NOSTOP;
706			pti->pt_send |= TIOCPKT_DOSTOP;
707			pti->pt_flags &= ~PF_NOSTOP;
708			ptcwakeup(tp, FREAD);
709		}
710	} else {
711		if (!stop) {
712			pti->pt_send &= ~TIOCPKT_DOSTOP;
713			pti->pt_send |= TIOCPKT_NOSTOP;
714			pti->pt_flags |= PF_NOSTOP;
715			ptcwakeup(tp, FREAD);
716		}
717	}
718	return (error);
719}
720