1 /* 2 * Copyright (c) 1982, 1986, 1993 3 * The Regents of the University of California. 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 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)subr_log.c 8.1 (Berkeley) 6/10/93 34 * $Id: subr_log.c,v 1.11 1995/11/29 10:48:25 julian Exp $ 35 */ 36 37 /* 38 * Error log buffer for kernel printf's. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/proc.h> 44 #include <sys/vnode.h> 45 #include <sys/ioctl.h> 46 #include <sys/msgbuf.h> 47 #include <sys/file.h> 48 #include <sys/signalvar.h> 49 50 #ifdef JREMOD 51 #include <sys/conf.h> 52 #include <sys/kernel.h> 53 #ifdef DEVFS 54 #include <sys/devfsext.h> 55 #endif /*DEVFS*/ 56 #define CDEV_MAJOR 7 57 #endif /*JREMOD*/ 58 59 #define LOG_RDPRI (PZERO + 1) 60 61 #define LOG_ASYNC 0x04 62 #define LOG_RDWAIT 0x08 63 64 struct logsoftc { 65 int sc_state; /* see above for possibilities */ 66 struct selinfo sc_selp; /* process waiting on select call */ 67 int sc_pgid; /* process/group for async I/O */ 68 } logsoftc; 69 70 int log_open; /* also used in log() */ 71 72 /*ARGSUSED*/ 73 int 74 logopen(dev, flags, mode, p) 75 dev_t dev; 76 int flags, mode; 77 struct proc *p; 78 { 79 if (log_open) 80 return (EBUSY); 81 log_open = 1; 82 logsoftc.sc_pgid = p->p_pid; /* signal process only */ 83 return (0); 84 } 85 86 /*ARGSUSED*/ 87 int 88 logclose(dev, flag, mode, p) 89 dev_t dev; 90 int flag, mode; 91 struct proc *p; 92 { 93 94 log_open = 0; 95 logsoftc.sc_state = 0; 96 return (0); 97 } 98 99 /*ARGSUSED*/ 100 int 101 logread(dev, uio, flag) 102 dev_t dev; 103 struct uio *uio; 104 int flag; 105 { 106 register struct msgbuf *mbp = msgbufp; 107 register long l; 108 register int s; 109 int error = 0; 110 111 s = splhigh(); 112 while (mbp->msg_bufr == mbp->msg_bufx) { 113 if (flag & IO_NDELAY) { 114 splx(s); 115 return (EWOULDBLOCK); 116 } 117 logsoftc.sc_state |= LOG_RDWAIT; 118 if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 119 "klog", 0))) { 120 splx(s); 121 return (error); 122 } 123 } 124 splx(s); 125 logsoftc.sc_state &= ~LOG_RDWAIT; 126 127 while (uio->uio_resid > 0) { 128 l = mbp->msg_bufx - mbp->msg_bufr; 129 if (l < 0) 130 l = MSG_BSIZE - mbp->msg_bufr; 131 l = min(l, uio->uio_resid); 132 if (l == 0) 133 break; 134 error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr], 135 (int)l, uio); 136 if (error) 137 break; 138 mbp->msg_bufr += l; 139 if (mbp->msg_bufr >= MSG_BSIZE) 140 mbp->msg_bufr = 0; 141 } 142 return (error); 143 } 144 145 /*ARGSUSED*/ 146 int 147 logselect(dev, rw, p) 148 dev_t dev; 149 int rw; 150 struct proc *p; 151 { 152 int s = splhigh(); 153 154 switch (rw) { 155 156 case FREAD: 157 if (msgbufp->msg_bufr != msgbufp->msg_bufx) { 158 splx(s); 159 return (1); 160 } 161 selrecord(p, &logsoftc.sc_selp); 162 break; 163 } 164 splx(s); 165 return (0); 166 } 167 168 void 169 logwakeup() 170 { 171 struct proc *p; 172 173 if (!log_open) 174 return; 175 selwakeup(&logsoftc.sc_selp); 176 if (logsoftc.sc_state & LOG_ASYNC) { 177 if (logsoftc.sc_pgid < 0) 178 gsignal(-logsoftc.sc_pgid, SIGIO); 179 else if ((p = pfind(logsoftc.sc_pgid))) 180 psignal(p, SIGIO); 181 } 182 if (logsoftc.sc_state & LOG_RDWAIT) { 183 wakeup((caddr_t)msgbufp); 184 logsoftc.sc_state &= ~LOG_RDWAIT; 185 } 186 } 187 188 /*ARGSUSED*/ 189 int 190 logioctl(dev, com, data, flag, p) 191 dev_t dev; 192 int com; 193 caddr_t data; 194 int flag; 195 struct proc *p; 196 { 197 long l; 198 int s; 199 200 switch (com) { 201 202 /* return number of characters immediately available */ 203 case FIONREAD: 204 s = splhigh(); 205 l = msgbufp->msg_bufx - msgbufp->msg_bufr; 206 splx(s); 207 if (l < 0) 208 l += MSG_BSIZE; 209 *(int *)data = l; 210 break; 211 212 case FIONBIO: 213 break; 214 215 case FIOASYNC: 216 if (*(int *)data) 217 logsoftc.sc_state |= LOG_ASYNC; 218 else 219 logsoftc.sc_state &= ~LOG_ASYNC; 220 break; 221 222 case TIOCSPGRP: 223 logsoftc.sc_pgid = *(int *)data; 224 break; 225 226 case TIOCGPGRP: 227 *(int *)data = logsoftc.sc_pgid; 228 break; 229 230 default: 231 return (ENOTTY); 232 } 233 return (0); 234 } 235 236 #ifdef JREMOD 237 struct cdevsw log_cdevsw = 238 { logopen, logclose, logread, nowrite, /*7*/ 239 logioctl, nostop, nullreset, nodevtotty,/* klog */ 240 logselect, nommap, NULL }; 241 242 static log_devsw_installed = 0; 243 244 static void log_drvinit(void *unused) 245 { 246 dev_t dev; 247 248 if( ! log_devsw_installed ) { 249 dev = makedev(CDEV_MAJOR,0); 250 cdevsw_add(&dev,&log_cdevsw,NULL); 251 log_devsw_installed = 1; 252 #ifdef DEVFS 253 { 254 int x; 255 /* default for a simple device with no probe routine (usually delete this) */ 256 x=devfs_add_devsw( 257 /* path name devsw minor type uid gid perm*/ 258 "/", "log", major(dev), 0, DV_CHR, 0, 0, 0600); 259 } 260 #endif 261 } 262 } 263 264 SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL) 265 266 #endif /* JREMOD */ 267 268