2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
5 * Portions of this software were developed under sponsorship from Snow
6 * B.V., the Netherlands.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include "opt_compat.h"
35 #include <sys/param.h>
38 #include <sys/fcntl.h>
39 #include <sys/filio.h>
41 #include <sys/ioctl_compat.h>
42 #endif /* COMPAT_43TTY */
43 #include <sys/kernel.h>
44 #include <sys/limits.h>
45 #include <sys/malloc.h>
46 #include <sys/mount.h>
50 #include <sys/serial.h>
51 #include <sys/signal.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
57 #include <sys/ttycom.h>
59 #include <sys/ttydefaults.h>
61 #include <sys/ucred.h>
63 #include <machine/stdarg.h>
65 static MALLOC_DEFINE(M_TTY
, "tty", "tty device");
67 static void tty_rel_free(struct tty
*tp
);
69 static TAILQ_HEAD(, tty
) tty_list
= TAILQ_HEAD_INITIALIZER(tty_list
);
70 static struct sx tty_list_sx
;
71 SX_SYSINIT(tty_list
, &tty_list_sx
, "tty list");
72 static unsigned int tty_list_count
= 0;
75 * Flags that are supported and stored by this implementation.
77 #define TTYSUP_IFLAG (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|\
78 INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL)
79 #define TTYSUP_OFLAG (OPOST|ONLCR|TAB3|ONOEOT|OCRNL|ONOCR|ONLRET)
80 #define TTYSUP_LFLAG (ECHOKE|ECHOE|ECHOK|ECHO|ECHONL|ECHOPRT|\
81 ECHOCTL|ISIG|ICANON|ALTWERASE|IEXTEN|TOSTOP|\
82 FLUSHO|NOKERNINFO|NOFLSH)
83 #define TTYSUP_CFLAG (CIGNORE|CSIZE|CSTOPB|CREAD|PARENB|PARODD|\
84 HUPCL|CLOCAL|CCTS_OFLOW|CRTS_IFLOW|CDTR_IFLOW|\
85 CDSR_OFLOW|CCAR_OFLOW)
87 #define TTY_CALLOUT(tp,d) ((tp)->t_dev != (d))
90 * Set TTY buffer sizes.
94 tty_watermarks(struct tty
*tp
)
98 /* Provide an input buffer for 0.2 seconds of data. */
99 sp
= MAX(tp
->t_termios
.c_ispeed
, 0);
100 ttyinq_setsize(&tp
->t_inq
, tp
, sp
/ 5);
102 /* Set low watermark at 10% (when 90% is available). */
103 tp
->t_inlow
= (ttyinq_getsize(&tp
->t_inq
) * 9) / 10;
105 /* Provide an ouput buffer for 0.2 seconds of data. */
106 sp
= MAX(tp
->t_termios
.c_ospeed
, 0);
107 ttyoutq_setsize(&tp
->t_outq
, tp
, sp
/ 5);
109 /* Set low watermark at 10% (when 90% is available). */
110 tp
->t_outlow
= (ttyoutq_getsize(&tp
->t_outq
) * 9) / 10;
114 tty_drain(struct tty
*tp
)
118 while (ttyoutq_bytesused(&tp
->t_outq
) > 0) {
119 ttydevsw_outwakeup(tp
);
120 /* Could be handled synchronously. */
121 if (ttyoutq_bytesused(&tp
->t_outq
) == 0)
124 /* Wait for data to be drained. */
125 error
= tty_wait(tp
, &tp
->t_outwait
);
134 * Because the revoke() call already calls d_close() without making sure
135 * all threads are purged from the TTY, we can only destroy the buffers
136 * and such when the last thread leaves the TTY. ttydev_enter() and
137 * ttydev_leave() are called from within the cdev functions, to make
138 * sure we can garbage collect the TTY.
142 ttydev_enter(struct tty
*tp
)
146 if (tty_gone(tp
) || !tty_opened(tp
)) {
147 /* Device is already gone. */
156 ttydev_leave(struct tty
*tp
)
158 tty_lock_assert(tp
, MA_OWNED
);
160 if (tty_opened(tp
) || tp
->t_flags
& TF_OPENCLOSE
) {
161 /* Device is still opened somewhere. */
166 tp
->t_flags
|= TF_OPENCLOSE
;
168 /* Stop asynchronous I/O. */
169 funsetown(&tp
->t_sigio
);
171 /* Remove console TTY. */
175 /* Drain any output. */
176 MPASS((tp
->t_flags
& TF_STOPPED
) == 0);
182 /* Destroy associated buffers already. */
183 ttyinq_free(&tp
->t_inq
);
185 ttyoutq_free(&tp
->t_outq
);
188 knlist_clear(&tp
->t_inpoll
.si_note
, 1);
189 knlist_clear(&tp
->t_outpoll
.si_note
, 1);
194 tp
->t_flags
&= ~TF_OPENCLOSE
;
199 * Operations that are exposed through the character device in /dev.
202 ttydev_open(struct cdev
*dev
, int oflags
, int devtype
, struct thread
*td
)
204 struct tty
*tp
= dev
->si_drv1
;
207 /* Disallow access when the TTY belongs to a different prison. */
208 if (dev
->si_cred
!= NULL
&&
209 dev
->si_cred
->cr_prison
!= td
->td_ucred
->cr_prison
&&
210 priv_check(td
, PRIV_TTY_PRISON
)) {
216 /* Device is already gone. */
221 * Prevent the TTY from being opened when being torn down or
222 * built up by unrelated processes.
224 if (tp
->t_flags
& TF_OPENCLOSE
) {
228 tp
->t_flags
|= TF_OPENCLOSE
;
231 * Make sure the "tty" and "cua" device cannot be opened at the
234 if (TTY_CALLOUT(tp
, dev
)) {
235 if (tp
->t_flags
& TF_OPENED_IN
) {
240 if (tp
->t_flags
& TF_OPENED_OUT
) {
246 if (tp
->t_flags
& TF_EXCLUDE
&& priv_check(td
, PRIV_TTY_EXCLUSIVE
)) {
251 if (!tty_opened(tp
)) {
252 /* Set proper termios flags. */
253 if (TTY_CALLOUT(tp
, dev
)) {
254 tp
->t_termios
= tp
->t_termios_init_out
;
256 tp
->t_termios
= tp
->t_termios_init_in
;
258 ttydevsw_param(tp
, &tp
->t_termios
);
260 ttydevsw_modem(tp
, SER_DTR
|SER_RTS
, 0);
262 error
= ttydevsw_open(tp
);
270 /* Wait for Carrier Detect. */
271 if (!TTY_CALLOUT(tp
, dev
) && (oflags
& O_NONBLOCK
) == 0 &&
272 (tp
->t_termios
.c_cflag
& CLOCAL
) == 0) {
273 while ((ttydevsw_modem(tp
, 0, 0) & SER_DCD
) == 0) {
274 error
= tty_wait(tp
, &tp
->t_dcdwait
);
280 if (TTY_CALLOUT(tp
, dev
)) {
281 tp
->t_flags
|= TF_OPENED_OUT
;
283 tp
->t_flags
|= TF_OPENED_IN
;
286 done
: tp
->t_flags
&= ~TF_OPENCLOSE
;
292 ttydev_close(struct cdev
*dev
, int fflag
, int devtype
, struct thread
*td
)
294 struct tty
*tp
= dev
->si_drv1
;
299 * This can only be called once. The callin and the callout
300 * devices cannot be opened at the same time.
302 MPASS((tp
->t_flags
& TF_OPENED
) != TF_OPENED
);
303 tp
->t_flags
&= ~(TF_OPENED
|TF_EXCLUDE
|TF_STOPPED
);
305 /* Properly wake up threads that are stuck - revoke(). */
307 tty_wakeup(tp
, FREAD
|FWRITE
);
308 cv_broadcast(&tp
->t_bgwait
);
316 tty_is_ctty(struct tty
*tp
, struct proc
*p
)
318 tty_lock_assert(tp
, MA_OWNED
);
320 return (p
->p_session
== tp
->t_session
&& p
->p_flag
& P_CONTROLT
);
324 tty_wait_background(struct tty
*tp
, struct thread
*td
, int sig
)
326 struct proc
*p
= td
->td_proc
;
330 MPASS(sig
== SIGTTIN
|| sig
== SIGTTOU
);
331 tty_lock_assert(tp
, MA_OWNED
);
336 * The process should only sleep, when:
337 * - This terminal is the controling terminal
338 * - Its process group is not the foreground process
340 * - The parent process isn't waiting for the child to
342 * - the signal to send to the process isn't masked
344 if (!tty_is_ctty(tp
, p
) ||
345 p
->p_pgrp
== tp
->t_pgrp
|| p
->p_flag
& P_PPWAIT
||
346 SIGISMEMBER(p
->p_sigacts
->ps_sigignore
, sig
) ||
347 SIGISMEMBER(td
->td_sigmask
, sig
)) {
348 /* Allow the action to happen. */
354 * Send the signal and sleep until we're the new
355 * foreground process group.
359 if (pg
->pg_jobc
== 0)
362 pgsignal(pg
, sig
, 1);
365 error
= tty_wait(tp
, &tp
->t_bgwait
);
372 ttydev_read(struct cdev
*dev
, struct uio
*uio
, int ioflag
)
374 struct tty
*tp
= dev
->si_drv1
;
377 error
= ttydev_enter(tp
);
381 error
= tty_wait_background(tp
, curthread
, SIGTTIN
);
385 error
= ttydisc_read(tp
, uio
, ioflag
);
386 done
: ttydev_leave(tp
);
389 * The read() and write() calls should not throw an error when
390 * the device is ripped offline.
399 ttydev_write(struct cdev
*dev
, struct uio
*uio
, int ioflag
)
401 struct tty
*tp
= dev
->si_drv1
;
404 error
= ttydev_enter(tp
);
408 if (tp
->t_termios
.c_lflag
& TOSTOP
) {
409 error
= tty_wait_background(tp
, curthread
, SIGTTOU
);
414 error
= ttydisc_write(tp
, uio
, ioflag
);
415 done
: ttydev_leave(tp
);
418 * The read() and write() calls should not throw an error when
419 * the device is ripped offline.
428 ttydev_ioctl(struct cdev
*dev
, u_long cmd
, caddr_t data
, int fflag
,
431 struct tty
*tp
= dev
->si_drv1
;
434 error
= ttydev_enter(tp
);
469 #endif /* COMPAT_43TTY */
471 * If the ioctl() causes the TTY to be modified, let it
472 * wait in the background.
474 error
= tty_wait_background(tp
, curthread
, SIGTTOU
);
479 error
= tty_ioctl(tp
, cmd
, data
, td
);
480 done
: ttydev_leave(tp
);
486 ttydev_poll(struct cdev
*dev
, int events
, struct thread
*td
)
488 struct tty
*tp
= dev
->si_drv1
;
489 int error
, revents
= 0;
491 error
= ttydev_enter(tp
);
493 /* Don't return the error here, but the event mask. */
495 (POLLHUP
|POLLIN
|POLLRDNORM
|POLLOUT
|POLLWRNORM
));
498 if (events
& (POLLIN
|POLLRDNORM
)) {
499 /* See if we can read something. */
500 if (ttydisc_read_poll(tp
) > 0)
501 revents
|= events
& (POLLIN
|POLLRDNORM
);
503 if (events
& (POLLOUT
|POLLWRNORM
)) {
504 /* See if we can write something. */
505 if (ttydisc_write_poll(tp
) > 0)
506 revents
|= events
& (POLLOUT
|POLLWRNORM
);
508 if (tp
->t_flags
& TF_ZOMBIE
)
509 /* Hangup flag on zombie state. */
510 revents
|= events
& POLLHUP
;
513 if (events
& (POLLIN
|POLLRDNORM
))
514 selrecord(td
, &tp
->t_inpoll
);
515 if (events
& (POLLOUT
|POLLWRNORM
))
516 selrecord(td
, &tp
->t_outpoll
);
525 ttydev_mmap(struct cdev
*dev
, vm_offset_t offset
, vm_paddr_t
*paddr
, int nprot
)
527 struct tty
*tp
= dev
->si_drv1
;
530 /* Handle mmap() through the driver. */
532 error
= ttydev_enter(tp
);
535 error
= ttydevsw_mmap(tp
, offset
, paddr
, nprot
);
546 tty_kqops_read_detach(struct knote
*kn
)
548 struct tty
*tp
= kn
->kn_hook
;
550 knlist_remove(&tp
->t_inpoll
.si_note
, kn
, 0);
554 tty_kqops_read_event(struct knote
*kn
, long hint
)
556 struct tty
*tp
= kn
->kn_hook
;
558 tty_lock_assert(tp
, MA_OWNED
);
560 if (tty_gone(tp
) || tp
->t_flags
& TF_ZOMBIE
) {
561 kn
->kn_flags
|= EV_EOF
;
564 kn
->kn_data
= ttydisc_read_poll(tp
);
565 return (kn
->kn_data
> 0);
570 tty_kqops_write_detach(struct knote
*kn
)
572 struct tty
*tp
= kn
->kn_hook
;
574 knlist_remove(&tp
->t_outpoll
.si_note
, kn
, 0);
578 tty_kqops_write_event(struct knote
*kn
, long hint
)
580 struct tty
*tp
= kn
->kn_hook
;
582 tty_lock_assert(tp
, MA_OWNED
);
585 kn
->kn_flags
|= EV_EOF
;
588 kn
->kn_data
= ttydisc_write_poll(tp
);
589 return (kn
->kn_data
> 0);
593 static struct filterops tty_kqops_read
=
594 { 1, NULL
, tty_kqops_read_detach
, tty_kqops_read_event
};
595 static struct filterops tty_kqops_write
=
596 { 1, NULL
, tty_kqops_write_detach
, tty_kqops_write_event
};
599 ttydev_kqfilter(struct cdev
*dev
, struct knote
*kn
)
601 struct tty
*tp
= dev
->si_drv1
;
604 error
= ttydev_enter(tp
);
608 switch (kn
->kn_filter
) {
611 kn
->kn_fop
= &tty_kqops_read
;
612 knlist_add(&tp
->t_inpoll
.si_note
, kn
, 1);
616 kn
->kn_fop
= &tty_kqops_write
;
617 knlist_add(&tp
->t_outpoll
.si_note
, kn
, 1);
628 static struct cdevsw ttydev_cdevsw
= {
629 .d_version
= D_VERSION
,
630 .d_open
= ttydev_open
,
631 .d_close
= ttydev_close
,
632 .d_read
= ttydev_read
,
633 .d_write
= ttydev_write
,
634 .d_ioctl
= ttydev_ioctl
,
635 .d_kqfilter
= ttydev_kqfilter
,
636 .d_poll
= ttydev_poll
,
637 .d_mmap
= ttydev_mmap
,
643 * Init/lock-state devices
647 ttyil_open(struct cdev
*dev
, int oflags
, int devtype
, struct thread
*td
)
649 struct tty
*tp
= dev
->si_drv1
;
661 ttyil_close(struct cdev
*dev
, int flag
, int mode
, struct thread
*td
)
667 ttyil_rdwr(struct cdev
*dev
, struct uio
*uio
, int ioflag
)
673 ttyil_ioctl(struct cdev
*dev
, u_long cmd
, caddr_t data
, int fflag
,
676 struct tty
*tp
= dev
->si_drv1
;
687 /* Obtain terminal flags through tcgetattr(). */
688 bcopy(dev
->si_drv2
, data
, sizeof(struct termios
));
691 /* Set terminal flags through tcsetattr(). */
692 error
= priv_check(td
, PRIV_TTY_SETA
);
695 bcopy(data
, dev
->si_drv2
, sizeof(struct termios
));
698 *(int *)data
= TTYDISC
;
701 bzero(data
, sizeof(struct winsize
));
707 done
: tty_unlock(tp
);
711 static struct cdevsw ttyil_cdevsw
= {
712 .d_version
= D_VERSION
,
713 .d_open
= ttyil_open
,
714 .d_close
= ttyil_close
,
715 .d_read
= ttyil_rdwr
,
716 .d_write
= ttyil_rdwr
,
717 .d_ioctl
= ttyil_ioctl
,
723 tty_init_termios(struct tty
*tp
)
725 struct termios
*t
= &tp
->t_termios_init_in
;
727 t
->c_cflag
= TTYDEF_CFLAG
;
728 t
->c_iflag
= TTYDEF_IFLAG
;
729 t
->c_lflag
= TTYDEF_LFLAG
;
730 t
->c_oflag
= TTYDEF_OFLAG
;
731 t
->c_ispeed
= TTYDEF_SPEED
;
732 t
->c_ospeed
= TTYDEF_SPEED
;
733 bcopy(ttydefchars
, &t
->c_cc
, sizeof ttydefchars
);
735 tp
->t_termios_init_out
= *t
;
739 tty_init_console(struct tty
*tp
, speed_t s
)
741 struct termios
*ti
= &tp
->t_termios_init_in
;
742 struct termios
*to
= &tp
->t_termios_init_out
;
745 ti
->c_ispeed
= ti
->c_ospeed
= s
;
746 to
->c_ispeed
= to
->c_ospeed
= s
;
749 ti
->c_cflag
|= CLOCAL
;
750 to
->c_cflag
|= CLOCAL
;
754 * Standard device routine implementations, mostly meant for
755 * pseudo-terminal device drivers. When a driver creates a new terminal
756 * device class, missing routines are patched.
760 ttydevsw_defopen(struct tty
*tp
)
767 ttydevsw_defclose(struct tty
*tp
)
772 ttydevsw_defoutwakeup(struct tty
*tp
)
775 panic("Terminal device has output, while not implemented");
779 ttydevsw_definwakeup(struct tty
*tp
)
784 ttydevsw_defioctl(struct tty
*tp
, u_long cmd
, caddr_t data
, struct thread
*td
)
791 ttydevsw_defparam(struct tty
*tp
, struct termios
*t
)
794 /* Use a fake baud rate, we're not a real device. */
795 t
->c_ispeed
= t
->c_ospeed
= TTYDEF_SPEED_PSEUDO
;
801 ttydevsw_defmodem(struct tty
*tp
, int sigon
, int sigoff
)
804 /* Simulate a carrier to make the TTY layer happy. */
809 ttydevsw_defmmap(struct tty
*tp
, vm_offset_t offset
, vm_paddr_t
*paddr
,
817 ttydevsw_defpktnotify(struct tty
*tp
, char event
)
822 ttydevsw_deffree(void *softc
)
825 panic("Terminal device freed without a free-handler");
829 * TTY allocation and deallocation. TTY devices can be deallocated when
830 * the driver doesn't use it anymore, when the TTY isn't a session's
831 * controlling TTY and when the device node isn't opened through devfs.
835 tty_alloc(struct ttydevsw
*tsw
, void *sc
, struct mtx
*mutex
)
839 /* Make sure the driver defines all routines. */
840 #define PATCH_FUNC(x) do { \
841 if (tsw->tsw_ ## x == NULL) \
842 tsw->tsw_ ## x = ttydevsw_def ## x; \
846 PATCH_FUNC(outwakeup
);
847 PATCH_FUNC(inwakeup
);
852 PATCH_FUNC(pktnotify
);
856 tp
= malloc(sizeof(struct tty
), M_TTY
, M_WAITOK
|M_ZERO
);
859 tp
->t_flags
= tsw
->tsw_flags
;
861 tty_init_termios(tp
);
863 cv_init(&tp
->t_inwait
, "tty input");
864 cv_init(&tp
->t_outwait
, "tty output");
865 cv_init(&tp
->t_bgwait
, "tty background");
866 cv_init(&tp
->t_dcdwait
, "tty dcd");
868 ttyinq_init(&tp
->t_inq
);
869 ttyoutq_init(&tp
->t_outq
);
871 /* Allow drivers to use a custom mutex to lock the TTY. */
875 tp
->t_mtx
= &tp
->t_mtxobj
;
876 mtx_init(&tp
->t_mtxobj
, "tty lock", NULL
, MTX_DEF
);
879 knlist_init(&tp
->t_inpoll
.si_note
, tp
->t_mtx
, NULL
, NULL
, NULL
);
880 knlist_init(&tp
->t_outpoll
.si_note
, tp
->t_mtx
, NULL
, NULL
, NULL
);
882 sx_xlock(&tty_list_sx
);
883 TAILQ_INSERT_TAIL(&tty_list
, tp
, t_list
);
885 sx_xunlock(&tty_list_sx
);
891 tty_dealloc(void *arg
)
893 struct tty
*tp
= arg
;
895 sx_xlock(&tty_list_sx
);
896 TAILQ_REMOVE(&tty_list
, tp
, t_list
);
898 sx_xunlock(&tty_list_sx
);
900 /* Make sure we haven't leaked buffers. */
901 MPASS(ttyinq_getsize(&tp
->t_inq
) == 0);
902 MPASS(ttyoutq_getsize(&tp
->t_outq
) == 0);
904 knlist_destroy(&tp
->t_inpoll
.si_note
);
905 knlist_destroy(&tp
->t_outpoll
.si_note
);
907 cv_destroy(&tp
->t_inwait
);
908 cv_destroy(&tp
->t_outwait
);
909 cv_destroy(&tp
->t_bgwait
);
910 cv_destroy(&tp
->t_dcdwait
);
912 if (tp
->t_mtx
== &tp
->t_mtxobj
)
913 mtx_destroy(&tp
->t_mtxobj
);
919 tty_rel_free(struct tty
*tp
)
923 tty_lock_assert(tp
, MA_OWNED
);
925 if (tp
->t_sessioncnt
!= 0 ||
926 (tp
->t_flags
& (TF_GONE
|TF_OPENED
)) != TF_GONE
) {
927 /* TTY is still in use. */
932 /* TTY can be deallocated. */
937 destroy_dev_sched_cb(dev
, tty_dealloc
, tp
);
941 tty_rel_pgrp(struct tty
*tp
, struct pgrp
*pg
)
943 tty_lock_assert(tp
, MA_OWNED
);
945 if (tp
->t_pgrp
== pg
)
950 tty_rel_sess(struct tty
*tp
, struct session
*sess
)
952 MPASS(tp
->t_sessioncnt
> 0);
954 /* Current session has left. */
955 if (tp
->t_session
== sess
) {
956 tp
->t_session
= NULL
;
957 MPASS(tp
->t_pgrp
== NULL
);
964 tty_rel_gone(struct tty
*tp
)
966 MPASS(!tty_gone(tp
));
968 /* Simulate carrier removal. */
969 ttydisc_modem(tp
, 0);
971 /* Wake up misc. blocked threads. */
972 cv_broadcast(&tp
->t_bgwait
);
973 cv_broadcast(&tp
->t_dcdwait
);
975 tp
->t_flags
|= TF_GONE
;
980 * Exposing information about current TTY's through sysctl
984 tty_to_xtty(struct tty
*tp
, struct xtty
*xt
)
986 tty_lock_assert(tp
, MA_OWNED
);
988 xt
->xt_size
= sizeof(struct xtty
);
989 xt
->xt_insize
= ttyinq_getsize(&tp
->t_inq
);
990 xt
->xt_incc
= ttyinq_bytescanonicalized(&tp
->t_inq
);
991 xt
->xt_inlc
= ttyinq_bytesline(&tp
->t_inq
);
992 xt
->xt_inlow
= tp
->t_inlow
;
993 xt
->xt_outsize
= ttyoutq_getsize(&tp
->t_outq
);
994 xt
->xt_outcc
= ttyoutq_bytesused(&tp
->t_outq
);
995 xt
->xt_outlow
= tp
->t_outlow
;
996 xt
->xt_column
= tp
->t_column
;
997 xt
->xt_pgid
= tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: 0;
998 xt
->xt_sid
= tp
->t_session
? tp
->t_session
->s_sid
: 0;
999 xt
->xt_flags
= tp
->t_flags
;
1000 xt
->xt_dev
= tp
->t_dev
? dev2udev(tp
->t_dev
) : NODEV
;
1004 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS
)
1006 unsigned long lsize
;
1007 struct xtty
*xtlist
, *xt
;
1011 sx_slock(&tty_list_sx
);
1012 lsize
= tty_list_count
* sizeof(struct xtty
);
1014 sx_sunlock(&tty_list_sx
);
1018 xtlist
= xt
= malloc(lsize
, M_TEMP
, M_WAITOK
);
1020 TAILQ_FOREACH(tp
, &tty_list
, t_list
) {
1022 tty_to_xtty(tp
, xt
);
1026 sx_sunlock(&tty_list_sx
);
1028 error
= SYSCTL_OUT(req
, xtlist
, lsize
);
1029 free(xtlist
, M_TEMP
);
1033 SYSCTL_PROC(_kern
, OID_AUTO
, ttys
, CTLTYPE_OPAQUE
|CTLFLAG_RD
,
1034 0, 0, sysctl_kern_ttys
, "S,xtty", "List of TTYs");
1037 * Device node creation. Device has been set up, now we can expose it to
1042 tty_makedev(struct tty
*tp
, struct ucred
*cred
, const char *fmt
, ...)
1046 const char *prefix
= "tty";
1047 char name
[SPECNAMELEN
- 3]; /* for "tty" and "cua". */
1052 /* Remove "tty" prefix from devices like PTY's. */
1053 if (tp
->t_flags
& TF_NOPREFIX
)
1057 vsnrprintf(name
, sizeof name
, 32, fmt
, ap
);
1061 /* System device. */
1064 mode
= S_IRUSR
|S_IWUSR
;
1067 uid
= cred
->cr_ruid
;
1069 mode
= S_IRUSR
|S_IWUSR
|S_IWGRP
;
1072 /* Master call-in device. */
1073 dev
= make_dev_cred(&ttydev_cdevsw
, 0, cred
,
1074 uid
, gid
, mode
, "%s%s", prefix
, name
);
1078 /* Slave call-in devices. */
1079 if (tp
->t_flags
& TF_INITLOCK
) {
1080 dev
= make_dev_cred(&ttyil_cdevsw
, 0, cred
,
1081 uid
, gid
, mode
, "%s%s.init", prefix
, name
);
1082 dev_depends(tp
->t_dev
, dev
);
1084 dev
->si_drv2
= &tp
->t_termios_init_in
;
1086 dev
= make_dev_cred(&ttyil_cdevsw
, 0, cred
,
1087 uid
, gid
, mode
, "%s%s.lock", prefix
, name
);
1088 dev_depends(tp
->t_dev
, dev
);
1090 dev
->si_drv2
= &tp
->t_termios_lock_in
;
1093 /* Call-out devices. */
1094 if (tp
->t_flags
& TF_CALLOUT
) {
1095 dev
= make_dev_cred(&ttydev_cdevsw
, 0, cred
,
1096 UID_UUCP
, GID_DIALER
, 0660, "cua%s", name
);
1097 dev_depends(tp
->t_dev
, dev
);
1100 /* Slave call-out devices. */
1101 if (tp
->t_flags
& TF_INITLOCK
) {
1102 dev
= make_dev_cred(&ttyil_cdevsw
, 0, cred
,
1103 UID_UUCP
, GID_DIALER
, 0660, "cua%s.init", name
);
1104 dev_depends(tp
->t_dev
, dev
);
1106 dev
->si_drv2
= &tp
->t_termios_init_out
;
1108 dev
= make_dev_cred(&ttyil_cdevsw
, 0, cred
,
1109 UID_UUCP
, GID_DIALER
, 0660, "cua%s.lock", name
);
1110 dev_depends(tp
->t_dev
, dev
);
1112 dev
->si_drv2
= &tp
->t_termios_lock_out
;
1118 * Signalling processes.
1122 tty_signal_sessleader(struct tty
*tp
, int sig
)
1126 tty_lock_assert(tp
, MA_OWNED
);
1127 MPASS(sig
>= 1 && sig
< NSIG
);
1129 /* Make signals start output again. */
1130 tp
->t_flags
&= ~TF_STOPPED
;
1132 if (tp
->t_session
!= NULL
&& tp
->t_session
->s_leader
!= NULL
) {
1133 p
= tp
->t_session
->s_leader
;
1141 tty_signal_pgrp(struct tty
*tp
, int sig
)
1143 tty_lock_assert(tp
, MA_OWNED
);
1144 MPASS(sig
>= 1 && sig
< NSIG
);
1146 /* Make signals start output again. */
1147 tp
->t_flags
&= ~TF_STOPPED
;
1149 if (sig
== SIGINFO
&& !(tp
->t_termios
.c_lflag
& NOKERNINFO
))
1151 if (tp
->t_pgrp
!= NULL
) {
1152 PGRP_LOCK(tp
->t_pgrp
);
1153 pgsignal(tp
->t_pgrp
, sig
, 1);
1154 PGRP_UNLOCK(tp
->t_pgrp
);
1159 tty_wakeup(struct tty
*tp
, int flags
)
1161 if (tp
->t_flags
& TF_ASYNC
&& tp
->t_sigio
!= NULL
)
1162 pgsigio(&tp
->t_sigio
, SIGIO
, (tp
->t_session
!= NULL
));
1164 if (flags
& FWRITE
) {
1165 cv_broadcast(&tp
->t_outwait
);
1166 selwakeup(&tp
->t_outpoll
);
1167 KNOTE_LOCKED(&tp
->t_outpoll
.si_note
, 0);
1169 if (flags
& FREAD
) {
1170 cv_broadcast(&tp
->t_inwait
);
1171 selwakeup(&tp
->t_inpoll
);
1172 KNOTE_LOCKED(&tp
->t_inpoll
.si_note
, 0);
1177 tty_wait(struct tty
*tp
, struct cv
*cv
)
1180 int revokecnt
= tp
->t_revokecnt
;
1183 /* XXX: /dev/console also picks up Giant. */
1184 tty_lock_assert(tp
, MA_OWNED
|MA_NOTRECURSED
);
1186 tty_lock_assert(tp
, MA_OWNED
);
1188 error
= cv_wait_sig(cv
, tp
->t_mtx
);
1190 /* Restart the system call when we may have been revoked. */
1191 if (tp
->t_revokecnt
!= revokecnt
)
1194 /* Bail out when the device slipped away. */
1202 tty_timedwait(struct tty
*tp
, struct cv
*cv
, int hz
)
1205 int revokecnt
= tp
->t_revokecnt
;
1208 /* XXX: /dev/console also picks up Giant. */
1209 tty_lock_assert(tp
, MA_OWNED
|MA_NOTRECURSED
);
1211 tty_lock_assert(tp
, MA_OWNED
);
1213 error
= cv_timedwait_sig(cv
, tp
->t_mtx
, hz
);
1215 /* Restart the system call when we may have been revoked. */
1216 if (tp
->t_revokecnt
!= revokecnt
)
1219 /* Bail out when the device slipped away. */
1227 tty_flush(struct tty
*tp
, int flags
)
1229 if (flags
& FWRITE
) {
1230 tp
->t_flags
&= ~TF_HIWAT_OUT
;
1231 ttyoutq_flush(&tp
->t_outq
);
1232 tty_wakeup(tp
, FWRITE
);
1233 ttydevsw_pktnotify(tp
, TIOCPKT_FLUSHWRITE
);
1235 if (flags
& FREAD
) {
1236 tty_hiwat_in_unblock(tp
);
1237 ttyinq_flush(&tp
->t_inq
);
1238 ttydevsw_inwakeup(tp
);
1239 ttydevsw_pktnotify(tp
, TIOCPKT_FLUSHREAD
);
1244 tty_generic_ioctl(struct tty
*tp
, u_long cmd
, void *data
, struct thread
*td
)
1251 * The SER_* and TIOCM_* flags are the same, but one bit
1252 * shifted. I don't know why.
1255 ttydevsw_modem(tp
, SER_DTR
, 0);
1258 ttydevsw_modem(tp
, 0, SER_DTR
);
1261 int bits
= *(int *)data
;
1263 (bits
& (TIOCM_DTR
| TIOCM_RTS
)) >> 1,
1264 ((~bits
) & (TIOCM_DTR
| TIOCM_RTS
)) >> 1);
1268 int bits
= *(int *)data
;
1269 ttydevsw_modem(tp
, (bits
& (TIOCM_DTR
| TIOCM_RTS
)) >> 1, 0);
1273 int bits
= *(int *)data
;
1274 ttydevsw_modem(tp
, 0, (bits
& (TIOCM_DTR
| TIOCM_RTS
)) >> 1);
1278 *(int *)data
= TIOCM_LE
+ (ttydevsw_modem(tp
, 0, 0) << 1);
1283 tp
->t_flags
|= TF_ASYNC
;
1285 tp
->t_flags
&= ~TF_ASYNC
;
1288 /* This device supports non-blocking operation. */
1291 *(int *)data
= ttyinq_bytescanonicalized(&tp
->t_inq
);
1294 if (tp
->t_session
!= NULL
&& !tty_is_ctty(tp
, td
->td_proc
))
1295 /* Not allowed to set ownership. */
1298 /* Temporarily unlock the TTY to set ownership. */
1300 error
= fsetown(*(int *)data
, &tp
->t_sigio
);
1304 if (tp
->t_session
!= NULL
&& !tty_is_ctty(tp
, td
->td_proc
))
1305 /* Not allowed to set ownership. */
1308 /* Get ownership. */
1309 *(int *)data
= fgetown(&tp
->t_sigio
);
1312 /* Obtain terminal flags through tcgetattr(). */
1313 bcopy(&tp
->t_termios
, data
, sizeof(struct termios
));
1318 struct termios
*t
= data
;
1321 * Who makes up these funny rules? According to POSIX,
1322 * input baud rate is set equal to the output baud rate
1325 if (t
->c_ispeed
== 0)
1326 t
->c_ispeed
= t
->c_ospeed
;
1328 /* Discard any unsupported bits. */
1329 t
->c_iflag
&= TTYSUP_IFLAG
;
1330 t
->c_oflag
&= TTYSUP_OFLAG
;
1331 t
->c_lflag
&= TTYSUP_LFLAG
;
1332 t
->c_cflag
&= TTYSUP_CFLAG
;
1334 /* Set terminal flags through tcsetattr(). */
1335 if (cmd
== TIOCSETAW
|| cmd
== TIOCSETAF
) {
1336 error
= tty_drain(tp
);
1339 if (cmd
== TIOCSETAF
)
1340 tty_flush(tp
, FREAD
);
1344 * Only call param() when the flags really change.
1346 if ((t
->c_cflag
& CIGNORE
) == 0 &&
1347 (tp
->t_termios
.c_cflag
!= t
->c_cflag
||
1348 tp
->t_termios
.c_ispeed
!= t
->c_ispeed
||
1349 tp
->t_termios
.c_ospeed
!= t
->c_ospeed
)) {
1350 error
= ttydevsw_param(tp
, t
);
1356 tp
->t_termios
.c_cflag
= t
->c_cflag
& ~CIGNORE
;
1357 tp
->t_termios
.c_ispeed
= t
->c_ispeed
;
1358 tp
->t_termios
.c_ospeed
= t
->c_ospeed
;
1360 /* Baud rate has changed - update watermarks. */
1364 /* Copy new non-device driver parameters. */
1365 tp
->t_termios
.c_iflag
= t
->c_iflag
;
1366 tp
->t_termios
.c_oflag
= t
->c_oflag
;
1367 tp
->t_termios
.c_lflag
= t
->c_lflag
;
1368 bcopy(t
->c_cc
, &tp
->t_termios
.c_cc
, sizeof(t
->c_cc
));
1370 ttydisc_optimize(tp
);
1372 if ((t
->c_lflag
& ICANON
) == 0) {
1374 * When in non-canonical mode, wake up all
1375 * readers. Canonicalize any partial input. VMIN
1376 * and VTIME could also be adjusted.
1378 ttyinq_canonicalize(&tp
->t_inq
);
1379 tty_wakeup(tp
, FREAD
);
1383 * For packet mode: notify the PTY consumer that VSTOP
1384 * and VSTART may have been changed.
1386 if (tp
->t_termios
.c_iflag
& IXON
&&
1387 tp
->t_termios
.c_cc
[VSTOP
] == CTRL('S') &&
1388 tp
->t_termios
.c_cc
[VSTART
] == CTRL('Q'))
1389 ttydevsw_pktnotify(tp
, TIOCPKT_DOSTOP
);
1391 ttydevsw_pktnotify(tp
, TIOCPKT_NOSTOP
);
1395 /* For compatibility - we only support TTYDISC. */
1396 *(int *)data
= TTYDISC
;
1399 if (!tty_is_ctty(tp
, td
->td_proc
))
1402 if (tp
->t_pgrp
!= NULL
)
1403 *(int *)data
= tp
->t_pgrp
->pg_id
;
1405 *(int *)data
= NO_PID
;
1408 if (!tty_is_ctty(tp
, td
->td_proc
))
1411 MPASS(tp
->t_session
);
1412 *(int *)data
= tp
->t_session
->s_sid
;
1415 struct proc
*p
= td
->td_proc
;
1417 /* XXX: This looks awful. */
1419 sx_xlock(&proctree_lock
);
1422 if (!SESS_LEADER(p
)) {
1423 /* Only the session leader may do this. */
1424 sx_xunlock(&proctree_lock
);
1428 if (tp
->t_session
!= NULL
&& tp
->t_session
== p
->p_session
) {
1429 /* This is already our controlling TTY. */
1430 sx_xunlock(&proctree_lock
);
1434 if (!SESS_LEADER(p
) || p
->p_session
->s_ttyvp
!= NULL
||
1435 (tp
->t_session
!= NULL
&& tp
->t_session
->s_ttyvp
!= NULL
)) {
1437 * There is already a relation between a TTY and
1438 * a session, or the caller is not the session
1441 * Allow the TTY to be stolen when the vnode is
1442 * NULL, but the reference to the TTY is still
1445 sx_xunlock(&proctree_lock
);
1449 /* Connect the session to the TTY. */
1450 tp
->t_session
= p
->p_session
;
1451 tp
->t_session
->s_ttyp
= tp
;
1453 sx_xunlock(&proctree_lock
);
1455 /* Assign foreground process group. */
1456 tp
->t_pgrp
= p
->p_pgrp
;
1458 p
->p_flag
|= P_CONTROLT
;
1467 * XXX: Temporarily unlock the TTY to locate the process
1468 * group. This code would be lot nicer if we would ever
1469 * decompose proctree_lock.
1472 sx_slock(&proctree_lock
);
1473 pg
= pgfind(*(int *)data
);
1476 if (pg
== NULL
|| pg
->pg_session
!= td
->td_proc
->p_session
) {
1477 sx_sunlock(&proctree_lock
);
1484 * Determine if this TTY is the controlling TTY after
1485 * relocking the TTY.
1487 if (!tty_is_ctty(tp
, td
->td_proc
)) {
1488 sx_sunlock(&proctree_lock
);
1492 sx_sunlock(&proctree_lock
);
1494 /* Wake up the background process groups. */
1495 cv_broadcast(&tp
->t_bgwait
);
1499 int flags
= *(int *)data
;
1502 flags
= (FREAD
|FWRITE
);
1504 flags
&= (FREAD
|FWRITE
);
1505 tty_flush(tp
, flags
);
1509 /* Drain TTY output. */
1510 return tty_drain(tp
);
1512 /* Set terminal as console TTY. */
1514 error
= priv_check(td
, PRIV_TTY_CONSOLE
);
1519 * XXX: constty should really need to be locked!
1520 * XXX: allow disconnected constty's to be stolen!
1525 if (constty
!= NULL
)
1531 } else if (constty
== tp
) {
1536 /* Obtain window size. */
1537 bcopy(&tp
->t_winsize
, data
, sizeof(struct winsize
));
1540 /* Set window size. */
1541 if (bcmp(&tp
->t_winsize
, data
, sizeof(struct winsize
)) == 0)
1543 bcopy(data
, &tp
->t_winsize
, sizeof(struct winsize
));
1544 tty_signal_pgrp(tp
, SIGWINCH
);
1547 tp
->t_flags
|= TF_EXCLUDE
;
1550 tp
->t_flags
&= ~TF_EXCLUDE
;
1553 *(unsigned int *)data
= ttyoutq_bytesused(&tp
->t_outq
);
1556 tp
->t_flags
|= TF_STOPPED
;
1557 ttydevsw_pktnotify(tp
, TIOCPKT_STOP
);
1560 tp
->t_flags
&= ~TF_STOPPED
;
1561 ttydevsw_outwakeup(tp
);
1562 ttydevsw_pktnotify(tp
, TIOCPKT_START
);
1570 return tty_ioctl_compat(tp
, cmd
, data
, td
);
1571 #else /* !COMPAT_43TTY */
1573 #endif /* COMPAT_43TTY */
1577 tty_ioctl(struct tty
*tp
, u_long cmd
, void *data
, struct thread
*td
)
1581 tty_lock_assert(tp
, MA_OWNED
);
1586 error
= ttydevsw_ioctl(tp
, cmd
, data
, td
);
1587 if (error
== ENOIOCTL
)
1588 error
= tty_generic_ioctl(tp
, cmd
, data
, td
);
1594 tty_udev(struct tty
*tp
)
1597 return dev2udev(tp
->t_dev
);
1603 tty_checkoutq(struct tty
*tp
)
1606 /* 256 bytes should be enough to print a log message. */
1607 return (ttyoutq_bytesleft(&tp
->t_outq
) >= 256);
1611 tty_hiwat_in_block(struct tty
*tp
)
1614 if ((tp
->t_flags
& TF_HIWAT_IN
) == 0 &&
1615 tp
->t_termios
.c_iflag
& IXOFF
&&
1616 tp
->t_termios
.c_cc
[VSTOP
] != _POSIX_VDISABLE
) {
1618 * Input flow control. Only enter the high watermark when we
1619 * can successfully store the VSTOP character.
1621 if (ttyoutq_write_nofrag(&tp
->t_outq
,
1622 &tp
->t_termios
.c_cc
[VSTOP
], 1) == 0)
1623 tp
->t_flags
|= TF_HIWAT_IN
;
1625 /* No input flow control. */
1626 tp
->t_flags
|= TF_HIWAT_IN
;
1631 tty_hiwat_in_unblock(struct tty
*tp
)
1634 if (tp
->t_flags
& TF_HIWAT_IN
&&
1635 tp
->t_termios
.c_iflag
& IXOFF
&&
1636 tp
->t_termios
.c_cc
[VSTART
] != _POSIX_VDISABLE
) {
1638 * Input flow control. Only leave the high watermark when we
1639 * can successfully store the VSTART character.
1641 if (ttyoutq_write_nofrag(&tp
->t_outq
,
1642 &tp
->t_termios
.c_cc
[VSTART
], 1) == 0)
1643 tp
->t_flags
&= ~TF_HIWAT_IN
;
1645 /* No input flow control. */
1646 tp
->t_flags
&= ~TF_HIWAT_IN
;
1650 ttydevsw_inwakeup(tp
);
1653 #include "opt_ddb.h"
1655 #include <ddb/ddb.h>
1662 { TF_NOPREFIX
, 'N' },
1664 { TF_INITLOCK
, 'I' },
1665 { TF_CALLOUT
, 'C' },
1667 /* Keep these together -> 'Oi' and 'Oo'. */
1669 { TF_OPENED_IN
, 'i' },
1670 { TF_OPENED_OUT
,'o' },
1673 { TF_OPENCLOSE
, 'B' },
1675 { TF_LITERAL
, 'L' },
1677 /* Keep these together -> 'Hi' and 'Ho'. */
1679 { TF_HIWAT_IN
, 'i' },
1680 { TF_HIWAT_OUT
, 'o' },
1682 { TF_STOPPED
, 'S' },
1683 { TF_EXCLUDE
, 'X' },
1690 /* DDB command to show TTY statistics. */
1691 DB_SHOW_COMMAND(ttys
, db_show_ttys
)
1697 /* Make the output look like `pstat -t'. */
1698 db_printf(" LINE INQ CAN LIN LOW OUTQ USE LOW "
1699 "COL SESS PGID STATE\n");
1701 TAILQ_FOREACH(tp
, &tty_list
, t_list
) {
1702 isiz
= tp
->t_inq
.ti_nblocks
* TTYINQ_DATASIZE
;
1703 osiz
= tp
->t_outq
.to_nblocks
* TTYOUTQ_DATASIZE
;
1705 db_printf("%10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
1708 tp
->t_inq
.ti_linestart
- tp
->t_inq
.ti_begin
,
1709 tp
->t_inq
.ti_end
- tp
->t_inq
.ti_linestart
,
1712 tp
->t_outq
.to_end
- tp
->t_outq
.to_begin
,
1713 osiz
- tp
->t_outlow
,
1715 tp
->t_session
? tp
->t_session
->s_sid
: 0,
1716 tp
->t_pgrp
? tp
->t_pgrp
->pg_id
: 0);
1719 for (i
= j
= 0; ttystates
[i
].flag
; i
++)
1720 if (tp
->t_flags
& ttystates
[i
].flag
) {
1721 db_printf("%c", ttystates
[i
].val
);