1 #ifndef NODEVFS 2 /*- 3 * Copyright (c) 2003 Poul-Henning Kamp. 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 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/conf.h> 32 #include <sys/kernel.h> 33 #include <sys/proc.h> 34 #include <sys/vnode.h> 35 36 static d_open_t cttyopen; 37 38 #define CDEV_MAJOR 1 39 40 static struct cdevsw ctty_cdevsw = { 41 /* open */ cttyopen, 42 /* close */ nullclose, 43 /* read */ noread, 44 /* write */ nowrite, 45 /* ioctl */ noioctl, 46 /* poll */ nopoll, 47 /* mmap */ nommap, 48 /* strategy */ nostrategy, 49 /* name */ "ctty", 50 /* maj */ CDEV_MAJOR, 51 /* dump */ nodump, 52 /* psize */ nopsize, 53 /* flags */ D_TTY, 54 }; 55 56 static dev_t ctty; 57 58 static int 59 cttyopen(dev_t dev, int flag, int mode, struct thread *td) 60 { 61 62 return (ENXIO); 63 } 64 65 static void 66 ctty_clone(void *arg, char *name, int namelen, dev_t *dev) 67 { 68 69 if (*dev != NODEV) 70 return; 71 if (strcmp(name, "tty")) 72 return; 73 if (!(curthread->td_proc->p_flag & P_CONTROLT)) 74 *dev = ctty; 75 else if (curthread->td_proc->p_session->s_ttyvp == NULL) 76 *dev = ctty; 77 else 78 *dev = curthread->td_proc->p_session->s_ttyvp->v_rdev; 79 } 80 81 static void 82 ctty_drvinit(void *unused) 83 { 84 85 EVENTHANDLER_REGISTER(dev_clone, ctty_clone, 0, 1000); 86 ctty = make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "ctty"); 87 } 88 89 SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL) 90 #else 91 /*- 92 * Copyright (c) 1982, 1986, 1991, 1993 93 * The Regents of the University of California. All rights reserved. 94 * 95 * Redistribution and use in source and binary forms, with or without 96 * modification, are permitted provided that the following conditions 97 * are met: 98 * 1. Redistributions of source code must retain the above copyright 99 * notice, this list of conditions and the following disclaimer. 100 * 2. Redistributions in binary form must reproduce the above copyright 101 * notice, this list of conditions and the following disclaimer in the 102 * documentation and/or other materials provided with the distribution. 103 * 3. All advertising materials mentioning features or use of this software 104 * must display the following acknowledgement: 105 * This product includes software developed by the University of 106 * California, Berkeley and its contributors. 107 * 4. Neither the name of the University nor the names of its contributors 108 * may be used to endorse or promote products derived from this software 109 * without specific prior written permission. 110 * 111 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 112 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 113 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 114 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 115 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 116 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 117 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 118 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 119 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 120 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 121 * SUCH DAMAGE. 122 * 123 * @(#)tty_tty.c 8.2 (Berkeley) 9/23/93 124 * $FreeBSD$ 125 */ 126 127 /* 128 * Indirect driver for controlling tty. 129 */ 130 131 #include "opt_mac.h" 132 133 #include <sys/param.h> 134 #include <sys/systm.h> 135 #include <sys/conf.h> 136 #include <sys/kernel.h> 137 #include <sys/lock.h> 138 #include <sys/mac.h> 139 #include <sys/mutex.h> 140 #include <sys/sx.h> 141 #include <sys/proc.h> 142 #include <sys/ttycom.h> 143 #include <sys/vnode.h> 144 145 static d_open_t cttyopen; 146 static d_read_t cttyread; 147 static d_write_t cttywrite; 148 static d_ioctl_t cttyioctl; 149 static d_poll_t cttypoll; 150 151 #define CDEV_MAJOR 1 152 153 static struct cdevsw ctty_cdevsw = { 154 /* open */ cttyopen, 155 /* close */ nullclose, 156 /* read */ cttyread, 157 /* write */ cttywrite, 158 /* ioctl */ cttyioctl, 159 /* poll */ cttypoll, 160 /* mmap */ nommap, 161 /* strategy */ nostrategy, 162 /* name */ "ctty", 163 /* maj */ CDEV_MAJOR, 164 /* dump */ nodump, 165 /* psize */ nopsize, 166 /* flags */ D_TTY, 167 }; 168 169 #define cttyvp(td) ((td)->td_proc->p_flag & P_CONTROLT ? (td)->td_proc->p_session->s_ttyvp : NULL) 170 171 /*ARGSUSED*/ 172 static int 173 cttyopen(dev, flag, mode, td) 174 dev_t dev; 175 int flag, mode; 176 struct thread *td; 177 { 178 struct vnode *ttyvp; 179 int error; 180 181 PROC_LOCK(td->td_proc); 182 SESS_LOCK(td->td_proc->p_session); 183 ttyvp = cttyvp(td); 184 SESS_UNLOCK(td->td_proc->p_session); 185 PROC_UNLOCK(td->td_proc); 186 187 if (ttyvp == NULL) 188 return (ENXIO); 189 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); 190 #ifdef MAC 191 error = mac_check_vnode_open(td->td_ucred, ttyvp, flag); 192 if (error) { 193 VOP_UNLOCK(ttyvp, 0, td); 194 return (error); 195 } 196 #endif 197 /* XXX: Shouldn't this cred be td->td_ucred not NOCRED? */ 198 error = VOP_OPEN(ttyvp, flag, NOCRED, td); 199 VOP_UNLOCK(ttyvp, 0, td); 200 return (error); 201 } 202 203 /*ARGSUSED*/ 204 static int 205 cttyread(dev, uio, flag) 206 dev_t dev; 207 struct uio *uio; 208 int flag; 209 { 210 struct thread *td = uio->uio_td; 211 register struct vnode *ttyvp; 212 int error; 213 214 PROC_LOCK(td->td_proc); 215 SESS_LOCK(td->td_proc->p_session); 216 ttyvp = cttyvp(td); 217 SESS_UNLOCK(td->td_proc->p_session); 218 PROC_UNLOCK(td->td_proc); 219 220 if (ttyvp == NULL) 221 return (EIO); 222 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); 223 #ifdef MAC 224 error = mac_check_vnode_read(td->td_ucred, NOCRED, ttyvp); 225 if (error == 0) 226 #endif 227 /* XXX: Shouldn't this cred be td->td_ucred not NOCRED? */ 228 error = VOP_READ(ttyvp, uio, flag, NOCRED); 229 VOP_UNLOCK(ttyvp, 0, td); 230 return (error); 231 } 232 233 /*ARGSUSED*/ 234 static int 235 cttywrite(dev, uio, flag) 236 dev_t dev; 237 struct uio *uio; 238 int flag; 239 { 240 struct thread *td = uio->uio_td; 241 struct vnode *ttyvp; 242 struct mount *mp; 243 int error; 244 245 PROC_LOCK(td->td_proc); 246 SESS_LOCK(td->td_proc->p_session); 247 ttyvp = cttyvp(td); 248 SESS_UNLOCK(td->td_proc->p_session); 249 PROC_UNLOCK(td->td_proc); 250 251 if (ttyvp == NULL) 252 return (EIO); 253 mp = NULL; 254 if (ttyvp->v_type != VCHR && 255 (error = vn_start_write(ttyvp, &mp, V_WAIT | PCATCH)) != 0) 256 return (error); 257 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); 258 #ifdef MAC 259 error = mac_check_vnode_write(td->td_ucred, NOCRED, ttyvp); 260 if (error == 0) 261 #endif 262 /* XXX: shouldn't this cred be td->td_ucred not NOCRED? */ 263 error = VOP_WRITE(ttyvp, uio, flag, NOCRED); 264 VOP_UNLOCK(ttyvp, 0, td); 265 vn_finished_write(mp); 266 return (error); 267 } 268 269 /*ARGSUSED*/ 270 static int 271 cttyioctl(dev, cmd, addr, flag, td) 272 dev_t dev; 273 u_long cmd; 274 caddr_t addr; 275 int flag; 276 struct thread *td; 277 { 278 struct vnode *ttyvp; 279 int error; 280 281 PROC_LOCK(td->td_proc); 282 SESS_LOCK(td->td_proc->p_session); 283 ttyvp = cttyvp(td); 284 SESS_UNLOCK(td->td_proc->p_session); 285 PROC_UNLOCK(td->td_proc); 286 287 if (ttyvp == NULL) 288 return (EIO); 289 if (cmd == TIOCSCTTY) /* don't allow controlling tty to be set */ 290 return EINVAL; /* to controlling tty -- infinite recursion */ 291 if (cmd == TIOCNOTTY) { 292 PROC_LOCK(td->td_proc); 293 SESS_LOCK(td->td_proc->p_session); 294 error = 0; 295 if (!SESS_LEADER(td->td_proc)) 296 td->td_proc->p_flag &= ~P_CONTROLT; 297 else 298 error = EINVAL; 299 SESS_UNLOCK(td->td_proc->p_session); 300 PROC_UNLOCK(td->td_proc); 301 return (error); 302 } 303 /* XXXMAC: Should this be td->td_ucred below? */ 304 return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, td)); 305 } 306 307 /*ARGSUSED*/ 308 static int 309 cttypoll(dev, events, td) 310 dev_t dev; 311 int events; 312 struct thread *td; 313 { 314 struct vnode *ttyvp; 315 #ifdef MAC 316 int error; 317 #endif 318 319 PROC_LOCK(td->td_proc); 320 SESS_LOCK(td->td_proc->p_session); 321 ttyvp = cttyvp(td); 322 SESS_UNLOCK(td->td_proc->p_session); 323 PROC_UNLOCK(td->td_proc); 324 325 if (ttyvp == NULL) 326 /* try operation to get EOF/failure */ 327 return (seltrue(dev, events, td)); 328 #ifdef MAC 329 vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td); 330 error = mac_check_vnode_poll(td->td_ucred, NOCRED, ttyvp); 331 VOP_UNLOCK(ttyvp, 0, td); 332 if (error) 333 return (error); 334 #endif 335 return (VOP_POLL(ttyvp, events, td->td_ucred, td)); 336 } 337 338 static void ctty_clone(void *arg, char *name, int namelen, dev_t *dev); 339 340 static dev_t ctty; 341 342 static void 343 ctty_clone(void *arg, char *name, int namelen, dev_t *dev) 344 { 345 struct vnode *vp; 346 347 if (*dev != NODEV) 348 return; 349 if (strcmp(name, "tty")) 350 return; 351 vp = cttyvp(curthread); 352 if (vp == NULL) { 353 if (ctty) 354 *dev = ctty; 355 } else 356 *dev = vp->v_rdev; 357 } 358 359 360 static void ctty_drvinit(void *unused); 361 static void 362 ctty_drvinit(unused) 363 void *unused; 364 { 365 366 make_dev(&ctty_cdevsw, 0, 0, 0, 0666, "tty"); 367 } 368 369 SYSINIT(cttydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ctty_drvinit,NULL) 370 #endif 371