xref: /netbsd-src/sys/kern/tty_pty.c (revision 3816d47b2c42fcd6e549e3407f842a5b1a1d23ad)
1 /*	$NetBSD: tty_pty.c,v 1.120 2009/12/20 19:06:44 pooka Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)tty_pty.c	8.4 (Berkeley) 2/20/95
32  */
33 
34 /*
35  * Pseudo-teletype Driver
36  * (Actually two drivers, requiring two entries in 'cdevsw')
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: tty_pty.c,v 1.120 2009/12/20 19:06:44 pooka Exp $");
41 
42 #include "opt_ptm.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/ioctl.h>
47 #include <sys/ioctl_compat.h>
48 #include <sys/proc.h>
49 #include <sys/tty.h>
50 #include <sys/stat.h>
51 #include <sys/file.h>
52 #include <sys/kernel.h>
53 #include <sys/vnode.h>
54 #include <sys/namei.h>
55 #include <sys/signalvar.h>
56 #include <sys/uio.h>
57 #include <sys/filedesc.h>
58 #include <sys/conf.h>
59 #include <sys/poll.h>
60 #include <sys/pty.h>
61 #include <sys/kauth.h>
62 
63 #define	DEFAULT_NPTYS		16	/* default number of initial ptys */
64 #define DEFAULT_MAXPTYS		992	/* default maximum number of ptys */
65 
66 #define BUFSIZ 100		/* Chunk size iomoved to/from user */
67 
68 struct	pt_softc {
69 	struct	tty *pt_tty;
70 	int	pt_flags;
71 	struct	selinfo pt_selr, pt_selw;
72 	u_char	pt_send;
73 	u_char	pt_ucntl;
74 };
75 
76 static struct pt_softc **pt_softc = NULL;	/* pty array */
77 static int maxptys = DEFAULT_MAXPTYS;	/* maximum number of ptys (sysctable) */
78 kmutex_t pt_softc_mutex;
79 int npty = 0;			/* for pstat -t */
80 
81 #define	PF_PKT		0x08		/* packet mode */
82 #define	PF_STOPPED	0x10		/* user told stopped */
83 #define	PF_REMOTE	0x20		/* remote and flow controlled input */
84 #define	PF_NOSTOP	0x40
85 #define PF_UCNTL	0x80		/* user control mode */
86 
87 void	ptyattach(int);
88 void	ptcwakeup(struct tty *, int);
89 void	ptsstart(struct tty *);
90 int	pty_maxptys(int, int);
91 
92 static struct pt_softc **ptyarralloc(int);
93 
94 dev_type_open(ptcopen);
95 dev_type_close(ptcclose);
96 dev_type_read(ptcread);
97 dev_type_write(ptcwrite);
98 dev_type_poll(ptcpoll);
99 dev_type_kqfilter(ptckqfilter);
100 
101 dev_type_open(ptsopen);
102 dev_type_close(ptsclose);
103 dev_type_read(ptsread);
104 dev_type_write(ptswrite);
105 dev_type_stop(ptsstop);
106 dev_type_poll(ptspoll);
107 
108 dev_type_ioctl(ptyioctl);
109 dev_type_tty(ptytty);
110 
111 const struct cdevsw ptc_cdevsw = {
112 	ptcopen, ptcclose, ptcread, ptcwrite, ptyioctl,
113 	nullstop, ptytty, ptcpoll, nommap, ptckqfilter, D_TTY
114 };
115 
116 const struct cdevsw pts_cdevsw = {
117 	ptsopen, ptsclose, ptsread, ptswrite, ptyioctl,
118 	ptsstop, ptytty, ptspoll, nommap, ttykqfilter, D_TTY
119 };
120 
121 #if defined(pmax)
122 /* see arch/pmax/conf/majors.pmax */
123 const struct cdevsw ptc_ultrix_cdevsw = {
124 	ptcopen, ptcclose, ptcread, ptcwrite, ptyioctl,
125 	nullstop, ptytty, ptcpoll, nommap, ptckqfilter, D_TTY
126 };
127 
128 const struct cdevsw pts_ultrix_cdevsw = {
129 	ptsopen, ptsclose, ptsread, ptswrite, ptyioctl,
130 	ptsstop, ptytty, ptspoll, nommap, ttykqfilter, D_TTY
131 };
132 #endif /* defined(pmax) */
133 
134 /*
135  * Check if a pty is free to use.
136  */
137 int
138 pty_isfree(int minor, int lock)
139 {
140 	struct pt_softc *pt = pt_softc[minor];
141 	if (lock)
142 		mutex_enter(&pt_softc_mutex);
143 	minor = pt == NULL || pt->pt_tty == NULL ||
144 	    pt->pt_tty->t_oproc == NULL;
145 	if (lock)
146 		mutex_exit(&pt_softc_mutex);
147 	return minor;
148 }
149 
150 /*
151  * Allocate and zero array of nelem elements.
152  */
153 static struct pt_softc **
154 ptyarralloc(int nelem)
155 {
156 	struct pt_softc **pt;
157 	nelem += 10;
158 	pt = kmem_zalloc(nelem * sizeof(*pt), KM_SLEEP);
159 	return pt;
160 }
161 
162 static void
163 ptyarrfree(struct pt_softc **pt, int nelem)
164 {
165 
166 	nelem += 10;
167 	kmem_free(pt, nelem * sizeof(*pt));
168 }
169 
170 /*
171  * Check if the minor is correct and ensure necessary structures
172  * are properly allocated.
173  */
174 int
175 pty_check(int ptn)
176 {
177 	struct pt_softc *pti;
178 
179 	if (ptn >= npty) {
180 		struct pt_softc **newpt, **oldpt;
181 		int newnpty;
182 		int oldnpty;
183 
184 		/* check if the requested pty can be granted */
185 		if (ptn >= maxptys) {
186 	    limit_reached:
187 			tablefull("pty", "increase kern.maxptys");
188 			return (ENXIO);
189 		}
190 
191 		/* Allocate a larger pty array */
192 		for (newnpty = npty; newnpty <= ptn;)
193 			newnpty *= 2;
194 		if (newnpty > maxptys)
195 			newnpty = maxptys;
196 		newpt = ptyarralloc(newnpty);
197 
198 		/*
199 		 * Now grab the pty array mutex - we need to ensure
200 		 * that the pty array is consistent while copying it's
201 		 * content to newly allocated, larger space; we also
202 		 * need to be safe against pty_maxptys().
203 		 */
204 		mutex_enter(&pt_softc_mutex);
205 
206 		if (newnpty >= maxptys) {
207 			/* limit cut away beneath us... */
208 			if (ptn >= maxptys) {
209 				mutex_exit(&pt_softc_mutex);
210 				ptyarrfree(newpt, newnpty);
211 				goto limit_reached;
212 			}
213 			newnpty = maxptys;
214 		}
215 
216 		/*
217 		 * If the pty array was not enlarged while we were waiting
218 		 * for mutex, copy current contents of pt_softc[] to newly
219 		 * allocated array and start using the new bigger array.
220 		 */
221 		if (newnpty > npty) {
222 			memcpy(newpt, pt_softc, npty*sizeof(struct pt_softc *));
223 			oldpt = pt_softc;
224 			oldnpty = npty;
225 			pt_softc = newpt;
226 			npty = newnpty;
227 		} else {
228 			/* was enlarged when waited for lock, free new space */
229 			oldpt = newpt;
230 			oldnpty = newnpty;
231 		}
232 
233 		mutex_exit(&pt_softc_mutex);
234 		ptyarrfree(oldpt, oldnpty);
235 	}
236 
237 	/*
238 	 * If the entry is not yet allocated, allocate one. The mutex is
239 	 * needed so that the state of pt_softc[] array is consistant
240 	 * in case it has been lengthened above.
241 	 */
242 	if (!pt_softc[ptn]) {
243 		pti = kmem_zalloc(sizeof(*pti), KM_SLEEP);
244 
245 		selinit(&pti->pt_selr);
246 		selinit(&pti->pt_selw);
247 		pti->pt_tty = ttymalloc();
248 
249 		mutex_enter(&pt_softc_mutex);
250 
251 		/*
252 		 * Check the entry again - it might have been
253 		 * added while we were waiting for mutex.
254 		 */
255 		if (pt_softc[ptn]) {
256 			mutex_exit(&pt_softc_mutex);
257 			ttyfree(pti->pt_tty);
258 			seldestroy(&pti->pt_selr);
259 			seldestroy(&pti->pt_selw);
260 			kmem_free(pti, sizeof(*pti));
261 			return (0);
262 		}
263 		tty_attach(pti->pt_tty);
264 		pt_softc[ptn] = pti;
265 
266 		mutex_exit(&pt_softc_mutex);
267 	}
268 
269 	return (0);
270 }
271 
272 /*
273  * Set maxpty in thread-safe way. Returns 0 in case of error, otherwise
274  * new value of maxptys.
275  */
276 int
277 pty_maxptys(int newmax, int set)
278 {
279 	if (!set)
280 		return (maxptys);
281 
282 	/*
283 	 * We have to grab the pt_softc lock, so that we would pick correct
284 	 * value of npty (might be modified in pty_check()).
285 	 */
286 	mutex_enter(&pt_softc_mutex);
287 
288 	/*
289 	 * The value cannot be set to value lower than the highest pty
290 	 * number ever allocated.
291 	 */
292 	if (newmax >= npty)
293 		maxptys = newmax;
294 	else
295 		newmax = 0;
296 
297 	mutex_exit(&pt_softc_mutex);
298 
299 	return newmax;
300 }
301 
302 /*
303  * Establish n (or default if n is 1) ptys in the system.
304  */
305 void
306 ptyattach(int n)
307 {
308 
309 	mutex_init(&pt_softc_mutex, MUTEX_DEFAULT, IPL_NONE);
310 
311 	/* maybe should allow 0 => none? */
312 	if (n <= 1)
313 		n = DEFAULT_NPTYS;
314 	pt_softc = ptyarralloc(n);
315 	npty = n;
316 #ifndef NO_DEV_PTM
317 	ptmattach(1);
318 #endif
319 }
320 
321 /*ARGSUSED*/
322 int
323 ptsopen(dev_t dev, int flag, int devtype, struct lwp *l)
324 {
325 	struct pt_softc *pti;
326 	struct tty *tp;
327 	int error;
328 	int ptn = minor(dev);
329 
330 	if ((error = pty_check(ptn)) != 0)
331 		return (error);
332 
333 	mutex_spin_enter(&tty_lock);
334 	pti = pt_softc[ptn];
335 	tp = pti->pt_tty;
336 	if (!ISSET(tp->t_state, TS_ISOPEN)) {
337 		ttychars(tp);		/* Set up default chars */
338 		tp->t_iflag = TTYDEF_IFLAG;
339 		tp->t_oflag = TTYDEF_OFLAG;
340 		tp->t_lflag = TTYDEF_LFLAG;
341 		tp->t_cflag = TTYDEF_CFLAG;
342 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
343 		ttsetwater(tp);		/* would be done in xxparam() */
344 	} else if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN,
345 	    tp) != 0) {
346 		mutex_spin_exit(&tty_lock);
347 		return (EBUSY);
348 	}
349 	if (tp->t_oproc)			/* Ctrlr still around. */
350 		SET(tp->t_state, TS_CARR_ON);
351 	if (!ISSET(flag, O_NONBLOCK)) {
352 		while (!ISSET(tp->t_state, TS_CARR_ON)) {
353 			tp->t_wopen++;
354 			error = ttysleep(tp, &tp->t_rawcv, true, 0);
355 			tp->t_wopen--;
356 			if (error) {
357 				mutex_spin_exit(&tty_lock);
358 				return (error);
359 			}
360 		}
361 	}
362 	mutex_spin_exit(&tty_lock);
363 	error = (*tp->t_linesw->l_open)(dev, tp);
364 	ptcwakeup(tp, FREAD|FWRITE);
365 	return (error);
366 }
367 
368 int
369 ptsclose(dev_t dev, int flag, int mode, struct lwp *l)
370 {
371 	struct pt_softc *pti = pt_softc[minor(dev)];
372 	struct tty *tp = pti->pt_tty;
373 	int error;
374 
375 	error = (*tp->t_linesw->l_close)(tp, flag);
376 	error |= ttyclose(tp);
377 	ptcwakeup(tp, FREAD|FWRITE);
378 	return (error);
379 }
380 
381 int
382 ptsread(dev_t dev, struct uio *uio, int flag)
383 {
384 	struct proc *p = curproc;
385 	struct pt_softc *pti = pt_softc[minor(dev)];
386 	struct tty *tp = pti->pt_tty;
387 	int error = 0;
388 	int cc, c;
389 
390 again:
391 	if (pti->pt_flags & PF_REMOTE) {
392 		mutex_spin_enter(&tty_lock);
393 		while (isbackground(p, tp)) {	/* XXXSMP */
394 			if (sigismasked(curlwp, SIGTTIN) ||
395 			    p->p_pgrp->pg_jobc == 0 ||
396 			    p->p_lflag & PL_PPWAIT) {
397 				mutex_spin_exit(&tty_lock);
398 				return (EIO);
399 			}
400 			ttysig(tp, TTYSIG_PG1, SIGTTIN);
401 			error = ttysleep(tp, &lbolt, true, 0);
402 			if (error) {
403 				mutex_spin_exit(&tty_lock);
404 				return (error);
405 			}
406 		}
407 		if (tp->t_canq.c_cc == 0) {
408 			if (flag & IO_NDELAY) {
409 				mutex_spin_exit(&tty_lock);
410 				return (EWOULDBLOCK);
411 			}
412 			error = ttysleep(tp, &tp->t_cancv, true, 0);
413 			mutex_spin_exit(&tty_lock);
414 			if (error)
415 				return (error);
416 			goto again;
417 		}
418 		while(error == 0 && tp->t_canq.c_cc > 1 && uio->uio_resid > 0) {
419 			c = getc(&tp->t_canq);
420 			mutex_spin_exit(&tty_lock);
421 			error = ureadc(c, uio);
422 			mutex_spin_enter(&tty_lock);
423 			/* Re-check terminal state here? */
424 		}
425 		if (tp->t_canq.c_cc == 1)
426 			(void) getc(&tp->t_canq);
427 		cc = tp->t_canq.c_cc;
428 		mutex_spin_exit(&tty_lock);
429 		if (cc)
430 			return (error);
431 	} else if (tp->t_oproc)
432 		error = (*tp->t_linesw->l_read)(tp, uio, flag);
433 	ptcwakeup(tp, FWRITE);
434 	return (error);
435 }
436 
437 /*
438  * Write to pseudo-tty.
439  * Wakeups of controlling tty will happen
440  * indirectly, when tty driver calls ptsstart.
441  */
442 int
443 ptswrite(dev_t dev, struct uio *uio, int flag)
444 {
445 	struct pt_softc *pti = pt_softc[minor(dev)];
446 	struct tty *tp = pti->pt_tty;
447 
448 	if (tp->t_oproc == 0)
449 		return (EIO);
450 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
451 }
452 
453 /*
454  * Poll pseudo-tty.
455  */
456 int
457 ptspoll(dev_t dev, int events, struct lwp *l)
458 {
459 	struct pt_softc *pti = pt_softc[minor(dev)];
460 	struct tty *tp = pti->pt_tty;
461 
462 	if (tp->t_oproc == 0)
463 		return (POLLHUP);
464 
465 	return ((*tp->t_linesw->l_poll)(tp, events, l));
466 }
467 
468 /*
469  * Start output on pseudo-tty.
470  * Wake up process polling or sleeping for input from controlling tty.
471  */
472 void
473 ptsstart(struct tty *tp)
474 {
475 	struct pt_softc *pti = pt_softc[minor(tp->t_dev)];
476 
477 	KASSERT(mutex_owned(&tty_lock));
478 
479 	if (ISSET(tp->t_state, TS_TTSTOP))
480 		return;
481 	if (pti->pt_flags & PF_STOPPED) {
482 		pti->pt_flags &= ~PF_STOPPED;
483 		pti->pt_send = TIOCPKT_START;
484 	}
485 
486 	selnotify(&pti->pt_selr, 0, NOTE_SUBMIT);
487 	cv_broadcast(&tp->t_outcvf);
488 }
489 
490 /*
491  * Stop output.
492  */
493 void
494 ptsstop(struct tty *tp, int flush)
495 {
496 	struct pt_softc *pti = pt_softc[minor(tp->t_dev)];
497 
498 	KASSERT(mutex_owned(&tty_lock));
499 
500 	/* note: FLUSHREAD and FLUSHWRITE already ok */
501 	if (flush == 0) {
502 		flush = TIOCPKT_STOP;
503 		pti->pt_flags |= PF_STOPPED;
504 	} else
505 		pti->pt_flags &= ~PF_STOPPED;
506 	pti->pt_send |= flush;
507 
508 	/* change of perspective */
509 	if (flush & FREAD) {
510 		selnotify(&pti->pt_selw, 0, NOTE_SUBMIT);
511 		cv_broadcast(&tp->t_rawcvf);
512 	}
513 	if (flush & FWRITE) {
514 		selnotify(&pti->pt_selr, 0, NOTE_SUBMIT);
515 		cv_broadcast(&tp->t_outcvf);
516 	}
517 }
518 
519 void
520 ptcwakeup(struct tty *tp, int flag)
521 {
522 	struct pt_softc *pti = pt_softc[minor(tp->t_dev)];
523 
524 	mutex_spin_enter(&tty_lock);
525 	if (flag & FREAD) {
526 		selnotify(&pti->pt_selr, 0, NOTE_SUBMIT);
527 		cv_broadcast(&tp->t_outcvf);
528 	}
529 	if (flag & FWRITE) {
530 		selnotify(&pti->pt_selw, 0, NOTE_SUBMIT);
531 		cv_broadcast(&tp->t_rawcvf);
532 	}
533 	mutex_spin_exit(&tty_lock);
534 }
535 
536 /*ARGSUSED*/
537 int
538 ptcopen(dev_t dev, int flag, int devtype, struct lwp *l)
539 {
540 	struct pt_softc *pti;
541 	struct tty *tp;
542 	int error;
543 	int ptn = minor(dev);
544 
545 	if ((error = pty_check(ptn)) != 0)
546 		return (error);
547 
548 	pti = pt_softc[ptn];
549 	tp = pti->pt_tty;
550 
551 	mutex_spin_enter(&tty_lock);
552 	if (tp->t_oproc) {
553 		mutex_spin_exit(&tty_lock);
554 		return (EIO);
555 	}
556 	tp->t_oproc = ptsstart;
557 	mutex_spin_exit(&tty_lock);
558 	(void)(*tp->t_linesw->l_modem)(tp, 1);
559 	CLR(tp->t_lflag, EXTPROC);
560 	pti->pt_flags = 0;
561 	pti->pt_send = 0;
562 	pti->pt_ucntl = 0;
563 	return (0);
564 }
565 
566 /*ARGSUSED*/
567 int
568 ptcclose(dev_t dev, int flag, int devtype, struct lwp *l)
569 {
570 	struct pt_softc *pti = pt_softc[minor(dev)];
571 	struct tty *tp = pti->pt_tty;
572 
573 	(void)(*tp->t_linesw->l_modem)(tp, 0);
574 	mutex_spin_enter(&tty_lock);
575 	CLR(tp->t_state, TS_CARR_ON);
576 	tp->t_oproc = 0;		/* mark closed */
577 	mutex_spin_exit(&tty_lock);
578 	return (0);
579 }
580 
581 int
582 ptcread(dev_t dev, struct uio *uio, int flag)
583 {
584 	struct pt_softc *pti = pt_softc[minor(dev)];
585 	struct tty *tp = pti->pt_tty;
586 	u_char bf[BUFSIZ];
587 	int error = 0, cc;
588 	int c;
589 
590 	if (uio->uio_resid <= 0)
591 		return EINVAL;
592 
593 	/*
594 	 * We want to block until the slave
595 	 * is open, and there's something to read;
596 	 * but if we lost the slave or we're NBIO,
597 	 * then return the appropriate error instead.
598 	 */
599 	mutex_spin_enter(&tty_lock);
600 	for (;;) {
601 		if (ISSET(tp->t_state, TS_ISOPEN)) {
602 			if (pti->pt_flags & PF_PKT && (c = pti->pt_send)) {
603 				pti->pt_send = 0;
604 				mutex_spin_exit(&tty_lock);
605 				error = ureadc(c, uio);
606 				if (error)
607 					return (error);
608 				/*
609 				 * Since we don't have the tty locked, there's
610 				 * a risk of messing up `t_termios'. This is
611 				 * relevant only if the tty got closed and then
612 				 * opened again while we were out uiomoving.
613 				 */
614 				if (pti->pt_send & TIOCPKT_IOCTL) {
615 					cc = min(uio->uio_resid,
616 						sizeof(tp->t_termios));
617 					uiomove((void *) &tp->t_termios,
618 						cc, uio);
619 				}
620 				return (0);
621 			}
622 			if (pti->pt_flags & PF_UCNTL && (c = pti->pt_ucntl)) {
623 				pti->pt_ucntl = 0;
624 				mutex_spin_exit(&tty_lock);
625 				error = ureadc(c, uio);
626 				if (error)
627 					return (error);
628 				return (0);
629 			}
630 			if (tp->t_outq.c_cc && !ISSET(tp->t_state, TS_TTSTOP))
631 				break;
632 		}
633 		if (!ISSET(tp->t_state, TS_CARR_ON)) {
634 			error = 0;	/* EOF */
635 			goto out;
636 		}
637 		if (flag & IO_NDELAY) {
638 			error = EWOULDBLOCK;
639 			goto out;
640 		}
641 		error = cv_wait_sig(&tp->t_outcvf, &tty_lock);
642 		if (error)
643 			goto out;
644 	}
645 
646 	if (pti->pt_flags & (PF_PKT|PF_UCNTL)) {
647 		mutex_spin_exit(&tty_lock);
648 		error = ureadc(0, uio);
649 		mutex_spin_enter(&tty_lock);
650 		if (error == 0 && !ISSET(tp->t_state, TS_ISOPEN))
651 			error = EIO;
652 	}
653 	while (uio->uio_resid > 0 && error == 0) {
654 		cc = q_to_b(&tp->t_outq, bf, min(uio->uio_resid, BUFSIZ));
655 		if (cc <= 0)
656 			break;
657 		mutex_spin_exit(&tty_lock);
658 		error = uiomove(bf, cc, uio);
659 		mutex_spin_enter(&tty_lock);
660 		if (error == 0 && !ISSET(tp->t_state, TS_ISOPEN))
661 			error = EIO;
662 	}
663 	ttypull(tp);
664 out:
665 	mutex_spin_exit(&tty_lock);
666 	return (error);
667 }
668 
669 
670 int
671 ptcwrite(dev_t dev, struct uio *uio, int flag)
672 {
673 	struct pt_softc *pti = pt_softc[minor(dev)];
674 	struct tty *tp = pti->pt_tty;
675 	u_char *cp = NULL;
676 	int cc = 0;
677 	u_char locbuf[BUFSIZ];
678 	int cnt = 0;
679 	int error = 0;
680 
681 again:
682 	mutex_spin_enter(&tty_lock);
683 	if (!ISSET(tp->t_state, TS_ISOPEN))
684 		goto block;
685 	if (pti->pt_flags & PF_REMOTE) {
686 		if (tp->t_canq.c_cc)
687 			goto block;
688 		while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
689 			if (cc == 0) {
690 				cc = min(uio->uio_resid, BUFSIZ);
691 				cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
692 				cp = locbuf;
693 				mutex_spin_exit(&tty_lock);
694 				error = uiomove((void *)cp, cc, uio);
695 				if (error)
696 					return (error);
697 				mutex_spin_enter(&tty_lock);
698 				/* check again for safety */
699 				if (!ISSET(tp->t_state, TS_ISOPEN)) {
700 					/*
701 					 * adjust for data copied in but not
702 					 * written
703 					 */
704 					uio->uio_resid += cc;
705 					error = EIO;
706 					goto out;
707 				}
708 			}
709 			if (cc)
710 				(void) b_to_q(cp, cc, &tp->t_canq);
711 			cc = 0;
712 		}
713 		(void) putc(0, &tp->t_canq);
714 		ttwakeup(tp);
715 		cv_broadcast(&tp->t_cancv);
716 		error = 0;
717 		goto out;
718 	}
719 	while (uio->uio_resid > 0) {
720 		if (cc == 0) {
721 			cc = min(uio->uio_resid, BUFSIZ);
722 			cp = locbuf;
723 			mutex_spin_exit(&tty_lock);
724 			error = uiomove((void *)cp, cc, uio);
725 			if (error)
726 				return (error);
727 			mutex_spin_enter(&tty_lock);
728 			/* check again for safety */
729 			if (!ISSET(tp->t_state, TS_ISOPEN)) {
730 				/* adjust for data copied in but not written */
731 				uio->uio_resid += cc;
732 				error = EIO;
733 				goto out;
734 			}
735 		}
736 		while (cc > 0) {
737 			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
738 			   (tp->t_canq.c_cc > 0 || !ISSET(tp->t_lflag, ICANON))) {
739 				cv_broadcast(&tp->t_rawcv);
740 				goto block;
741 			}
742 			/* XXX - should change l_rint to be called with lock
743 			 *	 see also tty.c:ttyinput_wlock()
744 			 */
745 			mutex_spin_exit(&tty_lock);
746 			(*tp->t_linesw->l_rint)(*cp++, tp);
747 			mutex_spin_enter(&tty_lock);
748 			cnt++;
749 			cc--;
750 		}
751 		cc = 0;
752 	}
753 	error = 0;
754 	goto out;
755 
756 block:
757 	/*
758 	 * Come here to wait for slave to open, for space
759 	 * in outq, or space in rawq.
760 	 */
761 	if (!ISSET(tp->t_state, TS_CARR_ON)) {
762 		/* adjust for data copied in but not written */
763 		uio->uio_resid += cc;
764 		error = EIO;
765 		goto out;
766 	}
767 	if (flag & IO_NDELAY) {
768 		/* adjust for data copied in but not written */
769 		uio->uio_resid += cc;
770 		error = cnt == 0 ? EWOULDBLOCK : 0;
771 		goto out;
772 	}
773 	error = cv_wait_sig(&tp->t_rawcvf, &tty_lock);
774 	mutex_spin_exit(&tty_lock);
775 	if (error) {
776 		/* adjust for data copied in but not written */
777 		uio->uio_resid += cc;
778 		return (error);
779 	}
780 	goto again;
781 
782 out:
783 	mutex_spin_exit(&tty_lock);
784 	return (error);
785 }
786 
787 int
788 ptcpoll(dev_t dev, int events, struct lwp *l)
789 {
790 	struct pt_softc *pti = pt_softc[minor(dev)];
791 	struct tty *tp = pti->pt_tty;
792 	int revents = 0;
793 
794 	mutex_spin_enter(&tty_lock);
795 
796 	if (events & (POLLIN | POLLRDNORM))
797 		if (ISSET(tp->t_state, TS_ISOPEN) &&
798 		    ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) ||
799 		     ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
800 		     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)))
801 			revents |= events & (POLLIN | POLLRDNORM);
802 
803 	if (events & (POLLOUT | POLLWRNORM))
804 		if (ISSET(tp->t_state, TS_ISOPEN) &&
805 		    ((pti->pt_flags & PF_REMOTE) ?
806 		     (tp->t_canq.c_cc == 0) :
807 		     ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) ||
808 		      (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON)))))
809 			revents |= events & (POLLOUT | POLLWRNORM);
810 
811 	if (events & POLLHUP)
812 		if (!ISSET(tp->t_state, TS_CARR_ON))
813 			revents |= POLLHUP;
814 
815 	if (revents == 0) {
816 		if (events & (POLLIN | POLLHUP | POLLRDNORM))
817 			selrecord(l, &pti->pt_selr);
818 
819 		if (events & (POLLOUT | POLLWRNORM))
820 			selrecord(l, &pti->pt_selw);
821 	}
822 
823 	mutex_spin_exit(&tty_lock);
824 
825 	return (revents);
826 }
827 
828 static void
829 filt_ptcrdetach(struct knote *kn)
830 {
831 	struct pt_softc *pti;
832 	struct tty	*tp;
833 
834 	pti = kn->kn_hook;
835 	tp = pti->pt_tty;
836 
837 	mutex_spin_enter(&tty_lock);
838 	SLIST_REMOVE(&pti->pt_selr.sel_klist, kn, knote, kn_selnext);
839 	mutex_spin_exit(&tty_lock);
840 }
841 
842 static int
843 filt_ptcread(struct knote *kn, long hint)
844 {
845 	struct pt_softc *pti;
846 	struct tty	*tp;
847 	int canread;
848 
849 	pti = kn->kn_hook;
850 	tp = pti->pt_tty;
851 
852 	if ((hint & NOTE_SUBMIT) == 0) {
853 		mutex_spin_enter(&tty_lock);
854 	}
855 
856 	canread = (ISSET(tp->t_state, TS_ISOPEN) &&
857 		    ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) ||
858 		     ((pti->pt_flags & PF_PKT) && pti->pt_send) ||
859 		     ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)));
860 
861 	if (canread) {
862 		/*
863 		 * c_cc is number of characters after output post-processing;
864 		 * the amount of data actually read(2) depends on
865 		 * setting of input flags for the terminal.
866 		 */
867 		kn->kn_data = tp->t_outq.c_cc;
868 		if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
869 		    ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))
870 			kn->kn_data++;
871 	}
872 
873 	if ((hint & NOTE_SUBMIT) == 0) {
874 		mutex_spin_exit(&tty_lock);
875 	}
876 
877 	return (canread);
878 }
879 
880 static void
881 filt_ptcwdetach(struct knote *kn)
882 {
883 	struct pt_softc *pti;
884 	struct tty	*tp;
885 
886 	pti = kn->kn_hook;
887 	tp = pti->pt_tty;
888 
889 	mutex_spin_enter(&tty_lock);
890 	SLIST_REMOVE(&pti->pt_selw.sel_klist, kn, knote, kn_selnext);
891 	mutex_spin_exit(&tty_lock);
892 }
893 
894 static int
895 filt_ptcwrite(struct knote *kn, long hint)
896 {
897 	struct pt_softc *pti;
898 	struct tty	*tp;
899 	int canwrite;
900 	int nwrite;
901 
902 	pti = kn->kn_hook;
903 	tp = pti->pt_tty;
904 
905 	if ((hint & NOTE_SUBMIT) == 0) {
906 		mutex_spin_enter(&tty_lock);
907 	}
908 
909 	canwrite = (ISSET(tp->t_state, TS_ISOPEN) &&
910 		    ((pti->pt_flags & PF_REMOTE) ?
911 		     (tp->t_canq.c_cc == 0) :
912 		     ((tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2) ||
913 		      (tp->t_canq.c_cc == 0 && ISSET(tp->t_lflag, ICANON)))));
914 
915 	if (canwrite) {
916 		if (pti->pt_flags & PF_REMOTE)
917 			nwrite = tp->t_canq.c_cn;
918 		else {
919 			/* this is guaranteed to be > 0 due to above check */
920 			nwrite = tp->t_canq.c_cn
921 				- (tp->t_rawq.c_cc + tp->t_canq.c_cc);
922 		}
923 		kn->kn_data = nwrite;
924 	}
925 
926 	if ((hint & NOTE_SUBMIT) == 0) {
927 		mutex_spin_exit(&tty_lock);
928 	}
929 
930 	return (canwrite);
931 }
932 
933 static const struct filterops ptcread_filtops =
934 	{ 1, NULL, filt_ptcrdetach, filt_ptcread };
935 static const struct filterops ptcwrite_filtops =
936 	{ 1, NULL, filt_ptcwdetach, filt_ptcwrite };
937 
938 int
939 ptckqfilter(dev_t dev, struct knote *kn)
940 {
941 	struct pt_softc *pti = pt_softc[minor(dev)];
942 	struct klist	*klist;
943 
944 	switch (kn->kn_filter) {
945 	case EVFILT_READ:
946 		klist = &pti->pt_selr.sel_klist;
947 		kn->kn_fop = &ptcread_filtops;
948 		break;
949 	case EVFILT_WRITE:
950 		klist = &pti->pt_selw.sel_klist;
951 		kn->kn_fop = &ptcwrite_filtops;
952 		break;
953 	default:
954 		return (EINVAL);
955 	}
956 
957 	kn->kn_hook = pti;
958 
959 	mutex_spin_enter(&tty_lock);
960 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
961 	mutex_spin_exit(&tty_lock);
962 
963 	return (0);
964 }
965 
966 struct tty *
967 ptytty(dev_t dev)
968 {
969 	struct pt_softc *pti = pt_softc[minor(dev)];
970 	struct tty *tp = pti->pt_tty;
971 
972 	return (tp);
973 }
974 
975 /*ARGSUSED*/
976 int
977 ptyioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
978 {
979 	struct pt_softc *pti = pt_softc[minor(dev)];
980 	struct tty *tp = pti->pt_tty;
981 	const struct cdevsw *cdev;
982 	u_char *cc = tp->t_cc;
983 	int stop, error, sig;
984 
985 	/*
986 	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
987 	 * ttywflush(tp) will hang if there are characters in the outq.
988 	 */
989 	if (cmd == TIOCEXT) {
990 		/*
991 		 * When the EXTPROC bit is being toggled, we need
992 		 * to send an TIOCPKT_IOCTL if the packet driver
993 		 * is turned on.
994 		 */
995 		if (*(int *)data) {
996 			if (pti->pt_flags & PF_PKT) {
997 				pti->pt_send |= TIOCPKT_IOCTL;
998 				ptcwakeup(tp, FREAD);
999 			}
1000 			SET(tp->t_lflag, EXTPROC);
1001 		} else {
1002 			if (ISSET(tp->t_lflag, EXTPROC) &&
1003 			    (pti->pt_flags & PF_PKT)) {
1004 				pti->pt_send |= TIOCPKT_IOCTL;
1005 				ptcwakeup(tp, FREAD);
1006 			}
1007 			CLR(tp->t_lflag, EXTPROC);
1008 		}
1009 		return(0);
1010 	}
1011 
1012 #ifndef NO_DEV_PTM
1013 	/* Allow getting the name from either the master or the slave */
1014 	if (cmd == TIOCPTSNAME)
1015 		return pty_fill_ptmget(l, dev, -1, -1, data);
1016 #endif
1017 
1018 	cdev = cdevsw_lookup(dev);
1019 	if (cdev != NULL && cdev->d_open == ptcopen)
1020 		switch (cmd) {
1021 #ifndef NO_DEV_PTM
1022 		case TIOCGRANTPT:
1023 			return pty_grant_slave(l, dev);
1024 #endif
1025 
1026 		case TIOCGPGRP:
1027 			/*
1028 			 * We avoid calling ttioctl on the controller since,
1029 			 * in that case, tp must be the controlling terminal.
1030 			 */
1031 			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1032 			return (0);
1033 
1034 		case TIOCPKT:
1035 			if (*(int *)data) {
1036 				if (pti->pt_flags & PF_UCNTL)
1037 					return (EINVAL);
1038 				pti->pt_flags |= PF_PKT;
1039 			} else
1040 				pti->pt_flags &= ~PF_PKT;
1041 			return (0);
1042 
1043 		case TIOCUCNTL:
1044 			if (*(int *)data) {
1045 				if (pti->pt_flags & PF_PKT)
1046 					return (EINVAL);
1047 				pti->pt_flags |= PF_UCNTL;
1048 			} else
1049 				pti->pt_flags &= ~PF_UCNTL;
1050 			return (0);
1051 
1052 		case TIOCREMOTE:
1053 			if (*(int *)data)
1054 				pti->pt_flags |= PF_REMOTE;
1055 			else
1056 				pti->pt_flags &= ~PF_REMOTE;
1057 			mutex_spin_enter(&tty_lock);
1058 			ttyflush(tp, FREAD|FWRITE);
1059 			mutex_spin_exit(&tty_lock);
1060 			return (0);
1061 
1062 		case TIOCSETP:
1063 		case TIOCSETN:
1064 		case TIOCSETD:
1065 		case TIOCSETA:
1066 		case TIOCSETAW:
1067 		case TIOCSETAF:
1068 			mutex_spin_enter(&tty_lock);
1069 			ndflush(&tp->t_outq, tp->t_outq.c_cc);
1070 			mutex_spin_exit(&tty_lock);
1071 			break;
1072 
1073 		case TIOCSIG:
1074 			sig = (int)(long)*(void **)data;
1075 			if (sig <= 0 || sig >= NSIG)
1076 				return (EINVAL);
1077 			mutex_spin_enter(&tty_lock);
1078 			if (!ISSET(tp->t_lflag, NOFLSH))
1079 				ttyflush(tp, FREAD|FWRITE);
1080 			tp->t_state |= TS_SIGINFO;
1081 			ttysig(tp, TTYSIG_PG1, sig);
1082 			mutex_spin_exit(&tty_lock);
1083 			return (0);
1084 
1085 		case FIONREAD:
1086 			mutex_spin_enter(&tty_lock);
1087 			*(int *)data = tp->t_outq.c_cc;
1088 			mutex_spin_exit(&tty_lock);
1089 			return (0);
1090 		}
1091 
1092 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
1093 	if (error == EPASSTHROUGH)
1094 		 error = ttioctl(tp, cmd, data, flag, l);
1095 	if (error == EPASSTHROUGH) {
1096 		if (pti->pt_flags & PF_UCNTL &&
1097 		    (cmd & ~0xff) == UIOCCMD(0)) {
1098 			if (cmd & 0xff) {
1099 				pti->pt_ucntl = (u_char)cmd;
1100 				ptcwakeup(tp, FREAD);
1101 			}
1102 			return (0);
1103 		}
1104 	}
1105 	/*
1106 	 * If external processing and packet mode send ioctl packet.
1107 	 */
1108 	if (ISSET(tp->t_lflag, EXTPROC) && (pti->pt_flags & PF_PKT)) {
1109 		switch(cmd) {
1110 		case TIOCSETA:
1111 		case TIOCSETAW:
1112 		case TIOCSETAF:
1113 		case TIOCSETP:
1114 		case TIOCSETN:
1115 		case TIOCSETC:
1116 		case TIOCSLTC:
1117 		case TIOCLBIS:
1118 		case TIOCLBIC:
1119 		case TIOCLSET:
1120 			pti->pt_send |= TIOCPKT_IOCTL;
1121 			ptcwakeup(tp, FREAD);
1122 		default:
1123 			break;
1124 		}
1125 	}
1126 	stop = ISSET(tp->t_iflag, IXON) && CCEQ(cc[VSTOP], CTRL('s'))
1127 		&& CCEQ(cc[VSTART], CTRL('q'));
1128 	if (pti->pt_flags & PF_NOSTOP) {
1129 		if (stop) {
1130 			pti->pt_send &= ~TIOCPKT_NOSTOP;
1131 			pti->pt_send |= TIOCPKT_DOSTOP;
1132 			pti->pt_flags &= ~PF_NOSTOP;
1133 			ptcwakeup(tp, FREAD);
1134 		}
1135 	} else {
1136 		if (!stop) {
1137 			pti->pt_send &= ~TIOCPKT_DOSTOP;
1138 			pti->pt_send |= TIOCPKT_NOSTOP;
1139 			pti->pt_flags |= PF_NOSTOP;
1140 			ptcwakeup(tp, FREAD);
1141 		}
1142 	}
1143 	return (error);
1144 }
1145