tty_tty.c revision 109524
1109524Sphk#ifndef NODEVFS
21541Srgrimes/*-
3109524Sphk * Copyright (c) 2003 Poul-Henning Kamp.  All rights reserved.
4109524Sphk *
5109524Sphk * Redistribution and use in source and binary forms, with or without
6109524Sphk * modification, are permitted provided that the following conditions
7109524Sphk * are met:
8109524Sphk * 1. Redistributions of source code must retain the above copyright
9109524Sphk *    notice, this list of conditions and the following disclaimer.
10109524Sphk * 2. Redistributions in binary form must reproduce the above copyright
11109524Sphk *    notice, this list of conditions and the following disclaimer in the
12109524Sphk *    documentation and/or other materials provided with the distribution.
13109524Sphk *
14109524Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15109524Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16109524Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17109524Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18109524Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19109524Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20109524Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21109524Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22109524Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23109524Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24109524Sphk * SUCH DAMAGE.
25109524Sphk *
26109524Sphk * $FreeBSD: head/sys/kern/tty_tty.c 109524 2003-01-19 10:23:47Z phk $
27109524Sphk */
28109524Sphk
29109524Sphk#include <sys/param.h>
30109524Sphk#include <sys/systm.h>
31109524Sphk#include <sys/conf.h>
32109524Sphk#include <sys/kernel.h>
33109524Sphk#include <sys/proc.h>
34109524Sphk#include <sys/vnode.h>
35109524Sphk
36109524Sphkstatic	d_open_t	cttyopen;
37109524Sphk
38109524Sphk#define	CDEV_MAJOR	1
39109524Sphk
40109524Sphkstatic struct cdevsw ctty_cdevsw = {
41109524Sphk	/* open */	cttyopen,
42109524Sphk	/* close */	nullclose,
43109524Sphk	/* read */	noread,
44109524Sphk	/* write */	nowrite,
45109524Sphk	/* ioctl */	noioctl,
46109524Sphk	/* poll */	nopoll,
47109524Sphk	/* mmap */	nommap,
48109524Sphk	/* strategy */	nostrategy,
49109524Sphk	/* name */	"ctty",
50109524Sphk	/* maj */	CDEV_MAJOR,
51109524Sphk	/* dump */	nodump,
52109524Sphk	/* psize */	nopsize,
53109524Sphk	/* flags */	D_TTY,
54109524Sphk};
55109524Sphk
56109524Sphkstatic dev_t ctty;
57109524Sphk
58109524Sphkstatic	int
59109524Sphkcttyopen(dev_t dev, int flag, int mode, struct thread *td)
60109524Sphk{
61109524Sphk
62109524Sphk	return (ENXIO);
63109524Sphk}
64109524Sphk
65109524Sphkstatic void
66109524Sphkctty_clone(void *arg, char *name, int namelen, dev_t *dev)
67109524Sphk{
68109524Sphk
69109524Sphk	if (*dev != NODEV)
70109524Sphk		return;
71109524Sphk	if (strcmp(name, "tty"))
72109524Sphk		return;
73109524Sphk	if (curthread->td_proc->p_flag & P_CONTROLT)
74109524Sphk		*dev = curthread->td_proc->p_session->s_ttyvp->v_rdev;
75109524Sphk	else
76109524Sphk		*dev = ctty;
77109524Sphk}
78109524Sphk
79109524Sphkstatic void
80109524Sphkctty_drvinit(void *unused)
81109524Sphk{
82109524Sphk
83109524Sphk	EVENTHANDLER_REGISTER(dev_clone, ctty_clone, 0, 1000);
84109524Sphk	ctty = make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "ctty");
85109524Sphk}
86109524Sphk
87109524SphkSYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL)
88109524Sphk#else
89109524Sphk/*-
901541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993
911541Srgrimes *	The Regents of the University of California.  All rights reserved.
921541Srgrimes *
931541Srgrimes * Redistribution and use in source and binary forms, with or without
941541Srgrimes * modification, are permitted provided that the following conditions
951541Srgrimes * are met:
961541Srgrimes * 1. Redistributions of source code must retain the above copyright
971541Srgrimes *    notice, this list of conditions and the following disclaimer.
981541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
991541Srgrimes *    notice, this list of conditions and the following disclaimer in the
1001541Srgrimes *    documentation and/or other materials provided with the distribution.
1011541Srgrimes * 3. All advertising materials mentioning features or use of this software
1021541Srgrimes *    must display the following acknowledgement:
1031541Srgrimes *	This product includes software developed by the University of
1041541Srgrimes *	California, Berkeley and its contributors.
1051541Srgrimes * 4. Neither the name of the University nor the names of its contributors
1061541Srgrimes *    may be used to endorse or promote products derived from this software
1071541Srgrimes *    without specific prior written permission.
1081541Srgrimes *
1091541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1101541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1111541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1121541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1131541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1141541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1151541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1161541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1171541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1181541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1191541Srgrimes * SUCH DAMAGE.
1201541Srgrimes *
1211541Srgrimes *	@(#)tty_tty.c	8.2 (Berkeley) 9/23/93
12250477Speter * $FreeBSD: head/sys/kern/tty_tty.c 109524 2003-01-19 10:23:47Z phk $
1231541Srgrimes */
1241541Srgrimes
1251541Srgrimes/*
1261541Srgrimes * Indirect driver for controlling tty.
1271541Srgrimes */
12832726Seivind
129101124Srwatson#include "opt_mac.h"
130101124Srwatson
1311541Srgrimes#include <sys/param.h>
13229354Speter#include <sys/systm.h>
1331541Srgrimes#include <sys/conf.h>
13476166Smarkm#include <sys/kernel.h>
13531561Sbde#include <sys/lock.h>
136101173Srwatson#include <sys/mac.h>
13791140Stanimura#include <sys/mutex.h>
13891140Stanimura#include <sys/sx.h>
1391541Srgrimes#include <sys/proc.h>
14031262Sbde#include <sys/ttycom.h>
1411541Srgrimes#include <sys/vnode.h>
14212675Sjulian
14312675Sjulianstatic	d_open_t	cttyopen;
14412675Sjulianstatic	d_read_t	cttyread;
14512675Sjulianstatic	d_write_t	cttywrite;
14612675Sjulianstatic	d_ioctl_t	cttyioctl;
14729354Speterstatic	d_poll_t	cttypoll;
14812675Sjulian
14938485Sbde#define	CDEV_MAJOR	1
15076572Sphk
15176572Sphkstatic struct cdevsw ctty_cdevsw = {
15247625Sphk	/* open */	cttyopen,
15347625Sphk	/* close */	nullclose,
15447625Sphk	/* read */	cttyread,
15547625Sphk	/* write */	cttywrite,
15647625Sphk	/* ioctl */	cttyioctl,
15747625Sphk	/* poll */	cttypoll,
15847625Sphk	/* mmap */	nommap,
15947625Sphk	/* strategy */	nostrategy,
16047625Sphk	/* name */	"ctty",
16147625Sphk	/* maj */	CDEV_MAJOR,
16247625Sphk	/* dump */	nodump,
16347625Sphk	/* psize */	nopsize,
16447625Sphk	/* flags */	D_TTY,
16538485Sbde};
16612517Sjulian
16783366Sjulian#define cttyvp(td) ((td)->td_proc->p_flag & P_CONTROLT ? (td)->td_proc->p_session->s_ttyvp : NULL)
1681541Srgrimes
1691541Srgrimes/*ARGSUSED*/
17012675Sjulianstatic	int
17183366Sjuliancttyopen(dev, flag, mode, td)
1721541Srgrimes	dev_t dev;
1731541Srgrimes	int flag, mode;
17483366Sjulian	struct thread *td;
1751541Srgrimes{
17691140Stanimura	struct vnode *ttyvp;
1771541Srgrimes	int error;
1781541Srgrimes
17991140Stanimura	PROC_LOCK(td->td_proc);
18091140Stanimura	SESS_LOCK(td->td_proc->p_session);
18191140Stanimura	ttyvp = cttyvp(td);
18291140Stanimura	SESS_UNLOCK(td->td_proc->p_session);
18391140Stanimura	PROC_UNLOCK(td->td_proc);
18491140Stanimura
1851541Srgrimes	if (ttyvp == NULL)
1861541Srgrimes		return (ENXIO);
18783366Sjulian	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
188101124Srwatson#ifdef MAC
189101124Srwatson	error = mac_check_vnode_open(td->td_ucred, ttyvp, flag);
190101124Srwatson	if (error) {
191101124Srwatson		VOP_UNLOCK(ttyvp, 0, td);
192101124Srwatson		return (error);
193101124Srwatson	}
194101124Srwatson#endif
195102129Srwatson	/* XXX: Shouldn't this cred be td->td_ucred not NOCRED? */
19683366Sjulian	error = VOP_OPEN(ttyvp, flag, NOCRED, td);
19783366Sjulian	VOP_UNLOCK(ttyvp, 0, td);
1981541Srgrimes	return (error);
1991541Srgrimes}
2001541Srgrimes
2011541Srgrimes/*ARGSUSED*/
20212675Sjulianstatic	int
2031541Srgrimescttyread(dev, uio, flag)
2041541Srgrimes	dev_t dev;
2051541Srgrimes	struct uio *uio;
2061541Srgrimes	int flag;
2071541Srgrimes{
20883366Sjulian	struct thread *td = uio->uio_td;
20991140Stanimura	register struct vnode *ttyvp;
2101541Srgrimes	int error;
2111541Srgrimes
21291140Stanimura	PROC_LOCK(td->td_proc);
21391140Stanimura	SESS_LOCK(td->td_proc->p_session);
21491140Stanimura	ttyvp = cttyvp(td);
21591140Stanimura	SESS_UNLOCK(td->td_proc->p_session);
21691140Stanimura	PROC_UNLOCK(td->td_proc);
21791140Stanimura
2181541Srgrimes	if (ttyvp == NULL)
2191541Srgrimes		return (EIO);
22083366Sjulian	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
221101745Srwatson#ifdef MAC
222102129Srwatson	error = mac_check_vnode_read(td->td_ucred, NOCRED, ttyvp);
223101745Srwatson	if (error == 0)
224101745Srwatson#endif
225102129Srwatson		/* XXX: Shouldn't this cred be td->td_ucred not NOCRED? */
226101745Srwatson		error = VOP_READ(ttyvp, uio, flag, NOCRED);
22783366Sjulian	VOP_UNLOCK(ttyvp, 0, td);
2281541Srgrimes	return (error);
2291541Srgrimes}
2301541Srgrimes
2311541Srgrimes/*ARGSUSED*/
23212675Sjulianstatic	int
2331541Srgrimescttywrite(dev, uio, flag)
2341541Srgrimes	dev_t dev;
2351541Srgrimes	struct uio *uio;
2361541Srgrimes	int flag;
2371541Srgrimes{
23883366Sjulian	struct thread *td = uio->uio_td;
23991140Stanimura	struct vnode *ttyvp;
24062976Smckusick	struct mount *mp;
2411541Srgrimes	int error;
2421541Srgrimes
24391140Stanimura	PROC_LOCK(td->td_proc);
24491140Stanimura	SESS_LOCK(td->td_proc->p_session);
24591140Stanimura	ttyvp = cttyvp(td);
24691140Stanimura	SESS_UNLOCK(td->td_proc->p_session);
24791140Stanimura	PROC_UNLOCK(td->td_proc);
24891140Stanimura
2491541Srgrimes	if (ttyvp == NULL)
2501541Srgrimes		return (EIO);
25162976Smckusick	mp = NULL;
25262976Smckusick	if (ttyvp->v_type != VCHR &&
25362976Smckusick	    (error = vn_start_write(ttyvp, &mp, V_WAIT | PCATCH)) != 0)
25462976Smckusick		return (error);
25583366Sjulian	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
256101124Srwatson#ifdef MAC
257102129Srwatson	error = mac_check_vnode_write(td->td_ucred, NOCRED, ttyvp);
258101124Srwatson	if (error == 0)
259101124Srwatson#endif
260102129Srwatson		/* XXX: shouldn't this cred be td->td_ucred not NOCRED? */
261101124Srwatson		error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
26283366Sjulian	VOP_UNLOCK(ttyvp, 0, td);
26362976Smckusick	vn_finished_write(mp);
2641541Srgrimes	return (error);
2651541Srgrimes}
2661541Srgrimes
2671541Srgrimes/*ARGSUSED*/
26812675Sjulianstatic	int
26983366Sjuliancttyioctl(dev, cmd, addr, flag, td)
2701541Srgrimes	dev_t dev;
27136735Sdfr	u_long cmd;
2721541Srgrimes	caddr_t addr;
2731541Srgrimes	int flag;
27483366Sjulian	struct thread *td;
2751541Srgrimes{
27691140Stanimura	struct vnode *ttyvp;
27791140Stanimura	int error;
2781541Srgrimes
27991140Stanimura	PROC_LOCK(td->td_proc);
28091140Stanimura	SESS_LOCK(td->td_proc->p_session);
28191140Stanimura	ttyvp = cttyvp(td);
28291140Stanimura	SESS_UNLOCK(td->td_proc->p_session);
28391140Stanimura	PROC_UNLOCK(td->td_proc);
28491140Stanimura
2851541Srgrimes	if (ttyvp == NULL)
2861541Srgrimes		return (EIO);
2874939Sache	if (cmd == TIOCSCTTY)  /* don't allow controlling tty to be set    */
2884939Sache		return EINVAL; /* to controlling tty -- infinite recursion */
2891541Srgrimes	if (cmd == TIOCNOTTY) {
29091140Stanimura		PROC_LOCK(td->td_proc);
29191140Stanimura		SESS_LOCK(td->td_proc->p_session);
29291140Stanimura		error = 0;
29391140Stanimura		if (!SESS_LEADER(td->td_proc))
29483366Sjulian			td->td_proc->p_flag &= ~P_CONTROLT;
29591140Stanimura		else
29691140Stanimura			error = EINVAL;
29791140Stanimura		SESS_UNLOCK(td->td_proc->p_session);
29891140Stanimura		PROC_UNLOCK(td->td_proc);
29991140Stanimura		return (error);
3001541Srgrimes	}
301101124Srwatson	/* XXXMAC: Should this be td->td_ucred below? */
30283366Sjulian	return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, td));
3031541Srgrimes}
3041541Srgrimes
3051541Srgrimes/*ARGSUSED*/
30612675Sjulianstatic	int
30783366Sjuliancttypoll(dev, events, td)
3081541Srgrimes	dev_t dev;
30929354Speter	int events;
31083366Sjulian	struct thread *td;
3111541Srgrimes{
31291140Stanimura	struct vnode *ttyvp;
313101124Srwatson#ifdef MAC
314101124Srwatson	int error;
315101124Srwatson#endif
3161541Srgrimes
31791140Stanimura	PROC_LOCK(td->td_proc);
31891140Stanimura	SESS_LOCK(td->td_proc->p_session);
31991140Stanimura	ttyvp = cttyvp(td);
32091140Stanimura	SESS_UNLOCK(td->td_proc->p_session);
32191140Stanimura	PROC_UNLOCK(td->td_proc);
32291140Stanimura
3231541Srgrimes	if (ttyvp == NULL)
32429354Speter		/* try operation to get EOF/failure */
32583366Sjulian		return (seltrue(dev, events, td));
326101124Srwatson#ifdef MAC
327101124Srwatson	vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
328102129Srwatson	error = mac_check_vnode_poll(td->td_ucred, NOCRED, ttyvp);
329101124Srwatson	VOP_UNLOCK(ttyvp, 0, td);
330101124Srwatson	if (error)
331101124Srwatson		return (error);
332101124Srwatson#endif
33391406Sjhb	return (VOP_POLL(ttyvp, events, td->td_ucred, td));
3341541Srgrimes}
33512517Sjulian
33692723Salfredstatic void ctty_clone(void *arg, char *name, int namelen, dev_t *dev);
33776572Sphk
33876628Sbrianstatic dev_t ctty;
33976628Sbrian
34076572Sphkstatic void
34176572Sphkctty_clone(void *arg, char *name, int namelen, dev_t *dev)
34276572Sphk{
34376572Sphk	struct vnode *vp;
34476572Sphk
34576572Sphk	if (*dev != NODEV)
34676572Sphk		return;
34776572Sphk	if (strcmp(name, "tty"))
34876572Sphk		return;
34983366Sjulian	vp = cttyvp(curthread);
35076628Sbrian	if (vp == NULL) {
35176628Sbrian		if (ctty)
35276628Sbrian			*dev = ctty;
35376628Sbrian	} else
35476628Sbrian		*dev = vp->v_rdev;
35576572Sphk}
35676572Sphk
35776572Sphk
35892723Salfredstatic void ctty_drvinit(void *unused);
35912675Sjulianstatic void
36029506Sbdectty_drvinit(unused)
36129506Sbde	void *unused;
36212517Sjulian{
36312517Sjulian
36476572Sphk	if (devfs_present) {
36576572Sphk		EVENTHANDLER_REGISTER(dev_clone, ctty_clone, 0, 1000);
36676628Sbrian		ctty = make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "ctty");
36776572Sphk	} else {
36876572Sphk		make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "tty");
36976572Sphk	}
37012517Sjulian}
37112517Sjulian
37212517SjulianSYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL)
373109524Sphk#endif
374