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.
14 * This is the "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/strsun.h>
28#include <sys/tty.h>
29#include <sys/user.h>
30#include <sys/conf.h>
31#include <sys/file.h>
32#include <sys/vnode.h>	/* 1/0 on the vomit meter */
33#include <sys/proc.h>
34#include <sys/uio.h>
35#include <sys/errno.h>
36#include <sys/strsubr.h>
37#include <sys/poll.h>
38#include <sys/sysmacros.h>
39#include <sys/debug.h>
40#include <sys/procset.h>
41#include <sys/cred.h>
42#include <sys/ptyvar.h>
43#include <sys/suntty.h>
44#include <sys/stat.h>
45#include <sys/policy.h>
46
47#include <sys/conf.h>
48#include <sys/ddi.h>
49#include <sys/sunddi.h>
50
51extern void gsignal(int pid, int sig);
52
53extern	int npty;	/* number of pseudo-ttys configured in */
54extern struct pty *pty_softc;
55
56extern struct pollhead	ptcph;	/* poll head for ptcpoll() use */
57
58#define	IFLAGS	(CS7|CREAD|PARENB)
59
60
61/*
62 * Most of these should be "void", but the people who defined the "streams"
63 * data structure for S5 didn't understand data types.
64 */
65
66/*
67 * Slave side.  This is a streams device.
68 */
69static int ptslopen(queue_t *, dev_t *, int flag, int, cred_t *);
70static int ptslclose(queue_t *, int, cred_t *);
71static int ptslrserv(queue_t *);
72
73/*
74 * To save instructions, since STREAMS ignores the return value
75 * from this function, it is defined as void here. Kind of icky, but...
76 */
77
78static void ptslwput(queue_t *q, mblk_t *mp);
79
80static struct module_info ptslm_info = {
81	0,
82	"ptys",
83	0,
84	INFPSZ,
85	2048,
86	200
87};
88
89static struct qinit ptslrinit = {
90	putq,
91	ptslrserv,
92	ptslopen,
93	ptslclose,
94	NULL,
95	&ptslm_info,
96	NULL
97};
98
99static struct qinit ptslwinit = {
100	(int (*)())ptslwput,
101	NULL,
102	NULL,
103	NULL,
104	NULL,
105	&ptslm_info,
106	NULL
107};
108
109struct	streamtab ptysinfo = {
110	&ptslrinit,
111	&ptslwinit,
112	NULL,
113	NULL
114};
115
116static void	ptslreioctl(void *);
117static void	ptslioctl(struct pty *, queue_t *, mblk_t *);
118static void	pt_sendstop(struct pty *);
119static void	ptcpollwakeup(struct pty *, int);
120
121
122static int ptsl_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
123static int ptsl_attach(dev_info_t *, ddi_attach_cmd_t);
124static dev_info_t *ptsl_dip;	/* for dev-to-dip conversions */
125
126DDI_DEFINE_STREAM_OPS(ptsl_ops, nulldev, nulldev,
127    ptsl_attach, nodev, nodev, ptsl_info, D_MP, &ptysinfo,
128    ddi_quiesce_not_supported);
129
130#include <sys/types.h>
131#include <sys/conf.h>
132#include <sys/param.h>
133#include <sys/systm.h>
134#include <sys/errno.h>
135#include <sys/modctl.h>
136
137char _depends_on[] = "drv/ptc";
138
139/*
140 * Module linkage information for the kernel.
141 */
142
143static struct modldrv modldrv = {
144	&mod_driverops, /* Type of module.  This one is a pseudo driver */
145	"tty pseudo driver slave 'ptsl'",
146	&ptsl_ops,	/* driver ops */
147};
148
149static struct modlinkage modlinkage = {
150	MODREV_1,
151	&modldrv,
152	NULL
153};
154
155int
156_init(void)
157{
158	return (mod_install(&modlinkage));
159}
160
161int
162_fini(void)
163{
164	return (mod_remove(&modlinkage));
165}
166
167int
168_info(struct modinfo *modinfop)
169{
170	return (mod_info(&modlinkage, modinfop));
171}
172
173static char	*tty_banks = PTY_BANKS;
174static char	*tty_digits = PTY_DIGITS;
175
176/* ARGSUSED */
177static int
178ptsl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
179{
180	char	name[8];
181	int	tty_num;
182	char	*tty_digit = tty_digits;
183	char	*tty_bank = tty_banks;
184
185	for (tty_num = 0; tty_num < npty; tty_num++) {
186		(void) sprintf(name, "tty%c%c", *tty_bank, *tty_digit);
187		if (ddi_create_minor_node(devi, name, S_IFCHR,
188		    tty_num, DDI_PSEUDO, NULL) == DDI_FAILURE) {
189			ddi_remove_minor_node(devi, NULL);
190			return (-1);
191		}
192		if (*(++tty_digit) == '\0') {
193			tty_digit = tty_digits;
194			if (*(++tty_bank) == '\0')
195				break;
196		}
197	}
198	ptsl_dip = devi;
199	return (DDI_SUCCESS);
200}
201
202/* ARGSUSED */
203static int
204ptsl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
205    void **result)
206{
207	int error;
208
209	switch (infocmd) {
210	case DDI_INFO_DEVT2DEVINFO:
211		if (ptsl_dip == NULL) {
212			error = DDI_FAILURE;
213		} else {
214			*result = (void *)ptsl_dip;
215			error = DDI_SUCCESS;
216		}
217		break;
218	case DDI_INFO_DEVT2INSTANCE:
219		*result = (void *)0;
220		error = DDI_SUCCESS;
221		break;
222	default:
223		error = DDI_FAILURE;
224	}
225	return (error);
226}
227
228
229/*
230 * Open the slave side of a pty.
231 */
232/*ARGSUSED*/
233static int
234ptslopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred)
235{
236	minor_t unit;
237	dev_t dev = *devp;
238	struct pty *pty;
239
240	unit = getminor(dev);
241	if (unit >= npty)
242		return (ENXIO);
243
244	pty = &pty_softc[unit];
245
246	mutex_enter(&pty->ptc_lock);
247	/*
248	 * Block waiting for controller to open, unless this is a no-delay
249	 * open.
250	 */
251again:
252	if (pty->pt_ttycommon.t_writeq == NULL) {
253		pty->pt_ttycommon.t_iflag = 0;
254		pty->pt_ttycommon.t_cflag = (B38400 << IBSHIFT)|B38400|IFLAGS;
255		pty->pt_ttycommon.t_iocpending = NULL;
256		pty->pt_wbufcid = 0;
257		pty->pt_ttycommon.t_size.ws_row = 0;
258		pty->pt_ttycommon.t_size.ws_col = 0;
259		pty->pt_ttycommon.t_size.ws_xpixel = 0;
260		pty->pt_ttycommon.t_size.ws_ypixel = 0;
261	} else if ((pty->pt_ttycommon.t_flags & TS_XCLUDE) &&
262	    secpolicy_excl_open(cred) != 0) {
263		mutex_exit(&pty->ptc_lock);
264		return (EBUSY);
265	}
266	if (!(flag & (FNONBLOCK|FNDELAY)) &&
267	    !(pty->pt_ttycommon.t_cflag & CLOCAL)) {
268		if (!(pty->pt_flags & PF_CARR_ON)) {
269			pty->pt_flags |= PF_WOPEN;
270			if (!cv_wait_sig(&pty->pt_cv_flags, &pty->ptc_lock)) {
271				pty->pt_flags &= ~PF_WOPEN;
272				mutex_exit(&pty->ptc_lock);
273				return (EINTR);
274			}
275			goto again;
276		}
277	}
278
279	pty->pt_sdev = dev;
280	q->q_ptr = WR(q)->q_ptr = pty;
281	pty->pt_flags &= ~PF_SLAVEGONE;
282	pty->pt_ttycommon.t_readq = pty->pt_ttycommon.t_writeq = NULL;
283
284	/*
285	 * Slave is ready to accept messages but master still can't send
286	 * messages to the slave queue since it is not plumbed
287	 * yet. So do qprocson() and finish slave initialization.
288	 */
289
290	mutex_exit(&pty->ptc_lock);
291
292	qprocson(q);
293
294	/*
295	 * Now it is safe to send messages to q, so wakeup master possibly
296	 * waiting for slave queue to finish open.
297	 */
298	mutex_enter(&pty->ptc_lock);
299	/*
300	 * queue has already been setup with a pointer to
301	 * the stream head that is being referenced
302	 */
303	pty->pt_vnode = strq2vp(q);
304	VN_RELE(pty->pt_vnode);
305	pty->pt_ttycommon.t_readq = q;
306	pty->pt_ttycommon.t_writeq = WR(q);
307	/* tell master device that slave is ready for writing */
308	if (pty->pt_flags & PF_CARR_ON)
309		cv_broadcast(&pty->pt_cv_readq);
310	mutex_exit(&pty->ptc_lock);
311
312	return (0);
313}
314
315static int
316ptslclose(queue_t *q, int flag, cred_t *cred)
317{
318	struct pty *pty;
319	bufcall_id_t pt_wbufcid = 0;
320
321#ifdef lint
322	flag = flag;
323	cred = cred;
324#endif
325
326	if ((pty = (struct pty *)q->q_ptr) == NULL)
327		return (ENODEV);	/* already been closed once */
328
329	/*
330	 * Prevent the queues from being uses by master device.
331	 * This should be done before qprocsoff or writer may attempt
332	 * to use the slave queue after qprocsoff removed it from the stream and
333	 * before entering mutex_enter().
334	 */
335	mutex_enter(&pty->ptc_lock);
336	pty->pt_ttycommon.t_readq = NULL;
337	pty->pt_ttycommon.t_writeq = NULL;
338	while (pty->pt_flags & PF_IOCTL) {
339		pty->pt_flags |= PF_WAIT;
340		cv_wait(&pty->pt_cv_flags, &pty->ptc_lock);
341	}
342	pty->pt_vnode = NULL;
343	mutex_exit(&pty->ptc_lock);
344
345	qprocsoff(q);
346
347	mutex_enter(&pty->ptc_lock);
348	/*
349	 * ptc_lock mutex is not dropped across
350	 * the call to the routine ttycommon_close
351	 */
352	ttycommon_close(&pty->pt_ttycommon);
353
354	/*
355	 * Cancel outstanding "bufcall" request.
356	 */
357	if (pty->pt_wbufcid) {
358		pt_wbufcid = pty->pt_wbufcid;
359		pty->pt_wbufcid = 0;
360	}
361
362	/*
363	 * Clear out all the slave-side state.
364	 */
365	pty->pt_flags &= ~(PF_WOPEN|PF_STOPPED|PF_NOSTOP);
366	if (pty->pt_flags & PF_CARR_ON) {
367		pty->pt_flags |= PF_SLAVEGONE;	/* let the controller know */
368		ptcpollwakeup(pty, 0);	/* wake up readers/selectors */
369		ptcpollwakeup(pty, FWRITE);	/* wake up writers/selectors */
370		cv_broadcast(&pty->pt_cv_flags);
371	}
372	pty->pt_sdev = 0;
373	q->q_ptr = WR(q)->q_ptr = NULL;
374	mutex_exit(&pty->ptc_lock);
375
376	if (pt_wbufcid)
377		unbufcall(pt_wbufcid);
378
379	return (0);
380}
381
382/*
383 * Put procedure for write queue.
384 * Respond to M_STOP, M_START, M_IOCTL, and M_FLUSH messages here;
385 * queue up M_DATA messages for processing by the controller "read"
386 * routine; discard everything else.
387 */
388static void
389ptslwput(queue_t *q, mblk_t *mp)
390{
391	struct pty *pty;
392	mblk_t *bp;
393
394	pty = (struct pty *)q->q_ptr;
395
396	mutex_enter(&pty->ptc_lock);
397
398	switch (mp->b_datap->db_type) {
399
400	case M_STOP:
401		if (!(pty->pt_flags & PF_STOPPED)) {
402			pty->pt_flags |= PF_STOPPED;
403			pty->pt_send |= TIOCPKT_STOP;
404			ptcpollwakeup(pty, 0);
405		}
406		freemsg(mp);
407		break;
408
409	case M_START:
410		if (pty->pt_flags & PF_STOPPED) {
411			pty->pt_flags &= ~PF_STOPPED;
412			pty->pt_send = TIOCPKT_START;
413			ptcpollwakeup(pty, 0);
414		}
415		ptcpollwakeup(pty, FREAD);	/* permit controller to read */
416		freemsg(mp);
417		break;
418
419	case M_IOCTL:
420		ptslioctl(pty, q, mp);
421		break;
422
423	case M_FLUSH:
424		if (*mp->b_rptr & FLUSHW) {
425			/*
426			 * Set the "flush write" flag, so that we
427			 * notify the controller if they're in packet
428			 * or user control mode.
429			 */
430			if (!(pty->pt_send & TIOCPKT_FLUSHWRITE)) {
431				pty->pt_send |= TIOCPKT_FLUSHWRITE;
432				ptcpollwakeup(pty, 0);
433			}
434			/*
435			 * Flush our write queue.
436			 */
437			flushq(q, FLUSHDATA);	/* XXX doesn't flush M_DELAY */
438			*mp->b_rptr &= ~FLUSHW;	/* it has been flushed */
439		}
440		if (*mp->b_rptr & FLUSHR) {
441			/*
442			 * Set the "flush read" flag, so that we
443			 * notify the controller if they're in packet
444			 * mode.
445			 */
446			if (!(pty->pt_send & TIOCPKT_FLUSHREAD)) {
447				pty->pt_send |= TIOCPKT_FLUSHREAD;
448				ptcpollwakeup(pty, 0);
449			}
450			flushq(RD(q), FLUSHDATA);
451			mutex_exit(&pty->ptc_lock);
452			qreply(q, mp);	/* give the read queues a crack at it */
453			return;
454		} else
455			freemsg(mp);
456		break;
457
458	case M_DATA:
459		/*
460		 * Throw away any leading zero-length blocks, and queue it up
461		 * for the controller to read.
462		 */
463		if (pty->pt_flags & PF_CARR_ON) {
464			bp = mp;
465			while ((bp->b_wptr - bp->b_rptr) == 0) {
466				mp = bp->b_cont;
467				freeb(bp);
468				if (mp == NULL) {
469					mutex_exit(&pty->ptc_lock);
470					return;	/* damp squib of a message */
471				}
472				bp = mp;
473			}
474			(void) putq(q, mp);
475			ptcpollwakeup(pty, FREAD);	/* soup's on! */
476		} else
477			freemsg(mp);	/* nobody listening */
478		break;
479
480	case M_CTL:
481		if ((*(int *)mp->b_rptr) == MC_CANONQUERY) {
482			/*
483			 * We're being asked whether we do canonicalization
484			 * or not.  Send a reply back up indicating whether
485			 * we do or not.
486			 */
487			(void) putctl1(RD(q), M_CTL,
488			    (pty->pt_flags & PF_REMOTE) ?
489			    MC_NOCANON : MC_DOCANON);
490		}
491		freemsg(mp);
492		break;
493
494	default:
495		/*
496		 * "No, I don't want a subscription to Chain Store Age,
497		 * thank you anyway."
498		 */
499		freemsg(mp);
500		break;
501	}
502	mutex_exit(&pty->ptc_lock);
503}
504
505/*
506 * Retry an "ioctl", now that "bufcall" claims we may be able to allocate
507 * the buffer we need.
508 */
509static void
510ptslreioctl(void *arg)
511{
512	struct pty *pty = arg;
513	queue_t *q;
514	mblk_t *mp;
515
516	mutex_enter(&pty->ptc_lock);
517	/*
518	 * The bufcall is no longer pending.
519	 */
520	if (pty->pt_wbufcid == 0) {
521		mutex_exit(&pty->ptc_lock);
522		return;
523	}
524
525	pty->pt_wbufcid = 0;
526	if ((q = pty->pt_ttycommon.t_writeq) == NULL) {
527		mutex_exit(&pty->ptc_lock);
528		return;
529	}
530	if ((mp = pty->pt_ttycommon.t_iocpending) != NULL) {
531		/* It's not pending any more. */
532		pty->pt_ttycommon.t_iocpending = NULL;
533		ptslioctl(pty, q, mp);
534	}
535	mutex_exit(&pty->ptc_lock);
536}
537
538/*
539 * Process an "ioctl" message sent down to us.
540 * Drops pty's ptc_lock mutex and then reacquire
541 */
542static void
543ptslioctl(struct pty *pty, queue_t *q, mblk_t *mp)
544{
545	struct iocblk *iocp;
546	int cmd;
547	size_t datasize;
548	int error = 0;
549
550	ASSERT(MUTEX_HELD(&pty->ptc_lock));
551
552	iocp = (struct iocblk *)mp->b_rptr;
553	cmd = iocp->ioc_cmd;
554
555	switch (cmd) {
556
557	case TIOCSTI: {
558		/*
559		 * The permission checking has already been done at the stream
560		 * head, since it has to be done in the context of the process
561		 * doing the call.
562		 */
563		mblk_t *bp;
564
565		error = miocpullup(mp, sizeof (char));
566		if (error != 0)
567			goto out;
568
569		/*
570		 * Simulate typing of a character at the terminal.
571		 */
572		if ((bp = allocb(1, BPRI_MED)) != NULL) {
573			*bp->b_wptr++ = *mp->b_cont->b_rptr;
574			if (!(pty->pt_flags & PF_REMOTE)) {
575				if (!canput(pty->pt_ttycommon.t_readq)) {
576					mutex_exit(&pty->ptc_lock);
577					ttycommon_qfull(&pty->pt_ttycommon, q);
578					mutex_enter(&pty->ptc_lock);
579					freemsg(bp);
580					error = EAGAIN;
581					goto out;
582				} else
583					(void) putq(
584					    pty->pt_ttycommon.t_readq, bp);
585			} else {
586				if (pty->pt_flags & PF_UCNTL) {
587					/*
588					 * XXX - flow control; don't overflow
589					 * this "queue".
590					 */
591					if (pty->pt_stuffqfirst != NULL) {
592						pty->pt_stuffqlast->b_next = bp;
593						bp->b_prev = pty->pt_stuffqlast;
594					} else {
595						pty->pt_stuffqfirst = bp;
596						bp->b_prev = NULL;
597					}
598					bp->b_next = NULL;
599					pty->pt_stuffqlast = bp;
600					pty->pt_stuffqlen++;
601					ptcpollwakeup(pty, 0);
602				}
603			}
604		} else {
605			error = EAGAIN;
606			goto out;
607		}
608
609		/*
610		 * Turn the ioctl message into an ioctl ACK message.
611		 */
612		iocp->ioc_count = 0;	/* no data returned */
613		mp->b_datap->db_type = M_IOCACK;
614		goto out;
615	}
616
617	case TIOCSSIZE: {
618		tty_common_t *tc = &pty->pt_ttycommon;
619		struct ttysize *tp;
620
621		error = miocpullup(mp, sizeof (struct ttysize));
622		if (error != 0)
623			goto out;
624
625		/*
626		 * Set the window size, but don't send a SIGWINCH.
627		 */
628		tp = (struct ttysize *)mp->b_cont->b_rptr;
629		tc->t_size.ws_row = tp->ts_lines;
630		tc->t_size.ws_col = tp->ts_cols;
631		tc->t_size.ws_xpixel = 0;
632		tc->t_size.ws_ypixel = 0;
633
634		/*
635		 * Send an ACK back.
636		 */
637		iocp->ioc_count = 0;	/* no data returned */
638		mp->b_datap->db_type = M_IOCACK;
639		goto out;
640	}
641
642	case TIOCGSIZE: {
643		tty_common_t *tc = &pty->pt_ttycommon;
644		mblk_t *datap;
645		struct ttysize *tp;
646
647		if ((datap = allocb(sizeof (struct ttysize),
648		    BPRI_HI)) == NULL) {
649			if (pty->pt_wbufcid) {
650				if (pty->pt_ttycommon.t_iocpending)
651					freemsg(pty->pt_ttycommon.t_iocpending);
652				pty->pt_ttycommon.t_iocpending = mp;
653				return;
654			}
655			pty->pt_wbufcid = bufcall(sizeof (struct ttysize),
656			    BPRI_HI, ptslreioctl, pty);
657			if (pty->pt_wbufcid == 0) {
658				error = ENOMEM;
659				goto out;
660			}
661			pty->pt_ttycommon.t_iocpending = mp;
662			return;
663		}
664		/*
665		 * Return the current size.
666		 */
667		tp = (struct ttysize *)datap->b_wptr;
668		tp->ts_lines = tc->t_size.ws_row;
669		tp->ts_cols = tc->t_size.ws_col;
670		datap->b_wptr += sizeof (struct ttysize);
671		iocp->ioc_count = sizeof (struct ttysize);
672
673		if (mp->b_cont != NULL)
674			freemsg(mp->b_cont);
675		mp->b_cont = datap;
676		mp->b_datap->db_type = M_IOCACK;
677		goto out;
678	}
679
680	/*
681	 * Imported from ttycommon_ioctl routine
682	 */
683
684	case TCSETSF: {
685		tty_common_t *tc = &pty->pt_ttycommon;
686		struct termios *cb;
687
688		error = miocpullup(mp, sizeof (struct termios));
689		if (error != 0)
690			goto out;
691
692		cb = (struct termios *)mp->b_cont->b_rptr;
693
694		flushq(RD(q), FLUSHDATA);
695		mutex_exit(&pty->ptc_lock);
696		(void) putnextctl1(RD(q), M_FLUSH, FLUSHR);
697		mutex_enter(&pty->ptc_lock);
698		mutex_enter(&tc->t_excl);
699		tc->t_iflag = cb->c_iflag;
700		tc->t_cflag = cb->c_cflag;
701		tc->t_stopc = cb->c_cc[VSTOP];
702		tc->t_startc = cb->c_cc[VSTART];
703		mutex_exit(&tc->t_excl);
704
705		/*
706		 * Turn the ioctl message into an ioctl ACK message.
707		 */
708		iocp->ioc_count = 0;	/* no data returned */
709		mp->b_datap->db_type = M_IOCACK;
710		goto ioctldone;
711	}
712
713	case TCSETAF: {
714		tty_common_t *tc = &pty->pt_ttycommon;
715		struct termios *cb;
716
717		error = miocpullup(mp, sizeof (struct termios));
718		if (error != 0)
719			goto out;
720
721		cb = (struct termios *)mp->b_cont->b_rptr;
722
723		flushq(RD(q), FLUSHDATA);
724		mutex_exit(&pty->ptc_lock);
725		(void) putnextctl1(RD(q), M_FLUSH, FLUSHR);
726		mutex_enter(&pty->ptc_lock);
727		mutex_enter(&tc->t_excl);
728		tc->t_iflag = (tc->t_iflag & 0xffff0000 | cb->c_iflag);
729		tc->t_cflag = (tc->t_cflag & 0xffff0000 | cb->c_cflag);
730		mutex_exit(&tc->t_excl);
731
732		/*
733		 * Turn the ioctl message into an ioctl ACK message.
734		 */
735		iocp->ioc_count = 0;	/* no data returned */
736		mp->b_datap->db_type = M_IOCACK;
737		goto ioctldone;
738	}
739
740	case TIOCSWINSZ: {
741		tty_common_t *tc = &pty->pt_ttycommon;
742		struct winsize *ws;
743
744		error = miocpullup(mp, sizeof (struct winsize));
745		if (error != 0)
746			goto out;
747
748		ws = (struct winsize *)mp->b_cont->b_rptr;
749		/*
750		 * If the window size changed, send a SIGWINCH.
751		 */
752		mutex_enter(&tc->t_excl);
753		if (bcmp(&tc->t_size, ws, sizeof (struct winsize))) {
754			tc->t_size = *ws;
755			mutex_exit(&tc->t_excl);
756			mutex_exit(&pty->ptc_lock);
757			(void) putnextctl1(RD(q), M_PCSIG, SIGWINCH);
758			mutex_enter(&pty->ptc_lock);
759		} else
760			mutex_exit(&tc->t_excl);
761
762		/*
763		 * Turn the ioctl message into an ioctl ACK message.
764		 */
765		iocp->ioc_count = 0;	/* no data returned */
766		mp->b_datap->db_type = M_IOCACK;
767		goto ioctldone;
768	}
769
770	/*
771	 * If they were just trying to drain output, that's OK.
772	 * If they are actually trying to send a break it's an error.
773	 */
774	case TCSBRK:
775		error = miocpullup(mp, sizeof (int));
776		if (error != 0)
777			goto out;
778
779		if (*(int *)mp->b_cont->b_rptr != 0) {
780			/*
781			 * Turn the ioctl message into an ioctl ACK message.
782			 */
783			iocp->ioc_count = 0;	/* no data returned */
784			mp->b_datap->db_type = M_IOCACK;
785		} else {
786			error = ENOTTY;
787		}
788		goto out;
789	}
790
791	/*
792	 * The only way in which "ttycommon_ioctl" can fail is if the "ioctl"
793	 * requires a response containing data to be returned to the user,
794	 * and no mblk could be allocated for the data.
795	 * No such "ioctl" alters our state.  Thus, we always go ahead and
796	 * do any state-changes the "ioctl" calls for.  If we couldn't allocate
797	 * the data, "ttycommon_ioctl" has stashed the "ioctl" away safely, so
798	 * we just call "bufcall" to request that we be called back when we
799	 * stand a better chance of allocating the data.
800	 */
801	if ((datasize =
802	    ttycommon_ioctl(&pty->pt_ttycommon, q, mp, &error)) != 0) {
803		if (pty->pt_wbufcid) {
804			if (pty->pt_ttycommon.t_iocpending)
805				freemsg(pty->pt_ttycommon.t_iocpending);
806			pty->pt_ttycommon.t_iocpending = mp;
807			return;
808		}
809		pty->pt_wbufcid = bufcall(datasize, BPRI_HI, ptslreioctl, pty);
810		if (pty->pt_wbufcid == 0) {
811			error = ENOMEM;
812			goto out;
813		}
814		pty->pt_ttycommon.t_iocpending = mp;
815		return;
816	}
817
818ioctldone:
819	if (error == 0) {
820		/*
821		 * "ttycommon_ioctl" did most of the work; we just use the
822		 * data it set up.
823		 */
824		switch (cmd) {
825
826		case TCSETSF:
827		case TCSETAF:
828			/*
829			 * Set the "flush read" flag, so that we
830			 * notify the controller if they're in packet
831			 * mode.
832			 */
833			if (!(pty->pt_send & TIOCPKT_FLUSHREAD)) {
834				pty->pt_send |= TIOCPKT_FLUSHREAD;
835				ptcpollwakeup(pty, 0);
836			}
837			/*FALLTHROUGH*/
838
839		case TCSETSW:
840		case TCSETAW:
841			cmd = TIOCSETP;	/* map backwards to old codes */
842			pt_sendstop(pty);
843			break;
844
845		case TCSETS:
846		case TCSETA:
847			cmd = TIOCSETN;	/* map backwards to old codes */
848			pt_sendstop(pty);
849			break;
850		}
851	}
852
853	if (pty->pt_flags & PF_43UCNTL) {
854		if (error < 0) {
855			if ((cmd & ~0xff) == _IO('u', 0)) {
856				if (cmd & 0xff) {
857					pty->pt_ucntl = (uchar_t)cmd & 0xff;
858					ptcpollwakeup(pty, FREAD);
859				}
860				error = 0; /* XXX */
861				goto out;
862			}
863			error = ENOTTY;
864		}
865	} else {
866		if ((pty->pt_flags & PF_UCNTL) &&
867		    (cmd & (IOC_INOUT | 0xff00)) == (IOC_IN|('t'<<8)) &&
868		    (cmd & 0xff)) {
869			pty->pt_ucntl = (uchar_t)cmd & 0xff;
870			ptcpollwakeup(pty, FREAD);
871			goto out;
872		}
873		if (error < 0)
874			error = ENOTTY;
875	}
876
877out:
878	if (error != 0) {
879		((struct iocblk *)mp->b_rptr)->ioc_error = error;
880		mp->b_datap->db_type = M_IOCNAK;
881	}
882
883	mutex_exit(&pty->ptc_lock);
884	qreply(q, mp);
885	mutex_enter(&pty->ptc_lock);
886}
887
888/*
889 * Service routine for read queue.
890 * Just wakes the controller side up so it can write some more data
891 * to that queue.
892 */
893static int
894ptslrserv(queue_t *q)
895{
896	struct pty *pty = (struct pty *)q->q_ptr;
897	mblk_t *mp;
898	mblk_t *head = NULL, *tail = NULL;
899	/*
900	 * Build up the link list of messages, then drop
901	 * drop the lock and do putnext()
902	 */
903	mutex_enter(&pty->ptc_lock);
904
905	while ((mp = getq(q)) != NULL) {
906		if ((mp->b_datap->db_type < QPCTL) && !canputnext(q)) {
907			(void) putbq(q, mp);
908			break;
909		}
910		if (!head) {
911			head = mp;
912			tail = mp;
913		} else {
914			tail->b_next = mp;
915			tail = mp;
916		}
917	}
918
919	if (q->q_count <= q->q_lowat)
920		ptcpollwakeup((struct pty *)q->q_ptr, FWRITE);
921
922	mutex_exit(&pty->ptc_lock);
923
924	while (head) {
925		mp = head;
926		head = mp->b_next;
927		mp->b_next = NULL;
928		putnext(q, mp);
929	}
930
931	return (0);
932}
933
934static void
935pt_sendstop(struct pty *pty)
936{
937	int stop;
938
939	ASSERT(MUTEX_HELD(&pty->ptc_lock));
940
941	if ((pty->pt_ttycommon.t_cflag&CBAUD) == 0) {
942		if (pty->pt_flags & PF_CARR_ON) {
943			/*
944			 * Let the controller know, then wake up
945			 * readers/selectors and writers/selectors.
946			 */
947			pty->pt_flags |= PF_SLAVEGONE;
948			ptcpollwakeup(pty, 0);
949			ptcpollwakeup(pty, FWRITE);
950		}
951	}
952
953	stop = (pty->pt_ttycommon.t_iflag & IXON) &&
954	    pty->pt_ttycommon.t_stopc == CTRL('s') &&
955	    pty->pt_ttycommon.t_startc == CTRL('q');
956
957	if (pty->pt_flags & PF_NOSTOP) {
958		if (stop) {
959			pty->pt_send &= ~TIOCPKT_NOSTOP;
960			pty->pt_send |= TIOCPKT_DOSTOP;
961			pty->pt_flags &= ~PF_NOSTOP;
962			ptcpollwakeup(pty, 0);
963		}
964	} else {
965		if (!stop) {
966			pty->pt_send &= ~TIOCPKT_DOSTOP;
967			pty->pt_send |= TIOCPKT_NOSTOP;
968			pty->pt_flags |= PF_NOSTOP;
969			ptcpollwakeup(pty, 0);
970		}
971	}
972}
973
974/*
975 * Wake up controller side.  "flag" is 0 if a special packet or
976 * user control mode message has been queued up (this data is readable,
977 * so we also treat it as a regular data event; should we send SIGIO,
978 * though?), FREAD if regular data has been queued up, or FWRITE if
979 * the slave's read queue has drained sufficiently to allow writing.
980 */
981static void
982ptcpollwakeup(struct pty *pty, int flag)
983{
984	ASSERT(MUTEX_HELD(&pty->ptc_lock));
985
986	if (flag == 0) {
987		/*
988		 * "Exceptional condition" occurred.  This means that
989		 * a "read" is now possible, so do a "read" wakeup.
990		 */
991		flag = FREAD;
992		pollwakeup(&ptcph, POLLIN | POLLRDBAND);
993		if (pty->pt_flags & PF_ASYNC)
994			gsignal(pty->pt_pgrp, SIGURG);
995	}
996	if (flag & FREAD) {
997		/*
998		 * Wake up the parent process as there is regular
999		 * data to read from slave's write queue
1000		 */
1001		pollwakeup(&ptcph, POLLIN | POLLRDNORM);
1002		cv_broadcast(&pty->pt_cv_writeq);
1003		if (pty->pt_flags & PF_ASYNC)
1004			gsignal(pty->pt_pgrp, SIGIO);
1005	}
1006	if (flag & FWRITE) {
1007		/*
1008		 * Wake up the parent process to write
1009		 * data into slave's read queue as the
1010		 * read queue has drained enough
1011		 */
1012		pollwakeup(&ptcph, POLLOUT | POLLWRNORM);
1013		cv_broadcast(&pty->pt_cv_readq);
1014		if (pty->pt_flags & PF_ASYNC)
1015			gsignal(pty->pt_pgrp, SIGIO);
1016	}
1017}
1018