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