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