tty.c revision 182764
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 182764 2008-09-04 16:39:02Z 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_defpktnotify(struct tty *tp, char event)
820{
821}
822
823static void
824ttydevsw_deffree(void *softc)
825{
826
827	panic("Terminal device freed without a free-handler");
828}
829
830/*
831 * TTY allocation and deallocation. TTY devices can be deallocated when
832 * the driver doesn't use it anymore, when the TTY isn't a session's
833 * controlling TTY and when the device node isn't opened through devfs.
834 */
835
836struct tty *
837tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
838{
839	struct tty *tp;
840
841	/* Make sure the driver defines all routines. */
842#define PATCH_FUNC(x) do {				\
843	if (tsw->tsw_ ## x == NULL)			\
844		tsw->tsw_ ## x = ttydevsw_def ## x;	\
845} while (0)
846	PATCH_FUNC(open);
847	PATCH_FUNC(close);
848	PATCH_FUNC(outwakeup);
849	PATCH_FUNC(inwakeup);
850	PATCH_FUNC(ioctl);
851	PATCH_FUNC(param);
852	PATCH_FUNC(modem);
853	PATCH_FUNC(mmap);
854	PATCH_FUNC(pktnotify);
855	PATCH_FUNC(free);
856#undef PATCH_FUNC
857
858	tp = malloc(sizeof(struct tty), M_TTY, M_WAITOK|M_ZERO);
859	tp->t_devsw = tsw;
860	tp->t_softc = sc;
861	tp->t_flags = tsw->tsw_flags;
862
863	tty_init_termios(tp);
864
865	cv_init(&tp->t_inwait, "tty input");
866	cv_init(&tp->t_outwait, "tty output");
867	cv_init(&tp->t_bgwait, "tty background");
868	cv_init(&tp->t_dcdwait, "tty dcd");
869
870	ttyinq_init(&tp->t_inq);
871	ttyoutq_init(&tp->t_outq);
872
873	/* Allow drivers to use a custom mutex to lock the TTY. */
874	if (mutex != NULL) {
875		tp->t_mtx = mutex;
876	} else {
877		tp->t_mtx = &tp->t_mtxobj;
878		mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
879	}
880
881	knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
882	knlist_init(&tp->t_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
883
884	sx_xlock(&tty_list_sx);
885	TAILQ_INSERT_TAIL(&tty_list, tp, t_list);
886	tty_list_count++;
887	sx_xunlock(&tty_list_sx);
888
889	return (tp);
890}
891
892static void
893tty_dealloc(void *arg)
894{
895	struct tty *tp = arg;
896
897	sx_xlock(&tty_list_sx);
898	TAILQ_REMOVE(&tty_list, tp, t_list);
899	tty_list_count--;
900	sx_xunlock(&tty_list_sx);
901
902	/* Make sure we haven't leaked buffers. */
903	MPASS(ttyinq_getsize(&tp->t_inq) == 0);
904	MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
905
906	knlist_destroy(&tp->t_inpoll.si_note);
907	knlist_destroy(&tp->t_outpoll.si_note);
908
909	cv_destroy(&tp->t_inwait);
910	cv_destroy(&tp->t_outwait);
911	cv_destroy(&tp->t_bgwait);
912	cv_destroy(&tp->t_dcdwait);
913
914	if (tp->t_mtx == &tp->t_mtxobj)
915		mtx_destroy(&tp->t_mtxobj);
916	ttydevsw_free(tp);
917	free(tp, M_TTY);
918}
919
920static void
921tty_rel_free(struct tty *tp)
922{
923	struct cdev *dev;
924
925	tty_lock_assert(tp, MA_OWNED);
926
927	if (tp->t_sessioncnt != 0 ||
928	    (tp->t_flags & (TF_GONE|TF_OPENED)) != TF_GONE) {
929		/* TTY is still in use. */
930		tty_unlock(tp);
931		return;
932	}
933
934	/* TTY can be deallocated. */
935	dev = tp->t_dev;
936	tp->t_dev = NULL;
937	tty_unlock(tp);
938
939	destroy_dev_sched_cb(dev, tty_dealloc, tp);
940}
941
942void
943tty_rel_pgrp(struct tty *tp, struct pgrp *pg)
944{
945	tty_lock_assert(tp, MA_OWNED);
946
947	if (tp->t_pgrp == pg)
948		tp->t_pgrp = NULL;
949}
950
951void
952tty_rel_sess(struct tty *tp, struct session *sess)
953{
954	MPASS(tp->t_sessioncnt > 0);
955
956	/* Current session has left. */
957	if (tp->t_session == sess) {
958		tp->t_session = NULL;
959		MPASS(tp->t_pgrp == NULL);
960	}
961	tp->t_sessioncnt--;
962	tty_rel_free(tp);
963}
964
965void
966tty_rel_gone(struct tty *tp)
967{
968	MPASS(!tty_gone(tp));
969
970	/* Simulate carrier removal. */
971	ttydisc_modem(tp, 0);
972
973	/* Wake up misc. blocked threads. */
974	cv_broadcast(&tp->t_bgwait);
975	cv_broadcast(&tp->t_dcdwait);
976
977	tp->t_flags |= TF_GONE;
978	tty_rel_free(tp);
979}
980
981/*
982 * Exposing information about current TTY's through sysctl
983 */
984
985static void
986tty_to_xtty(struct tty *tp, struct xtty *xt)
987{
988	tty_lock_assert(tp, MA_OWNED);
989
990	xt->xt_size = sizeof(struct xtty);
991	xt->xt_insize = ttyinq_getsize(&tp->t_inq);
992	xt->xt_incc = ttyinq_bytescanonicalized(&tp->t_inq);
993	xt->xt_inlc = ttyinq_bytesline(&tp->t_inq);
994	xt->xt_inlow = tp->t_inlow;
995	xt->xt_outsize = ttyoutq_getsize(&tp->t_outq);
996	xt->xt_outcc = ttyoutq_bytesused(&tp->t_outq);
997	xt->xt_outlow = tp->t_outlow;
998	xt->xt_column = tp->t_column;
999	xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1000	xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0;
1001	xt->xt_flags = tp->t_flags;
1002	xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV;
1003}
1004
1005static int
1006sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
1007{
1008	unsigned long lsize;
1009	struct xtty *xtlist, *xt;
1010	struct tty *tp;
1011	int error;
1012
1013	sx_slock(&tty_list_sx);
1014	lsize = tty_list_count * sizeof(struct xtty);
1015	if (lsize == 0) {
1016		sx_sunlock(&tty_list_sx);
1017		return (0);
1018	}
1019
1020	xtlist = xt = malloc(lsize, M_TEMP, M_WAITOK);
1021
1022	TAILQ_FOREACH(tp, &tty_list, t_list) {
1023		tty_lock(tp);
1024		tty_to_xtty(tp, xt);
1025		tty_unlock(tp);
1026		xt++;
1027	}
1028	sx_sunlock(&tty_list_sx);
1029
1030	error = SYSCTL_OUT(req, xtlist, lsize);
1031	free(xtlist, M_TEMP);
1032	return (error);
1033}
1034
1035SYSCTL_PROC(_kern, OID_AUTO, ttys, CTLTYPE_OPAQUE|CTLFLAG_RD,
1036	0, 0, sysctl_kern_ttys, "S,xtty", "List of TTYs");
1037
1038/*
1039 * Device node creation. Device has been set up, now we can expose it to
1040 * the user.
1041 */
1042
1043void
1044tty_makedev(struct tty *tp, struct ucred *cred, const char *fmt, ...)
1045{
1046	va_list ap;
1047	struct cdev *dev;
1048	const char *prefix = "tty";
1049	char name[SPECNAMELEN - 3]; /* for "tty" and "cua". */
1050	uid_t uid;
1051	gid_t gid;
1052	mode_t mode;
1053
1054	/* Remove "tty" prefix from devices like PTY's. */
1055	if (tp->t_flags & TF_NOPREFIX)
1056		prefix = "";
1057
1058	va_start(ap, fmt);
1059	vsnrprintf(name, sizeof name, 32, fmt, ap);
1060	va_end(ap);
1061
1062	if (cred == NULL) {
1063		/* System device. */
1064		uid = UID_ROOT;
1065		gid = GID_WHEEL;
1066		mode = S_IRUSR|S_IWUSR;
1067	} else {
1068		/* User device. */
1069		uid = cred->cr_ruid;
1070		gid = GID_TTY;
1071		mode = S_IRUSR|S_IWUSR|S_IWGRP;
1072	}
1073
1074	/* Master call-in device. */
1075	dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1076	    uid, gid, mode, "%s%s", prefix, name);
1077	dev->si_drv1 = tp;
1078	tp->t_dev = dev;
1079
1080	/* Slave call-in devices. */
1081	if (tp->t_flags & TF_INITLOCK) {
1082		dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1083		    uid, gid, mode, "%s%s.init", prefix, name);
1084		dev_depends(tp->t_dev, dev);
1085		dev->si_drv1 = tp;
1086		dev->si_drv2 = &tp->t_termios_init_in;
1087
1088		dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1089		    uid, gid, mode, "%s%s.lock", prefix, name);
1090		dev_depends(tp->t_dev, dev);
1091		dev->si_drv1 = tp;
1092		dev->si_drv2 = &tp->t_termios_lock_in;
1093	}
1094
1095	/* Call-out devices. */
1096	if (tp->t_flags & TF_CALLOUT) {
1097		dev = make_dev_cred(&ttydev_cdevsw, 0, cred,
1098		    UID_UUCP, GID_DIALER, 0660, "cua%s", name);
1099		dev_depends(tp->t_dev, dev);
1100		dev->si_drv1 = tp;
1101
1102		/* Slave call-out devices. */
1103		if (tp->t_flags & TF_INITLOCK) {
1104			dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1105			    UID_UUCP, GID_DIALER, 0660, "cua%s.init", name);
1106			dev_depends(tp->t_dev, dev);
1107			dev->si_drv1 = tp;
1108			dev->si_drv2 = &tp->t_termios_init_out;
1109
1110			dev = make_dev_cred(&ttyil_cdevsw, 0, cred,
1111			    UID_UUCP, GID_DIALER, 0660, "cua%s.lock", name);
1112			dev_depends(tp->t_dev, dev);
1113			dev->si_drv1 = tp;
1114			dev->si_drv2 = &tp->t_termios_lock_out;
1115		}
1116	}
1117}
1118
1119/*
1120 * Signalling processes.
1121 */
1122
1123void
1124tty_signal_sessleader(struct tty *tp, int sig)
1125{
1126	struct proc *p;
1127
1128	tty_lock_assert(tp, MA_OWNED);
1129	MPASS(sig >= 1 && sig < NSIG);
1130
1131	/* Make signals start output again. */
1132	tp->t_flags &= ~TF_STOPPED;
1133
1134	if (tp->t_session != NULL && tp->t_session->s_leader != NULL) {
1135		p = tp->t_session->s_leader;
1136		PROC_LOCK(p);
1137		psignal(p, sig);
1138		PROC_UNLOCK(p);
1139	}
1140}
1141
1142void
1143tty_signal_pgrp(struct tty *tp, int sig)
1144{
1145	tty_lock_assert(tp, MA_OWNED);
1146	MPASS(sig >= 1 && sig < NSIG);
1147
1148	/* Make signals start output again. */
1149	tp->t_flags &= ~TF_STOPPED;
1150
1151	if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
1152		tty_info(tp);
1153	if (tp->t_pgrp != NULL) {
1154		PGRP_LOCK(tp->t_pgrp);
1155		pgsignal(tp->t_pgrp, sig, 1);
1156		PGRP_UNLOCK(tp->t_pgrp);
1157	}
1158}
1159
1160void
1161tty_wakeup(struct tty *tp, int flags)
1162{
1163	if (tp->t_flags & TF_ASYNC && tp->t_sigio != NULL)
1164		pgsigio(&tp->t_sigio, SIGIO, (tp->t_session != NULL));
1165
1166	if (flags & FWRITE) {
1167		cv_broadcast(&tp->t_outwait);
1168		selwakeup(&tp->t_outpoll);
1169		KNOTE_LOCKED(&tp->t_outpoll.si_note, 0);
1170	}
1171	if (flags & FREAD) {
1172		cv_broadcast(&tp->t_inwait);
1173		selwakeup(&tp->t_inpoll);
1174		KNOTE_LOCKED(&tp->t_inpoll.si_note, 0);
1175	}
1176}
1177
1178int
1179tty_wait(struct tty *tp, struct cv *cv)
1180{
1181	int error;
1182	int revokecnt = tp->t_revokecnt;
1183
1184#if 0
1185	/* XXX: /dev/console also picks up Giant. */
1186	tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1187#endif
1188	tty_lock_assert(tp, MA_OWNED);
1189
1190	error = cv_wait_sig(cv, tp->t_mtx);
1191
1192	/* Restart the system call when we may have been revoked. */
1193	if (tp->t_revokecnt != revokecnt)
1194		return (ERESTART);
1195
1196	/* Bail out when the device slipped away. */
1197	if (tty_gone(tp))
1198		return (ENXIO);
1199
1200	return (error);
1201}
1202
1203int
1204tty_timedwait(struct tty *tp, struct cv *cv, int hz)
1205{
1206	int error;
1207	int revokecnt = tp->t_revokecnt;
1208
1209#if 0
1210	/* XXX: /dev/console also picks up Giant. */
1211	tty_lock_assert(tp, MA_OWNED|MA_NOTRECURSED);
1212#endif
1213	tty_lock_assert(tp, MA_OWNED);
1214
1215	error = cv_timedwait_sig(cv, tp->t_mtx, hz);
1216
1217	/* Restart the system call when we may have been revoked. */
1218	if (tp->t_revokecnt != revokecnt)
1219		return (ERESTART);
1220
1221	/* Bail out when the device slipped away. */
1222	if (tty_gone(tp))
1223		return (ENXIO);
1224
1225	return (error);
1226}
1227
1228void
1229tty_flush(struct tty *tp, int flags)
1230{
1231	if (flags & FWRITE) {
1232		tp->t_flags &= ~TF_HIWAT_OUT;
1233		ttyoutq_flush(&tp->t_outq);
1234		tty_wakeup(tp, FWRITE);
1235		ttydevsw_pktnotify(tp, TIOCPKT_FLUSHWRITE);
1236	}
1237	if (flags & FREAD) {
1238		tty_hiwat_in_unblock(tp);
1239		ttyinq_flush(&tp->t_inq);
1240		ttydevsw_inwakeup(tp);
1241		ttydevsw_pktnotify(tp, TIOCPKT_FLUSHREAD);
1242	}
1243}
1244
1245static int
1246tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1247{
1248	int error;
1249
1250	switch (cmd) {
1251	/*
1252	 * Modem commands.
1253	 * The SER_* and TIOCM_* flags are the same, but one bit
1254	 * shifted. I don't know why.
1255	 */
1256	case TIOCSDTR:
1257		ttydevsw_modem(tp, SER_DTR, 0);
1258		return (0);
1259	case TIOCCDTR:
1260		ttydevsw_modem(tp, 0, SER_DTR);
1261		return (0);
1262	case TIOCMSET: {
1263		int bits = *(int *)data;
1264		ttydevsw_modem(tp,
1265		    (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1,
1266		    ((~bits) & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1267		return (0);
1268	}
1269	case TIOCMBIS: {
1270		int bits = *(int *)data;
1271		ttydevsw_modem(tp, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1, 0);
1272		return (0);
1273	}
1274	case TIOCMBIC: {
1275		int bits = *(int *)data;
1276		ttydevsw_modem(tp, 0, (bits & (TIOCM_DTR | TIOCM_RTS)) >> 1);
1277		return (0);
1278	}
1279	case TIOCMGET:
1280		*(int *)data = TIOCM_LE + (ttydevsw_modem(tp, 0, 0) << 1);
1281		return (0);
1282
1283	case FIOASYNC:
1284		if (*(int *)data)
1285			tp->t_flags |= TF_ASYNC;
1286		else
1287			tp->t_flags &= ~TF_ASYNC;
1288		return (0);
1289	case FIONBIO:
1290		/* This device supports non-blocking operation. */
1291		return (0);
1292	case FIONREAD:
1293		*(int *)data = ttyinq_bytescanonicalized(&tp->t_inq);
1294		return (0);
1295	case FIOSETOWN:
1296		if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1297			/* Not allowed to set ownership. */
1298			return (ENOTTY);
1299
1300		/* Temporarily unlock the TTY to set ownership. */
1301		tty_unlock(tp);
1302		error = fsetown(*(int *)data, &tp->t_sigio);
1303		tty_lock(tp);
1304		return (error);
1305	case FIOGETOWN:
1306		if (tp->t_session != NULL && !tty_is_ctty(tp, td->td_proc))
1307			/* Not allowed to set ownership. */
1308			return (ENOTTY);
1309
1310		/* Get ownership. */
1311		*(int *)data = fgetown(&tp->t_sigio);
1312		return (0);
1313	case TIOCGETA:
1314		/* Obtain terminal flags through tcgetattr(). */
1315		bcopy(&tp->t_termios, data, sizeof(struct termios));
1316		return (0);
1317	case TIOCSETA:
1318	case TIOCSETAW:
1319	case TIOCSETAF: {
1320		struct termios *t = data;
1321
1322		/*
1323		 * Who makes up these funny rules? According to POSIX,
1324		 * input baud rate is set equal to the output baud rate
1325		 * when zero.
1326		 */
1327		if (t->c_ispeed == 0)
1328			t->c_ispeed = t->c_ospeed;
1329
1330		/* Discard any unsupported bits. */
1331		t->c_iflag &= TTYSUP_IFLAG;
1332		t->c_oflag &= TTYSUP_OFLAG;
1333		t->c_lflag &= TTYSUP_LFLAG;
1334		t->c_cflag &= TTYSUP_CFLAG;
1335
1336		/* Set terminal flags through tcsetattr(). */
1337		if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
1338			error = tty_drain(tp);
1339			if (error)
1340				return (error);
1341			if (cmd == TIOCSETAF)
1342				tty_flush(tp, FREAD);
1343		}
1344
1345		/*
1346		 * Only call param() when the flags really change.
1347		 */
1348		if ((t->c_cflag & CIGNORE) == 0 &&
1349		    (tp->t_termios.c_cflag != t->c_cflag ||
1350		    tp->t_termios.c_ispeed != t->c_ispeed ||
1351		    tp->t_termios.c_ospeed != t->c_ospeed)) {
1352			error = ttydevsw_param(tp, t);
1353			if (error)
1354				return (error);
1355
1356			/* XXX: CLOCAL? */
1357
1358			tp->t_termios.c_cflag = t->c_cflag & ~CIGNORE;
1359			tp->t_termios.c_ispeed = t->c_ispeed;
1360			tp->t_termios.c_ospeed = t->c_ospeed;
1361
1362			/* Baud rate has changed - update watermarks. */
1363			tty_watermarks(tp);
1364		}
1365
1366		/* Copy new non-device driver parameters. */
1367		tp->t_termios.c_iflag = t->c_iflag;
1368		tp->t_termios.c_oflag = t->c_oflag;
1369		tp->t_termios.c_lflag = t->c_lflag;
1370		bcopy(t->c_cc, &tp->t_termios.c_cc, sizeof(t->c_cc));
1371
1372		ttydisc_optimize(tp);
1373
1374		if ((t->c_lflag & ICANON) == 0) {
1375			/*
1376			 * When in non-canonical mode, wake up all
1377			 * readers. Canonicalize any partial input. VMIN
1378			 * and VTIME could also be adjusted.
1379			 */
1380			ttyinq_canonicalize(&tp->t_inq);
1381			tty_wakeup(tp, FREAD);
1382		}
1383
1384		/*
1385		 * For packet mode: notify the PTY consumer that VSTOP
1386		 * and VSTART may have been changed.
1387		 */
1388		if (tp->t_termios.c_iflag & IXON &&
1389		    tp->t_termios.c_cc[VSTOP] == CTRL('S') &&
1390		    tp->t_termios.c_cc[VSTART] == CTRL('Q'))
1391			ttydevsw_pktnotify(tp, TIOCPKT_DOSTOP);
1392		else
1393			ttydevsw_pktnotify(tp, TIOCPKT_NOSTOP);
1394		return (0);
1395	}
1396	case TIOCGETD:
1397		/* For compatibility - we only support TTYDISC. */
1398		*(int *)data = TTYDISC;
1399		return (0);
1400	case TIOCGPGRP:
1401		if (!tty_is_ctty(tp, td->td_proc))
1402			return (ENOTTY);
1403
1404		if (tp->t_pgrp != NULL)
1405			*(int *)data = tp->t_pgrp->pg_id;
1406		else
1407			*(int *)data = NO_PID;
1408		return (0);
1409	case TIOCGSID:
1410		if (!tty_is_ctty(tp, td->td_proc))
1411			return (ENOTTY);
1412
1413		MPASS(tp->t_session);
1414		*(int *)data = tp->t_session->s_sid;
1415		return (0);
1416	case TIOCSCTTY: {
1417		struct proc *p = td->td_proc;
1418
1419		/* XXX: This looks awful. */
1420		tty_unlock(tp);
1421		sx_xlock(&proctree_lock);
1422		tty_lock(tp);
1423
1424		if (!SESS_LEADER(p)) {
1425			/* Only the session leader may do this. */
1426			sx_xunlock(&proctree_lock);
1427			return (EPERM);
1428		}
1429
1430		if (tp->t_session != NULL && tp->t_session == p->p_session) {
1431			/* This is already our controlling TTY. */
1432			sx_xunlock(&proctree_lock);
1433			return (0);
1434		}
1435
1436		if (!SESS_LEADER(p) || p->p_session->s_ttyvp != NULL ||
1437		    (tp->t_session != NULL && tp->t_session->s_ttyvp != NULL)) {
1438			/*
1439			 * There is already a relation between a TTY and
1440			 * a session, or the caller is not the session
1441			 * leader.
1442			 *
1443			 * Allow the TTY to be stolen when the vnode is
1444			 * NULL, but the reference to the TTY is still
1445			 * active.
1446			 */
1447			sx_xunlock(&proctree_lock);
1448			return (EPERM);
1449		}
1450
1451		/* Connect the session to the TTY. */
1452		tp->t_session = p->p_session;
1453		tp->t_session->s_ttyp = tp;
1454		tp->t_sessioncnt++;
1455		sx_xunlock(&proctree_lock);
1456
1457		/* Assign foreground process group. */
1458		tp->t_pgrp = p->p_pgrp;
1459		PROC_LOCK(p);
1460		p->p_flag |= P_CONTROLT;
1461		PROC_UNLOCK(p);
1462
1463		return (0);
1464	}
1465	case TIOCSPGRP: {
1466		struct pgrp *pg;
1467
1468		/*
1469		 * XXX: Temporarily unlock the TTY to locate the process
1470		 * group. This code would be lot nicer if we would ever
1471		 * decompose proctree_lock.
1472		 */
1473		tty_unlock(tp);
1474		sx_slock(&proctree_lock);
1475		pg = pgfind(*(int *)data);
1476		if (pg != NULL)
1477			PGRP_UNLOCK(pg);
1478		if (pg == NULL || pg->pg_session != td->td_proc->p_session) {
1479			sx_sunlock(&proctree_lock);
1480			tty_lock(tp);
1481			return (EPERM);
1482		}
1483		tty_lock(tp);
1484
1485		/*
1486		 * Determine if this TTY is the controlling TTY after
1487		 * relocking the TTY.
1488		 */
1489		if (!tty_is_ctty(tp, td->td_proc)) {
1490			sx_sunlock(&proctree_lock);
1491			return (ENOTTY);
1492		}
1493		tp->t_pgrp = pg;
1494		sx_sunlock(&proctree_lock);
1495
1496		/* Wake up the background process groups. */
1497		cv_broadcast(&tp->t_bgwait);
1498		return (0);
1499	}
1500	case TIOCFLUSH: {
1501		int flags = *(int *)data;
1502
1503		if (flags == 0)
1504			flags = (FREAD|FWRITE);
1505		else
1506			flags &= (FREAD|FWRITE);
1507		tty_flush(tp, flags);
1508		return (0);
1509	}
1510	case TIOCDRAIN:
1511		/* Drain TTY output. */
1512		return tty_drain(tp);
1513	case TIOCCONS:
1514		/* Set terminal as console TTY. */
1515		if (*(int *)data) {
1516			struct nameidata nd;
1517			int vfslocked;
1518
1519			/*
1520			 * XXX: TTY won't slip away, but constty would
1521			 * really need to be locked!
1522			 */
1523			tty_unlock(tp);
1524
1525			if (constty == tp) {
1526				tty_lock(tp);
1527				return (0);
1528			}
1529			if (constty != NULL) {
1530				tty_lock(tp);
1531				return (EBUSY);
1532			}
1533			/* XXX: allow disconnected constty's to be stolen! */
1534
1535			/*
1536			 * Only allow this to work when the user can
1537			 * open /dev/console.
1538			 */
1539			NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF|MPSAFE,
1540			    UIO_SYSSPACE, "/dev/console", td);
1541			if ((error = namei(&nd)) != 0) {
1542				tty_lock(tp);
1543				return (error);
1544			}
1545			vfslocked = NDHASGIANT(&nd);
1546			NDFREE(&nd, NDF_ONLY_PNBUF);
1547
1548			error = VOP_ACCESS(nd.ni_vp, VREAD, td->td_ucred, td);
1549			vput(nd.ni_vp);
1550			VFS_UNLOCK_GIANT(vfslocked);
1551			if (error) {
1552				tty_lock(tp);
1553				return (error);
1554			}
1555
1556			constty_set(tp);
1557			tty_lock(tp);
1558		} else if (constty == tp) {
1559			constty_clear();
1560		}
1561		return (0);
1562	case TIOCGWINSZ:
1563		/* Obtain window size. */
1564		bcopy(&tp->t_winsize, data, sizeof(struct winsize));
1565		return (0);
1566	case TIOCSWINSZ:
1567		/* Set window size. */
1568		if (bcmp(&tp->t_winsize, data, sizeof(struct winsize)) == 0)
1569			return (0);
1570		bcopy(data, &tp->t_winsize, sizeof(struct winsize));
1571		tty_signal_pgrp(tp, SIGWINCH);
1572		return (0);
1573	case TIOCEXCL:
1574		tp->t_flags |= TF_EXCLUDE;
1575		return (0);
1576	case TIOCNXCL:
1577		tp->t_flags &= ~TF_EXCLUDE;
1578		return (0);
1579	case TIOCOUTQ:
1580		*(unsigned int *)data = ttyoutq_bytesused(&tp->t_outq);
1581		return (0);
1582	case TIOCSTOP:
1583		tp->t_flags |= TF_STOPPED;
1584		ttydevsw_pktnotify(tp, TIOCPKT_STOP);
1585		return (0);
1586	case TIOCSTART:
1587		tp->t_flags &= ~TF_STOPPED;
1588		ttydevsw_outwakeup(tp);
1589		ttydevsw_pktnotify(tp, TIOCPKT_START);
1590		return (0);
1591	case TIOCSTAT:
1592		tty_info(tp);
1593		return (0);
1594	}
1595
1596#ifdef COMPAT_43TTY
1597	return tty_ioctl_compat(tp, cmd, data, td);
1598#else /* !COMPAT_43TTY */
1599	return (ENOIOCTL);
1600#endif /* COMPAT_43TTY */
1601}
1602
1603int
1604tty_ioctl(struct tty *tp, u_long cmd, void *data, struct thread *td)
1605{
1606	int error;
1607
1608	tty_lock_assert(tp, MA_OWNED);
1609
1610	if (tty_gone(tp))
1611		return (ENXIO);
1612
1613	error = ttydevsw_ioctl(tp, cmd, data, td);
1614	if (error == ENOIOCTL)
1615		error = tty_generic_ioctl(tp, cmd, data, td);
1616
1617	return (error);
1618}
1619
1620dev_t
1621tty_udev(struct tty *tp)
1622{
1623	if (tp->t_dev)
1624		return dev2udev(tp->t_dev);
1625	else
1626		return NODEV;
1627}
1628
1629int
1630tty_checkoutq(struct tty *tp)
1631{
1632
1633	/* 256 bytes should be enough to print a log message. */
1634	return (ttyoutq_bytesleft(&tp->t_outq) >= 256);
1635}
1636
1637void
1638tty_hiwat_in_block(struct tty *tp)
1639{
1640
1641	if ((tp->t_flags & TF_HIWAT_IN) == 0 &&
1642	    tp->t_termios.c_iflag & IXOFF &&
1643	    tp->t_termios.c_cc[VSTOP] != _POSIX_VDISABLE) {
1644		/*
1645		 * Input flow control. Only enter the high watermark when we
1646		 * can successfully store the VSTOP character.
1647		 */
1648		if (ttyoutq_write_nofrag(&tp->t_outq,
1649		    &tp->t_termios.c_cc[VSTOP], 1) == 0)
1650			tp->t_flags |= TF_HIWAT_IN;
1651	} else {
1652		/* No input flow control. */
1653		tp->t_flags |= TF_HIWAT_IN;
1654	}
1655}
1656
1657void
1658tty_hiwat_in_unblock(struct tty *tp)
1659{
1660
1661	if (tp->t_flags & TF_HIWAT_IN &&
1662	    tp->t_termios.c_iflag & IXOFF &&
1663	    tp->t_termios.c_cc[VSTART] != _POSIX_VDISABLE) {
1664		/*
1665		 * Input flow control. Only leave the high watermark when we
1666		 * can successfully store the VSTART character.
1667		 */
1668		if (ttyoutq_write_nofrag(&tp->t_outq,
1669		    &tp->t_termios.c_cc[VSTART], 1) == 0)
1670			tp->t_flags &= ~TF_HIWAT_IN;
1671	} else {
1672		/* No input flow control. */
1673		tp->t_flags &= ~TF_HIWAT_IN;
1674	}
1675
1676	if (!tty_gone(tp))
1677		ttydevsw_inwakeup(tp);
1678}
1679
1680#include "opt_ddb.h"
1681#ifdef DDB
1682#include <ddb/ddb.h>
1683
1684static struct {
1685	int flag;
1686	char val;
1687} ttystates[] = {
1688#if 0
1689	{ TF_NOPREFIX,	'N' },
1690#endif
1691	{ TF_INITLOCK,	'I' },
1692	{ TF_CALLOUT,	'C' },
1693
1694	/* Keep these together -> 'Oi' and 'Oo'. */
1695	{ TF_OPENED,	'O' },
1696	{ TF_OPENED_IN,	'i' },
1697	{ TF_OPENED_OUT,'o' },
1698
1699	{ TF_GONE,	'G' },
1700	{ TF_OPENCLOSE,	'B' },
1701	{ TF_ASYNC,	'Y' },
1702	{ TF_LITERAL,	'L' },
1703
1704	/* Keep these together -> 'Hi' and 'Ho'. */
1705	{ TF_HIWAT,	'H' },
1706	{ TF_HIWAT_IN,	'i' },
1707	{ TF_HIWAT_OUT,	'o' },
1708
1709	{ TF_STOPPED,	'S' },
1710	{ TF_EXCLUDE,	'X' },
1711	{ TF_BYPASS,	'l' },
1712	{ TF_ZOMBIE,	'Z' },
1713
1714	{ 0,	       '\0' },
1715};
1716
1717/* DDB command to show TTY statistics. */
1718DB_SHOW_COMMAND(ttys, db_show_ttys)
1719{
1720	struct tty *tp;
1721	size_t isiz, osiz;
1722	int i, j;
1723
1724	/* Make the output look like `pstat -t'. */
1725	db_printf("      LINE   INQ  CAN  LIN  LOW  OUTQ  USE  LOW   "
1726	    "COL  SESS  PGID STATE\n");
1727
1728	TAILQ_FOREACH(tp, &tty_list, t_list) {
1729		isiz = tp->t_inq.ti_nblocks * TTYINQ_DATASIZE;
1730		osiz = tp->t_outq.to_nblocks * TTYOUTQ_DATASIZE;
1731
1732		db_printf("%10s %5zu %4u %4u %4zu %5zu %4u %4zu %5u %5d %5d ",
1733		    tty_devname(tp),
1734		    isiz,
1735		    tp->t_inq.ti_linestart - tp->t_inq.ti_begin,
1736		    tp->t_inq.ti_end - tp->t_inq.ti_linestart,
1737		    isiz - tp->t_inlow,
1738		    osiz,
1739		    tp->t_outq.to_end - tp->t_outq.to_begin,
1740		    osiz - tp->t_outlow,
1741		    tp->t_column,
1742		    tp->t_session ? tp->t_session->s_sid : 0,
1743		    tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
1744
1745		/* Flag bits. */
1746		for (i = j = 0; ttystates[i].flag; i++)
1747			if (tp->t_flags & ttystates[i].flag) {
1748				db_printf("%c", ttystates[i].val);
1749				j++;
1750			}
1751		if (j == 0)
1752			db_printf("-");
1753		db_printf("\n");
1754	}
1755}
1756#endif /* DDB */
1757