tty_tty.c revision 76572
1214082Sdim/*- 2214082Sdim * Copyright (c) 1982, 1986, 1991, 1993 3214082Sdim * The Regents of the University of California. All rights reserved. 4214082Sdim * 5214082Sdim * Redistribution and use in source and binary forms, with or without 6214082Sdim * modification, are permitted provided that the following conditions 7214082Sdim * are met: 8214082Sdim * 1. Redistributions of source code must retain the above copyright 9214082Sdim * notice, this list of conditions and the following disclaimer. 10214082Sdim * 2. Redistributions in binary form must reproduce the above copyright 11214082Sdim * notice, this list of conditions and the following disclaimer in the 12214082Sdim * documentation and/or other materials provided with the distribution. 13214082Sdim * 3. All advertising materials mentioning features or use of this software 14214082Sdim * must display the following acknowledgement: 15214082Sdim * This product includes software developed by the University of 16214082Sdim * California, Berkeley and its contributors. 17214082Sdim * 4. Neither the name of the University nor the names of its contributors 18214082Sdim * may be used to endorse or promote products derived from this software 19214082Sdim * without specific prior written permission. 20214082Sdim * 21214082Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22214082Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23214082Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24214082Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25214082Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26214082Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27214082Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28214082Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29214082Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30214082Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31214082Sdim * SUCH DAMAGE. 32214082Sdim * 33214082Sdim * @(#)tty_tty.c 8.2 (Berkeley) 9/23/93 34214082Sdim * $FreeBSD: head/sys/kern/tty_tty.c 76572 2001-05-14 08:22:56Z phk $ 35214082Sdim */ 36214082Sdim 37214082Sdim/* 38214082Sdim * Indirect driver for controlling tty. 39214082Sdim */ 40214082Sdim 41214082Sdim#include <sys/param.h> 42214082Sdim#include <sys/systm.h> 43214082Sdim#include <sys/conf.h> 44214082Sdim#include <sys/kernel.h> 45214082Sdim#include <sys/lock.h> 46214082Sdim#include <sys/proc.h> 47214082Sdim#include <sys/ttycom.h> 48214082Sdim#include <sys/vnode.h> 49214082Sdim 50214082Sdimstatic d_open_t cttyopen; 51214082Sdimstatic d_read_t cttyread; 52214082Sdimstatic d_write_t cttywrite; 53214082Sdimstatic d_ioctl_t cttyioctl; 54214082Sdimstatic d_poll_t cttypoll; 55214082Sdim 56214082Sdim#define CDEV_MAJOR 1 57214082Sdim 58214082Sdimstatic struct cdevsw ctty_cdevsw = { 59214082Sdim /* open */ cttyopen, 60214082Sdim /* close */ nullclose, 61214082Sdim /* read */ cttyread, 62214082Sdim /* write */ cttywrite, 63214082Sdim /* ioctl */ cttyioctl, 64214082Sdim /* poll */ cttypoll, 65214082Sdim /* mmap */ nommap, 66214082Sdim /* strategy */ nostrategy, 67214082Sdim /* 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 error = VOP_OPEN(ttyvp, flag, NOCRED, p); 90 VOP_UNLOCK(ttyvp, 0, p); 91 return (error); 92} 93 94/*ARGSUSED*/ 95static int 96cttyread(dev, uio, flag) 97 dev_t dev; 98 struct uio *uio; 99 int flag; 100{ 101 struct proc *p = uio->uio_procp; 102 register struct vnode *ttyvp = cttyvp(p); 103 int error; 104 105 if (ttyvp == NULL) 106 return (EIO); 107 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); 108 error = VOP_READ(ttyvp, uio, flag, NOCRED); 109 VOP_UNLOCK(ttyvp, 0, p); 110 return (error); 111} 112 113/*ARGSUSED*/ 114static int 115cttywrite(dev, uio, flag) 116 dev_t dev; 117 struct uio *uio; 118 int flag; 119{ 120 struct proc *p = uio->uio_procp; 121 struct vnode *ttyvp = cttyvp(uio->uio_procp); 122 struct mount *mp; 123 int error; 124 125 if (ttyvp == NULL) 126 return (EIO); 127 mp = NULL; 128 if (ttyvp->v_type != VCHR && 129 (error = vn_start_write(ttyvp, &mp, V_WAIT | PCATCH)) != 0) 130 return (error); 131 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, p); 132 error = VOP_WRITE(ttyvp, uio, flag, NOCRED); 133 VOP_UNLOCK(ttyvp, 0, p); 134 vn_finished_write(mp); 135 return (error); 136} 137 138/*ARGSUSED*/ 139static int 140cttyioctl(dev, cmd, addr, flag, p) 141 dev_t dev; 142 u_long cmd; 143 caddr_t addr; 144 int flag; 145 struct proc *p; 146{ 147 struct vnode *ttyvp = cttyvp(p); 148 149 if (ttyvp == NULL) 150 return (EIO); 151 if (cmd == TIOCSCTTY) /* don't allow controlling tty to be set */ 152 return EINVAL; /* to controlling tty -- infinite recursion */ 153 if (cmd == TIOCNOTTY) { 154 if (!SESS_LEADER(p)) { 155 p->p_flag &= ~P_CONTROLT; 156 return (0); 157 } else 158 return (EINVAL); 159 } 160 return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, p)); 161} 162 163/*ARGSUSED*/ 164static int 165cttypoll(dev, events, p) 166 dev_t dev; 167 int events; 168 struct proc *p; 169{ 170 struct vnode *ttyvp = cttyvp(p); 171 172 if (ttyvp == NULL) 173 /* try operation to get EOF/failure */ 174 return (seltrue(dev, events, p)); 175 return (VOP_POLL(ttyvp, events, p->p_ucred, p)); 176} 177 178static void ctty_clone __P((void *arg, char *name, int namelen, dev_t *dev)); 179 180static void 181ctty_clone(void *arg, char *name, int namelen, dev_t *dev) 182{ 183 struct vnode *vp; 184 185 if (*dev != NODEV) 186 return; 187 if (strcmp(name, "tty")) 188 return; 189 vp = cttyvp(curproc); 190 if (vp == NULL) 191 return; 192 *dev = vp->v_rdev; 193} 194 195 196static void ctty_drvinit __P((void *unused)); 197static void 198ctty_drvinit(unused) 199 void *unused; 200{ 201 202 if (devfs_present) { 203 EVENTHANDLER_REGISTER(dev_clone, ctty_clone, 0, 1000); 204 } else { 205 make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "tty"); 206 } 207} 208 209SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL) 210