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_drain(struct tty *tp)
120 while (ttyoutq_bytesused(&tp->t_outq) > 0) {
121 ttydevsw_outwakeup(tp);
122 /* Could be handled synchronously. */
123 if (ttyoutq_bytesused(&tp->t_outq) == 0)
126 /* Wait for data to be drained. */
127 error = tty_wait(tp, &tp->t_outwait);
136 * Because the revoke() call already calls d_close() without making sure
137 * all threads are purged from the TTY, we can only destroy the buffers
138 * and such when the last thread leaves the TTY. ttydev_enter() and
139 * ttydev_leave() are called from within the cdev functions, to make
140 * sure we can garbage collect the TTY.
144 ttydev_enter(struct tty *tp)
148 if (tty_gone(tp) || !tty_opened(tp)) {
149 /* Device is already gone. */
158 ttydev_leave(struct tty *tp)
160 tty_lock_assert(tp, MA_OWNED);
162 if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) {
163 /* Device is still opened somewhere. */
168 tp->t_flags |= TF_OPENCLOSE;
170 /* Stop asynchronous I/O. */
171 funsetown(&tp->t_sigio);
173 /* Remove console TTY. */
177 /* Drain any output. */
178 MPASS((tp->t_flags & TF_STOPPED) == 0);
184 /* Destroy associated buffers already. */
185 ttyinq_free(&tp->t_inq);
187 ttyoutq_free(&tp->t_outq);
190 knlist_clear(&tp->t_inpoll.si_note, 1);
191 knlist_clear(&tp->t_outpoll.si_note, 1);
196 tp->t_flags &= ~TF_OPENCLOSE;
201 * Operations that are exposed through the character device in /dev.
204 ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
206 struct tty *tp = dev->si_drv1;
209 /* Disallow access when the TTY belongs to a different prison. */
210 if (dev->si_cred != NULL &&
211 dev->si_cred->cr_prison != td->td_ucred->cr_prison &&
212 priv_check(td, PRIV_TTY_PRISON)) {
218 /* Device is already gone. */
223 * Prevent the TTY from being opened when being torn down or
224 * built up by unrelated processes.
226 if (tp->t_flags & TF_OPENCLOSE) {
230 tp->t_flags |= TF_OPENCLOSE;
233 * Make sure the "tty" and "cua" device cannot be opened at the
236 if (TTY_CALLOUT(tp, dev)) {
237 if (tp->t_flags & TF_OPENED_IN) {
242 if (tp->t_flags & TF_OPENED_OUT) {
248 if (tp->t_flags & TF_EXCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE)) {
253 if (!tty_opened(tp)) {
254 /* Set proper termios flags. */
255 if (TTY_CALLOUT(tp, dev)) {
256 tp->t_termios = tp->t_termios_init_out;
258 tp->t_termios = tp->t_termios_init_in;
260 ttydevsw_param(tp, &tp->t_termios);
262 ttydevsw_modem(tp, SER_DTR|SER_RTS, 0);
264 error = ttydevsw_open(tp);
272 /* Wait for Carrier Detect. */
273 if (!TTY_CALLOUT(tp, dev) && (oflags & O_NONBLOCK) == 0 &&
274 (tp->t_termios.c_cflag & CLOCAL) == 0) {
275 while ((ttydevsw_modem(tp, 0, 0) & SER_DCD) == 0) {
276 error = tty_wait(tp, &tp->t_dcdwait);
282 if (TTY_CALLOUT(tp, dev)) {
283 tp->t_flags |= TF_OPENED_OUT;
285 tp->t_flags |= TF_OPENED_IN;
288 done: tp->t_flags &= ~TF_OPENCLOSE;
294 ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
296 struct tty *tp = dev->si_drv1;
301 * This can only be called once. The callin and the callout
302 * devices cannot be opened at the same time.
304 MPASS((tp->t_flags & TF_OPENED) != TF_OPENED);
305 tp->t_flags &= ~(TF_OPENED|TF_EXCLUDE|TF_STOPPED);
307 /* Properly wake up threads that are stuck - revoke(). */
309 tty_wakeup(tp, FREAD|FWRITE);
310 cv_broadcast(&tp->t_bgwait);
318 tty_is_ctty(struct tty *tp, struct proc *p)
320 tty_lock_assert(tp, MA_OWNED);
322 return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT);
326 tty_wait_background(struct tty *tp, struct thread *td, int sig)
328 struct proc *p = td->td_proc;
332 MPASS(sig == SIGTTIN || sig == SIGTTOU);
333 tty_lock_assert(tp, MA_OWNED);
338 * The process should only sleep, when:
339 * - This terminal is the controling terminal
340 * - Its process group is not the foreground process
342 * - The parent process isn't waiting for the child to
344 * - the signal to send to the process isn't masked
346 if (!tty_is_ctty(tp, p) ||
347 p->p_pgrp == tp->t_pgrp || p->p_flag & P_PPWAIT ||
348 SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) ||
349 SIGISMEMBER(td->td_sigmask, sig)) {
350 /* Allow the action to happen. */
356 * Send the signal and sleep until we're the new
357 * foreground process group.
361 if (pg->pg_jobc == 0)
364 pgsignal(pg, sig, 1);
367 error = tty_wait(tp, &tp->t_bgwait);
374 ttydev_read(struct cdev *dev, struct uio *uio, int ioflag)
376 struct tty *tp = dev->si_drv1;
379 error = ttydev_enter(tp);
383 error = tty_wait_background(tp, curthread, SIGTTIN);
387 error = ttydisc_read(tp, uio, ioflag);
388 done: ttydev_leave(tp);
391 * The read() and write() calls should not throw an error when
392 * the device is ripped offline.
401 ttydev_write(struct cdev *dev, struct uio *uio, int ioflag)
403 struct tty *tp = dev->si_drv1;
406 error = ttydev_enter(tp);
410 if (tp->t_termios.c_lflag & TOSTOP) {
411 error = tty_wait_background(tp, curthread, SIGTTOU);
416 error = ttydisc_write(tp, uio, ioflag);
417 done: ttydev_leave(tp);
420 * The read() and write() calls should not throw an error when
421 * the device is ripped offline.
430 ttydev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
433 struct tty *tp = dev->si_drv1;
436 error = ttydev_enter(tp);
471 #endif /* COMPAT_43TTY */
473 * If the ioctl() causes the TTY to be modified, let it
474 * wait in the background.
476 error = tty_wait_background(tp, curthread, SIGTTOU);
481 error = tty_ioctl(tp, cmd, data, td);
482 done: ttydev_leave(tp);
488 ttydev_poll(struct cdev *dev, int events, struct thread *td)
490 struct tty *tp = dev->si_drv1;
491 int error, revents = 0;
493 error = ttydev_enter(tp);
495 /* Don't return the error here, but the event mask. */
497 (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
500 if (events & (POLLIN|POLLRDNORM)) {
501 /* See if we can read something. */
502 if (ttydisc_read_poll(tp) > 0)
503 revents |= events & (POLLIN|POLLRDNORM);
505 if (events & (POLLOUT|POLLWRNORM)) {
506 /* See if we can write something. */
507 if (ttydisc_write_poll(tp) > 0)
508 revents |= events & (POLLOUT|POLLWRNORM);
510 if (tp->t_flags & TF_ZOMBIE)
511 /* Hangup flag on zombie state. */
512 revents |= events & POLLHUP;
515 if (events & (POLLIN|POLLRDNORM))
516 selrecord(td, &tp->t_inpoll);
517 if (events & (POLLOUT|POLLWRNORM))
518 selrecord(td, &tp->t_outpoll);
527 ttydev_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
529 struct tty *tp = dev->si_drv1;
532 /* Handle mmap() through the driver. */
534 error = ttydev_enter(tp);
537 error = ttydevsw_mmap(tp, offset, paddr, nprot);
548 tty_kqops_read_detach(struct knote *kn)
550 struct tty *tp = kn->kn_hook;
552 knlist_remove(&tp->t_inpoll.si_note, kn, 0);
556 tty_kqops_read_event(struct knote *kn, long hint)
558 struct tty *tp = kn->kn_hook;
560 tty_lock_assert(tp, MA_OWNED);
562 if (tty_gone(tp) || tp->t_flags & TF_ZOMBIE) {
563 kn->kn_flags |= EV_EOF;
566 kn->kn_data = ttydisc_read_poll(tp);
567 return (kn->kn_data > 0);
572 tty_kqops_write_detach(struct knote *kn)
574 struct tty *tp = kn->kn_hook;
576 knlist_remove(&tp->t_outpoll.si_note, kn, 0);
580 tty_kqops_write_event(struct knote *kn, long hint)
582 struct tty *tp = kn->kn_hook;
584 tty_lock_assert(tp, MA_OWNED);
587 kn->kn_flags |= EV_EOF;
590 kn->kn_data = ttydisc_write_poll(tp);
591 return (kn->kn_data > 0);
595 static struct filterops tty_kqops_read =
596 { 1, NULL, tty_kqops_read_detach, tty_kqops_read_event };
597 static struct filterops tty_kqops_write =
598 { 1, NULL, tty_kqops_write_detach, tty_kqops_write_event };
601 ttydev_kqfilter(struct cdev *dev, struct knote *kn)
603 struct tty *tp = dev->si_drv1;
606 error = ttydev_enter(tp);
610 switch (kn->kn_filter) {
613 kn->kn_fop = &tty_kqops_read;
614 knlist_add(&tp->t_inpoll.si_note, kn, 1);
618 kn->kn_fop = &tty_kqops_write;
619 knlist_add(&tp->t_outpoll.si_note, kn, 1);
630 static struct cdevsw ttydev_cdevsw = {
631 .d_version = D_VERSION,
632 .d_open = ttydev_open,
633 .d_close = ttydev_close,
634 .d_read = ttydev_read,
635 .d_write = ttydev_write,
636 .d_ioctl = ttydev_ioctl,
637 .d_kqfilter = ttydev_kqfilter,
638 .d_poll = ttydev_poll,
639 .d_mmap = ttydev_mmap,
645 * Init/lock-state devices
649 ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
651 struct tty *tp = dev->si_drv1;
663 ttyil_close(struct cdev *dev, int flag, int mode, struct thread *td)
669 ttyil_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
675 ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
678 struct tty *tp = dev->si_drv1;
689 /* Obtain terminal flags through tcgetattr(). */
690 bcopy(dev->si_drv2, data, sizeof(struct termios));
693 /* Set terminal flags through tcsetattr(). */
694 error = priv_check(td, PRIV_TTY_SETA);
697 bcopy(data, dev->si_drv2, sizeof(struct termios));
700 *(int *)data = TTYDISC;
703 bzero(data, sizeof(struct winsize));
709 done: tty_unlock(tp);
713 static struct cdevsw ttyil_cdevsw = {
714 .d_version = D_VERSION,
715 .d_open = ttyil_open,
716 .d_close = ttyil_close,
717 .d_read = ttyil_rdwr,
718 .d_write = ttyil_rdwr,
719 .d_ioctl = ttyil_ioctl,
725 tty_init_termios(struct tty *tp)
727 struct termios *t = &tp->t_termios_init_in;
729 t->c_cflag = TTYDEF_CFLAG;
730 t->c_iflag = TTYDEF_IFLAG;
731 t->c_lflag = TTYDEF_LFLAG;
732 t->c_oflag = TTYDEF_OFLAG;
733 t->c_ispeed = TTYDEF_SPEED;
734 t->c_ospeed = TTYDEF_SPEED;
735 bcopy(ttydefchars, &t->c_cc, sizeof ttydefchars);
737 tp->t_termios_init_out = *t;
741 tty_init_console(struct tty *tp, speed_t s)
743 struct termios *ti = &tp->t_termios_init_in;
744 struct termios *to = &tp->t_termios_init_out;
747 ti->c_ispeed = ti->c_ospeed = s;
748 to->c_ispeed = to->c_ospeed = s;
751 ti->c_cflag |= CLOCAL;
752 to->c_cflag |= CLOCAL;
756 * Standard device routine implementations, mostly meant for
757 * pseudo-terminal device drivers. When a driver creates a new terminal
758 * device class, missing routines are patched.
762 ttydevsw_defopen(struct tty *tp)
769 ttydevsw_defclose(struct tty *tp)
774 ttydevsw_defoutwakeup(struct tty *tp)
777 panic("Terminal device has output, while not implemented");
781 ttydevsw_definwakeup(struct tty *tp)
786 ttydevsw_defioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
793 ttydevsw_defparam(struct tty *tp, struct termios *t)
796 /* Use a fake baud rate, we're not a real device. */
797 t->c_ispeed = t->c_ospeed = TTYDEF_SPEED_PSEUDO;
803 ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff)
806 /* Simulate a carrier to make the TTY layer happy. */
811 ttydevsw_defmmap(struct tty *tp, vm_offset_t offset, vm_paddr_t *paddr,
819 ttydevsw_deffree(void *softc)
822 panic("Terminal device freed without a free-handler");
826 * TTY allocation and deallocation. TTY devices can be deallocated when
827 * the driver doesn't use it anymore, when the TTY isn't a session's
828 * controlling TTY and when the device node isn't opened through devfs.
832 tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
836 /* Make sure the driver defines all routines. */
837 #define PATCH_FUNC(x) do { \
838 if (tsw->tsw_ ## x == NULL) \
839 tsw->tsw_ ## x = ttydevsw_def ## x; \
843 PATCH_FUNC(outwakeup);
844 PATCH_FUNC(inwakeup);
852 tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
855 tp->t_flags = tsw->tsw_flags;
857 tty_init_termios(tp);
859 cv_init(&tp->t_inwait, "tty input");
860 cv_init(&tp->t_outwait, "tty output");
861 cv_init(&tp->t_bgwait, "tty background");
862 cv_init(&tp->t_dcdwait, "tty dcd");
864 ttyinq_init(&tp->t_inq);
865 ttyoutq_init(&tp->t_outq);
867 /* Allow drivers to use a custom mutex to lock the TTY. */
871 tp->t_mtx = &tp->t_mtxobj;
872 mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
875 knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
876 knlist_init(&tp->t_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
878 sx_xlock(&tty_list_sx);
879 TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
881 sx_xunlock(&tty_list_sx);
887 tty_dealloc(void *arg)
889 struct tty *tp = arg;
891 sx_xlock(&tty_list_sx);
892 TAILQ_REMOVE(&tty_list, tp, t_list);
894 sx_xunlock(&tty_list_sx);
896 /* Make sure we haven't leaked buffers. */
897 MPASS(ttyinq_getsize(&tp->t_inq) == 0);
898 MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
900 knlist_destroy(&tp->t_inpoll.si_note);
901 knlist_destroy(&tp->t_outpoll.si_note);
903 cv_destroy(&tp->t_inwait);
904 cv_destroy(&tp->t_outwait);
905 cv_destroy(&tp->t_bgwait);
906 cv_destroy(&tp->t_dcdwait);
908 if (tp->t_mtx == &tp->t_mtxobj)
909 mtx_destroy(&tp->t_mtxobj);
915 tty_rel_free(struct tty *tp)
919 tty_lock_assert(tp, MA_OWNED);
921 if (tp->t_sessioncnt != 0 ||
922 (tp->t_flags & (TF_GONE|TF_OPENED)) != TF_GONE) {
923 /* TTY is still in use. */
928 /* TTY can be deallocated. */
933 destroy_dev_sched_cb(dev, tty_dealloc, tp);
937 tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
939 tty_lock_assert(tp, MA_OWNED);
941 if (tp->t_pgrp == pg)
946 tty_rel_sess(struct tty *tp, struct session *sess)
948 MPASS(tp->t_sessioncnt > 0);
950 /* Current session has left. */
951 if (tp->t_session == sess) {
952 tp->t_session = NULL;
953 MPASS(tp->t_pgrp == NULL);
960 tty_rel_gone(struct tty *tp)
962 MPASS(!tty_gone(tp));
964 /* Simulate carrier removal. */
965 ttydisc_modem(tp, 0);
967 /* Wake up misc. blocked threads. */
968 cv_broadcast(&tp->t_bgwait);
969 cv_broadcast(&tp->t_dcdwait);
971 tp->t_flags |= TF_GONE;
976 * Exposing information about current TTY's through sysctl
980 tty_to_xtty(struct tty *tp, struct xtty *xt)
982 tty_lock_assert(tp, MA_OWNED);
984 xt->xt_size = sizeof(struct xtty);
985 xt->xt_insize = ttyinq_getsize(&tp->t_inq);
986 xt->xt_incc = ttyinq_bytescanonicalized(&tp->t_inq);
987 xt->xt_inlc = ttyinq_bytesline(&tp->t_inq);
988 xt->xt_inlow = tp->t_inlow;
989 xt->xt_outsize = ttyoutq_getsize(&tp->t_outq);
990 xt->xt_outcc = ttyoutq_bytesused(&tp->t_outq);
991 xt->xt_outlow = tp->t_outlow;
992 xt->xt_column = tp->t_column;
993 xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
994 xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0;
995 xt->xt_flags = tp->t_flags;
996 xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV;
1000 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
1002 unsigned long lsize;
1003 struct xtty *xtlist, *xt;
1007 sx_slock(&tty_list_sx);
1008 lsize = tty_list_count * sizeof(struct xtty);
1010 sx_sunlock(&tty_list_sx);
1014 xtlist = xt = malloc(lsize, M_TEMP, M_WAITOK);
1016 TAILQ_FOREACH(tp, &tty_list, t_list) {
1018 tty_to_xtty(tp, xt);
1022 sx_sunlock(&tty_list_sx);
1024 error = SYSCTL_OUT(req, xtlist, lsize);
1025 free(xtlist, M_TEMP);
1029 SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
1030 0, 0, sysctl_kern_ttys, "S,xtty", "List of TTYs");
1033 * Device node creation. Device has been set up, now we can expose it to
1038 tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
1042 const char *prefix = "tty";
1043 char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */
1048 /* Remove "tty" prefix from devices like PTY's. */
1049 if (tp->t_flags & TF_NOPREFIX)
1053 vsnrprintf(name, sizeof name, 32, fmt, ap);
1057 /* System device. */
1060 mode = S_IRUSR|S_IWUSR;
1063 uid = cred->cr_ruid;
1065 mode = S_IRUSR|S_IWUSR|S_IWGRP;
1068 /* Master call-in device. */
1069 dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1070 uid, gid, mode, "%s%s", prefix, name);
1074 /* Slave call-in devices. */
1075 if (tp->t_flags & TF_INITLOCK) {
1076 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1077 uid, gid, mode, "%s%s.init", prefix, name);
1078 dev_depends(tp->t_dev, dev);
1080 dev->si_drv2 = &tp->t_termios_init_in;
1082 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1083 uid, gid, mode, "%s%s.lock", prefix, name);
1084 dev_depends(tp->t_dev, dev);
1086 dev->si_drv2 = &tp->t_termios_lock_in;
1089 /* Call-out devices. */
1090 if (tp->t_flags & TF_CALLOUT) {
1091 dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1092 UID_UUCP, GID_DIALER, 0660, "cua%s", name);
1093 dev_depends(tp->t_dev, dev);
1096 /* Slave call-out devices. */
1097 if (tp->t_flags & TF_INITLOCK) {
1098 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1099 UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
1100 dev_depends(tp->t_dev, dev);
1102 dev->si_drv2 = &tp->t_termios_init_out;
1104 dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1105 UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
1106 dev_depends(tp->t_dev, dev);
1108 dev->si_drv2 = &tp->t_termios_lock_out;
1114 * Signalling processes.
1118 tty_signal_sessleader(struct tty *tp, int sig)
1122 tty_lock_assert(tp, MA_OWNED);
1123 MPASS(sig >= 1 && sig < NSIG);
1125 /* Make signals start output again. */
1126 tp->t_flags &= ~TF_STOPPED;
1128 if (tp->t_session != NULL && tp->t_session->s_leader != NULL) {
1129 p = tp->t_session->s_leader;
1137 tty_signal_pgrp(struct tty *tp, int sig)
1139 tty_lock_assert(tp, MA_OWNED);
1140 MPASS(sig >= 1 && sig < NSIG);
1142 /* Make signals start output again. */
1143 tp->t_flags &= ~TF_STOPPED;
1145 if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
1147 if (tp->t_pgrp != NULL) {
1148 PGRP_LOCK(tp->t_pgrp);
1149 pgsignal(tp->t_pgrp, sig, 1);
1150 PGRP_UNLOCK(tp->t_pgrp);
1155 tty_wakeup(struct tty *tp, int flags)
1157 if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL)
1158 pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
1160 if (flags & FWRITE) {
1161 cv_broadcast(&tp->t_outwait);
1162 selwakeup(&tp->t_outpoll);
1163 KNOTE_LOCKED(&tp->t_outpoll.si_note, 0);
1165 if (flags & FREAD) {
1166 cv_broadcast(&tp->t_inwait);
1167 selwakeup(&tp->t_inpoll);
1168 KNOTE_LOCKED(&tp->t_inpoll.si_note, 0);
1173 tty_wait(struct tty *tp, struct cv *cv)
1176 int revokecnt = tp->t_revokecnt;
1179 /* XXX: /dev/console also picks up Giant. */
1180 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1182 tty_lock_assert(tp, MA_OWNED);
1184 error = cv_wait_sig(cv, tp->t_mtx);
1186 /* Restart the system call when we may have been revoked. */
1187 if (tp->t_revokecnt != revokecnt)
1190 /* Bail out when the device slipped away. */
1198 tty_timedwait(struct tty *tp, struct cv *cv, int hz)
1201 int revokecnt = tp->t_revokecnt;
1204 /* XXX: /dev/console also picks up Giant. */
1205 tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1207 tty_lock_assert(tp, MA_OWNED);
1209 error = cv_timedwait_sig(cv, tp->t_mtx, hz);
1211 /* Restart the system call when we may have been revoked. */
1212 if (tp->t_revokecnt != revokecnt)
1215 /* Bail out when the device slipped away. */
1223 tty_flush(struct tty *tp, int flags)
1225 if (flags & FWRITE) {
1226 tp->t_flags &= ~TF_HIWAT_OUT;
1227 ttyoutq_flush(&tp->t_outq);
1228 tty_wakeup(tp, FWRITE);
1230 if (flags & FREAD) {
1231 tty_hiwat_in_unblock(tp);
1232 ttyinq_flush(&tp->t_inq);
1233 ttydevsw_inwakeup(tp);
1238 tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1245 * The SER_* and TIOCM_* flags are the same, but one bit
1246 * shifted. I don't know why.
1249 ttydevsw_modem(tp, SER_DTR, 0);
1252 ttydevsw_modem(tp, 0, SER_DTR);
1255 int bits = *(int *)data;
1257 (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1,
1258 ((~bits) & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1262 int bits = *(int *)data;
1263 ttydevsw_modem(tp, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 0);
1267 int bits = *(int *)data;
1268 ttydevsw_modem(tp, 0, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1272 *(int *)data = TIOCM_LE + (ttydevsw_modem(tp, 0, 0) << 1);
1277 tp->t_flags |= TF_ASYNC;
1279 tp->t_flags &= ~TF_ASYNC;
1282 /* This device supports non-blocking operation. */
1285 *(int *)data = ttyinq_bytescanonicalized(&tp->t_inq);
1288 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1289 /* Not allowed to set ownership. */
1292 /* Temporarily unlock the TTY to set ownership. */
1294 error = fsetown(*(int *)data, &tp->t_sigio);
1298 if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1299 /* Not allowed to set ownership. */
1302 /* Get ownership. */
1303 *(int *)data = fgetown(&tp->t_sigio);
1306 /* Obtain terminal flags through tcgetattr(). */
1307 bcopy(&tp->t_termios, data, sizeof(struct termios));
1312 struct termios *t = data;
1315 * Who makes up these funny rules? According to POSIX,
1316 * input baud rate is set equal to the output baud rate
1319 if (t->c_ispeed == 0)
1320 t->c_ispeed = t->c_ospeed;
1322 /* Discard any unsupported bits. */
1323 t->c_iflag &= TTYSUP_IFLAG;
1324 t->c_oflag &= TTYSUP_OFLAG;
1325 t->c_lflag &= TTYSUP_LFLAG;
1326 t->c_cflag &= TTYSUP_CFLAG;
1328 /* Set terminal flags through tcsetattr(). */
1329 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1330 error = tty_drain(tp);
1333 if (cmd == TIOCSETAF)
1334 tty_flush(tp, FREAD);
1338 * Only call param() when the flags really change.
1340 if ((t->c_cflag & CIGNORE) == 0 &&
1341 (tp->t_termios.c_cflag != t->c_cflag ||
1342 tp->t_termios.c_ispeed != t->c_ispeed ||
1343 tp->t_termios.c_ospeed != t->c_ospeed)) {
1344 error = ttydevsw_param(tp, t);
1350 tp->t_termios.c_cflag = t->c_cflag & ~CIGNORE;
1351 tp->t_termios.c_ispeed = t->c_ispeed;
1352 tp->t_termios.c_ospeed = t->c_ospeed;
1354 /* Baud rate has changed - update watermarks. */
1358 /* Copy new non-device driver parameters. */
1359 tp->t_termios.c_iflag = t->c_iflag;
1360 tp->t_termios.c_oflag = t->c_oflag;
1361 tp->t_termios.c_lflag = t->c_lflag;
1362 bcopy(t->c_cc, &tp->t_termios.c_cc, sizeof(t->c_cc));
1364 ttydisc_optimize(tp);
1366 if ((t->c_lflag & ICANON) == 0) {
1368 * When in non-canonical mode, wake up all
1369 * readers. Canonicalize any partial input. VMIN
1370 * and VTIME could also be adjusted.
1372 ttyinq_canonicalize(&tp->t_inq);
1373 tty_wakeup(tp, FREAD);
1378 /* For compatibility - we only support TTYDISC. */
1379 *(int *)data = TTYDISC;
1382 if (!tty_is_ctty(tp, td->td_proc))
1385 if (tp->t_pgrp != NULL)
1386 *(int *)data = tp->t_pgrp->pg_id;
1388 *(int *)data = NO_PID;
1391 if (!tty_is_ctty(tp, td->td_proc))
1394 MPASS(tp->t_session);
1395 *(int *)data = tp->t_session->s_sid;
1398 struct proc *p = td->td_proc;
1400 /* XXX: This looks awful. */
1402 sx_xlock(&proctree_lock);
1405 if (!SESS_LEADER(p)) {
1406 /* Only the session leader may do this. */
1407 sx_xunlock(&proctree_lock);
1411 if (tp->t_session != NULL && tp->t_session == p->p_session) {
1412 /* This is already our controlling TTY. */
1413 sx_xunlock(&proctree_lock);
1417 if (!SESS_LEADER(p) || p->p_session->s_ttyvp != NULL ||
1418 (tp->t_session != NULL && tp->t_session->s_ttyvp != NULL)) {
1420 * There is already a relation between a TTY and
1421 * a session, or the caller is not the session
1424 * Allow the TTY to be stolen when the vnode is
1425 * NULL, but the reference to the TTY is still
1428 sx_xunlock(&proctree_lock);
1432 /* Connect the session to the TTY. */
1433 tp->t_session = p->p_session;
1434 tp->t_session->s_ttyp = tp;
1436 sx_xunlock(&proctree_lock);
1438 /* Assign foreground process group. */
1439 tp->t_pgrp = p->p_pgrp;
1441 p->p_flag |= P_CONTROLT;
1450 * XXX: Temporarily unlock the TTY to locate the process
1451 * group. This code would be lot nicer if we would ever
1452 * decompose proctree_lock.
1455 sx_slock(&proctree_lock);
1456 pg = pgfind(*(int *)data);
1459 if (pg == NULL || pg->pg_session != td->td_proc->p_session) {
1460 sx_sunlock(&proctree_lock);
1467 * Determine if this TTY is the controlling TTY after
1468 * relocking the TTY.
1470 if (!tty_is_ctty(tp, td->td_proc)) {
1471 sx_sunlock(&proctree_lock);
1475 sx_sunlock(&proctree_lock);
1477 /* Wake up the background process groups. */
1478 cv_broadcast(&tp->t_bgwait);
1482 int flags = *(int *)data;
1485 flags = (FREAD|FWRITE);
1487 flags &= (FREAD|FWRITE);
1488 tty_flush(tp, flags);
1492 /* Drain TTY output. */
1493 return tty_drain(tp);
1495 /* Set terminal as console TTY. */
1497 struct nameidata nd;
1501 * XXX: TTY won't slip away, but constty would
1502 * really need to be locked!
1506 if (constty == tp) {
1510 if (constty != NULL) {
1514 /* XXX: allow disconnected constty's to be stolen! */
1517 * Only allow this to work when the user can
1518 * open /dev/console.
1520 NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF|MPSAFE,
1521 UIO_SYSSPACE, "/dev/console", td);
1522 if ((error = namei(&nd)) != 0) {
1526 vfslocked = NDHASGIANT(&nd);
1527 NDFREE(&nd, NDF_ONLY_PNBUF);
1529 error = VOP_ACCESS(nd.ni_vp, VREAD, td->td_ucred, td);
1531 VFS_UNLOCK_GIANT(vfslocked);
1539 } else if (constty == tp) {
1544 /* Obtain window size. */
1545 bcopy(&tp->t_winsize, data, sizeof(struct winsize));
1548 /* Set window size. */
1549 if (bcmp(&tp->t_winsize, data, sizeof(struct winsize)) == 0)
1551 bcopy(data, &tp->t_winsize, sizeof(struct winsize));
1552 tty_signal_pgrp(tp, SIGWINCH);
1555 tp->t_flags |= TF_EXCLUDE;
1558 tp->t_flags &= ~TF_EXCLUDE;
1561 *(unsigned int *)data = ttyoutq_bytesused(&tp->t_outq);
1564 tp->t_flags |= TF_STOPPED;
1567 tp->t_flags &= ~TF_STOPPED;
1568 ttydevsw_outwakeup(tp);
1576 return tty_ioctl_compat(tp, cmd, data, td);
1577 #else /* !COMPAT_43TTY */
1579 #endif /* COMPAT_43TTY */
1583 tty_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1587 tty_lock_assert(tp, MA_OWNED);
1592 error = ttydevsw_ioctl(tp, cmd, data, td);
1593 if (error == ENOIOCTL)
1594 error = tty_generic_ioctl(tp, cmd, data, td);
1600 tty_udev(struct tty *tp)
1603 return dev2udev(tp->t_dev);
1609 tty_checkoutq(struct tty *tp)
1612 /* 256 bytes should be enough to print a log message. */
1613 return (ttyoutq_bytesleft(&tp->t_outq) >= 256);
1617 tty_hiwat_in_block(struct tty *tp)
1620 if ((tp->t_flags & TF_HIWAT_IN) == 0 &&
1621 tp->t_termios.c_iflag & IXOFF &&
1622 tp->t_termios.c_cc[VSTOP] != _POSIX_VDISABLE) {
1624 * Input flow control. Only enter the high watermark when we
1625 * can successfully store the VSTOP character.
1627 if (ttyoutq_write_nofrag(&tp->t_outq,
1628 &tp->t_termios.c_cc[VSTOP], 1) == 0)
1629 tp->t_flags |= TF_HIWAT_IN;
1631 /* No input flow control. */
1632 tp->t_flags |= TF_HIWAT_IN;
1637 tty_hiwat_in_unblock(struct tty *tp)
1640 if (tp->t_flags & TF_HIWAT_IN &&
1641 tp->t_termios.c_iflag & IXOFF &&
1642 tp->t_termios.c_cc[VSTART] != _POSIX_VDISABLE) {
1644 * Input flow control. Only leave the high watermark when we
1645 * can successfully store the VSTART character.
1647 if (ttyoutq_write_nofrag(&tp->t_outq,
1648 &tp->t_termios.c_cc[VSTART], 1) == 0)
1649 tp->t_flags &= ~TF_HIWAT_IN;
1651 /* No input flow control. */
1652 tp->t_flags &= ~TF_HIWAT_IN;
1656 ttydevsw_inwakeup(tp);
1659 #include "opt_ddb.h"
1661 #include <ddb/ddb.h>
1668 { TF_NOPREFIX, 'N' },
1670 { TF_INITLOCK, 'I' },
1671 { TF_CALLOUT, 'C' },
1673 /* Keep these together -> 'Oi' and 'Oo'. */
1675 { TF_OPENED_IN, 'i' },
1676 { TF_OPENED_OUT,'o' },
1679 { TF_OPENCLOSE, 'B' },
1681 { TF_LITERAL, 'L' },
1683 /* Keep these together -> 'Hi' and 'Ho'. */
1685 { TF_HIWAT_IN, 'i' },
1686 { TF_HIWAT_OUT, 'o' },
1688 { TF_STOPPED, 'S' },
1689 { TF_EXCLUDE, 'X' },
1696 /* DDB command to show TTY statistics. */
1697 DB_SHOW_COMMAND(ttys, db_show_ttys)
1703 /* Make the output look like `pstat -t'. */
1704 db_printf(" LINE INQ CAN LIN LOW OUTQ USE LOW "
1705 "COL SESS PGID STATE\n");
1707 TAILQ_FOREACH(tp, &tty_list, t_list) {
1708 isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE;
1709 osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE;
1711 db_printf("%10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
1714 tp->t_inq.ti_linestart - tp->t_inq.ti_begin,
1715 tp->t_inq.ti_end - tp->t_inq.ti_linestart,
1718 tp->t_outq.to_end - tp->t_outq.to_begin,
1719 osiz - tp->t_outlow,
1721 tp->t_session ? tp->t_session->s_sid : 0,
1722 tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
1725 for (i = j = 0; ttystates[i].flag; i++)
1726 if (tp->t_flags & ttystates[i].flag) {
1727 db_printf("%c", ttystates[i].val);