subr_log.c revision 12678
1238106Sdes/* 2238106Sdes * Copyright (c) 1982, 1986, 1993 3238106Sdes * The Regents of the University of California. All rights reserved. 4238106Sdes * 5238106Sdes * Redistribution and use in source and binary forms, with or without 6238106Sdes * modification, are permitted provided that the following conditions 7238106Sdes * are met: 8238106Sdes * 1. Redistributions of source code must retain the above copyright 9238106Sdes * notice, this list of conditions and the following disclaimer. 10238106Sdes * 2. Redistributions in binary form must reproduce the above copyright 11238106Sdes * notice, this list of conditions and the following disclaimer in the 12238106Sdes * documentation and/or other materials provided with the distribution. 13238106Sdes * 3. All advertising materials mentioning features or use of this software 14238106Sdes * must display the following acknowledgement: 15238106Sdes * This product includes software developed by the University of 16238106Sdes * California, Berkeley and its contributors. 17238106Sdes * 4. Neither the name of the University nor the names of its contributors 18238106Sdes * may be used to endorse or promote products derived from this software 19238106Sdes * without specific prior written permission. 20238106Sdes * 21238106Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22238106Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23238106Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24238106Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25238106Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26238106Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27238106Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28238106Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29238106Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30238106Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31238106Sdes * SUCH DAMAGE. 32238106Sdes * 33238106Sdes * @(#)subr_log.c 8.1 (Berkeley) 6/10/93 34238106Sdes * $Id: subr_log.c,v 1.14 1995/12/08 11:17:06 julian Exp $ 35238106Sdes */ 36238106Sdes 37238106Sdes/* 38238106Sdes * Error log buffer for kernel printf's. 39238106Sdes */ 40238106Sdes 41238106Sdes#include <sys/param.h> 42238106Sdes#include <sys/systm.h> 43238106Sdes#include <sys/conf.h> 44238106Sdes#include <sys/proc.h> 45238106Sdes#include <sys/vnode.h> 46238106Sdes#include <sys/ioctl.h> 47238106Sdes#include <sys/msgbuf.h> 48238106Sdes#include <sys/file.h> 49238106Sdes#include <sys/signalvar.h> 50238106Sdes#include <sys/kernel.h> 51238106Sdes#ifdef DEVFS 52238106Sdes#include <sys/devfsext.h> 53238106Sdes#endif /*DEVFS*/ 54238106Sdes 55238106Sdes#define LOG_RDPRI (PZERO + 1) 56238106Sdes 57238106Sdes#define LOG_ASYNC 0x04 58238106Sdes#define LOG_RDWAIT 0x08 59238106Sdes 60238106Sdesstatic d_open_t logopen; 61238106Sdesstatic d_close_t logclose; 62238106Sdesstatic d_read_t logread; 63238106Sdesstatic d_ioctl_t logioctl; 64238106Sdesstatic d_select_t logselect; 65238106Sdes 66238106Sdes#define CDEV_MAJOR 7 67238106Sdesstatic struct cdevsw log_cdevsw = 68238106Sdes { logopen, logclose, logread, nowrite, /*7*/ 69238106Sdes logioctl, nostop, nullreset, nodevtotty,/* klog */ 70238106Sdes logselect, nommap, NULL, "log", NULL, -1 }; 71238106Sdes 72238106Sdesstruct logsoftc { 73238106Sdes int sc_state; /* see above for possibilities */ 74238106Sdes struct selinfo sc_selp; /* process waiting on select call */ 75238106Sdes int sc_pgid; /* process/group for async I/O */ 76238106Sdes} logsoftc; 77238106Sdes 78238106Sdesint log_open; /* also used in log() */ 79238106Sdes 80238106Sdes/*ARGSUSED*/ 81238106Sdesstatic int 82238106Sdeslogopen(dev, flags, mode, p) 83238106Sdes dev_t dev; 84238106Sdes int flags, mode; 85238106Sdes struct proc *p; 86238106Sdes{ 87238106Sdes if (log_open) 88238106Sdes return (EBUSY); 89238106Sdes log_open = 1; 90238106Sdes logsoftc.sc_pgid = p->p_pid; /* signal process only */ 91238106Sdes return (0); 92238106Sdes} 93238106Sdes 94238106Sdes/*ARGSUSED*/ 95238106Sdesstatic int 96238106Sdeslogclose(dev, flag, mode, p) 97238106Sdes dev_t dev; 98238106Sdes int flag, mode; 99238106Sdes struct proc *p; 100238106Sdes{ 101238106Sdes 102238106Sdes log_open = 0; 103238106Sdes logsoftc.sc_state = 0; 104238106Sdes return (0); 105238106Sdes} 106238106Sdes 107238106Sdes/*ARGSUSED*/ 108238106Sdesstatic int 109238106Sdeslogread(dev, uio, flag) 110238106Sdes dev_t dev; 111238106Sdes struct uio *uio; 112238106Sdes int flag; 113238106Sdes{ 114238106Sdes register struct msgbuf *mbp = msgbufp; 115238106Sdes register long l; 116238106Sdes register int s; 117238106Sdes int error = 0; 118238106Sdes 119238106Sdes s = splhigh(); 120238106Sdes while (mbp->msg_bufr == mbp->msg_bufx) { 121238106Sdes if (flag & IO_NDELAY) { 122238106Sdes splx(s); 123238106Sdes return (EWOULDBLOCK); 124238106Sdes } 125238106Sdes logsoftc.sc_state |= LOG_RDWAIT; 126238106Sdes if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 127238106Sdes "klog", 0))) { 128238106Sdes splx(s); 129238106Sdes return (error); 130238106Sdes } 131238106Sdes } 132238106Sdes splx(s); 133238106Sdes logsoftc.sc_state &= ~LOG_RDWAIT; 134238106Sdes 135238106Sdes while (uio->uio_resid > 0) { 136238106Sdes l = mbp->msg_bufx - mbp->msg_bufr; 137238106Sdes if (l < 0) 138238106Sdes l = MSG_BSIZE - mbp->msg_bufr; 139238106Sdes l = min(l, uio->uio_resid); 140238106Sdes if (l == 0) 141238106Sdes break; 142238106Sdes error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr], 143238106Sdes (int)l, uio); 144238106Sdes if (error) 145238106Sdes break; 146238106Sdes mbp->msg_bufr += l; 147238106Sdes if (mbp->msg_bufr >= MSG_BSIZE) 148238106Sdes mbp->msg_bufr = 0; 149238106Sdes } 150238106Sdes return (error); 151238106Sdes} 152238106Sdes 153238106Sdes/*ARGSUSED*/ 154238106Sdesstatic int 155238106Sdeslogselect(dev, rw, p) 156238106Sdes dev_t dev; 157238106Sdes int rw; 158238106Sdes struct proc *p; 159238106Sdes{ 160238106Sdes int s = splhigh(); 161238106Sdes 162238106Sdes switch (rw) { 163238106Sdes 164238106Sdes case FREAD: 165238106Sdes if (msgbufp->msg_bufr != msgbufp->msg_bufx) { 166238106Sdes splx(s); 167238106Sdes return (1); 168238106Sdes } 169238106Sdes selrecord(p, &logsoftc.sc_selp); 170238106Sdes break; 171238106Sdes } 172238106Sdes splx(s); 173238106Sdes return (0); 174238106Sdes} 175238106Sdes 176238106Sdesvoid 177238106Sdeslogwakeup() 178238106Sdes{ 179238106Sdes struct proc *p; 180238106Sdes 181238106Sdes if (!log_open) 182238106Sdes return; 183238106Sdes selwakeup(&logsoftc.sc_selp); 184238106Sdes if (logsoftc.sc_state & LOG_ASYNC) { 185238106Sdes if (logsoftc.sc_pgid < 0) 186238106Sdes gsignal(-logsoftc.sc_pgid, SIGIO); 187238106Sdes else if ((p = pfind(logsoftc.sc_pgid))) 188238106Sdes psignal(p, SIGIO); 189238106Sdes } 190238106Sdes if (logsoftc.sc_state & LOG_RDWAIT) { 191238106Sdes wakeup((caddr_t)msgbufp); 192238106Sdes logsoftc.sc_state &= ~LOG_RDWAIT; 193238106Sdes } 194238106Sdes} 195238106Sdes 196238106Sdes/*ARGSUSED*/ 197238106Sdesstatic int 198238106Sdeslogioctl(dev, com, data, flag, p) 199238106Sdes dev_t dev; 200238106Sdes int com; 201238106Sdes caddr_t data; 202238106Sdes int flag; 203238106Sdes struct proc *p; 204238106Sdes{ 205238106Sdes long l; 206 int s; 207 208 switch (com) { 209 210 /* return number of characters immediately available */ 211 case FIONREAD: 212 s = splhigh(); 213 l = msgbufp->msg_bufx - msgbufp->msg_bufr; 214 splx(s); 215 if (l < 0) 216 l += MSG_BSIZE; 217 *(int *)data = l; 218 break; 219 220 case FIONBIO: 221 break; 222 223 case FIOASYNC: 224 if (*(int *)data) 225 logsoftc.sc_state |= LOG_ASYNC; 226 else 227 logsoftc.sc_state &= ~LOG_ASYNC; 228 break; 229 230 case TIOCSPGRP: 231 logsoftc.sc_pgid = *(int *)data; 232 break; 233 234 case TIOCGPGRP: 235 *(int *)data = logsoftc.sc_pgid; 236 break; 237 238 default: 239 return (ENOTTY); 240 } 241 return (0); 242} 243 244static log_devsw_installed = 0; 245static void *log_devfs_token; 246 247static void 248log_drvinit(void *unused) 249{ 250 dev_t dev; 251 252 if( ! log_devsw_installed ) { 253 dev = makedev(CDEV_MAJOR,0); 254 cdevsw_add(&dev,&log_cdevsw,NULL); 255 log_devsw_installed = 1; 256#ifdef DEVFS 257 log_devfs_token = devfs_add_devsw( 258 "/", "log", &log_cdevsw, 0, DV_CHR, 0, 0, 0600); 259#endif 260 } 261} 262 263SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL) 264 265 266