1 /* $OpenBSD: cons.c,v 1.10 2001/04/17 04:30:49 aaron Exp $ */ 2 /* $NetBSD: cons.c,v 1.30 1996/04/08 19:57:30 jonathan Exp $ */ 3 4 /* 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1990, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: Utah $Hdr: cons.c 1.7 92/01/21$ 42 * 43 * @(#)cons.c 8.2 (Berkeley) 1/12/94 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/proc.h> 49 #include <sys/user.h> 50 #include <sys/buf.h> 51 #include <sys/ioctl.h> 52 #include <sys/tty.h> 53 #include <sys/file.h> 54 #include <sys/conf.h> 55 #include <sys/vnode.h> 56 57 #include <dev/cons.h> 58 59 struct tty *constty = NULL; /* virtual console output device */ 60 struct consdev *cn_tab; /* physical console device info */ 61 struct vnode *cn_devvp; /* vnode for underlying device. */ 62 63 int 64 cnopen(dev, flag, mode, p) 65 dev_t dev; 66 int flag, mode; 67 struct proc *p; 68 { 69 dev_t cndev; 70 71 if (cn_tab == NULL) 72 return (0); 73 74 /* 75 * always open the 'real' console device, so we don't get nailed 76 * later. This follows normal device semantics; they always get 77 * open() calls. 78 */ 79 cndev = cn_tab->cn_dev; 80 if (cndev == NODEV) 81 return (ENXIO); 82 #ifdef DIAGNOSTIC 83 if (cndev == dev) 84 panic("cnopen: recursive"); 85 #endif 86 if (cn_devvp == NULLVP) { 87 /* try to get a reference on its vnode, but fail silently */ 88 cdevvp(cndev, &cn_devvp); 89 } 90 return ((*cdevsw[major(cndev)].d_open)(cndev, flag, mode, p)); 91 } 92 93 int 94 cnclose(dev, flag, mode, p) 95 dev_t dev; 96 int flag, mode; 97 struct proc *p; 98 { 99 struct vnode *vp; 100 101 if (cn_tab == NULL) 102 return (0); 103 104 /* 105 * If the real console isn't otherwise open, close it. 106 * If it's otherwise open, don't close it, because that'll 107 * screw up others who have it open. 108 */ 109 dev = cn_tab->cn_dev; 110 if (cn_devvp != NULLVP) { 111 /* release our reference to real dev's vnode */ 112 vrele(cn_devvp); 113 cn_devvp = NULLVP; 114 } 115 if (vfinddev(dev, VCHR, &vp) && vcount(vp)) 116 return (0); 117 return ((*cdevsw[major(dev)].d_close)(dev, flag, mode, p)); 118 } 119 120 int 121 cnread(dev, uio, flag) 122 dev_t dev; 123 struct uio *uio; 124 int flag; 125 { 126 127 /* 128 * If we would redirect input, punt. This will keep strange 129 * things from happening to people who are using the real 130 * console. Nothing should be using /dev/console for 131 * input (except a shell in single-user mode, but then, 132 * one wouldn't TIOCCONS then). 133 */ 134 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE)) 135 return 0; 136 else if (cn_tab == NULL) 137 return ENXIO; 138 139 dev = cn_tab->cn_dev; 140 return ((*cdevsw[major(dev)].d_read)(dev, uio, flag)); 141 } 142 143 int 144 cnwrite(dev, uio, flag) 145 dev_t dev; 146 struct uio *uio; 147 int flag; 148 { 149 150 /* 151 * Redirect output, if that's appropriate. 152 * If there's no real console, return ENXIO. 153 */ 154 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE)) 155 dev = constty->t_dev; 156 else if (cn_tab == NULL) 157 return ENXIO; 158 else 159 dev = cn_tab->cn_dev; 160 return ((*cdevsw[major(dev)].d_write)(dev, uio, flag)); 161 } 162 163 int 164 cnstop(tp, flag) 165 struct tty *tp; 166 int flag; 167 { 168 return (0); 169 } 170 171 int 172 cnioctl(dev, cmd, data, flag, p) 173 dev_t dev; 174 u_long cmd; 175 caddr_t data; 176 int flag; 177 struct proc *p; 178 { 179 int error; 180 181 /* 182 * Superuser can always use this to wrest control of console 183 * output from the "virtual" console. 184 */ 185 if (cmd == TIOCCONS && constty != NULL) { 186 error = suser(p->p_ucred, (u_short *) NULL); 187 if (error) 188 return (error); 189 constty = NULL; 190 return (0); 191 } 192 193 /* 194 * Redirect the ioctl, if that's appropriate. 195 * Note that strange things can happen, if a program does 196 * ioctls on /dev/console, then the console is redirected 197 * out from under it. 198 */ 199 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE)) 200 dev = constty->t_dev; 201 else if (cn_tab == NULL) 202 return ENXIO; 203 else 204 dev = cn_tab->cn_dev; 205 return ((*cdevsw[major(dev)].d_ioctl)(dev, cmd, data, flag, p)); 206 } 207 208 /*ARGSUSED*/ 209 int 210 cnselect(dev, rw, p) 211 dev_t dev; 212 int rw; 213 struct proc *p; 214 { 215 216 /* 217 * Redirect the select, if that's appropriate. 218 * I don't want to think of the possible side effects 219 * of console redirection here. 220 */ 221 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE)) 222 dev = constty->t_dev; 223 else if (cn_tab == NULL) 224 return ENXIO; 225 else 226 dev = cn_tab->cn_dev; 227 return (ttselect(cn_tab->cn_dev, rw, p)); 228 } 229 230 231 int 232 cnkqfilter(dev, kn) 233 dev_t dev; 234 struct knote *kn; 235 { 236 if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE)) 237 return 0; 238 if (cn_tab == NULL) 239 return (1); 240 241 dev = cn_tab->cn_dev; 242 if (cdevsw[major(dev)].d_type & D_KQFILTER) 243 return ((*cdevsw[major(dev)].d_kqfilter)(dev, kn)); 244 return (1); 245 } 246 247 int 248 cngetc() 249 { 250 251 if (cn_tab == NULL) 252 return (0); 253 return ((*cn_tab->cn_getc)(cn_tab->cn_dev)); 254 } 255 256 void 257 cnputc(c) 258 register int c; 259 { 260 261 if (cn_tab == NULL) 262 return; 263 264 if (c) { 265 (*cn_tab->cn_putc)(cn_tab->cn_dev, c); 266 if (c == '\n') 267 (*cn_tab->cn_putc)(cn_tab->cn_dev, '\r'); 268 } 269 } 270 271 void 272 cnpollc(on) 273 int on; 274 { 275 static int refcount = 0; 276 277 if (cn_tab == NULL) 278 return; 279 if (!on) 280 --refcount; 281 if (refcount == 0) 282 (*cn_tab->cn_pollc)(cn_tab->cn_dev, on); 283 if (on) 284 ++refcount; 285 } 286 287 void 288 nullcnpollc(dev, on) 289 dev_t dev; 290 int on; 291 { 292 293 } 294 295 void 296 cnbell(pitch, period, volume) 297 u_int pitch, period, volume; 298 { 299 if (cn_tab == NULL || cn_tab->cn_bell == NULL) 300 return; 301 302 (*cn_tab->cn_bell)(cn_tab->cn_dev, pitch, period, volume); 303 } 304 305