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