1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Copyright (c) 1983 Regents of the University of California.
8 * All rights reserved. The Berkeley software License Agreement
9 * specifies the terms and conditions for redistribution.
10 */
11
12/*
13 * PTY - Stream "pseudo-tty" device.  For each "controller" side
14 * it connects to a "slave" side.
15 */
16
17
18#include <sys/param.h>
19#include <sys/systm.h>
20#include <sys/filio.h>
21#include <sys/ioccom.h>
22#include <sys/termios.h>
23#include <sys/termio.h>
24#include <sys/ttold.h>
25#include <sys/stropts.h>
26#include <sys/stream.h>
27#include <sys/tty.h>
28#include <sys/user.h>
29#include <sys/conf.h>
30#include <sys/file.h>
31#include <sys/vnode.h>	/* 1/0 on the vomit meter */
32#include <sys/proc.h>
33#include <sys/uio.h>
34#include <sys/errno.h>
35#include <sys/strsubr.h>
36#include <sys/poll.h>
37#include <sys/sysmacros.h>
38#include <sys/debug.h>
39#include <sys/procset.h>
40#include <sys/cred.h>
41#include <sys/ptyvar.h>
42#include <sys/suntty.h>
43#include <sys/stat.h>
44
45#include <sys/conf.h>
46#include <sys/ddi.h>
47#include <sys/sunddi.h>
48
49extern int npty;	/* number of pseudo-ttys configured in */
50extern struct pty *pty_softc;
51extern struct pollhead	ptcph;	/* poll head for ptcpoll() use */
52
53int ptcopen(dev_t *, int, int, struct cred *);
54int ptcclose(dev_t, int, int, struct cred *);
55int ptcwrite(dev_t, struct uio *, struct cred *);
56int ptcread(dev_t, struct uio *, struct cred *);
57int ptcioctl(dev_t, int, intptr_t, int, struct cred *, int *);
58int ptcpoll(dev_t, short, int, short *, struct pollhead **);
59
60static int ptc_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
61static int ptc_attach(dev_info_t *, ddi_attach_cmd_t);
62static dev_info_t *ptc_dip;	/* for dev-to-dip conversions */
63
64static void ptc_init(void), ptc_uninit(void);
65
66static int makemsg(ssize_t count, struct uio *uiop,
67    struct pty *pty, mblk_t **mpp);
68
69struct cb_ops	ptc_cb_ops = {
70	ptcopen,		/* open */
71	ptcclose,		/* close */
72	nodev,			/* strategy */
73	nodev,			/* print */
74	nodev,			/* dump */
75	ptcread,		/* read */
76	ptcwrite,		/* write */
77	ptcioctl, 		/* ioctl */
78	nodev,			/* devmap */
79	nodev,			/* mmap */
80	nodev,			/* segmap */
81	ptcpoll,		/* poll */
82	ddi_prop_op,		/* prop_op */
83	0,			/* streamtab */
84	D_NEW | D_MP		/* Driver compatibility flag */
85};
86
87struct dev_ops	ptc_ops = {
88	DEVO_REV,		/* devo_rev */
89	0,			/* refcnt */
90	ptc_info,		/* info */
91	nulldev,		/* identify */
92	nulldev,		/* probe */
93	ptc_attach,		/* attach */
94	nodev,			/* detach */
95	nodev,			/* reset */
96	&ptc_cb_ops,		/* driver operations */
97	(struct bus_ops *)0,	/* bus operations */
98	NULL,			/* power */
99	ddi_quiesce_not_supported,	/* devo_quiesce */
100};
101
102#include <sys/types.h>
103#include <sys/conf.h>
104#include <sys/param.h>
105#include <sys/systm.h>
106#include <sys/errno.h>
107#include <sys/modctl.h>
108
109extern int dseekneg_flag;
110extern struct mod_ops mod_driverops;
111extern struct dev_ops ptc_ops;
112
113/*
114 * Module linkage information for the kernel.
115 */
116
117static struct modldrv modldrv = {
118	&mod_driverops, /* Type of module.  This one is a pseudo driver */
119	"tty pseudo driver control 'ptc'",
120	&ptc_ops,	/* driver ops */
121};
122
123static struct modlinkage modlinkage = {
124	MODREV_1,
125	&modldrv,
126	NULL
127};
128
129int
130_init()
131{
132	int rc;
133
134	if ((rc = mod_install(&modlinkage)) == 0)
135		ptc_init();
136	return (rc);
137}
138
139
140int
141_fini()
142{
143	int rc;
144
145	if ((rc = mod_remove(&modlinkage)) == 0)
146		ptc_uninit();
147	return (rc);
148}
149
150int
151_info(struct modinfo *modinfop)
152{
153	return (mod_info(&modlinkage, modinfop));
154}
155
156static char	*pty_banks = PTY_BANKS;
157static char	*pty_digits = PTY_DIGITS;
158
159/* ARGSUSED */
160static int
161ptc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
162{
163	char	name[8];
164	int	pty_num;
165	char	*pty_digit = pty_digits;
166	char	*pty_bank = pty_banks;
167
168	for (pty_num = 0; pty_num < npty; pty_num++) {
169		(void) sprintf(name, "pty%c%c", *pty_bank, *pty_digit);
170		if (ddi_create_minor_node(devi, name, S_IFCHR,
171		    pty_num, DDI_PSEUDO, NULL) == DDI_FAILURE) {
172			ddi_remove_minor_node(devi, NULL);
173			return (-1);
174		}
175		if (*(++pty_digit) == '\0') {
176			pty_digit = pty_digits;
177			if (*(++pty_bank) == '\0')
178				break;
179		}
180	}
181	ptc_dip = devi;
182	return (DDI_SUCCESS);
183}
184
185/* ARGSUSED */
186static int
187ptc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
188{
189	int error;
190
191	switch (infocmd) {
192	case DDI_INFO_DEVT2DEVINFO:
193		if (ptc_dip == NULL) {
194			*result = (void *)NULL;
195			error = DDI_FAILURE;
196		} else {
197			*result = (void *) ptc_dip;
198			error = DDI_SUCCESS;
199		}
200		break;
201	case DDI_INFO_DEVT2INSTANCE:
202		*result = (void *)0;
203		error = DDI_SUCCESS;
204		break;
205	default:
206		error = DDI_FAILURE;
207	}
208	return (error);
209}
210
211static void
212ptc_init(void)
213{
214	minor_t dev;
215
216	for (dev = 0; dev < npty; dev++) {
217		cv_init(&pty_softc[dev].pt_cv_flags, NULL, CV_DEFAULT, NULL);
218		cv_init(&pty_softc[dev].pt_cv_readq, NULL, CV_DEFAULT, NULL);
219		cv_init(&pty_softc[dev].pt_cv_writeq, NULL, CV_DEFAULT, NULL);
220		mutex_init(&pty_softc[dev].ptc_lock, NULL, MUTEX_DEFAULT, NULL);
221	}
222}
223
224static void
225ptc_uninit(void)
226{
227	minor_t dev;
228
229	for (dev = 0; dev < npty; dev++) {
230		cv_destroy(&pty_softc[dev].pt_cv_flags);
231		cv_destroy(&pty_softc[dev].pt_cv_readq);
232		cv_destroy(&pty_softc[dev].pt_cv_writeq);
233		mutex_destroy(&pty_softc[dev].ptc_lock);
234	}
235}
236
237/*
238 * Controller side.  This is not, alas, a streams device; there are too
239 * many old features that we must support and that don't work well
240 * with streams.
241 */
242
243/*ARGSUSED*/
244int
245ptcopen(dev_t *devp, int flag, int otyp, struct cred *cred)
246{
247	dev_t dev = *devp;
248	struct pty *pty;
249	queue_t *q;
250
251	if (getminor(dev) >= npty) {
252		return (ENXIO);
253	}
254	pty = &pty_softc[getminor(dev)];
255	mutex_enter(&pty->ptc_lock);
256	if (pty->pt_flags & PF_CARR_ON) {
257		mutex_exit(&pty->ptc_lock);
258		return (EIO);	/* controller is exclusive use */
259				/* XXX - should be EBUSY! */
260	}
261	if (pty->pt_flags & PF_WOPEN) {
262		pty->pt_flags &= ~PF_WOPEN;
263		cv_broadcast(&pty->pt_cv_flags);
264	}
265
266	if ((q = pty->pt_ttycommon.t_readq) != NULL) {
267		/*
268		 * Send an un-hangup to the slave, since "carrier" is
269		 * coming back up.  Make sure we're doing canonicalization.
270		 */
271		(void) putctl(q, M_UNHANGUP);
272		(void) putctl1(q, M_CTL, MC_DOCANON);
273	}
274	pty->pt_flags |= PF_CARR_ON;
275	pty->pt_send = 0;
276	pty->pt_ucntl = 0;
277
278	mutex_exit(&pty->ptc_lock);
279	return (0);
280}
281
282/*ARGSUSED1*/
283int
284ptcclose(dev_t dev, int flag, int otyp, struct cred *cred)
285{
286	struct pty *pty;
287	mblk_t *bp;
288	queue_t *q;
289
290	pty = &pty_softc[getminor(dev)];
291
292	mutex_enter(&pty->ptc_lock);
293	if ((q = pty->pt_ttycommon.t_readq) != NULL) {
294		/*
295		 * Send a hangup to the slave, since "carrier" is dropping.
296		 */
297		(void) putctl(q, M_HANGUP);
298	}
299
300	/*
301	 * Clear out all the controller-side state.  This also
302	 * clears PF_CARR_ON, which is correct because the
303	 * "carrier" is dropping since the controller process
304	 * is going away.
305	 */
306	pty->pt_flags &= (PF_WOPEN|PF_STOPPED|PF_NOSTOP);
307	while ((bp = pty->pt_stuffqfirst) != NULL) {
308		if ((pty->pt_stuffqfirst = bp->b_next) == NULL)
309			pty->pt_stuffqlast = NULL;
310		else
311			pty->pt_stuffqfirst->b_prev = NULL;
312		pty->pt_stuffqlen--;
313		bp->b_next = bp->b_prev = NULL;
314		freemsg(bp);
315	}
316	mutex_exit(&pty->ptc_lock);
317	return (0);
318}
319
320int
321ptcread(dev_t dev, struct uio *uio, struct cred *cred)
322{
323	struct pty *pty = &pty_softc[getminor(dev)];
324	mblk_t *bp, *nbp;
325	queue_t *q;
326	unsigned char tmp;
327	ssize_t cc;
328	int error;
329	off_t off;
330
331#ifdef lint
332	cred = cred;
333#endif
334
335	off = uio->uio_offset;
336
337	mutex_enter(&pty->ptc_lock);
338
339	for (;;) {
340		while (pty->pt_flags & PF_READ) {
341			pty->pt_flags |= PF_WREAD;
342			cv_wait(&pty->pt_cv_flags, &pty->ptc_lock);
343		}
344		pty->pt_flags |= PF_READ;
345
346		/*
347		 * If there's a TIOCPKT packet waiting, pass it back.
348		 */
349		while (pty->pt_flags&(PF_PKT|PF_UCNTL) && pty->pt_send) {
350			tmp = pty->pt_send;
351			pty->pt_send = 0;
352			mutex_exit(&pty->ptc_lock);
353			error = ureadc((int)tmp, uio);
354			uio->uio_offset = off;
355			mutex_enter(&pty->ptc_lock);
356			if (error) {
357				pty->pt_send |= tmp;
358				goto out;
359			}
360			if (pty->pt_send == 0)
361				goto out;
362		}
363
364		/*
365		 * If there's a user-control packet waiting, pass the
366		 * "ioctl" code back.
367		 */
368		while ((pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) &&
369		    pty->pt_ucntl) {
370			tmp = pty->pt_ucntl;
371			pty->pt_ucntl = 0;
372			mutex_exit(&pty->ptc_lock);
373			error = ureadc((int)tmp, uio);
374			uio->uio_offset = off;
375			mutex_enter(&pty->ptc_lock);
376			if (error) {
377				if (pty->pt_ucntl == 0)
378					pty->pt_ucntl = tmp;
379				goto out;
380			}
381			if (pty->pt_ucntl == 0)
382				goto out;
383		}
384
385		/*
386		 * If there's any data waiting, pass it back.
387		 */
388		if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
389		    q->q_first != NULL &&
390		    !(pty->pt_flags & PF_STOPPED)) {
391			if (pty->pt_flags & (PF_PKT|PF_UCNTL|PF_43UCNTL)) {
392				/*
393				 * We're about to begin a move in packet or
394				 * user-control mode; precede the data with a
395				 * data header.
396				 */
397				mutex_exit(&pty->ptc_lock);
398				error = ureadc(TIOCPKT_DATA, uio);
399				uio->uio_offset = off;
400				mutex_enter(&pty->ptc_lock);
401				if (error != 0)
402					goto out;
403				if ((q = pty->pt_ttycommon.t_writeq) == NULL)
404					goto out;
405			}
406			if ((bp = getq(q)) == NULL)
407				goto out;
408			while (uio->uio_resid > 0) {
409				while ((cc = bp->b_wptr - bp->b_rptr) == 0) {
410					nbp = bp->b_cont;
411					freeb(bp);
412					if ((bp = nbp) == NULL) {
413						if ((q == NULL) ||
414						    (bp = getq(q)) == NULL)
415							goto out;
416					}
417				}
418				cc = MIN(cc, uio->uio_resid);
419				mutex_exit(&pty->ptc_lock);
420				error = uiomove((caddr_t)bp->b_rptr,
421				    cc, UIO_READ, uio);
422				uio->uio_offset = off;
423				mutex_enter(&pty->ptc_lock);
424				if (error != 0) {
425					freemsg(bp);
426					goto out;
427				}
428				q = pty->pt_ttycommon.t_writeq;
429				bp->b_rptr += cc;
430			}
431			/*
432			 * Strip off zero-length blocks from the front of
433			 * what we're putting back on the queue.
434			 */
435			while ((bp->b_wptr - bp->b_rptr) == 0) {
436				nbp = bp->b_cont;
437				freeb(bp);
438				if ((bp = nbp) == NULL)
439					goto out;	/* nothing left */
440			}
441			if (q != NULL)
442				(void) putbq(q, bp);
443			else
444				freemsg(bp);
445			goto out;
446		}
447
448		/*
449		 * If there's any TIOCSTI-stuffed characters, pass
450		 * them back.  (They currently arrive after all output;
451		 * is this correct?)
452		 */
453		if (pty->pt_flags&PF_UCNTL && pty->pt_stuffqfirst != NULL) {
454			mutex_exit(&pty->ptc_lock);
455			error = ureadc(TIOCSTI&0xff, uio);
456			mutex_enter(&pty->ptc_lock);
457			while (error == 0 &&
458			    (bp = pty->pt_stuffqfirst) != NULL &&
459			    uio->uio_resid > 0) {
460				pty->pt_stuffqlen--;
461				if ((pty->pt_stuffqfirst = bp->b_next) == NULL)
462					pty->pt_stuffqlast = NULL;
463				else
464					pty->pt_stuffqfirst->b_prev = NULL;
465				mutex_exit(&pty->ptc_lock);
466				error = ureadc((int)*bp->b_rptr, uio);
467				bp->b_next = bp->b_prev = NULL;
468				freemsg(bp);
469				mutex_enter(&pty->ptc_lock);
470			}
471			uio->uio_offset = off;
472			goto out;
473		}
474
475		/*
476		 * There's no data available.
477		 * We want to block until the slave is open, and there's
478		 * something to read; but if we lost the slave or we're NBIO,
479		 * then return the appropriate error instead.  POSIX-style
480		 * non-block has top billing and gives -1 with errno = EAGAIN,
481		 * BSD-style comes next and gives -1 with errno = EWOULDBLOCK,
482		 * SVID-style comes last and gives 0.
483		 */
484		if (pty->pt_flags & PF_SLAVEGONE) {
485			error = EIO;
486			goto out;
487		}
488		if (uio->uio_fmode & FNONBLOCK) {
489			error = EAGAIN;
490			goto out;
491		}
492		if (pty->pt_flags & PF_NBIO) {
493			error = EWOULDBLOCK;
494			goto out;
495		}
496		if (uio->uio_fmode & FNDELAY)
497			goto out;
498
499		if (pty->pt_flags & PF_WREAD)
500			cv_broadcast(&pty->pt_cv_flags);
501
502		pty->pt_flags &= ~(PF_READ | PF_WREAD);
503
504
505		if (!cv_wait_sig(&pty->pt_cv_writeq, &pty->ptc_lock)) {
506			mutex_exit(&pty->ptc_lock);
507			return (EINTR);
508		}
509	}
510
511out:
512	if (pty->pt_flags & PF_WREAD)
513		cv_broadcast(&pty->pt_cv_flags);
514
515	pty->pt_flags &= ~(PF_READ | PF_WREAD);
516
517	mutex_exit(&pty->ptc_lock);
518	return (error);
519}
520
521int
522ptcwrite(dev_t dev, struct uio *uio, struct cred *cred)
523{
524	struct pty *pty = &pty_softc[getminor(dev)];
525	queue_t *q;
526	int written;
527	mblk_t *mp;
528	int fmode = 0;
529	int error = 0;
530
531	off_t off;
532	off = uio->uio_offset;
533
534#ifdef lint
535	cred = cred;
536#endif
537
538
539	mutex_enter(&pty->ptc_lock);
540
541again:
542	while (pty->pt_flags & PF_WRITE) {
543		pty->pt_flags |= PF_WWRITE;
544		cv_wait(&pty->pt_cv_flags, &pty->ptc_lock);
545	}
546
547	pty->pt_flags |= PF_WRITE;
548
549	if ((q = pty->pt_ttycommon.t_readq) == NULL) {
550
551		/*
552		 * Wait for slave to open.
553		 */
554		if (pty->pt_flags & PF_SLAVEGONE) {
555			error = EIO;
556			goto out;
557		}
558		if (uio->uio_fmode & FNONBLOCK) {
559			error = EAGAIN;
560			goto out;
561		}
562		if (pty->pt_flags & PF_NBIO) {
563			error = EWOULDBLOCK;
564			goto out;
565		}
566		if (uio->uio_fmode & FNDELAY)
567			goto out;
568
569		if (pty->pt_flags & PF_WWRITE)
570			cv_broadcast(&pty->pt_cv_flags);
571
572		pty->pt_flags &= ~(PF_WRITE | PF_WWRITE);
573
574		if (!cv_wait_sig(&pty->pt_cv_readq, &pty->ptc_lock)) {
575			mutex_exit(&pty->ptc_lock);
576			return (EINTR);
577		}
578
579		goto again;
580	}
581
582	/*
583	 * If in remote mode, even zero-length writes generate messages.
584	 */
585	written = 0;
586	if ((pty->pt_flags & PF_REMOTE) || uio->uio_resid > 0) {
587		do {
588			while (!canput(q)) {
589				/*
590				 * Wait for slave's read queue to unclog.
591				 */
592				if (pty->pt_flags & PF_SLAVEGONE) {
593					error = EIO;
594					goto out;
595				}
596				if (uio->uio_fmode & FNONBLOCK) {
597					if (!written)
598						error = EAGAIN;
599					goto out;
600				}
601				if (pty->pt_flags & PF_NBIO) {
602					if (!written)
603						error = EWOULDBLOCK;
604					goto out;
605				}
606				if (uio->uio_fmode & FNDELAY)
607					goto out;
608
609				if (pty->pt_flags & PF_WWRITE)
610					cv_broadcast(&pty->pt_cv_flags);
611
612				pty->pt_flags &= ~(PF_WRITE | PF_WWRITE);
613
614				if (!cv_wait_sig(&pty->pt_cv_readq,
615				    &pty->ptc_lock)) {
616					mutex_exit(&pty->ptc_lock);
617					return (EINTR);
618				}
619
620				while (pty->pt_flags & PF_WRITE) {
621					pty->pt_flags |= PF_WWRITE;
622					cv_wait(&pty->pt_cv_flags,
623					    &pty->ptc_lock);
624				}
625
626				pty->pt_flags |= PF_WRITE;
627			}
628
629			if ((pty->pt_flags & PF_NBIO) &&
630			    !(uio->uio_fmode & FNONBLOCK)) {
631				fmode = uio->uio_fmode;
632				uio->uio_fmode |= FNONBLOCK;
633			}
634
635			error = makemsg(uio->uio_resid, uio, pty, &mp);
636			uio->uio_offset = off;
637			if (fmode)
638				uio->uio_fmode = fmode;
639			if (error != 0) {
640				if (error != EAGAIN && error != EWOULDBLOCK)
641					goto out;
642				if (uio->uio_fmode & FNONBLOCK) {
643					if (!written)
644						error = EAGAIN;
645					goto out;
646				}
647				if (pty->pt_flags & PF_NBIO) {
648					if (!written)
649						error = EWOULDBLOCK;
650					goto out;
651				}
652				if (uio->uio_fmode & FNDELAY)
653					goto out;
654				cmn_err(CE_PANIC,
655				    "ptcwrite: non null return from"
656				    " makemsg");
657			}
658
659			/*
660			 * Check again for safety; since "uiomove" can take a
661			 * page fault, there's no guarantee that "pt_flags"
662			 * didn't change while it was happening.
663			 */
664			if ((q = pty->pt_ttycommon.t_readq) == NULL) {
665				if (mp)
666					freemsg(mp);
667				error = EIO;
668				goto out;
669			}
670			if (mp)
671				(void) putq(q, mp);
672			written = 1;
673		} while (uio->uio_resid > 0);
674	}
675out:
676	if (pty->pt_flags & PF_WWRITE)
677		cv_broadcast(&pty->pt_cv_flags);
678
679	pty->pt_flags &= ~(PF_WRITE | PF_WWRITE);
680
681	mutex_exit(&pty->ptc_lock);
682	return (error);
683}
684
685#define	copy_in(data, d_arg) \
686	if (copyin((caddr_t)data, &d_arg, sizeof (int)) != 0) \
687		return (EFAULT)
688
689#define	copy_out(d_arg, data) \
690	if (copyout(&d_arg, (caddr_t)data, sizeof (int)) != 0) \
691		return (EFAULT)
692
693int
694ptcioctl(dev_t dev, int cmd, intptr_t data, int flag, struct cred *cred,
695    int *rvalp)
696{
697	struct pty *pty = &pty_softc[getminor(dev)];
698	queue_t *q;
699	struct ttysize tty_arg;
700	struct winsize win_arg;
701	int d_arg;
702	int err;
703
704	switch (cmd) {
705
706	case TIOCPKT:
707		copy_in(data, d_arg);
708		mutex_enter(&pty->ptc_lock);
709		if (d_arg) {
710			if (pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) {
711				mutex_exit(&pty->ptc_lock);
712				return (EINVAL);
713			}
714			pty->pt_flags |= PF_PKT;
715		} else
716			pty->pt_flags &= ~PF_PKT;
717		mutex_exit(&pty->ptc_lock);
718		break;
719
720	case TIOCUCNTL:
721		copy_in(data, d_arg);
722		mutex_enter(&pty->ptc_lock);
723		if (d_arg) {
724			if (pty->pt_flags & (PF_PKT|PF_UCNTL)) {
725				mutex_exit(&pty->ptc_lock);
726				return (EINVAL);
727			}
728			pty->pt_flags |= PF_43UCNTL;
729		} else
730			pty->pt_flags &= ~PF_43UCNTL;
731		mutex_exit(&pty->ptc_lock);
732		break;
733
734	case TIOCTCNTL:
735		copy_in(data, d_arg);
736		mutex_enter(&pty->ptc_lock);
737		if (d_arg) {
738			if (pty->pt_flags & PF_PKT) {
739				mutex_exit(&pty->ptc_lock);
740				return (EINVAL);
741			}
742			pty->pt_flags |= PF_UCNTL;
743		} else
744			pty->pt_flags &= ~PF_UCNTL;
745		mutex_exit(&pty->ptc_lock);
746		break;
747
748	case TIOCREMOTE:
749		copy_in(data, d_arg);
750		mutex_enter(&pty->ptc_lock);
751		if (d_arg) {
752			if ((q = pty->pt_ttycommon.t_readq) != NULL)
753				(void) putctl1(q, M_CTL, MC_NOCANON);
754			pty->pt_flags |= PF_REMOTE;
755		} else {
756			if ((q = pty->pt_ttycommon.t_readq) != NULL)
757				(void) putctl1(q, M_CTL, MC_DOCANON);
758			pty->pt_flags &= ~PF_REMOTE;
759		}
760		mutex_exit(&pty->ptc_lock);
761		break;
762
763	case TIOCSIGNAL:
764		/*
765		 * Blast a M_PCSIG message up the slave stream; the
766		 * signal number is the argument to the "ioctl".
767		 */
768		copy_in(data, d_arg);
769		mutex_enter(&pty->ptc_lock);
770		if ((q = pty->pt_ttycommon.t_readq) != NULL)
771			(void) putctl1(q, M_PCSIG, (int)d_arg);
772		mutex_exit(&pty->ptc_lock);
773		break;
774
775	case FIONBIO:
776		copy_in(data, d_arg);
777		mutex_enter(&pty->ptc_lock);
778		if (d_arg)
779			pty->pt_flags |= PF_NBIO;
780		else
781			pty->pt_flags &= ~PF_NBIO;
782		mutex_exit(&pty->ptc_lock);
783		break;
784
785	case FIOASYNC:
786		copy_in(data, d_arg);
787		mutex_enter(&pty->ptc_lock);
788		if (d_arg)
789			pty->pt_flags |= PF_ASYNC;
790		else
791			pty->pt_flags &= ~PF_ASYNC;
792		mutex_exit(&pty->ptc_lock);
793		break;
794
795	/*
796	 * These, at least, can work on the controller-side process
797	 * group.
798	 */
799	case FIOGETOWN:
800		mutex_enter(&pty->ptc_lock);
801		d_arg = -pty->pt_pgrp;
802		mutex_exit(&pty->ptc_lock);
803		copy_out(d_arg, data);
804		break;
805
806	case FIOSETOWN:
807		copy_in(data, d_arg);
808		mutex_enter(&pty->ptc_lock);
809		pty->pt_pgrp = (short)(-d_arg);
810		mutex_exit(&pty->ptc_lock);
811		break;
812
813	case FIONREAD: {
814		/*
815		 * Return the total number of bytes of data in all messages
816		 * in slave write queue, which is master read queue, unless a
817		 * special message would be read.
818		 */
819		mblk_t *mp;
820		size_t count = 0;
821
822		mutex_enter(&pty->ptc_lock);
823		if (pty->pt_flags&(PF_PKT|PF_UCNTL) && pty->pt_send)
824			count = 1;	/* will return 1 byte */
825		else if ((pty->pt_flags & (PF_UCNTL|PF_43UCNTL)) &&
826		    pty->pt_ucntl)
827			count = 1;	/* will return 1 byte */
828		else if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
829		    q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) {
830			/*
831			 * Will return whatever data is queued up.
832			 */
833			for (mp = q->q_first; mp != NULL; mp = mp->b_next)
834				count += msgdsize(mp);
835		} else if ((pty->pt_flags & PF_UCNTL) &&
836		    pty->pt_stuffqfirst != NULL) {
837			/*
838			 * Will return STI'ed data.
839			 */
840			count = pty->pt_stuffqlen + 1;
841		}
842
843		/*
844		 * Under LP64 we could have more than INT_MAX bytes to report,
845		 * but the interface is defined in terms of int, so we cap it.
846		 */
847		d_arg = MIN(count, INT_MAX);
848		mutex_exit(&pty->ptc_lock);
849		copy_out(d_arg, data);
850		break;
851	}
852
853	case TIOCSWINSZ:
854		/*
855		 * Unfortunately, TIOCSWINSZ and the old TIOCSSIZE "ioctl"s
856		 * share the same code.  If the upper 16 bits of the number
857		 * of lines is non-zero, it was probably a TIOCSWINSZ,
858		 * with both "ws_row" and "ws_col" non-zero.
859		 */
860		if (copyin((caddr_t)data,
861		    &tty_arg, sizeof (struct ttysize)) != 0)
862			return (EFAULT);
863
864		if ((tty_arg.ts_lines & 0xffff0000) != 0) {
865			/*
866			 * It's a TIOCSWINSZ.
867			 */
868			win_arg = *(struct winsize *)&tty_arg;
869
870			mutex_enter(&pty->ptc_lock);
871			/*
872			 * If the window size changed, send a SIGWINCH.
873			 */
874			if (bcmp(&pty->pt_ttycommon.t_size,
875			    &win_arg, sizeof (struct winsize))) {
876				pty->pt_ttycommon.t_size = win_arg;
877				if ((q = pty->pt_ttycommon.t_readq) != NULL)
878					(void) putctl1(q, M_PCSIG, SIGWINCH);
879			}
880			mutex_exit(&pty->ptc_lock);
881			break;
882		}
883		/* FALLTHROUGH */
884
885	case TIOCSSIZE:
886		if (copyin((caddr_t)data,
887		    &tty_arg, sizeof (struct ttysize)) != 0)
888			return (EFAULT);
889		mutex_enter(&pty->ptc_lock);
890		pty->pt_ttycommon.t_size.ws_row = (ushort_t)tty_arg.ts_lines;
891		pty->pt_ttycommon.t_size.ws_col = (ushort_t)tty_arg.ts_cols;
892		pty->pt_ttycommon.t_size.ws_xpixel = 0;
893		pty->pt_ttycommon.t_size.ws_ypixel = 0;
894		mutex_exit(&pty->ptc_lock);
895		break;
896
897	case TIOCGWINSZ:
898		mutex_enter(&pty->ptc_lock);
899		win_arg = pty->pt_ttycommon.t_size;
900		mutex_exit(&pty->ptc_lock);
901		if (copyout(&win_arg, (caddr_t)data,
902		    sizeof (struct winsize)) != 0)
903			return (EFAULT);
904		break;
905
906	case TIOCGSIZE:
907		mutex_enter(&pty->ptc_lock);
908		tty_arg.ts_lines = pty->pt_ttycommon.t_size.ws_row;
909		tty_arg.ts_cols = pty->pt_ttycommon.t_size.ws_col;
910		mutex_exit(&pty->ptc_lock);
911		if (copyout(&tty_arg, (caddr_t)data,
912		    sizeof (struct ttysize)) != 0)
913			return (EFAULT);
914		break;
915
916	/*
917	 * XXX These should not be here.  The only reason why an
918	 * "ioctl" on the controller side should get the
919	 * slave side's process group is so that the process on
920	 * the controller side can send a signal to the slave
921	 * side's process group; however, this is better done
922	 * with TIOCSIGNAL, both because it doesn't require us
923	 * to know about the slave side's process group and because
924	 * the controller side process may not have permission to
925	 * send that signal to the entire process group.
926	 *
927	 * However, since vanilla 4BSD doesn't provide TIOCSIGNAL,
928	 * we can't just get rid of them.
929	 */
930	case TIOCGPGRP:
931	case TIOCSPGRP:
932	/*
933	 * This is amazingly disgusting, but the stupid semantics of
934	 * 4BSD pseudo-ttys makes us do it.  If we do one of these guys
935	 * on the controller side, it really applies to the slave-side
936	 * stream.  It should NEVER have been possible to do ANY sort
937	 * of tty operations on the controller side, but it's too late
938	 * to fix that now.  However, we won't waste our time implementing
939	 * anything that the original pseudo-tty driver didn't handle.
940	 */
941	case TIOCGETP:
942	case TIOCSETP:
943	case TIOCSETN:
944	case TIOCGETC:
945	case TIOCSETC:
946	case TIOCGLTC:
947	case TIOCSLTC:
948	case TIOCLGET:
949	case TIOCLSET:
950	case TIOCLBIS:
951	case TIOCLBIC:
952		mutex_enter(&pty->ptc_lock);
953		if (pty->pt_vnode == NULL) {
954			mutex_exit(&pty->ptc_lock);
955			return (EIO);
956		}
957		pty->pt_flags |= PF_IOCTL;
958		mutex_exit(&pty->ptc_lock);
959		err = strioctl(pty->pt_vnode, cmd, data, flag,
960		    U_TO_K, cred, rvalp);
961		mutex_enter(&pty->ptc_lock);
962		if (pty->pt_flags & PF_WAIT)
963			cv_signal(&pty->pt_cv_flags);
964		pty->pt_flags &= ~(PF_IOCTL|PF_WAIT);
965		mutex_exit(&pty->ptc_lock);
966		return (err);
967
968	default:
969		return (ENOTTY);
970	}
971
972	return (0);
973}
974
975
976int
977ptcpoll(dev_t dev,
978	short events,
979	int anyyet,
980	short *reventsp,
981	struct pollhead **phpp)
982{
983	struct pty *pty = &pty_softc[getminor(dev)];
984	pollhead_t *php = &ptcph;
985	queue_t *q;
986	int pos = 0;
987
988#ifdef lint
989	anyyet = anyyet;
990#endif
991	polllock(php, &pty->ptc_lock);
992
993	ASSERT(MUTEX_HELD(&pty->ptc_lock));
994
995	*reventsp = 0;
996	if (pty->pt_flags & PF_SLAVEGONE) {
997		if (events & (POLLIN|POLLRDNORM))
998			*reventsp |= (events & (POLLIN|POLLRDNORM));
999		if (events & (POLLOUT|POLLWRNORM))
1000			*reventsp |= (events & (POLLOUT|POLLWRNORM));
1001		mutex_exit(&pty->ptc_lock);
1002		/*
1003		 * A non NULL pollhead pointer should be returned in case
1004		 * user polls for 0 events.
1005		 */
1006		*phpp = !anyyet && !*reventsp ? php : (struct pollhead *)NULL;
1007		return (0);
1008	}
1009	if (events & (POLLIN|POLLRDNORM)) {
1010		if ((q = pty->pt_ttycommon.t_writeq) != NULL &&
1011		    q->q_first != NULL && !(pty->pt_flags & PF_STOPPED)) {
1012			/*
1013			 * Regular data is available.
1014			 */
1015			*reventsp |= (events & (POLLIN|POLLRDNORM));
1016			pos++;
1017		}
1018		if (pty->pt_flags & (PF_PKT|PF_UCNTL) && pty->pt_send) {
1019			/*
1020			 * A control packet is available.
1021			 */
1022			*reventsp |= (events & (POLLIN|POLLRDNORM));
1023			pos++;
1024		}
1025		if ((pty->pt_flags & PF_UCNTL) &&
1026		    (pty->pt_ucntl || pty->pt_stuffqfirst != NULL)) {
1027			/*
1028			 * "ioctl" or TIOCSTI data is available.
1029			 */
1030			*reventsp |= (events & (POLLIN|POLLRDNORM));
1031			pos++;
1032		}
1033		if ((pty->pt_flags & PF_43UCNTL) && pty->pt_ucntl) {
1034			*reventsp |= (events & (POLLIN|POLLRDNORM));
1035			pos++;
1036		}
1037	}
1038	if (events & (POLLOUT|POLLWRNORM)) {
1039		if ((q = pty->pt_ttycommon.t_readq) != NULL &&
1040		    canput(q)) {
1041			*reventsp |= (events & (POLLOUT|POLLWRNORM));
1042			pos++;
1043		}
1044	}
1045	if (events & POLLERR) {
1046		*reventsp |= POLLERR;
1047		pos++;
1048	}
1049	if (events == 0) {	/* "exceptional conditions" */
1050		if (((pty->pt_flags & (PF_PKT|PF_UCNTL)) && pty->pt_send) ||
1051		    ((pty->pt_flags & PF_UCNTL) &&
1052		    (pty->pt_ucntl || pty->pt_stuffqfirst != NULL))) {
1053			pos++;
1054		}
1055		if ((pty->pt_flags & PF_43UCNTL) && pty->pt_ucntl) {
1056			pos++;
1057		}
1058	}
1059
1060	/*
1061	 * Arrange to have poll waken up when event occurs.
1062	 * if (!anyyet)
1063	 */
1064	if (!pos) {
1065		*phpp = php;
1066		*reventsp = 0;
1067	}
1068
1069	mutex_exit(&pty->ptc_lock);
1070	return (0);
1071}
1072
1073void
1074gsignal(int pid, int sig)
1075{
1076	procset_t set;
1077	sigsend_t v;
1078
1079	bzero(&v, sizeof (v));
1080	v.sig = sig;
1081	v.perm = 0;
1082	v.checkperm = 1;
1083	v.value.sival_ptr = NULL;
1084
1085	setprocset(&set, POP_AND, P_PGID, -pid, P_ALL, P_MYID);
1086	(void) sigsendset(&set, &v);
1087}
1088
1089static int
1090makemsg(ssize_t count, struct uio *uiop, struct pty *pty, mblk_t **mpp)
1091{
1092	int pri = BPRI_LO;
1093	int error;
1094	mblk_t *bp = NULL;
1095
1096	ASSERT(MUTEX_HELD(&pty->ptc_lock));
1097
1098	*mpp = NULL;
1099
1100	/*
1101	 * Create data part of message, if any.
1102	 */
1103	if (count >= 0) {
1104		if ((bp = allocb(count, pri)) == NULL)
1105			return (ENOSR);
1106
1107		mutex_exit(&pty->ptc_lock);
1108		error = uiomove((caddr_t)bp->b_wptr, count, UIO_WRITE, uiop);
1109		mutex_enter(&pty->ptc_lock);
1110		if (error) {
1111			freeb(bp);
1112			return (error);
1113		}
1114
1115		bp->b_wptr += count;
1116	}
1117
1118	*mpp = bp;
1119	return (0);
1120}
1121