tty.c revision 183076
1/*-
2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Portions of this software were developed under sponsorship from Snow
6 * B.V., the Netherlands.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
16 *
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
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/kern/tty.c 183076 2008-09-16 14:57:23Z ed $");
32
33#include "opt_compat.h"
34
35#include <sys/param.h>
36#include <sys/conf.h>
37#include <sys/cons.h>
38#include <sys/fcntl.h>
39#include <sys/filio.h>
40#ifdef COMPAT_43TTY
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/poll.h>
48#include <sys/priv.h>
49#include <sys/proc.h>
50#include <sys/serial.h>
51#include <sys/signal.h>
52#include <sys/stat.h>
53#include <sys/sx.h>
54#include <sys/sysctl.h>
55#include <sys/systm.h>
56#include <sys/tty.h>
57#include <sys/ttycom.h>
58#define TTYDEFCHARS
59#include <sys/ttydefaults.h>
60#undef TTYDEFCHARS
61#include <sys/ucred.h>
62
63#include <machine/stdarg.h>
64
65static MALLOC_DEFINE(M_TTY, "tty", "tty device");
66
67static void tty_rel_free(struct tty *tp);
68
69static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list);
70static struct sx tty_list_sx;
71SX_SYSINIT(tty_list, &tty_list_sx, "tty list");
72static unsigned int tty_list_count = 0;
73
74/*
75 * Flags that are supported and stored by this implementation.
76 */
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)
86
87#define TTY_CALLOUT(tp,d) ((tp)->t_dev != (d))
88
89/*
90 * Set TTY buffer sizes.
91 */
92
93static void
94tty_watermarks(struct tty *tp)
95{
96	speed_t sp;
97
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);
101
102	/* Set low watermark at 10% (when 90% is available). */
103	tp->t_inlow = (ttyinq_getsize(&tp->t_inq) * 9) / 10;
104
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);
108
109	/* Set low watermark at 10% (when 90% is available). */
110	tp->t_outlow = (ttyoutq_getsize(&tp->t_outq) * 9) / 10;
111}
112
113static int
114tty_drain(struct tty *tp)
115{
116	int error;
117
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)
122			return (0);
123
124		/* Wait for data to be drained. */
125		error = tty_wait(tp, &tp->t_outwait);
126		if (error)
127			return (error);
128	}
129
130	return (0);
131}
132
133/*
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.
139 */
140
141static __inline int
142ttydev_enter(struct tty *tp)
143{
144	tty_lock(tp);
145
146	if (tty_gone(tp) || !tty_opened(tp)) {
147		/* Device is already gone. */
148		tty_unlock(tp);
149		return (ENXIO);
150	}
151
152	return (0);
153}
154
155static void
156ttydev_leave(struct tty *tp)
157{
158	tty_lock_assert(tp, MA_OWNED);
159
160	if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) {
161		/* Device is still opened somewhere. */
162		tty_unlock(tp);
163		return;
164	}
165
166	tp->t_flags |= TF_OPENCLOSE;
167
168	/* Stop asynchronous I/O. */
169	funsetown(&tp->t_sigio);
170
171	/* Remove console TTY. */
172	if (constty == tp)
173		constty_clear();
174
175	/* Drain any output. */
176	MPASS((tp->t_flags & TF_STOPPED) == 0);
177	if (!tty_gone(tp))
178		tty_drain(tp);
179
180	ttydisc_close(tp);
181
182	/* Destroy associated buffers already. */
183	ttyinq_free(&tp->t_inq);
184	tp->t_inlow = 0;
185	ttyoutq_free(&tp->t_outq);
186	tp->t_outlow = 0;
187
188	knlist_clear(&tp->t_inpoll.si_note, 1);
189	knlist_clear(&tp->t_outpoll.si_note, 1);
190
191	if (!tty_gone(tp))
192		ttydevsw_close(tp);
193
194	tp->t_flags &= ~TF_OPENCLOSE;
195	tty_rel_free(tp);
196}
197
198/*
199 * Operations that are exposed through the character device in /dev.
200 */
201static int
202ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
203{
204	struct tty *tp = dev->si_drv1;
205	int error;
206
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)) {
211		return (EPERM);
212	}
213
214	tty_lock(tp);
215	if (tty_gone(tp)) {
216		/* Device is already gone. */
217		tty_unlock(tp);
218		return (ENXIO);
219	}
220	/*
221	 * Prevent the TTY from being opened when being torn down or
222	 * built up by unrelated processes.
223	 */
224	if (tp->t_flags & TF_OPENCLOSE) {
225		tty_unlock(tp);
226		return (EBUSY);
227	}
228	tp->t_flags |= TF_OPENCLOSE;
229
230	/*
231	 * Make sure the "tty" and "cua" device cannot be opened at the
232	 * same time.
233	 */
234	if (TTY_CALLOUT(tp, dev)) {
235		if (tp->t_flags & TF_OPENED_IN) {
236			error = EBUSY;
237			goto done;
238		}
239	} else {
240		if (tp->t_flags & TF_OPENED_OUT) {
241			error = EBUSY;
242			goto done;
243		}
244	}
245
246	if (tp->t_flags & TF_EXCLUDE && priv_check(td, PRIV_TTY_EXCLUSIVE)) {
247		error = EBUSY;
248		goto done;
249	}
250
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;
255		} else {
256			tp->t_termios = tp->t_termios_init_in;
257		}
258		ttydevsw_param(tp, &tp->t_termios);
259
260		ttydevsw_modem(tp, SER_DTR|SER_RTS, 0);
261
262		error = ttydevsw_open(tp);
263		if (error != 0)
264			goto done;
265
266		ttydisc_open(tp);
267		tty_watermarks(tp);
268	}
269
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);
275			if (error != 0)
276				goto done;
277		}
278	}
279
280	if (TTY_CALLOUT(tp, dev)) {
281		tp->t_flags |= TF_OPENED_OUT;
282	} else {
283		tp->t_flags |= TF_OPENED_IN;
284	}
285
286done:	tp->t_flags &= ~TF_OPENCLOSE;
287	ttydev_leave(tp);
288	return (error);
289}
290
291static int
292ttydev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
293{
294	struct tty *tp = dev->si_drv1;
295
296	tty_lock(tp);
297
298	/*
299	 * This can only be called once. The callin and the callout
300	 * devices cannot be opened at the same time.
301	 */
302	MPASS((tp->t_flags & TF_OPENED) != TF_OPENED);
303	tp->t_flags &= ~(TF_OPENED|TF_EXCLUDE|TF_STOPPED);
304
305	/* Properly wake up threads that are stuck - revoke(). */
306	tp->t_revokecnt++;
307	tty_wakeup(tp, FREAD|FWRITE);
308	cv_broadcast(&tp->t_bgwait);
309
310	ttydev_leave(tp);
311
312	return (0);
313}
314
315static __inline int
316tty_is_ctty(struct tty *tp, struct proc *p)
317{
318	tty_lock_assert(tp, MA_OWNED);
319
320	return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT);
321}
322
323static int
324tty_wait_background(struct tty *tp, struct thread *td, int sig)
325{
326	struct proc *p = td->td_proc;
327	struct pgrp *pg;
328	int error;
329
330	MPASS(sig == SIGTTIN || sig == SIGTTOU);
331	tty_lock_assert(tp, MA_OWNED);
332
333	for (;;) {
334		PROC_LOCK(p);
335		/*
336		 * The process should only sleep, when:
337		 * - This terminal is the controling terminal
338		 * - Its process group is not the foreground process
339		 *   group
340		 * - The parent process isn't waiting for the child to
341		 *   exit
342		 * - the signal to send to the process isn't masked
343		 */
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. */
349			PROC_UNLOCK(p);
350			return (0);
351		}
352
353		/*
354		 * Send the signal and sleep until we're the new
355		 * foreground process group.
356		 */
357		pg = p->p_pgrp;
358		PROC_UNLOCK(p);
359		if (pg->pg_jobc == 0)
360			return (EIO);
361		PGRP_LOCK(pg);
362		pgsignal(pg, sig, 1);
363		PGRP_UNLOCK(pg);
364
365		error = tty_wait(tp, &tp->t_bgwait);
366		if (error)
367			return (error);
368	}
369}
370
371static int
372ttydev_read(struct cdev *dev, struct uio *uio, int ioflag)
373{
374	struct tty *tp = dev->si_drv1;
375	int error;
376
377	error = ttydev_enter(tp);
378	if (error)
379		return (0);
380
381	error = tty_wait_background(tp, curthread, SIGTTIN);
382	if (error)
383		goto done;
384
385	error = ttydisc_read(tp, uio, ioflag);
386done:	ttydev_leave(tp);
387
388	/*
389	 * The read() and write() calls should not throw an error when
390	 * the device is ripped offline.
391	 */
392	if (error == ENXIO)
393		return (0);
394
395	return (error);
396}
397
398static int
399ttydev_write(struct cdev *dev, struct uio *uio, int ioflag)
400{
401	struct tty *tp = dev->si_drv1;
402	int error;
403
404	error = ttydev_enter(tp);
405	if (error)
406		return (0);
407
408	if (tp->t_termios.c_lflag & TOSTOP) {
409		error = tty_wait_background(tp, curthread, SIGTTOU);
410		if (error)
411			goto done;
412	}
413
414	error = ttydisc_write(tp, uio, ioflag);
415done:	ttydev_leave(tp);
416
417	/*
418	 * The read() and write() calls should not throw an error when
419	 * the device is ripped offline.
420	 */
421	if (error == ENXIO)
422		return (0);
423
424	return (error);
425}
426
427static int
428ttydev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
429    struct thread *td)
430{
431	struct tty *tp = dev->si_drv1;
432	int error;
433
434	error = ttydev_enter(tp);
435	if (error)
436		return (error);
437
438	switch (cmd) {
439	case TIOCCBRK:
440	case TIOCCONS:
441	case TIOCDRAIN:
442	case TIOCEXCL:
443	case TIOCFLUSH:
444	case TIOCNXCL:
445	case TIOCSBRK:
446	case TIOCSCTTY:
447	case TIOCSETA:
448	case TIOCSETAF:
449	case TIOCSETAW:
450	case TIOCSPGRP:
451	case TIOCSTART:
452	case TIOCSTAT:
453	case TIOCSTOP:
454	case TIOCSWINSZ:
455#if 0
456	case TIOCSDRAINWAIT:
457	case TIOCSETD:
458	case TIOCSTI:
459#endif
460#ifdef COMPAT_43TTY
461	case  TIOCLBIC:
462	case  TIOCLBIS:
463	case  TIOCLSET:
464	case  TIOCSETC:
465	case OTIOCSETD:
466	case  TIOCSETN:
467	case  TIOCSETP:
468	case  TIOCSLTC:
469#endif /* COMPAT_43TTY */
470		/*
471		 * If the ioctl() causes the TTY to be modified, let it
472		 * wait in the background.
473		 */
474		error = tty_wait_background(tp, curthread, SIGTTOU);
475		if (error)
476			goto done;
477	}
478
479	error = tty_ioctl(tp, cmd, data, td);
480done:	ttydev_leave(tp);
481
482	return (error);
483}
484
485static int
486ttydev_poll(struct cdev *dev, int events, struct thread *td)
487{
488	struct tty *tp = dev->si_drv1;
489	int error, revents = 0;
490
491	error = ttydev_enter(tp);
492	if (error) {
493		/* Don't return the error here, but the event mask. */
494		return (events &
495		    (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
496	}
497
498	if (events & (POLLIN|POLLRDNORM)) {
499		/* See if we can read something. */
500		if (ttydisc_read_poll(tp) > 0)
501			revents |= events & (POLLIN|POLLRDNORM);
502	}
503	if (events & (POLLOUT|POLLWRNORM)) {
504		/* See if we can write something. */
505		if (ttydisc_write_poll(tp) > 0)
506			revents |= events & (POLLOUT|POLLWRNORM);
507	}
508	if (tp->t_flags & TF_ZOMBIE)
509		/* Hangup flag on zombie state. */
510		revents |= events & POLLHUP;
511
512	if (revents == 0) {
513		if (events & (POLLIN|POLLRDNORM))
514			selrecord(td, &tp->t_inpoll);
515		if (events & (POLLOUT|POLLWRNORM))
516			selrecord(td, &tp->t_outpoll);
517	}
518
519	ttydev_leave(tp);
520
521	return (revents);
522}
523
524static int
525ttydev_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
526{
527	struct tty *tp = dev->si_drv1;
528	int error;
529
530	/* Handle mmap() through the driver. */
531
532	error = ttydev_enter(tp);
533	if (error)
534		return (-1);
535	error = ttydevsw_mmap(tp, offset, paddr, nprot);
536	ttydev_leave(tp);
537
538	return (error);
539}
540
541/*
542 * kqueue support.
543 */
544
545static void
546tty_kqops_read_detach(struct knote *kn)
547{
548	struct tty *tp = kn->kn_hook;
549
550	knlist_remove(&tp->t_inpoll.si_note, kn, 0);
551}
552
553static int
554tty_kqops_read_event(struct knote *kn, long hint)
555{
556	struct tty *tp = kn->kn_hook;
557
558	tty_lock_assert(tp, MA_OWNED);
559
560	if (tty_gone(tp) || tp->t_flags & TF_ZOMBIE) {
561		kn->kn_flags |= EV_EOF;
562		return (1);
563	} else {
564		kn->kn_data = ttydisc_read_poll(tp);
565		return (kn->kn_data > 0);
566	}
567}
568
569static void
570tty_kqops_write_detach(struct knote *kn)
571{
572	struct tty *tp = kn->kn_hook;
573
574	knlist_remove(&tp->t_outpoll.si_note, kn, 0);
575}
576
577static int
578tty_kqops_write_event(struct knote *kn, long hint)
579{
580	struct tty *tp = kn->kn_hook;
581
582	tty_lock_assert(tp, MA_OWNED);
583
584	if (tty_gone(tp)) {
585		kn->kn_flags |= EV_EOF;
586		return (1);
587	} else {
588		kn->kn_data = ttydisc_write_poll(tp);
589		return (kn->kn_data > 0);
590	}
591}
592
593static struct filterops tty_kqops_read =
594    { 1, NULL, tty_kqops_read_detach, tty_kqops_read_event };
595static struct filterops tty_kqops_write =
596    { 1, NULL, tty_kqops_write_detach, tty_kqops_write_event };
597
598static int
599ttydev_kqfilter(struct cdev *dev, struct knote *kn)
600{
601	struct tty *tp = dev->si_drv1;
602	int error;
603
604	error = ttydev_enter(tp);
605	if (error)
606		return (error);
607
608	switch (kn->kn_filter) {
609	case EVFILT_READ:
610		kn->kn_hook = tp;
611		kn->kn_fop = &tty_kqops_read;
612		knlist_add(&tp->t_inpoll.si_note, kn, 1);
613		break;
614	case EVFILT_WRITE:
615		kn->kn_hook = tp;
616		kn->kn_fop = &tty_kqops_write;
617		knlist_add(&tp->t_outpoll.si_note, kn, 1);
618		break;
619	default:
620		error = EINVAL;
621		break;
622	}
623
624	ttydev_leave(tp);
625	return (error);
626}
627
628static 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,
638	.d_name		= "ttydev",
639	.d_flags	= D_TTY,
640};
641
642/*
643 * Init/lock-state devices
644 */
645
646static int
647ttyil_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
648{
649	struct tty *tp = dev->si_drv1;
650	int error = 0;
651
652	tty_lock(tp);
653	if (tty_gone(tp))
654		error = ENODEV;
655	tty_unlock(tp);
656
657	return (error);
658}
659
660static int
661ttyil_close(struct cdev *dev, int flag, int mode, struct thread *td)
662{
663	return (0);
664}
665
666static int
667ttyil_rdwr(struct cdev *dev, struct uio *uio, int ioflag)
668{
669	return (ENODEV);
670}
671
672static int
673ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
674    struct thread *td)
675{
676	struct tty *tp = dev->si_drv1;
677	int error = 0;
678
679	tty_lock(tp);
680	if (tty_gone(tp)) {
681		error = ENODEV;
682		goto done;
683	}
684
685	switch (cmd) {
686	case TIOCGETA:
687		/* Obtain terminal flags through tcgetattr(). */
688		bcopy(dev->si_drv2, data, sizeof(struct termios));
689		break;
690	case TIOCSETA:
691		/* Set terminal flags through tcsetattr(). */
692		error = priv_check(td, PRIV_TTY_SETA);
693		if (error)
694			break;
695		bcopy(data, dev->si_drv2, sizeof(struct termios));
696		break;
697	case TIOCGETD:
698		*(int *)data = TTYDISC;
699		break;
700	case TIOCGWINSZ:
701		bzero(data, sizeof(struct winsize));
702		break;
703	default:
704		error = ENOTTY;
705	}
706
707done:	tty_unlock(tp);
708	return (error);
709}
710
711static 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,
718	.d_name		= "ttyil",
719	.d_flags	= D_TTY,
720};
721
722static void
723tty_init_termios(struct tty *tp)
724{
725	struct termios *t = &tp->t_termios_init_in;
726
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);
734
735	tp->t_termios_init_out = *t;
736}
737
738void
739tty_init_console(struct tty *tp, speed_t s)
740{
741	struct termios *ti = &tp->t_termios_init_in;
742	struct termios *to = &tp->t_termios_init_out;
743
744	if (s != 0) {
745		ti->c_ispeed = ti->c_ospeed = s;
746		to->c_ispeed = to->c_ospeed = s;
747	}
748
749	ti->c_cflag |= CLOCAL;
750	to->c_cflag |= CLOCAL;
751}
752
753/*
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.
757 */
758
759static int
760ttydevsw_defopen(struct tty *tp)
761{
762
763	return (0);
764}
765
766static void
767ttydevsw_defclose(struct tty *tp)
768{
769}
770
771static void
772ttydevsw_defoutwakeup(struct tty *tp)
773{
774
775	panic("Terminal device has output, while not implemented");
776}
777
778static void
779ttydevsw_definwakeup(struct tty *tp)
780{
781}
782
783static int
784ttydevsw_defioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
785{
786
787	return (ENOIOCTL);
788}
789
790static int
791ttydevsw_defparam(struct tty *tp, struct termios *t)
792{
793
794	/* Use a fake baud rate, we're not a real device. */
795	t->c_ispeed = t->c_ospeed = TTYDEF_SPEED_PSEUDO;
796
797	return (0);
798}
799
800static int
801ttydevsw_defmodem(struct tty *tp, int sigon, int sigoff)
802{
803
804	/* Simulate a carrier to make the TTY layer happy. */
805	return (SER_DCD);
806}
807
808static int
809ttydevsw_defmmap(struct tty *tp, vm_offset_t offset, vm_paddr_t *paddr,
810    int nprot)
811{
812
813	return (-1);
814}
815
816static void
817ttydevsw_defpktnotify(struct tty *tp, char event)
818{
819}
820
821static void
822ttydevsw_deffree(void *softc)
823{
824
825	panic("Terminal device freed without a free-handler");
826}
827
828/*
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.
832 */
833
834struct tty *
835tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
836{
837	struct tty *tp;
838
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;	\
843} while (0)
844	PATCH_FUNC(open);
845	PATCH_FUNC(close);
846	PATCH_FUNC(outwakeup);
847	PATCH_FUNC(inwakeup);
848	PATCH_FUNC(ioctl);
849	PATCH_FUNC(param);
850	PATCH_FUNC(modem);
851	PATCH_FUNC(mmap);
852	PATCH_FUNC(pktnotify);
853	PATCH_FUNC(free);
854#undef PATCH_FUNC
855
856	tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
857	tp->t_devsw = tsw;
858	tp->t_softc = sc;
859	tp->t_flags = tsw->tsw_flags;
860
861	tty_init_termios(tp);
862
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");
867
868	ttyinq_init(&tp->t_inq);
869	ttyoutq_init(&tp->t_outq);
870
871	/* Allow drivers to use a custom mutex to lock the TTY. */
872	if (mutex != NULL) {
873		tp->t_mtx = mutex;
874	} else {
875		tp->t_mtx = &tp->t_mtxobj;
876		mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
877	}
878
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);
881
882	sx_xlock(&tty_list_sx);
883	TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
884	tty_list_count++;
885	sx_xunlock(&tty_list_sx);
886
887	return (tp);
888}
889
890static void
891tty_dealloc(void *arg)
892{
893	struct tty *tp = arg;
894
895	sx_xlock(&tty_list_sx);
896	TAILQ_REMOVE(&tty_list, tp, t_list);
897	tty_list_count--;
898	sx_xunlock(&tty_list_sx);
899
900	/* Make sure we haven't leaked buffers. */
901	MPASS(ttyinq_getsize(&tp->t_inq) == 0);
902	MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
903
904	knlist_destroy(&tp->t_inpoll.si_note);
905	knlist_destroy(&tp->t_outpoll.si_note);
906
907	cv_destroy(&tp->t_inwait);
908	cv_destroy(&tp->t_outwait);
909	cv_destroy(&tp->t_bgwait);
910	cv_destroy(&tp->t_dcdwait);
911
912	if (tp->t_mtx == &tp->t_mtxobj)
913		mtx_destroy(&tp->t_mtxobj);
914	ttydevsw_free(tp);
915	free(tp, M_TTY);
916}
917
918static void
919tty_rel_free(struct tty *tp)
920{
921	struct cdev *dev;
922
923	tty_lock_assert(tp, MA_OWNED);
924
925	if (tp->t_sessioncnt != 0 ||
926	    (tp->t_flags & (TF_GONE|TF_OPENED)) != TF_GONE) {
927		/* TTY is still in use. */
928		tty_unlock(tp);
929		return;
930	}
931
932	/* TTY can be deallocated. */
933	dev = tp->t_dev;
934	tp->t_dev = NULL;
935	tty_unlock(tp);
936
937	destroy_dev_sched_cb(dev, tty_dealloc, tp);
938}
939
940void
941tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
942{
943	MPASS(tp->t_sessioncnt > 0);
944	tty_lock_assert(tp, MA_OWNED);
945
946	if (tp->t_pgrp == pg)
947		tp->t_pgrp = NULL;
948
949	tty_unlock(tp);
950}
951
952void
953tty_rel_sess(struct tty *tp, struct session *sess)
954{
955	MPASS(tp->t_sessioncnt > 0);
956
957	/* Current session has left. */
958	if (tp->t_session == sess) {
959		tp->t_session = NULL;
960		MPASS(tp->t_pgrp == NULL);
961	}
962	tp->t_sessioncnt--;
963	tty_rel_free(tp);
964}
965
966void
967tty_rel_gone(struct tty *tp)
968{
969	MPASS(!tty_gone(tp));
970
971	/* Simulate carrier removal. */
972	ttydisc_modem(tp, 0);
973
974	/* Wake up misc. blocked threads. */
975	cv_broadcast(&tp->t_bgwait);
976	cv_broadcast(&tp->t_dcdwait);
977
978	tp->t_flags |= TF_GONE;
979	tty_rel_free(tp);
980}
981
982/*
983 * Exposing information about current TTY's through sysctl
984 */
985
986static void
987tty_to_xtty(struct tty *tp, struct xtty *xt)
988{
989	tty_lock_assert(tp, MA_OWNED);
990
991	xt->xt_size = sizeof(struct xtty);
992	xt->xt_insize = ttyinq_getsize(&tp->t_inq);
993	xt->xt_incc = ttyinq_bytescanonicalized(&tp->t_inq);
994	xt->xt_inlc = ttyinq_bytesline(&tp->t_inq);
995	xt->xt_inlow = tp->t_inlow;
996	xt->xt_outsize = ttyoutq_getsize(&tp->t_outq);
997	xt->xt_outcc = ttyoutq_bytesused(&tp->t_outq);
998	xt->xt_outlow = tp->t_outlow;
999	xt->xt_column = tp->t_column;
1000	xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1001	xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0;
1002	xt->xt_flags = tp->t_flags;
1003	xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV;
1004}
1005
1006static int
1007sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
1008{
1009	unsigned long lsize;
1010	struct xtty *xtlist, *xt;
1011	struct tty *tp;
1012	int error;
1013
1014	sx_slock(&tty_list_sx);
1015	lsize = tty_list_count * sizeof(struct xtty);
1016	if (lsize == 0) {
1017		sx_sunlock(&tty_list_sx);
1018		return (0);
1019	}
1020
1021	xtlist = xt = malloc(lsize, M_TEMP, M_WAITOK);
1022
1023	TAILQ_FOREACH(tp, &tty_list, t_list) {
1024		tty_lock(tp);
1025		tty_to_xtty(tp, xt);
1026		tty_unlock(tp);
1027		xt++;
1028	}
1029	sx_sunlock(&tty_list_sx);
1030
1031	error = SYSCTL_OUT(req, xtlist, lsize);
1032	free(xtlist, M_TEMP);
1033	return (error);
1034}
1035
1036SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
1037	0, 0, sysctl_kern_ttys, "S,xtty", "List of TTYs");
1038
1039/*
1040 * Device node creation. Device has been set up, now we can expose it to
1041 * the user.
1042 */
1043
1044void
1045tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
1046{
1047	va_list ap;
1048	struct cdev *dev;
1049	const char *prefix = "tty";
1050	char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */
1051	uid_t uid;
1052	gid_t gid;
1053	mode_t mode;
1054
1055	/* Remove "tty" prefix from devices like PTY's. */
1056	if (tp->t_flags & TF_NOPREFIX)
1057		prefix = "";
1058
1059	va_start(ap, fmt);
1060	vsnrprintf(name, sizeof name, 32, fmt, ap);
1061	va_end(ap);
1062
1063	if (cred == NULL) {
1064		/* System device. */
1065		uid = UID_ROOT;
1066		gid = GID_WHEEL;
1067		mode = S_IRUSR|S_IWUSR;
1068	} else {
1069		/* User device. */
1070		uid = cred->cr_ruid;
1071		gid = GID_TTY;
1072		mode = S_IRUSR|S_IWUSR|S_IWGRP;
1073	}
1074
1075	/* Master call-in device. */
1076	dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1077	    uid, gid, mode, "%s%s", prefix, name);
1078	dev->si_drv1 = tp;
1079	tp->t_dev = dev;
1080
1081	/* Slave call-in devices. */
1082	if (tp->t_flags & TF_INITLOCK) {
1083		dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1084		    uid, gid, mode, "%s%s.init", prefix, name);
1085		dev_depends(tp->t_dev, dev);
1086		dev->si_drv1 = tp;
1087		dev->si_drv2 = &tp->t_termios_init_in;
1088
1089		dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1090		    uid, gid, mode, "%s%s.lock", prefix, name);
1091		dev_depends(tp->t_dev, dev);
1092		dev->si_drv1 = tp;
1093		dev->si_drv2 = &tp->t_termios_lock_in;
1094	}
1095
1096	/* Call-out devices. */
1097	if (tp->t_flags & TF_CALLOUT) {
1098		dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1099		    UID_UUCP, GID_DIALER, 0660, "cua%s", name);
1100		dev_depends(tp->t_dev, dev);
1101		dev->si_drv1 = tp;
1102
1103		/* Slave call-out devices. */
1104		if (tp->t_flags & TF_INITLOCK) {
1105			dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1106			    UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
1107			dev_depends(tp->t_dev, dev);
1108			dev->si_drv1 = tp;
1109			dev->si_drv2 = &tp->t_termios_init_out;
1110
1111			dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1112			    UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
1113			dev_depends(tp->t_dev, dev);
1114			dev->si_drv1 = tp;
1115			dev->si_drv2 = &tp->t_termios_lock_out;
1116		}
1117	}
1118}
1119
1120/*
1121 * Signalling processes.
1122 */
1123
1124void
1125tty_signal_sessleader(struct tty *tp, int sig)
1126{
1127	struct proc *p;
1128
1129	tty_lock_assert(tp, MA_OWNED);
1130	MPASS(sig >= 1 && sig < NSIG);
1131
1132	/* Make signals start output again. */
1133	tp->t_flags &= ~TF_STOPPED;
1134
1135	if (tp->t_session != NULL && tp->t_session->s_leader != NULL) {
1136		p = tp->t_session->s_leader;
1137		PROC_LOCK(p);
1138		psignal(p, sig);
1139		PROC_UNLOCK(p);
1140	}
1141}
1142
1143void
1144tty_signal_pgrp(struct tty *tp, int sig)
1145{
1146	tty_lock_assert(tp, MA_OWNED);
1147	MPASS(sig >= 1 && sig < NSIG);
1148
1149	/* Make signals start output again. */
1150	tp->t_flags &= ~TF_STOPPED;
1151
1152	if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
1153		tty_info(tp);
1154	if (tp->t_pgrp != NULL) {
1155		PGRP_LOCK(tp->t_pgrp);
1156		pgsignal(tp->t_pgrp, sig, 1);
1157		PGRP_UNLOCK(tp->t_pgrp);
1158	}
1159}
1160
1161void
1162tty_wakeup(struct tty *tp, int flags)
1163{
1164	if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL)
1165		pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
1166
1167	if (flags & FWRITE) {
1168		cv_broadcast(&tp->t_outwait);
1169		selwakeup(&tp->t_outpoll);
1170		KNOTE_LOCKED(&tp->t_outpoll.si_note, 0);
1171	}
1172	if (flags & FREAD) {
1173		cv_broadcast(&tp->t_inwait);
1174		selwakeup(&tp->t_inpoll);
1175		KNOTE_LOCKED(&tp->t_inpoll.si_note, 0);
1176	}
1177}
1178
1179int
1180tty_wait(struct tty *tp, struct cv *cv)
1181{
1182	int error;
1183	int revokecnt = tp->t_revokecnt;
1184
1185#if 0
1186	/* XXX: /dev/console also picks up Giant. */
1187	tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1188#endif
1189	tty_lock_assert(tp, MA_OWNED);
1190
1191	error = cv_wait_sig(cv, tp->t_mtx);
1192
1193	/* Restart the system call when we may have been revoked. */
1194	if (tp->t_revokecnt != revokecnt)
1195		return (ERESTART);
1196
1197	/* Bail out when the device slipped away. */
1198	if (tty_gone(tp))
1199		return (ENXIO);
1200
1201	return (error);
1202}
1203
1204int
1205tty_timedwait(struct tty *tp, struct cv *cv, int hz)
1206{
1207	int error;
1208	int revokecnt = tp->t_revokecnt;
1209
1210#if 0
1211	/* XXX: /dev/console also picks up Giant. */
1212	tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1213#endif
1214	tty_lock_assert(tp, MA_OWNED);
1215
1216	error = cv_timedwait_sig(cv, tp->t_mtx, hz);
1217
1218	/* Restart the system call when we may have been revoked. */
1219	if (tp->t_revokecnt != revokecnt)
1220		return (ERESTART);
1221
1222	/* Bail out when the device slipped away. */
1223	if (tty_gone(tp))
1224		return (ENXIO);
1225
1226	return (error);
1227}
1228
1229void
1230tty_flush(struct tty *tp, int flags)
1231{
1232	if (flags & FWRITE) {
1233		tp->t_flags &= ~TF_HIWAT_OUT;
1234		ttyoutq_flush(&tp->t_outq);
1235		tty_wakeup(tp, FWRITE);
1236		ttydevsw_pktnotify(tp, TIOCPKT_FLUSHWRITE);
1237	}
1238	if (flags & FREAD) {
1239		tty_hiwat_in_unblock(tp);
1240		ttyinq_flush(&tp->t_inq);
1241		ttydevsw_inwakeup(tp);
1242		ttydevsw_pktnotify(tp, TIOCPKT_FLUSHREAD);
1243	}
1244}
1245
1246static int
1247tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1248{
1249	int error;
1250
1251	switch (cmd) {
1252	/*
1253	 * Modem commands.
1254	 * The SER_* and TIOCM_* flags are the same, but one bit
1255	 * shifted. I don't know why.
1256	 */
1257	case TIOCSDTR:
1258		ttydevsw_modem(tp, SER_DTR, 0);
1259		return (0);
1260	case TIOCCDTR:
1261		ttydevsw_modem(tp, 0, SER_DTR);
1262		return (0);
1263	case TIOCMSET: {
1264		int bits = *(int *)data;
1265		ttydevsw_modem(tp,
1266		    (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1,
1267		    ((~bits) & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1268		return (0);
1269	}
1270	case TIOCMBIS: {
1271		int bits = *(int *)data;
1272		ttydevsw_modem(tp, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 0);
1273		return (0);
1274	}
1275	case TIOCMBIC: {
1276		int bits = *(int *)data;
1277		ttydevsw_modem(tp, 0, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1278		return (0);
1279	}
1280	case TIOCMGET:
1281		*(int *)data = TIOCM_LE + (ttydevsw_modem(tp, 0, 0) << 1);
1282		return (0);
1283
1284	case FIOASYNC:
1285		if (*(int *)data)
1286			tp->t_flags |= TF_ASYNC;
1287		else
1288			tp->t_flags &= ~TF_ASYNC;
1289		return (0);
1290	case FIONBIO:
1291		/* This device supports non-blocking operation. */
1292		return (0);
1293	case FIONREAD:
1294		*(int *)data = ttyinq_bytescanonicalized(&tp->t_inq);
1295		return (0);
1296	case FIOSETOWN:
1297		if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1298			/* Not allowed to set ownership. */
1299			return (ENOTTY);
1300
1301		/* Temporarily unlock the TTY to set ownership. */
1302		tty_unlock(tp);
1303		error = fsetown(*(int *)data, &tp->t_sigio);
1304		tty_lock(tp);
1305		return (error);
1306	case FIOGETOWN:
1307		if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1308			/* Not allowed to set ownership. */
1309			return (ENOTTY);
1310
1311		/* Get ownership. */
1312		*(int *)data = fgetown(&tp->t_sigio);
1313		return (0);
1314	case TIOCGETA:
1315		/* Obtain terminal flags through tcgetattr(). */
1316		bcopy(&tp->t_termios, data, sizeof(struct termios));
1317		return (0);
1318	case TIOCSETA:
1319	case TIOCSETAW:
1320	case TIOCSETAF: {
1321		struct termios *t = data;
1322
1323		/*
1324		 * Who makes up these funny rules? According to POSIX,
1325		 * input baud rate is set equal to the output baud rate
1326		 * when zero.
1327		 */
1328		if (t->c_ispeed == 0)
1329			t->c_ispeed = t->c_ospeed;
1330
1331		/* Discard any unsupported bits. */
1332		t->c_iflag &= TTYSUP_IFLAG;
1333		t->c_oflag &= TTYSUP_OFLAG;
1334		t->c_lflag &= TTYSUP_LFLAG;
1335		t->c_cflag &= TTYSUP_CFLAG;
1336
1337		/* Set terminal flags through tcsetattr(). */
1338		if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1339			error = tty_drain(tp);
1340			if (error)
1341				return (error);
1342			if (cmd == TIOCSETAF)
1343				tty_flush(tp, FREAD);
1344		}
1345
1346		/*
1347		 * Only call param() when the flags really change.
1348		 */
1349		if ((t->c_cflag & CIGNORE) == 0 &&
1350		    (tp->t_termios.c_cflag != t->c_cflag ||
1351		    tp->t_termios.c_ispeed != t->c_ispeed ||
1352		    tp->t_termios.c_ospeed != t->c_ospeed)) {
1353			error = ttydevsw_param(tp, t);
1354			if (error)
1355				return (error);
1356
1357			/* XXX: CLOCAL? */
1358
1359			tp->t_termios.c_cflag = t->c_cflag & ~CIGNORE;
1360			tp->t_termios.c_ispeed = t->c_ispeed;
1361			tp->t_termios.c_ospeed = t->c_ospeed;
1362
1363			/* Baud rate has changed - update watermarks. */
1364			tty_watermarks(tp);
1365		}
1366
1367		/* Copy new non-device driver parameters. */
1368		tp->t_termios.c_iflag = t->c_iflag;
1369		tp->t_termios.c_oflag = t->c_oflag;
1370		tp->t_termios.c_lflag = t->c_lflag;
1371		bcopy(t->c_cc, &tp->t_termios.c_cc, sizeof(t->c_cc));
1372
1373		ttydisc_optimize(tp);
1374
1375		if ((t->c_lflag & ICANON) == 0) {
1376			/*
1377			 * When in non-canonical mode, wake up all
1378			 * readers. Canonicalize any partial input. VMIN
1379			 * and VTIME could also be adjusted.
1380			 */
1381			ttyinq_canonicalize(&tp->t_inq);
1382			tty_wakeup(tp, FREAD);
1383		}
1384
1385		/*
1386		 * For packet mode: notify the PTY consumer that VSTOP
1387		 * and VSTART may have been changed.
1388		 */
1389		if (tp->t_termios.c_iflag & IXON &&
1390		    tp->t_termios.c_cc[VSTOP] == CTRL('S') &&
1391		    tp->t_termios.c_cc[VSTART] == CTRL('Q'))
1392			ttydevsw_pktnotify(tp, TIOCPKT_DOSTOP);
1393		else
1394			ttydevsw_pktnotify(tp, TIOCPKT_NOSTOP);
1395		return (0);
1396	}
1397	case TIOCGETD:
1398		/* For compatibility - we only support TTYDISC. */
1399		*(int *)data = TTYDISC;
1400		return (0);
1401	case TIOCGPGRP:
1402		if (!tty_is_ctty(tp, td->td_proc))
1403			return (ENOTTY);
1404
1405		if (tp->t_pgrp != NULL)
1406			*(int *)data = tp->t_pgrp->pg_id;
1407		else
1408			*(int *)data = NO_PID;
1409		return (0);
1410	case TIOCGSID:
1411		if (!tty_is_ctty(tp, td->td_proc))
1412			return (ENOTTY);
1413
1414		MPASS(tp->t_session);
1415		*(int *)data = tp->t_session->s_sid;
1416		return (0);
1417	case TIOCSCTTY: {
1418		struct proc *p = td->td_proc;
1419
1420		/* XXX: This looks awful. */
1421		tty_unlock(tp);
1422		sx_xlock(&proctree_lock);
1423		tty_lock(tp);
1424
1425		if (!SESS_LEADER(p)) {
1426			/* Only the session leader may do this. */
1427			sx_xunlock(&proctree_lock);
1428			return (EPERM);
1429		}
1430
1431		if (tp->t_session != NULL && tp->t_session == p->p_session) {
1432			/* This is already our controlling TTY. */
1433			sx_xunlock(&proctree_lock);
1434			return (0);
1435		}
1436
1437		if (!SESS_LEADER(p) || p->p_session->s_ttyvp != NULL ||
1438		    (tp->t_session != NULL && tp->t_session->s_ttyvp != NULL)) {
1439			/*
1440			 * There is already a relation between a TTY and
1441			 * a session, or the caller is not the session
1442			 * leader.
1443			 *
1444			 * Allow the TTY to be stolen when the vnode is
1445			 * NULL, but the reference to the TTY is still
1446			 * active.
1447			 */
1448			sx_xunlock(&proctree_lock);
1449			return (EPERM);
1450		}
1451
1452		/* Connect the session to the TTY. */
1453		tp->t_session = p->p_session;
1454		tp->t_session->s_ttyp = tp;
1455		tp->t_sessioncnt++;
1456		sx_xunlock(&proctree_lock);
1457
1458		/* Assign foreground process group. */
1459		tp->t_pgrp = p->p_pgrp;
1460		PROC_LOCK(p);
1461		p->p_flag |= P_CONTROLT;
1462		PROC_UNLOCK(p);
1463
1464		return (0);
1465	}
1466	case TIOCSPGRP: {
1467		struct pgrp *pg;
1468
1469		/*
1470		 * XXX: Temporarily unlock the TTY to locate the process
1471		 * group. This code would be lot nicer if we would ever
1472		 * decompose proctree_lock.
1473		 */
1474		tty_unlock(tp);
1475		sx_slock(&proctree_lock);
1476		pg = pgfind(*(int *)data);
1477		if (pg != NULL)
1478			PGRP_UNLOCK(pg);
1479		if (pg == NULL || pg->pg_session != td->td_proc->p_session) {
1480			sx_sunlock(&proctree_lock);
1481			tty_lock(tp);
1482			return (EPERM);
1483		}
1484		tty_lock(tp);
1485
1486		/*
1487		 * Determine if this TTY is the controlling TTY after
1488		 * relocking the TTY.
1489		 */
1490		if (!tty_is_ctty(tp, td->td_proc)) {
1491			sx_sunlock(&proctree_lock);
1492			return (ENOTTY);
1493		}
1494		tp->t_pgrp = pg;
1495		sx_sunlock(&proctree_lock);
1496
1497		/* Wake up the background process groups. */
1498		cv_broadcast(&tp->t_bgwait);
1499		return (0);
1500	}
1501	case TIOCFLUSH: {
1502		int flags = *(int *)data;
1503
1504		if (flags == 0)
1505			flags = (FREAD|FWRITE);
1506		else
1507			flags &= (FREAD|FWRITE);
1508		tty_flush(tp, flags);
1509		return (0);
1510	}
1511	case TIOCDRAIN:
1512		/* Drain TTY output. */
1513		return tty_drain(tp);
1514	case TIOCCONS:
1515		/* Set terminal as console TTY. */
1516		if (*(int *)data) {
1517			error = priv_check(td, PRIV_TTY_CONSOLE);
1518			if (error)
1519				return (error);
1520
1521			/*
1522			 * XXX: constty should really need to be locked!
1523			 * XXX: allow disconnected constty's to be stolen!
1524			 */
1525
1526			if (constty == tp)
1527				return (0);
1528			if (constty != NULL)
1529				return (EBUSY);
1530
1531			tty_unlock(tp);
1532			constty_set(tp);
1533			tty_lock(tp);
1534		} else if (constty == tp) {
1535			constty_clear();
1536		}
1537		return (0);
1538	case TIOCGWINSZ:
1539		/* Obtain window size. */
1540		bcopy(&tp->t_winsize, data, sizeof(struct winsize));
1541		return (0);
1542	case TIOCSWINSZ:
1543		/* Set window size. */
1544		if (bcmp(&tp->t_winsize, data, sizeof(struct winsize)) == 0)
1545			return (0);
1546		bcopy(data, &tp->t_winsize, sizeof(struct winsize));
1547		tty_signal_pgrp(tp, SIGWINCH);
1548		return (0);
1549	case TIOCEXCL:
1550		tp->t_flags |= TF_EXCLUDE;
1551		return (0);
1552	case TIOCNXCL:
1553		tp->t_flags &= ~TF_EXCLUDE;
1554		return (0);
1555	case TIOCOUTQ:
1556		*(unsigned int *)data = ttyoutq_bytesused(&tp->t_outq);
1557		return (0);
1558	case TIOCSTOP:
1559		tp->t_flags |= TF_STOPPED;
1560		ttydevsw_pktnotify(tp, TIOCPKT_STOP);
1561		return (0);
1562	case TIOCSTART:
1563		tp->t_flags &= ~TF_STOPPED;
1564		ttydevsw_outwakeup(tp);
1565		ttydevsw_pktnotify(tp, TIOCPKT_START);
1566		return (0);
1567	case TIOCSTAT:
1568		tty_info(tp);
1569		return (0);
1570	}
1571
1572#ifdef COMPAT_43TTY
1573	return tty_ioctl_compat(tp, cmd, data, td);
1574#else /* !COMPAT_43TTY */
1575	return (ENOIOCTL);
1576#endif /* COMPAT_43TTY */
1577}
1578
1579int
1580tty_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1581{
1582	int error;
1583
1584	tty_lock_assert(tp, MA_OWNED);
1585
1586	if (tty_gone(tp))
1587		return (ENXIO);
1588
1589	error = ttydevsw_ioctl(tp, cmd, data, td);
1590	if (error == ENOIOCTL)
1591		error = tty_generic_ioctl(tp, cmd, data, td);
1592
1593	return (error);
1594}
1595
1596dev_t
1597tty_udev(struct tty *tp)
1598{
1599	if (tp->t_dev)
1600		return dev2udev(tp->t_dev);
1601	else
1602		return NODEV;
1603}
1604
1605int
1606tty_checkoutq(struct tty *tp)
1607{
1608
1609	/* 256 bytes should be enough to print a log message. */
1610	return (ttyoutq_bytesleft(&tp->t_outq) >= 256);
1611}
1612
1613void
1614tty_hiwat_in_block(struct tty *tp)
1615{
1616
1617	if ((tp->t_flags & TF_HIWAT_IN) == 0 &&
1618	    tp->t_termios.c_iflag & IXOFF &&
1619	    tp->t_termios.c_cc[VSTOP] != _POSIX_VDISABLE) {
1620		/*
1621		 * Input flow control. Only enter the high watermark when we
1622		 * can successfully store the VSTOP character.
1623		 */
1624		if (ttyoutq_write_nofrag(&tp->t_outq,
1625		    &tp->t_termios.c_cc[VSTOP], 1) == 0)
1626			tp->t_flags |= TF_HIWAT_IN;
1627	} else {
1628		/* No input flow control. */
1629		tp->t_flags |= TF_HIWAT_IN;
1630	}
1631}
1632
1633void
1634tty_hiwat_in_unblock(struct tty *tp)
1635{
1636
1637	if (tp->t_flags & TF_HIWAT_IN &&
1638	    tp->t_termios.c_iflag & IXOFF &&
1639	    tp->t_termios.c_cc[VSTART] != _POSIX_VDISABLE) {
1640		/*
1641		 * Input flow control. Only leave the high watermark when we
1642		 * can successfully store the VSTART character.
1643		 */
1644		if (ttyoutq_write_nofrag(&tp->t_outq,
1645		    &tp->t_termios.c_cc[VSTART], 1) == 0)
1646			tp->t_flags &= ~TF_HIWAT_IN;
1647	} else {
1648		/* No input flow control. */
1649		tp->t_flags &= ~TF_HIWAT_IN;
1650	}
1651
1652	if (!tty_gone(tp))
1653		ttydevsw_inwakeup(tp);
1654}
1655
1656#include "opt_ddb.h"
1657#ifdef DDB
1658#include <ddb/ddb.h>
1659
1660static struct {
1661	int flag;
1662	char val;
1663} ttystates[] = {
1664#if 0
1665	{ TF_NOPREFIX,	'N' },
1666#endif
1667	{ TF_INITLOCK,	'I' },
1668	{ TF_CALLOUT,	'C' },
1669
1670	/* Keep these together -> 'Oi' and 'Oo'. */
1671	{ TF_OPENED,	'O' },
1672	{ TF_OPENED_IN,	'i' },
1673	{ TF_OPENED_OUT,'o' },
1674
1675	{ TF_GONE,	'G' },
1676	{ TF_OPENCLOSE,	'B' },
1677	{ TF_ASYNC,	'Y' },
1678	{ TF_LITERAL,	'L' },
1679
1680	/* Keep these together -> 'Hi' and 'Ho'. */
1681	{ TF_HIWAT,	'H' },
1682	{ TF_HIWAT_IN,	'i' },
1683	{ TF_HIWAT_OUT,	'o' },
1684
1685	{ TF_STOPPED,	'S' },
1686	{ TF_EXCLUDE,	'X' },
1687	{ TF_BYPASS,	'l' },
1688	{ TF_ZOMBIE,	'Z' },
1689
1690	{ 0,	       '\0' },
1691};
1692
1693/* DDB command to show TTY statistics. */
1694DB_SHOW_COMMAND(ttys, db_show_ttys)
1695{
1696	struct tty *tp;
1697	size_t isiz, osiz;
1698	int i, j;
1699
1700	/* Make the output look like `pstat -t'. */
1701	db_printf("      LINE   INQ  CAN  LIN  LOW  OUTQ  USE  LOW   "
1702	    "COL  SESS  PGID STATE\n");
1703
1704	TAILQ_FOREACH(tp, &tty_list, t_list) {
1705		isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE;
1706		osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE;
1707
1708		db_printf("%10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
1709		    tty_devname(tp),
1710		    isiz,
1711		    tp->t_inq.ti_linestart - tp->t_inq.ti_begin,
1712		    tp->t_inq.ti_end - tp->t_inq.ti_linestart,
1713		    isiz - tp->t_inlow,
1714		    osiz,
1715		    tp->t_outq.to_end - tp->t_outq.to_begin,
1716		    osiz - tp->t_outlow,
1717		    tp->t_column,
1718		    tp->t_session ? tp->t_session->s_sid : 0,
1719		    tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
1720
1721		/* Flag bits. */
1722		for (i = j = 0; ttystates[i].flag; i++)
1723			if (tp->t_flags & ttystates[i].flag) {
1724				db_printf("%c", ttystates[i].val);
1725				j++;
1726			}
1727		if (j == 0)
1728			db_printf("-");
1729		db_printf("\n");
1730	}
1731}
1732#endif /* DDB */
1733