tty_tty.c revision 76166
1/*-
2 * Copyright (c) 1982, 1986, 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *	@(#)tty_tty.c	8.2 (Berkeley) 9/23/93
34 * $FreeBSD: head/sys/kern/tty_tty.c 76166 2001-05-01 08:13:21Z markm $
35 */
36
37/*
38 * Indirect driver for controlling tty.
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/conf.h>
44#include <sys/kernel.h>
45#include <sys/lock.h>
46#include <sys/proc.h>
47#include <sys/ttycom.h>
48#include <sys/vnode.h>
49
50static	d_open_t	cttyopen;
51static	d_read_t	cttyread;
52static	d_write_t	cttywrite;
53static	d_ioctl_t	cttyioctl;
54static	d_poll_t	cttypoll;
55
56#define	CDEV_MAJOR	1
57/* Don't make this static, since fdesc_vnops uses it. */
58struct cdevsw ctty_cdevsw = {
59	/* open */	cttyopen,
60	/* close */	nullclose,
61	/* read */	cttyread,
62	/* write */	cttywrite,
63	/* ioctl */	cttyioctl,
64	/* poll */	cttypoll,
65	/* mmap */	nommap,
66	/* strategy */	nostrategy,
67	/* name */	"ctty",
68	/* maj */	CDEV_MAJOR,
69	/* dump */	nodump,
70	/* psize */	nopsize,
71	/* flags */	D_TTY,
72};
73
74#define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
75
76/*ARGSUSED*/
77static	int
78cttyopen(dev, flag, mode, p)
79	dev_t dev;
80	int flag, mode;
81	struct proc *p;
82{
83	struct vnode *ttyvp = cttyvp(p);
84	int error;
85
86	if (ttyvp == NULL)
87		return (ENXIO);
88	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p);
89#ifdef PARANOID
90	/*
91	 * Since group is tty and mode is 620 on most terminal lines
92	 * and since sessions protect terminals from processes outside
93	 * your session, this check is probably no longer necessary.
94	 * Since it inhibits setuid root programs that later switch
95	 * to another user from accessing /dev/tty, we have decided
96	 * to delete this test. (mckusick 5/93)
97	 */
98	error = VOP_ACCESS(ttyvp,
99	  (flag&FREAD ? VREAD : 0) | (flag&FWRITE ? VWRITE : 0), p->p_ucred, p);
100	if (!error)
101#endif /* PARANOID */
102		error = VOP_OPEN(ttyvp, flag, NOCRED, p);
103	VOP_UNLOCK(ttyvp, 0, p);
104	return (error);
105}
106
107/*ARGSUSED*/
108static	int
109cttyread(dev, uio, flag)
110	dev_t dev;
111	struct uio *uio;
112	int flag;
113{
114	struct proc *p = uio->uio_procp;
115	register struct vnode *ttyvp = cttyvp(p);
116	int error;
117
118	if (ttyvp == NULL)
119		return (EIO);
120	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p);
121	error = VOP_READ(ttyvp, uio, flag, NOCRED);
122	VOP_UNLOCK(ttyvp, 0, p);
123	return (error);
124}
125
126/*ARGSUSED*/
127static	int
128cttywrite(dev, uio, flag)
129	dev_t dev;
130	struct uio *uio;
131	int flag;
132{
133	struct proc *p = uio->uio_procp;
134	struct vnode *ttyvp = cttyvp(uio->uio_procp);
135	struct mount *mp;
136	int error;
137
138	if (ttyvp == NULL)
139		return (EIO);
140	mp = NULL;
141	if (ttyvp->v_type != VCHR &&
142	    (error = vn_start_write(ttyvp, &mp, V_WAIT | PCATCH)) != 0)
143		return (error);
144	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p);
145	error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
146	VOP_UNLOCK(ttyvp, 0, p);
147	vn_finished_write(mp);
148	return (error);
149}
150
151/*ARGSUSED*/
152static	int
153cttyioctl(dev, cmd, addr, flag, p)
154	dev_t dev;
155	u_long cmd;
156	caddr_t addr;
157	int flag;
158	struct proc *p;
159{
160	struct vnode *ttyvp = cttyvp(p);
161
162	if (ttyvp == NULL)
163		return (EIO);
164	if (cmd == TIOCSCTTY)  /* don't allow controlling tty to be set    */
165		return EINVAL; /* to controlling tty -- infinite recursion */
166	if (cmd == TIOCNOTTY) {
167		if (!SESS_LEADER(p)) {
168			p->p_flag &= ~P_CONTROLT;
169			return (0);
170		} else
171			return (EINVAL);
172	}
173	return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, p));
174}
175
176/*ARGSUSED*/
177static	int
178cttypoll(dev, events, p)
179	dev_t dev;
180	int events;
181	struct proc *p;
182{
183	struct vnode *ttyvp = cttyvp(p);
184
185	if (ttyvp == NULL)
186		/* try operation to get EOF/failure */
187		return (seltrue(dev, events, p));
188	return (VOP_POLL(ttyvp, events, p->p_ucred, p));
189}
190
191static void ctty_drvinit __P((void *unused));
192static void
193ctty_drvinit(unused)
194	void *unused;
195{
196
197	make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "tty");
198}
199
200SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL)
201