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>
47 #include <sys/namei.h>
51 #include <sys/serial.h>
52 #include <sys/signal.h>
55 #include <sys/sysctl.h>
56 #include <sys/systm.h>
58 #include <sys/ttycom.h>
60 #include <sys/ttydefaults.h>
62 #include <sys/ucred.h>
63 #include <sys/vnode.h>
65 #include <machine/stdarg.h>
67 static MALLOC_DEFINE(M_TTY, "tty", "tty device");
69 static void tty_rel_free(struct tty *tp);
71 static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
72 static struct sx tty_list_sx;
73 SX_SYSINIT(tty_list, &tty_list_sx, "tty list");
74 static unsigned int tty_list_count = 0;
77 * Flags that are supported and stored by this implementation.
79 #define TTYSUP_IFLAG (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|\
80 INLCR|IGNCR|ICRNL|IXON|IXOFF|IXANY|IMAXBEL)
81 #define TTYSUP_OFLAG (OPOST|ONLCR|TAB3|ONOEOT|OCRNL|ONOCR|ONLRET)
82 #define TTYSUP_LFLAG (ECHOKE|ECHOE|ECHOK|ECHO|ECHONL|ECHOPRT|\
83 ECHOCTL|ISIG|ICANON|ALTWERASE|IEXTEN|TOSTOP|\
84 FLUSHO|NOKERNINFO|NOFLSH)
85 #define TTYSUP_CFLAG (CIGNORE|CSIZE|CSTOPB|CREAD|PARENB|PARODD|\
86 HUPCL|CLOCAL|CCTS_OFLOW|CRTS_IFLOW|CDTR_IFLOW|\
87 CDSR_OFLOW|CCAR_OFLOW)
89 #define TTY_CALLOUT(tp,d) ((tp)->t_dev != (d))
92 * Set TTY buffer sizes.
96 tty_watermarks(struct tty *tp)
100 /* Provide an input buffer for 0.2 seconds of data. */
101 sp = MAX(tp->t_termios.c_ispeed, 0);
102 ttyinq_setsize(&tp->t_inq, tp, sp / 5);
104 /* Set low watermark at 10% (when 90% is available). */
105 tp->t_inlow = (ttyinq_getsize(&tp->t_inq) * 9) / 10;
107 /* Provide an ouput buffer for 0.2 seconds of data. */
108 sp = MAX(tp->t_termios.c_ospeed, 0);
109 ttyoutq_setsize(&tp->t_outq, tp, sp / 5);
111 /* Set low watermark at 10% (when 90% is available). */
112 tp->t_outlow = (ttyoutq_getsize(&tp->t_outq) * 9) / 10;
116 tty_freebuffers(struct tty *tp)
119 /* Destroy input buffers. */
120 ttyinq_flush(&tp->t_inq);
121 ttyinq_setsize(&tp->t_inq, NULL, 0);
122 MPASS(ttyinq_getsize(&tp->t_inq) == 0);
125 /* Destroy output buffers. */
126 ttyoutq_flush(&tp->t_outq);
127 ttyoutq_setsize(&tp->t_outq, NULL, 0);
128 MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
133 tty_drain(struct tty *tp)
137 while (ttyoutq_bytesused(&tp->t_outq) > 0) {
138 ttydevsw_outwakeup(tp);
139 /* Could be handled synchronously. */
140 if (ttyoutq_bytesused(&tp->t_outq) == 0)
143 /* Wait for data to be drained. */
144 error = tty_wait(tp, &tp->t_outwait);
153 * Because the revoke() call already calls d_close() without making sure
154 * all threads are purged from the TTY, we can only destroy the buffers
155 * and such when the last thread leaves the TTY. ttydev_enter() and
156 * ttydev_leave() are called from within the cdev functions, to make
157 * sure we can garbage collect the TTY.
161 ttydev_enter(struct tty *tp)
165 if (tty_gone(tp) || !tty_opened(tp)) {
166 /* Device is already gone. */
175 ttydev_leave(struct tty *tp)
177 tty_lock_assert(tp, MA_OWNED);
179 if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) {
180 /* Device is still opened somewhere. */
185 tp->t_flags |= TF_OPENCLOSE;
187 /* Stop asynchronous I/O. */
188 funsetown(&tp->t_sigio);
190 /* Remove console TTY. */
194 /* Drain any output. */
195 MPASS((tp->t_flags & TF_STOPPED) == 0);
201 /* Destroy associated buffers already. */
204 knlist_clear(&tp->t_inpoll.si_note, 1);
205 knlist_clear(&tp->t_outpoll.si_note, 1);
210 tp->t_flags &= ~TF_OPENCLOSE;
215 * Operations that are exposed through the character device in /dev.
218 ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
220 struct tty *tp = dev->si_drv1;
223 /* Disallow access when the TTY belongs to a different prison. */
224 if (dev->si_cred != NULL &&
225 dev->si_cred->cr_prison != td->td_ucred->cr_prison &&
226 priv_check(td, PRIV_TTY_PRISON)) {
232 /* Device is already gone. */
237 * Prevent the TTY from being opened when being torn down or
238 * built up by unrelated processes.
240 if (tp->t_flags & TF_OPENCLOSE) {
244 tp->t_flags |= TF_OPENCLOSE;
247 * Make sure the "tty" and "cua" device cannot be opened at the
250 if (TTY_CALLOUT(tp, dev)) {
251 if (tp->t_flags & TF_OPENED_IN) {
256 if (tp->t_flags & TF_OPENED_OUT) {
262 if (tp->t_flags & TF_EXCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE)) {
267 if (!tty_opened(tp)) {
268 /* Set proper termios flags. */
269 if (TTY_CALLOUT(tp, dev)) {
270 tp->t_termios = tp->t_termios_init_out;
272 tp->t_termios = tp->t_termios_init_in;
274 ttydevsw_param(tp, &tp->t_termios);
276 ttydevsw_modem(tp, SER_DTR|SER_RTS, 0);
278 error = ttydevsw_open(tp);
286 /* Wait for Carrier Detect. */
287 if (!TTY_CALLOUT(tp, dev) && (oflags & O_NONBLOCK) == 0 &&
288 (tp->t_termios.c_cflag & CLOCAL) == 0) {
289 while ((ttydevsw_modem(tp, 0, 0) & SER_DCD) == 0) {
290 error = tty_wait(tp, &tp->t_dcdwait);
296 if (TTY_CALLOUT(tp, dev)) {
297 tp->t_flags |= TF_OPENED_OUT;
299 tp->t_flags |= TF_OPENED_IN;
302 done: tp->t_flags &= ~TF_OPENCLOSE;
308 ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
310 struct tty *tp = dev->si_drv1;
315 * This can only be called once. The callin and the callout
316 * devices cannot be opened at the same time.
318 MPASS((tp->t_flags & TF_OPENED) != TF_OPENED);
319 tp->t_flags &= ~(TF_OPENED|TF_EXCLUDE|TF_STOPPED);
321 /* Properly wake up threads that are stuck - revoke(). */
323 tty_wakeup(tp, FREAD|FWRITE);
324 cv_broadcast(&tp->t_bgwait);
332 tty_is_ctty(struct tty *tp, struct proc *p)
334 tty_lock_assert(tp, MA_OWNED);
336 return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT);
340 tty_wait_background(struct tty *tp, struct thread *td, int sig)
342 struct proc *p = td->td_proc;
346 MPASS(sig == SIGTTIN || sig == SIGTTOU);
347 tty_lock_assert(tp, MA_OWNED);
352 * The process should only sleep, when:
353 * - This terminal is the controling terminal
354 * - Its process group is not the foreground process
356 * - The parent process isn't waiting for the child to
358 * - the signal to send to the process isn't masked
360 if (!tty_is_ctty(tp, p) ||
361 p->p_pgrp == tp->t_pgrp || p->p_flag & P_PPWAIT ||
362 SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) ||
363 SIGISMEMBER(td->td_sigmask, sig)) {
364 /* Allow the action to happen. */
370 * Send the signal and sleep until we're the new
371 * foreground process group.
375 if (pg->pg_jobc == 0)
378 pgsignal(pg, sig, 1);
381 error = tty_wait(tp, &tp->t_bgwait);
388 ttydev_read(struct cdev *dev, struct uio *uio, int ioflag)
390 struct tty *tp = dev->si_drv1;
393 error = ttydev_enter(tp);
397 error = tty_wait_background(tp, curthread, SIGTTIN);
401 error = ttydisc_read(tp, uio, ioflag);
402 done: ttydev_leave(tp);
405 * The read() and write() calls should not throw an error when
406 * the device is ripped offline.
415 ttydev_write(struct cdev *dev, struct uio *uio, int ioflag)
417 struct tty *tp = dev->si_drv1;
420 error = ttydev_enter(tp);
424 if (tp->t_termios.c_lflag & TOSTOP) {
425 error = tty_wait_background(tp, curthread, SIGTTOU);
430 error = ttydisc_write(tp, uio, ioflag);
431 done: ttydev_leave(tp);
434 * The read() and write() calls should not throw an error when
435 * the device is ripped offline.
444 ttydev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
447 struct tty *tp = dev->si_drv1;
450 error = ttydev_enter(tp);
485 #endif /* COMPAT_43TTY */
487 * If the ioctl() causes the TTY to be modified, let it
488 * wait in the background.
490 error = tty_wait_background(tp, curthread, SIGTTOU);
495 error = tty_ioctl(tp, cmd, data, td);
496 done: ttydev_leave(tp);
502 ttydev_poll(struct cdev *dev, int events, struct thread *td)
504 struct tty *tp = dev->si_drv1;
505 int error, revents = 0;
507 error = ttydev_enter(tp);
509 /* Don't return the error here, but the event mask. */
511 (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
514 if (events & (POLLIN|POLLRDNORM)) {
515 /* See if we can read something. */
516 if (ttydisc_read_poll(tp) > 0)
517 revents |= events & (POLLIN|POLLRDNORM);
519 if (events & (POLLOUT|POLLWRNORM)) {
520 /* See if we can write something. */
521 if (ttydisc_write_poll(tp) > 0)
522 revents |= events & (POLLOUT|POLLWRNORM);
524 if (tp->t_flags & TF_ZOMBIE)
525 /* Hangup flag on zombie state. */
526 revents |= events & POLLHUP;
529 if (events & (POLLIN|POLLRDNORM))
530 selrecord(td, &tp->t_inpoll);
531 if (events & (POLLOUT|POLLWRNORM))
532 selrecord(td, &tp->t_outpoll);
541 ttydev_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
543 struct tty *tp = dev->si_drv1;
546 /* Handle mmap() through the driver. */
548 error = ttydev_enter(tp);
551 error = ttydevsw_mmap(tp, offset, paddr, nprot);
562 tty_kqops_read_detach(struct knote *kn)
564 struct tty *tp = kn->kn_hook;
566 knlist_remove(&tp->t_inpoll.si_note, kn, 0);
570 tty_kqops_read_event(struct knote *kn, long hint)
572 struct tty *tp = kn->kn_hook;
574 tty_lock_assert(tp, MA_OWNED);
576 if (tty_gone(tp) || tp->t_flags & TF_ZOMBIE) {
577 kn->kn_flags |= EV_EOF;
580 kn->kn_data = ttydisc_read_poll(tp);
581 return (kn->kn_data > 0);
586 tty_kqops_write_detach(struct knote *kn)
588 struct tty *tp = kn->kn_hook;
590 knlist_remove(&tp->t_outpoll.si_note, kn, 0);
594 tty_kqops_write_event(struct knote *kn, long hint)
596 struct tty *tp = kn->kn_hook;
598 tty_lock_assert(tp, MA_OWNED);
601 kn->kn_flags |= EV_EOF;
604 kn->kn_data = ttydisc_write_poll(tp);
605 return (kn->kn_data > 0);
609 static struct filterops tty_kqops_read =
610 { 1, NULL, tty_kqops_read_detach, tty_kqops_read_event };
611 static struct filterops tty_kqops_write =
612 { 1, NULL, tty_kqops_write_detach, tty_kqops_write_event };
615 ttydev_kqfilter(struct cdev *dev, struct knote *kn)
617 struct tty *tp = dev->si_drv1;
620 error = ttydev_enter(tp);
624 switch (kn->kn_filter) {
627 kn->kn_fop = &tty_kqops_read;
628 knlist_add(&tp->t_inpoll.si_note, kn, 1);
632 kn->kn_fop = &tty_kqops_write;
633 knlist_add(&tp->t_outpoll.si_note, kn, 1);
644 static struct cdevsw ttydev_cdevsw = {
645 .d_version = D_VERSION,
646 .d_open = ttydev_open,
647 .d_close = ttydev_close,
648 .d_read = ttydev_read,
649 .d_write = ttydev_write,
650 .d_ioctl = ttydev_ioctl,
651 .d_kqfilter = ttydev_kqfilter,
652 .d_poll = ttydev_poll,
653 .d_mmap = ttydev_mmap,
659 * Init/lock-state devices
663 ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
665 struct tty *tp = dev->si_drv1;
677 ttyil_close(struct cdev *dev, int flag, int mode, struct thread *td)
683 ttyil_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
689 ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
692 struct tty *tp = dev->si_drv1;
703 /* Obtain terminal flags through tcgetattr(). */
704 bcopy(dev->si_drv2, data, sizeof(struct termios));
707 /* Set terminal flags through tcsetattr(). */
708 error = priv_check(td, PRIV_TTY_SETA);
711 bcopy(data, dev->si_drv2, sizeof(struct termios));
715 *(int *)data = TTYDISC;
718 bzero(data, sizeof(struct winsize));
724 done: tty_unlock(tp);
728 static struct cdevsw ttyil_cdevsw = {
729 .d_version = D_VERSION,
730 .d_open = ttyil_open,
731 .d_close = ttyil_close,
732 .d_read = ttyil_rdwr,
733 .d_write = ttyil_rdwr,
734 .d_ioctl = ttyil_ioctl,
740 tty_init_termios(struct tty *tp)
742 struct termios *t = &tp->t_termios_init_in;
744 t->c_cflag = TTYDEF_CFLAG;
745 t->c_iflag = TTYDEF_IFLAG;
746 t->c_lflag = TTYDEF_LFLAG;
747 t->c_oflag = TTYDEF_OFLAG;
748 t->c_ispeed = TTYDEF_SPEED;
749 t->c_ospeed = TTYDEF_SPEED;
750 bcopy(ttydefchars, &t->c_cc, sizeof ttydefchars);
752 tp->t_termios_init_out = *t;
756 tty_init_console(struct tty *tp, speed_t s)
758 struct termios *ti = &tp->t_termios_init_in;
759 struct termios *to = &tp->t_termios_init_out;
762 ti->c_ispeed = ti->c_ospeed = s;
763 to->c_ispeed = to->c_ospeed = s;
766 ti->c_cflag |= CLOCAL;
767 to->c_cflag |= CLOCAL;
771 * Standard device routine implementations, mostly meant for
772 * pseudo-terminal device drivers. When a driver creates a new terminal
773 * device class, missing routines are patched.
777 ttydevsw_defopen(struct tty *tp)
784 ttydevsw_defclose(struct tty *tp)
789 ttydevsw_defoutwakeup(struct tty *tp)
792 panic("Terminal device has output, while not implemented");
796 ttydevsw_definwakeup(struct tty *tp)
801 ttydevsw_defioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
808 ttydevsw_defparam(struct tty *tp, struct termios *t)
811 /* Use a fake baud rate, we're not a real device. */
812 t->c_ispeed = t->c_ospeed = TTYDEF_SPEED_PSEUDO;
818 ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff)
821 /* Simulate a carrier to make the TTY layer happy. */
826 ttydevsw_defmmap(struct tty *tp, vm_offset_t offset, vm_paddr_t *paddr,
834 ttydevsw_deffree(void *softc)
837 panic("Terminal device freed without a free-handler");
841 * TTY allocation and deallocation. TTY devices can be deallocated when
842 * the driver doesn't use it anymore, when the TTY isn't a session's
843 * controlling TTY and when the device node isn't opened through devfs.
847 tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
851 /* Make sure the driver defines all routines. */
852 #define PATCH_FUNC(x) do { \
853 if (tsw->tsw_ ## x == NULL) \
854 tsw->tsw_ ## x = ttydevsw_def ## x; \
858 PATCH_FUNC(outwakeup);
859 PATCH_FUNC(inwakeup);
867 tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
870 tp->t_flags = tsw->tsw_flags;
872 tty_init_termios(tp);
874 cv_init(&tp->t_inwait, "tty input");
875 cv_init(&tp->t_outwait, "tty output");
876 cv_init(&tp->t_bgwait, "tty background");
877 cv_init(&tp->t_dcdwait, "tty dcd");
879 TAILQ_INIT(&tp->t_inq.ti_list);
880 STAILQ_INIT(&tp->t_outq.to_list);
882 /* Allow drivers to use a custom mutex to lock the TTY. */
886 tp->t_mtx = &tp->t_mtxobj;
887 mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
890 knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
891 knlist_init(&tp->t_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
893 sx_xlock(&tty_list_sx);
894 TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
896 sx_xunlock(&tty_list_sx);
902 tty_dealloc(void *arg)
904 struct tty *tp = arg;
906 sx_xlock(&tty_list_sx);
907 TAILQ_REMOVE(&tty_list, tp, t_list);
909 sx_xunlock(&tty_list_sx);
911 knlist_destroy(&tp->t_inpoll.si_note);
912 knlist_destroy(&tp->t_outpoll.si_note);
914 cv_destroy(&tp->t_inwait);
915 cv_destroy(&tp->t_outwait);
916 cv_destroy(&tp->t_bgwait);
917 cv_destroy(&tp->t_dcdwait);
919 if (tp->t_mtx == &tp->t_mtxobj)
920 mtx_destroy(&tp->t_mtxobj);
926 tty_rel_free(struct tty *tp)
930 tty_lock_assert(tp, MA_OWNED);
932 if (tp->t_sessioncnt != 0 ||
933 (tp->t_flags & (TF_GONE|TF_OPENED)) != TF_GONE) {
934 /* TTY is still in use. */
941 /* TTY can be deallocated. */
946 destroy_dev_sched_cb(dev, tty_dealloc, tp);
950 tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
952 tty_lock_assert(tp, MA_OWNED);
954 if (tp->t_pgrp == pg)
959 tty_rel_sess(struct tty *tp, struct session *sess)
961 MPASS(tp->t_sessioncnt > 0);
963 /* Current session has left. */
964 if (tp->t_session == sess) {
965 tp->t_session = NULL;
966 MPASS(tp->t_pgrp == NULL);
973 tty_rel_gone(struct tty *tp)
975 MPASS(!tty_gone(tp));
977 /* Simulate carrier removal. */
978 ttydisc_modem(tp, 0);
980 /* Wake up misc. blocked threads. */
981 cv_broadcast(&tp->t_bgwait);
982 cv_broadcast(&tp->t_dcdwait);
984 tp->t_flags |= TF_GONE;
989 * Exposing information about current TTY's through sysctl
993 tty_to_xtty(struct tty *tp, struct xtty *xt)
995 tty_lock_assert(tp, MA_OWNED);
997 xt->xt_size = sizeof(struct xtty);
998 xt->xt_insize = ttyinq_getsize(&tp->t_inq);
999 xt->xt_incc = ttyinq_bytescanonicalized(&tp->t_inq);
1000 xt->xt_inlc = ttyinq_bytesline(&tp->t_inq);
1001 xt->xt_inlow = tp->t_inlow;
1002 xt->xt_outsize = ttyoutq_getsize(&tp->t_outq);
1003 xt->xt_outcc = ttyoutq_bytesused(&tp->t_outq);
1004 xt->xt_outlow = tp->t_outlow;
1005 xt->xt_column = tp->t_column;
1006 xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1007 xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0;
1008 xt->xt_flags = tp->t_flags;
1009 xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV;
1013 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
1015 unsigned long lsize;
1016 struct xtty *xtlist, *xt;
1020 sx_slock(&tty_list_sx);
1021 lsize = tty_list_count * sizeof(struct xtty);
1023 sx_sunlock(&tty_list_sx);
1027 xtlist = xt = malloc(lsize, M_TEMP, M_WAITOK);
1029 TAILQ_FOREACH(tp, &tty_list, t_list) {
1031 tty_to_xtty(tp, xt);
1035 sx_sunlock(&tty_list_sx);
1037 error = SYSCTL_OUT(req, xtlist, lsize);
1038 free(xtlist, M_TEMP);
1042 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
1043 0, 0, sysctl_kern_ttys, "S,xtty", "List of TTYs");
1046 * Device node creation. Device has been set up, now we can expose it to
1051 tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
1055 const char *prefix = "tty";
1056 char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */
1061 /* Remove "tty" prefix from devices like PTY's. */
1062 if (tp->t_flags & TF_NOPREFIX)
1066 vsnrprintf(name, sizeof name, 32, fmt, ap);
1070 /* System device. */
1073 mode = S_IRUSR|S_IWUSR;
1076 uid = cred->cr_ruid;
1078 mode = S_IRUSR|S_IWUSR|S_IWGRP;
1081 /* Master call-in device. */
1082 dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1083 uid, gid, mode, "%s%s", prefix, name);
1087 /* Slave call-in devices. */
1088 if (tp->t_flags & TF_INITLOCK) {
1089 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1090 uid, gid, mode, "%s%s.init", prefix, name);
1091 dev_depends(tp->t_dev, dev);
1093 dev->si_drv2 = &tp->t_termios_init_in;
1095 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1096 uid, gid, mode, "%s%s.lock", prefix, name);
1097 dev_depends(tp->t_dev, dev);
1099 dev->si_drv2 = &tp->t_termios_lock_in;
1102 /* Call-out devices. */
1103 if (tp->t_flags & TF_CALLOUT) {
1104 dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1105 UID_UUCP, GID_DIALER, 0660, "cua%s", name);
1106 dev_depends(tp->t_dev, dev);
1109 /* Slave call-out devices. */
1110 if (tp->t_flags & TF_INITLOCK) {
1111 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1112 UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
1113 dev_depends(tp->t_dev, dev);
1115 dev->si_drv2 = &tp->t_termios_init_out;
1117 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1118 UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
1119 dev_depends(tp->t_dev, dev);
1121 dev->si_drv2 = &tp->t_termios_lock_out;
1127 * Signalling processes.
1131 tty_signal_sessleader(struct tty *tp, int sig)
1135 tty_lock_assert(tp, MA_OWNED);
1136 MPASS(sig >= 1 && sig < NSIG);
1138 /* Make signals start output again. */
1139 tp->t_flags &= ~TF_STOPPED;
1141 if (tp->t_session != NULL && tp->t_session->s_leader != NULL) {
1142 p = tp->t_session->s_leader;
1150 tty_signal_pgrp(struct tty *tp, int sig)
1152 tty_lock_assert(tp, MA_OWNED);
1153 MPASS(sig >= 1 && sig < NSIG);
1155 /* Make signals start output again. */
1156 tp->t_flags &= ~TF_STOPPED;
1158 if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
1160 if (tp->t_pgrp != NULL) {
1161 PGRP_LOCK(tp->t_pgrp);
1162 pgsignal(tp->t_pgrp, sig, 1);
1163 PGRP_UNLOCK(tp->t_pgrp);
1168 tty_wakeup(struct tty *tp, int flags)
1170 if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL)
1171 pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
1173 if (flags & FWRITE) {
1174 cv_broadcast(&tp->t_outwait);
1175 selwakeup(&tp->t_outpoll);
1176 KNOTE_LOCKED(&tp->t_outpoll.si_note, 0);
1178 if (flags & FREAD) {
1179 cv_broadcast(&tp->t_inwait);
1180 selwakeup(&tp->t_inpoll);
1181 KNOTE_LOCKED(&tp->t_inpoll.si_note, 0);
1186 tty_wait(struct tty *tp, struct cv *cv)
1189 int revokecnt = tp->t_revokecnt;
1192 /* XXX: /dev/console also picks up Giant. */
1193 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1195 tty_lock_assert(tp, MA_OWNED);
1197 error = cv_wait_sig(cv, tp->t_mtx);
1199 /* Restart the system call when we may have been revoked. */
1200 if (tp->t_revokecnt != revokecnt)
1203 /* Bail out when the device slipped away. */
1211 tty_timedwait(struct tty *tp, struct cv *cv, int hz)
1214 int revokecnt = tp->t_revokecnt;
1217 /* XXX: /dev/console also picks up Giant. */
1218 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1220 tty_lock_assert(tp, MA_OWNED);
1222 error = cv_timedwait_sig(cv, tp->t_mtx, hz);
1224 /* Restart the system call when we may have been revoked. */
1225 if (tp->t_revokecnt != revokecnt)
1228 /* Bail out when the device slipped away. */
1236 tty_flush(struct tty *tp, int flags)
1238 if (flags & FWRITE) {
1239 tp->t_flags &= ~TF_HIWAT_OUT;
1240 ttyoutq_flush(&tp->t_outq);
1241 tty_wakeup(tp, FWRITE);
1243 if (flags & FREAD) {
1244 tty_hiwat_in_unblock(tp);
1245 ttyinq_flush(&tp->t_inq);
1246 ttydevsw_inwakeup(tp);
1251 tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1258 * The SER_* and TIOCM_* flags are the same, but one bit
1259 * shifted. I don't know why.
1262 ttydevsw_modem(tp, SER_DTR, 0);
1265 ttydevsw_modem(tp, 0, SER_DTR);
1268 int bits = *(int *)data;
1270 (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1,
1271 ((~bits) & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1275 int bits = *(int *)data;
1276 ttydevsw_modem(tp, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 0);
1280 int bits = *(int *)data;
1281 ttydevsw_modem(tp, 0, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1285 *(int *)data = TIOCM_LE + (ttydevsw_modem(tp, 0, 0) << 1);
1290 tp->t_flags |= TF_ASYNC;
1292 tp->t_flags &= ~TF_ASYNC;
1295 /* This device supports non-blocking operation. */
1298 *(int *)data = ttyinq_bytescanonicalized(&tp->t_inq);
1301 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1302 /* Not allowed to set ownership. */
1305 /* Temporarily unlock the TTY to set ownership. */
1307 error = fsetown(*(int *)data, &tp->t_sigio);
1311 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1312 /* Not allowed to set ownership. */
1315 /* Get ownership. */
1316 *(int *)data = fgetown(&tp->t_sigio);
1319 /* Obtain terminal flags through tcgetattr(). */
1320 bcopy(&tp->t_termios, data, sizeof(struct termios));
1325 struct termios *t = data;
1328 * Who makes up these funny rules? According to POSIX,
1329 * input baud rate is set equal to the output baud rate
1332 if (t->c_ispeed == 0)
1333 t->c_ispeed = t->c_ospeed;
1335 /* Don't allow invalid flags to be set. */
1336 if ((t->c_iflag & ~TTYSUP_IFLAG) != 0 ||
1337 (t->c_oflag & ~TTYSUP_OFLAG) != 0 ||
1338 (t->c_lflag & ~TTYSUP_LFLAG) != 0 ||
1339 (t->c_cflag & ~TTYSUP_CFLAG) != 0)
1342 /* Set terminal flags through tcsetattr(). */
1343 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1344 error = tty_drain(tp);
1347 if (cmd == TIOCSETAF)
1348 tty_flush(tp, FREAD);
1352 * Only call param() when the flags really change.
1354 if ((t->c_cflag & CIGNORE) == 0 &&
1355 (tp->t_termios.c_cflag != t->c_cflag ||
1356 tp->t_termios.c_ispeed != t->c_ispeed ||
1357 tp->t_termios.c_ospeed != t->c_ospeed)) {
1358 error = ttydevsw_param(tp, t);
1364 tp->t_termios.c_cflag = t->c_cflag;
1365 tp->t_termios.c_ispeed = t->c_ispeed;
1366 tp->t_termios.c_ospeed = t->c_ospeed;
1368 /* Baud rate has changed - update watermarks. */
1372 /* Copy new non-device driver parameters. */
1373 tp->t_termios.c_iflag = t->c_iflag;
1374 tp->t_termios.c_oflag = t->c_oflag;
1375 tp->t_termios.c_lflag = t->c_lflag;
1376 bcopy(t->c_cc, &tp->t_termios.c_cc, sizeof(t->c_cc));
1378 ttydisc_optimize(tp);
1380 if ((t->c_lflag & ICANON) == 0) {
1382 * When in non-canonical mode, wake up all
1383 * readers. Canonicalize any partial input. VMIN
1384 * and VTIME could also be adjusted.
1386 ttyinq_canonicalize(&tp->t_inq);
1387 tty_wakeup(tp, FREAD);
1392 /* For compatibility - we only support TTYDISC. */
1393 *(int *)data = TTYDISC;
1396 if (!tty_is_ctty(tp, td->td_proc))
1399 if (tp->t_pgrp != NULL)
1400 *(int *)data = tp->t_pgrp->pg_id;
1402 *(int *)data = NO_PID;
1405 if (!tty_is_ctty(tp, td->td_proc))
1408 MPASS(tp->t_session);
1409 *(int *)data = tp->t_session->s_sid;
1412 struct proc *p = td->td_proc;
1414 /* XXX: This looks awful. */
1416 sx_xlock(&proctree_lock);
1419 if (!SESS_LEADER(p)) {
1420 /* Only the session leader may do this. */
1421 sx_xunlock(&proctree_lock);
1425 if (tp->t_session != NULL && tp->t_session == p->p_session) {
1426 /* This is already our controlling TTY. */
1427 sx_xunlock(&proctree_lock);
1431 if (!SESS_LEADER(p) || p->p_session->s_ttyvp != NULL ||
1432 (tp->t_session != NULL && tp->t_session->s_ttyvp != NULL)) {
1434 * There is already a relation between a TTY and
1435 * a session, or the caller is not the session
1438 * Allow the TTY to be stolen when the vnode is
1439 * NULL, but the reference to the TTY is still
1442 sx_xunlock(&proctree_lock);
1446 /* Connect the session to the TTY. */
1447 tp->t_session = p->p_session;
1448 tp->t_session->s_ttyp = tp;
1450 sx_xunlock(&proctree_lock);
1452 /* Assign foreground process group. */
1453 tp->t_pgrp = p->p_pgrp;
1455 p->p_flag |= P_CONTROLT;
1464 * XXX: Temporarily unlock the TTY to locate the process
1465 * group. This code would be lot nicer if we would ever
1466 * decompose proctree_lock.
1469 sx_slock(&proctree_lock);
1470 pg = pgfind(*(int *)data);
1473 if (pg == NULL || pg->pg_session != td->td_proc->p_session) {
1474 sx_sunlock(&proctree_lock);
1481 * Determine if this TTY is the controlling TTY after
1482 * relocking the TTY.
1484 if (!tty_is_ctty(tp, td->td_proc)) {
1485 sx_sunlock(&proctree_lock);
1489 sx_sunlock(&proctree_lock);
1491 /* Wake up the background process groups. */
1492 cv_broadcast(&tp->t_bgwait);
1496 int flags = *(int *)data;
1499 flags = (FREAD|FWRITE);
1501 flags &= (FREAD|FWRITE);
1502 tty_flush(tp, flags);
1506 /* Drain TTY output. */
1507 return tty_drain(tp);
1509 /* Set terminal as console TTY. */
1511 struct nameidata nd;
1515 * XXX: TTY won't slip away, but constty would
1516 * really need to be locked!
1520 if (constty == tp) {
1524 if (constty != NULL) {
1528 /* XXX: allow disconnected constty's to be stolen! */
1531 * Only allow this to work when the user can
1532 * open /dev/console.
1534 NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF|MPSAFE,
1535 UIO_SYSSPACE, "/dev/console", td);
1536 if ((error = namei(&nd)) != 0) {
1540 vfslocked = NDHASGIANT(&nd);
1541 NDFREE(&nd, NDF_ONLY_PNBUF);
1543 error = VOP_ACCESS(nd.ni_vp, VREAD, td->td_ucred, td);
1545 VFS_UNLOCK_GIANT(vfslocked);
1553 } else if (constty == tp) {
1558 /* Obtain window size. */
1559 bcopy(&tp->t_winsize, data, sizeof(struct winsize));
1562 /* Set window size. */
1563 if (bcmp(&tp->t_winsize, data, sizeof(struct winsize)) == 0)
1565 bcopy(data, &tp->t_winsize, sizeof(struct winsize));
1566 tty_signal_pgrp(tp, SIGWINCH);
1569 tp->t_flags |= TF_EXCLUDE;
1572 tp->t_flags &= ~TF_EXCLUDE;
1575 *(unsigned int *)data = ttyoutq_bytesused(&tp->t_outq);
1578 tp->t_flags |= TF_STOPPED;
1581 tp->t_flags &= ~TF_STOPPED;
1582 ttydevsw_outwakeup(tp);
1590 return tty_ioctl_compat(tp, cmd, data, td);
1591 #else /* !COMPAT_43TTY */
1593 #endif /* COMPAT_43TTY */
1597 tty_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1601 tty_lock_assert(tp, MA_OWNED);
1606 error = ttydevsw_ioctl(tp, cmd, data, td);
1607 if (error == ENOIOCTL)
1608 error = tty_generic_ioctl(tp, cmd, data, td);
1614 tty_udev(struct tty *tp)
1617 return dev2udev(tp->t_dev);
1623 tty_checkoutq(struct tty *tp)
1626 /* 256 bytes should be enough to print a log message. */
1627 return (ttyoutq_bytesleft(&tp->t_outq) >= 256);
1631 tty_hiwat_in_block(struct tty *tp)
1634 if ((tp->t_flags & TF_HIWAT_IN) == 0 &&
1635 tp->t_termios.c_iflag & IXOFF &&
1636 tp->t_termios.c_cc[VSTOP] != _POSIX_VDISABLE) {
1638 * Input flow control. Only enter the high watermark when we
1639 * can successfully store the VSTOP character.
1641 if (ttyoutq_write_nofrag(&tp->t_outq,
1642 &tp->t_termios.c_cc[VSTOP], 1) == 0)
1643 tp->t_flags |= TF_HIWAT_IN;
1645 /* No input flow control. */
1646 tp->t_flags |= TF_HIWAT_IN;
1651 tty_hiwat_in_unblock(struct tty *tp)
1654 if ((tp->t_flags & TF_HIWAT_IN) == 0 &&
1655 tp->t_termios.c_iflag & IXOFF &&
1656 tp->t_termios.c_cc[VSTART] != _POSIX_VDISABLE) {
1658 * Input flow control. Only leave the high watermark when we
1659 * can successfully store the VSTART character.
1661 if (ttyoutq_write_nofrag(&tp->t_outq,
1662 &tp->t_termios.c_cc[VSTART], 1) == 0)
1663 tp->t_flags &= ~TF_HIWAT_IN;
1665 /* No input flow control. */
1666 tp->t_flags &= ~TF_HIWAT_IN;
1670 ttydevsw_inwakeup(tp);
1673 #include "opt_ddb.h"
1675 #include <ddb/ddb.h>
1682 { TF_NOPREFIX, 'N' },
1684 { TF_INITLOCK, 'I' },
1685 { TF_CALLOUT, 'C' },
1687 /* Keep these together -> 'Oi' and 'Oo'. */
1689 { TF_OPENED_IN, 'i' },
1690 { TF_OPENED_OUT,'o' },
1693 { TF_OPENCLOSE, 'B' },
1695 { TF_LITERAL, 'L' },
1697 /* Keep these together -> 'Hi' and 'Ho'. */
1699 { TF_HIWAT_IN, 'i' },
1700 { TF_HIWAT_OUT, 'o' },
1702 { TF_STOPPED, 'S' },
1703 { TF_EXCLUDE, 'X' },
1710 /* DDB command to show TTY statistics. */
1711 DB_SHOW_COMMAND(ttys, db_show_ttys)
1717 /* Make the output look like `pstat -t'. */
1718 db_printf(" LINE INQ CAN LIN LOW OUTQ USE LOW "
1719 "COL SESS PGID STATE\n");
1721 TAILQ_FOREACH(tp, &tty_list, t_list) {
1722 isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE;
1723 osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE;
1725 db_printf("%10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
1728 tp->t_inq.ti_linestart - tp->t_inq.ti_begin,
1729 tp->t_inq.ti_end - tp->t_inq.ti_linestart,
1732 tp->t_outq.to_end - tp->t_outq.to_begin,
1733 osiz - tp->t_outlow,
1735 tp->t_session ? tp->t_session->s_sid : 0,
1736 tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
1739 for (i = j = 0; ttystates[i].flag; i++)
1740 if (tp->t_flags & ttystates[i].flag) {
1741 db_printf("%c", ttystates[i].val);