1 /* $NetBSD: tty_pty.c,v 1.119 2009/10/14 19:25:39 dsl Exp $ */
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
35 * Pseudo-teletype Driver
36 * (Actually two drivers, requiring two entries in 'cdevsw')
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: tty_pty.c,v 1.119 2009/10/14 19:25:39 dsl Exp $");
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/ioctl.h>
47 #include <sys/ioctl_compat.h>
52 #include <sys/kernel.h>
53 #include <sys/vnode.h>
54 #include <sys/namei.h>
55 #include <sys/signalvar.h>
57 #include <sys/filedesc.h>
61 #include <sys/kauth.h>
63 #define DEFAULT_NPTYS 16 /* default number of initial ptys */
64 #define DEFAULT_MAXPTYS 992 /* default maximum number of ptys */
66 #define BUFSIZ 100 /* Chunk size iomoved to/from user */
71 struct selinfo pt_selr
, pt_selw
;
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 */
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 */
88 void ptcwakeup(struct tty
*, int);
89 void ptsstart(struct tty
*);
90 int pty_maxptys(int, int);
92 static struct pt_softc
**ptyarralloc(int);
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
);
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
);
108 dev_type_ioctl(ptyioctl
);
109 dev_type_tty(ptytty
);
111 const struct cdevsw ptc_cdevsw
= {
112 ptcopen
, ptcclose
, ptcread
, ptcwrite
, ptyioctl
,
113 nullstop
, ptytty
, ptcpoll
, nommap
, ptckqfilter
, D_TTY
116 const struct cdevsw pts_cdevsw
= {
117 ptsopen
, ptsclose
, ptsread
, ptswrite
, ptyioctl
,
118 ptsstop
, ptytty
, ptspoll
, nommap
, ttykqfilter
, D_TTY
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
128 const struct cdevsw pts_ultrix_cdevsw
= {
129 ptsopen
, ptsclose
, ptsread
, ptswrite
, ptyioctl
,
130 ptsstop
, ptytty
, ptspoll
, nommap
, ttykqfilter
, D_TTY
132 #endif /* defined(pmax) */
135 * Check if a pty is free to use.
138 pty_isfree(int minor
, int lock
)
140 struct pt_softc
*pt
= pt_softc
[minor
];
142 mutex_enter(&pt_softc_mutex
);
143 minor
= pt
== NULL
|| pt
->pt_tty
== NULL
||
144 pt
->pt_tty
->t_oproc
== NULL
;
146 mutex_exit(&pt_softc_mutex
);
151 * Allocate and zero array of nelem elements.
153 static struct pt_softc
**
154 ptyarralloc(int nelem
)
156 struct pt_softc
**pt
;
158 pt
= kmem_zalloc(nelem
* sizeof(*pt
), KM_SLEEP
);
163 ptyarrfree(struct pt_softc
**pt
, int nelem
)
167 kmem_free(pt
, nelem
* sizeof(*pt
));
171 * Check if the minor is correct and ensure necessary structures
172 * are properly allocated.
177 struct pt_softc
*pti
;
180 struct pt_softc
**newpt
, **oldpt
;
184 /* check if the requested pty can be granted */
185 if (ptn
>= maxptys
) {
187 tablefull("pty", "increase kern.maxptys");
191 /* Allocate a larger pty array */
192 for (newnpty
= npty
; newnpty
<= ptn
;)
194 if (newnpty
> maxptys
)
196 newpt
= ptyarralloc(newnpty
);
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().
204 mutex_enter(&pt_softc_mutex
);
206 if (newnpty
>= maxptys
) {
207 /* limit cut away beneath us... */
208 if (ptn
>= maxptys
) {
209 mutex_exit(&pt_softc_mutex
);
210 ptyarrfree(newpt
, newnpty
);
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.
221 if (newnpty
> npty
) {
222 memcpy(newpt
, pt_softc
, npty
*sizeof(struct pt_softc
*));
228 /* was enlarged when waited for lock, free new space */
233 mutex_exit(&pt_softc_mutex
);
234 ptyarrfree(oldpt
, oldnpty
);
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.
242 if (!pt_softc
[ptn
]) {
243 pti
= kmem_zalloc(sizeof(*pti
), KM_SLEEP
);
245 selinit(&pti
->pt_selr
);
246 selinit(&pti
->pt_selw
);
247 pti
->pt_tty
= ttymalloc();
249 mutex_enter(&pt_softc_mutex
);
252 * Check the entry again - it might have been
253 * added while we were waiting for mutex.
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
));
263 tty_attach(pti
->pt_tty
);
266 mutex_exit(&pt_softc_mutex
);
273 * Set maxpty in thread-safe way. Returns 0 in case of error, otherwise
274 * new value of maxptys.
277 pty_maxptys(int newmax
, int set
)
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()).
286 mutex_enter(&pt_softc_mutex
);
289 * The value cannot be set to value lower than the highest pty
290 * number ever allocated.
297 mutex_exit(&pt_softc_mutex
);
303 * Establish n (or default if n is 1) ptys in the system.
309 mutex_init(&pt_softc_mutex
, MUTEX_DEFAULT
, IPL_NONE
);
311 /* maybe should allow 0 => none? */
314 pt_softc
= ptyarralloc(n
);
323 ptsopen(dev_t dev
, int flag
, int devtype
, struct lwp
*l
)
325 struct pt_softc
*pti
;
328 int ptn
= minor(dev
);
330 if ((error
= pty_check(ptn
)) != 0)
333 mutex_spin_enter(&tty_lock
);
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
,
346 mutex_spin_exit(&tty_lock
);
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
)) {
354 error
= ttysleep(tp
, &tp
->t_rawcv
, true, 0);
357 mutex_spin_exit(&tty_lock
);
362 mutex_spin_exit(&tty_lock
);
363 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
364 ptcwakeup(tp
, FREAD
|FWRITE
);
369 ptsclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
371 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
372 struct tty
*tp
= pti
->pt_tty
;
375 error
= (*tp
->t_linesw
->l_close
)(tp
, flag
);
376 error
|= ttyclose(tp
);
377 ptcwakeup(tp
, FREAD
|FWRITE
);
382 ptsread(dev_t dev
, struct uio
*uio
, int flag
)
384 struct proc
*p
= curproc
;
385 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
386 struct tty
*tp
= pti
->pt_tty
;
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
);
400 ttysig(tp
, TTYSIG_PG1
, SIGTTIN
);
401 error
= ttysleep(tp
, &lbolt
, true, 0);
403 mutex_spin_exit(&tty_lock
);
407 if (tp
->t_canq
.c_cc
== 0) {
408 if (flag
& IO_NDELAY
) {
409 mutex_spin_exit(&tty_lock
);
410 return (EWOULDBLOCK
);
412 error
= ttysleep(tp
, &tp
->t_cancv
, true, 0);
413 mutex_spin_exit(&tty_lock
);
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? */
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
);
431 } else if (tp
->t_oproc
)
432 error
= (*tp
->t_linesw
->l_read
)(tp
, uio
, flag
);
433 ptcwakeup(tp
, FWRITE
);
438 * Write to pseudo-tty.
439 * Wakeups of controlling tty will happen
440 * indirectly, when tty driver calls ptsstart.
443 ptswrite(dev_t dev
, struct uio
*uio
, int flag
)
445 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
446 struct tty
*tp
= pti
->pt_tty
;
448 if (tp
->t_oproc
== 0)
450 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
457 ptspoll(dev_t dev
, int events
, struct lwp
*l
)
459 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
460 struct tty
*tp
= pti
->pt_tty
;
462 if (tp
->t_oproc
== 0)
465 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
469 * Start output on pseudo-tty.
470 * Wake up process polling or sleeping for input from controlling tty.
473 ptsstart(struct tty
*tp
)
475 struct pt_softc
*pti
= pt_softc
[minor(tp
->t_dev
)];
477 KASSERT(mutex_owned(&tty_lock
));
479 if (ISSET(tp
->t_state
, TS_TTSTOP
))
481 if (pti
->pt_flags
& PF_STOPPED
) {
482 pti
->pt_flags
&= ~PF_STOPPED
;
483 pti
->pt_send
= TIOCPKT_START
;
486 selnotify(&pti
->pt_selr
, 0, NOTE_SUBMIT
);
487 cv_broadcast(&tp
->t_outcvf
);
494 ptsstop(struct tty
*tp
, int flush
)
496 struct pt_softc
*pti
= pt_softc
[minor(tp
->t_dev
)];
498 KASSERT(mutex_owned(&tty_lock
));
500 /* note: FLUSHREAD and FLUSHWRITE already ok */
502 flush
= TIOCPKT_STOP
;
503 pti
->pt_flags
|= PF_STOPPED
;
505 pti
->pt_flags
&= ~PF_STOPPED
;
506 pti
->pt_send
|= flush
;
508 /* change of perspective */
510 selnotify(&pti
->pt_selw
, 0, NOTE_SUBMIT
);
511 cv_broadcast(&tp
->t_rawcvf
);
513 if (flush
& FWRITE
) {
514 selnotify(&pti
->pt_selr
, 0, NOTE_SUBMIT
);
515 cv_broadcast(&tp
->t_outcvf
);
520 ptcwakeup(struct tty
*tp
, int flag
)
522 struct pt_softc
*pti
= pt_softc
[minor(tp
->t_dev
)];
524 mutex_spin_enter(&tty_lock
);
526 selnotify(&pti
->pt_selr
, 0, NOTE_SUBMIT
);
527 cv_broadcast(&tp
->t_outcvf
);
530 selnotify(&pti
->pt_selw
, 0, NOTE_SUBMIT
);
531 cv_broadcast(&tp
->t_rawcvf
);
533 mutex_spin_exit(&tty_lock
);
538 ptcopen(dev_t dev
, int flag
, int devtype
, struct lwp
*l
)
540 struct pt_softc
*pti
;
543 int ptn
= minor(dev
);
545 if ((error
= pty_check(ptn
)) != 0)
551 mutex_spin_enter(&tty_lock
);
553 mutex_spin_exit(&tty_lock
);
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
);
568 ptcclose(dev_t dev
, int flag
, int devtype
, struct lwp
*l
)
570 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
571 struct tty
*tp
= pti
->pt_tty
;
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
);
582 ptcread(dev_t dev
, struct uio
*uio
, int flag
)
584 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
585 struct tty
*tp
= pti
->pt_tty
;
590 if (uio
->uio_resid
<= 0)
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.
599 mutex_spin_enter(&tty_lock
);
601 if (ISSET(tp
->t_state
, TS_ISOPEN
)) {
602 if (pti
->pt_flags
& PF_PKT
&& (c
= pti
->pt_send
)) {
604 mutex_spin_exit(&tty_lock
);
605 error
= ureadc(c
, uio
);
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.
614 if (pti
->pt_send
& TIOCPKT_IOCTL
) {
615 cc
= min(uio
->uio_resid
,
616 sizeof(tp
->t_termios
));
617 uiomove((void *) &tp
->t_termios
,
622 if (pti
->pt_flags
& PF_UCNTL
&& (c
= pti
->pt_ucntl
)) {
624 mutex_spin_exit(&tty_lock
);
625 error
= ureadc(c
, uio
);
630 if (tp
->t_outq
.c_cc
&& !ISSET(tp
->t_state
, TS_TTSTOP
))
633 if (!ISSET(tp
->t_state
, TS_CARR_ON
)) {
637 if (flag
& IO_NDELAY
) {
641 error
= cv_wait_sig(&tp
->t_outcvf
, &tty_lock
);
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
))
653 while (uio
->uio_resid
> 0 && error
== 0) {
654 cc
= q_to_b(&tp
->t_outq
, bf
, min(uio
->uio_resid
, BUFSIZ
));
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
))
665 mutex_spin_exit(&tty_lock
);
671 ptcwrite(dev_t dev
, struct uio
*uio
, int flag
)
673 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
674 struct tty
*tp
= pti
->pt_tty
;
677 u_char locbuf
[BUFSIZ
];
682 mutex_spin_enter(&tty_lock
);
683 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
685 if (pti
->pt_flags
& PF_REMOTE
) {
688 while (uio
->uio_resid
> 0 && tp
->t_canq
.c_cc
< TTYHOG
- 1) {
690 cc
= min(uio
->uio_resid
, BUFSIZ
);
691 cc
= min(cc
, TTYHOG
- 1 - tp
->t_canq
.c_cc
);
693 mutex_spin_exit(&tty_lock
);
694 error
= uiomove((void *)cp
, cc
, uio
);
697 mutex_spin_enter(&tty_lock
);
698 /* check again for safety */
699 if (!ISSET(tp
->t_state
, TS_ISOPEN
)) {
701 * adjust for data copied in but not
704 uio
->uio_resid
+= cc
;
710 (void) b_to_q(cp
, cc
, &tp
->t_canq
);
713 (void) putc(0, &tp
->t_canq
);
715 cv_broadcast(&tp
->t_cancv
);
719 while (uio
->uio_resid
> 0) {
721 cc
= min(uio
->uio_resid
, BUFSIZ
);
723 mutex_spin_exit(&tty_lock
);
724 error
= uiomove((void *)cp
, cc
, uio
);
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
;
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
);
742 /* XXX - should change l_rint to be called with lock
743 * see also tty.c:ttyinput_wlock()
745 mutex_spin_exit(&tty_lock
);
746 (*tp
->t_linesw
->l_rint
)(*cp
++, tp
);
747 mutex_spin_enter(&tty_lock
);
758 * Come here to wait for slave to open, for space
759 * in outq, or space in rawq.
761 if (!ISSET(tp
->t_state
, TS_CARR_ON
)) {
762 /* adjust for data copied in but not written */
763 uio
->uio_resid
+= cc
;
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;
773 error
= cv_wait_sig(&tp
->t_rawcvf
, &tty_lock
);
774 mutex_spin_exit(&tty_lock
);
776 /* adjust for data copied in but not written */
777 uio
->uio_resid
+= cc
;
783 mutex_spin_exit(&tty_lock
);
788 ptcpoll(dev_t dev
, int events
, struct lwp
*l
)
790 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
791 struct tty
*tp
= pti
->pt_tty
;
794 mutex_spin_enter(&tty_lock
);
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
);
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
);
811 if (events
& POLLHUP
)
812 if (!ISSET(tp
->t_state
, TS_CARR_ON
))
816 if (events
& (POLLIN
| POLLHUP
| POLLRDNORM
))
817 selrecord(l
, &pti
->pt_selr
);
819 if (events
& (POLLOUT
| POLLWRNORM
))
820 selrecord(l
, &pti
->pt_selw
);
823 mutex_spin_exit(&tty_lock
);
829 filt_ptcrdetach(struct knote
*kn
)
831 struct pt_softc
*pti
;
837 mutex_spin_enter(&tty_lock
);
838 SLIST_REMOVE(&pti
->pt_selr
.sel_klist
, kn
, knote
, kn_selnext
);
839 mutex_spin_exit(&tty_lock
);
843 filt_ptcread(struct knote
*kn
, long hint
)
845 struct pt_softc
*pti
;
852 if ((hint
& NOTE_SUBMIT
) == 0) {
853 mutex_spin_enter(&tty_lock
);
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
)));
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.
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
))
873 if ((hint
& NOTE_SUBMIT
) == 0) {
874 mutex_spin_exit(&tty_lock
);
881 filt_ptcwdetach(struct knote
*kn
)
883 struct pt_softc
*pti
;
889 mutex_spin_enter(&tty_lock
);
890 SLIST_REMOVE(&pti
->pt_selw
.sel_klist
, kn
, knote
, kn_selnext
);
891 mutex_spin_exit(&tty_lock
);
895 filt_ptcwrite(struct knote
*kn
, long hint
)
897 struct pt_softc
*pti
;
905 if ((hint
& NOTE_SUBMIT
) == 0) {
906 mutex_spin_enter(&tty_lock
);
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
)))));
916 if (pti
->pt_flags
& PF_REMOTE
)
917 nwrite
= tp
->t_canq
.c_cn
;
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
);
923 kn
->kn_data
= nwrite
;
926 if ((hint
& NOTE_SUBMIT
) == 0) {
927 mutex_spin_exit(&tty_lock
);
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
};
939 ptckqfilter(dev_t dev
, struct knote
*kn
)
941 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
944 switch (kn
->kn_filter
) {
946 klist
= &pti
->pt_selr
.sel_klist
;
947 kn
->kn_fop
= &ptcread_filtops
;
950 klist
= &pti
->pt_selw
.sel_klist
;
951 kn
->kn_fop
= &ptcwrite_filtops
;
959 mutex_spin_enter(&tty_lock
);
960 SLIST_INSERT_HEAD(klist
, kn
, kn_selnext
);
961 mutex_spin_exit(&tty_lock
);
969 struct pt_softc
*pti
= pt_softc
[minor(dev
)];
970 struct tty
*tp
= pti
->pt_tty
;
977 ptyioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
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
;
986 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
987 * ttywflush(tp) will hang if there are characters in the outq.
989 if (cmd
== TIOCEXT
) {
991 * When the EXTPROC bit is being toggled, we need
992 * to send an TIOCPKT_IOCTL if the packet driver
996 if (pti
->pt_flags
& PF_PKT
) {
997 pti
->pt_send
|= TIOCPKT_IOCTL
;
998 ptcwakeup(tp
, FREAD
);
1000 SET(tp
->t_lflag
, EXTPROC
);
1002 if (ISSET(tp
->t_lflag
, EXTPROC
) &&
1003 (pti
->pt_flags
& PF_PKT
)) {
1004 pti
->pt_send
|= TIOCPKT_IOCTL
;
1005 ptcwakeup(tp
, FREAD
);
1007 CLR(tp
->t_lflag
, EXTPROC
);
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
);
1018 cdev
= cdevsw_lookup(dev
);
1019 if (cdev
!= NULL
&& cdev
->d_open
== ptcopen
)
1023 return pty_grant_slave(l
, dev
);
1028 * We avoid calling ttioctl on the controller since,
1029 * in that case, tp must be the controlling terminal.
1031 *(int *)data
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: 0;
1036 if (pti
->pt_flags
& PF_UCNTL
)
1038 pti
->pt_flags
|= PF_PKT
;
1040 pti
->pt_flags
&= ~PF_PKT
;
1045 if (pti
->pt_flags
& PF_PKT
)
1047 pti
->pt_flags
|= PF_UCNTL
;
1049 pti
->pt_flags
&= ~PF_UCNTL
;
1054 pti
->pt_flags
|= PF_REMOTE
;
1056 pti
->pt_flags
&= ~PF_REMOTE
;
1057 mutex_spin_enter(&tty_lock
);
1058 ttyflush(tp
, FREAD
|FWRITE
);
1059 mutex_spin_exit(&tty_lock
);
1068 mutex_spin_enter(&tty_lock
);
1069 ndflush(&tp
->t_outq
, tp
->t_outq
.c_cc
);
1070 mutex_spin_exit(&tty_lock
);
1074 sig
= (int)(long)*(void **)data
;
1075 if (sig
<= 0 || sig
>= NSIG
)
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
);
1086 mutex_spin_enter(&tty_lock
);
1087 *(int *)data
= tp
->t_outq
.c_cc
;
1088 mutex_spin_exit(&tty_lock
);
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)) {
1099 pti
->pt_ucntl
= (u_char
)cmd
;
1100 ptcwakeup(tp
, FREAD
);
1106 * If external processing and packet mode send ioctl packet.
1108 if (ISSET(tp
->t_lflag
, EXTPROC
) && (pti
->pt_flags
& PF_PKT
)) {
1120 pti
->pt_send
|= TIOCPKT_IOCTL
;
1121 ptcwakeup(tp
, FREAD
);
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
) {
1130 pti
->pt_send
&= ~TIOCPKT_NOSTOP
;
1131 pti
->pt_send
|= TIOCPKT_DOSTOP
;
1132 pti
->pt_flags
&= ~PF_NOSTOP
;
1133 ptcwakeup(tp
, FREAD
);
1137 pti
->pt_send
&= ~TIOCPKT_DOSTOP
;
1138 pti
->pt_send
|= TIOCPKT_NOSTOP
;
1139 pti
->pt_flags
|= PF_NOSTOP
;
1140 ptcwakeup(tp
, FREAD
);