1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 7df8bae1dSRodney W. Grimes * are met: 8df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 9df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 10df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 11df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 12df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 13df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 14df8bae1dSRodney W. Grimes * must display the following acknowledgement: 15df8bae1dSRodney W. Grimes * This product includes software developed by the University of 16df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 17df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 18df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 19df8bae1dSRodney W. Grimes * without specific prior written permission. 20df8bae1dSRodney W. Grimes * 21df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31df8bae1dSRodney W. Grimes * SUCH DAMAGE. 32df8bae1dSRodney W. Grimes * 33df8bae1dSRodney W. Grimes * @(#)subr_log.c 8.1 (Berkeley) 6/10/93 3420982410SBruce Evans * $Id: subr_log.c,v 1.21 1997/03/23 03:36:22 bde Exp $ 35df8bae1dSRodney W. Grimes */ 36df8bae1dSRodney W. Grimes 37df8bae1dSRodney W. Grimes /* 38df8bae1dSRodney W. Grimes * Error log buffer for kernel printf's. 39df8bae1dSRodney W. Grimes */ 40df8bae1dSRodney W. Grimes 41df8bae1dSRodney W. Grimes #include <sys/param.h> 42df8bae1dSRodney W. Grimes #include <sys/systm.h> 4398d93822SBruce Evans #include <sys/conf.h> 44df8bae1dSRodney W. Grimes #include <sys/proc.h> 45df8bae1dSRodney W. Grimes #include <sys/vnode.h> 4620982410SBruce Evans #include <sys/filio.h> 4720982410SBruce Evans #include <sys/ttycom.h> 48df8bae1dSRodney W. Grimes #include <sys/msgbuf.h> 493ac4d1efSBruce Evans #include <sys/fcntl.h> 50797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 5153ac6efbSJulian Elischer #include <sys/kernel.h> 5253ac6efbSJulian Elischer #ifdef DEVFS 5353ac6efbSJulian Elischer #include <sys/devfsext.h> 5453ac6efbSJulian Elischer #endif /*DEVFS*/ 5553ac6efbSJulian Elischer 56df8bae1dSRodney W. Grimes #define LOG_RDPRI (PZERO + 1) 57df8bae1dSRodney W. Grimes 58df8bae1dSRodney W. Grimes #define LOG_ASYNC 0x04 59df8bae1dSRodney W. Grimes #define LOG_RDWAIT 0x08 60df8bae1dSRodney W. Grimes 6187f6c662SJulian Elischer static d_open_t logopen; 6287f6c662SJulian Elischer static d_close_t logclose; 6387f6c662SJulian Elischer static d_read_t logread; 6487f6c662SJulian Elischer static d_ioctl_t logioctl; 6587f6c662SJulian Elischer static d_select_t logselect; 6687f6c662SJulian Elischer 6787f6c662SJulian Elischer #define CDEV_MAJOR 7 68d2f265faSPoul-Henning Kamp static struct cdevsw log_cdevsw = 6987f6c662SJulian Elischer { logopen, logclose, logread, nowrite, /*7*/ 7087f6c662SJulian Elischer logioctl, nostop, nullreset, nodevtotty,/* klog */ 7187f6c662SJulian Elischer logselect, nommap, NULL, "log", NULL, -1 }; 7287f6c662SJulian Elischer 7387b6de2bSPoul-Henning Kamp static struct logsoftc { 74df8bae1dSRodney W. Grimes int sc_state; /* see above for possibilities */ 75df8bae1dSRodney W. Grimes struct selinfo sc_selp; /* process waiting on select call */ 76df8bae1dSRodney W. Grimes int sc_pgid; /* process/group for async I/O */ 77df8bae1dSRodney W. Grimes } logsoftc; 78df8bae1dSRodney W. Grimes 79df8bae1dSRodney W. Grimes int log_open; /* also used in log() */ 80df8bae1dSRodney W. Grimes 81df8bae1dSRodney W. Grimes /*ARGSUSED*/ 8287f6c662SJulian Elischer static int 83df8bae1dSRodney W. Grimes logopen(dev, flags, mode, p) 84df8bae1dSRodney W. Grimes dev_t dev; 85df8bae1dSRodney W. Grimes int flags, mode; 86df8bae1dSRodney W. Grimes struct proc *p; 87df8bae1dSRodney W. Grimes { 88df8bae1dSRodney W. Grimes if (log_open) 89df8bae1dSRodney W. Grimes return (EBUSY); 90df8bae1dSRodney W. Grimes log_open = 1; 91df8bae1dSRodney W. Grimes logsoftc.sc_pgid = p->p_pid; /* signal process only */ 92df8bae1dSRodney W. Grimes return (0); 93df8bae1dSRodney W. Grimes } 94df8bae1dSRodney W. Grimes 95df8bae1dSRodney W. Grimes /*ARGSUSED*/ 9687f6c662SJulian Elischer static int 97df8bae1dSRodney W. Grimes logclose(dev, flag, mode, p) 98df8bae1dSRodney W. Grimes dev_t dev; 99df8bae1dSRodney W. Grimes int flag, mode; 100df8bae1dSRodney W. Grimes struct proc *p; 101df8bae1dSRodney W. Grimes { 102df8bae1dSRodney W. Grimes 103df8bae1dSRodney W. Grimes log_open = 0; 104df8bae1dSRodney W. Grimes logsoftc.sc_state = 0; 105df8bae1dSRodney W. Grimes return (0); 106df8bae1dSRodney W. Grimes } 107df8bae1dSRodney W. Grimes 108df8bae1dSRodney W. Grimes /*ARGSUSED*/ 10987f6c662SJulian Elischer static int 110df8bae1dSRodney W. Grimes logread(dev, uio, flag) 111df8bae1dSRodney W. Grimes dev_t dev; 112df8bae1dSRodney W. Grimes struct uio *uio; 113df8bae1dSRodney W. Grimes int flag; 114df8bae1dSRodney W. Grimes { 115df8bae1dSRodney W. Grimes register struct msgbuf *mbp = msgbufp; 116df8bae1dSRodney W. Grimes register long l; 117df8bae1dSRodney W. Grimes register int s; 118df8bae1dSRodney W. Grimes int error = 0; 119df8bae1dSRodney W. Grimes 120df8bae1dSRodney W. Grimes s = splhigh(); 121df8bae1dSRodney W. Grimes while (mbp->msg_bufr == mbp->msg_bufx) { 122df8bae1dSRodney W. Grimes if (flag & IO_NDELAY) { 123df8bae1dSRodney W. Grimes splx(s); 124df8bae1dSRodney W. Grimes return (EWOULDBLOCK); 125df8bae1dSRodney W. Grimes } 126df8bae1dSRodney W. Grimes logsoftc.sc_state |= LOG_RDWAIT; 127bb56ec4aSPoul-Henning Kamp if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 128bb56ec4aSPoul-Henning Kamp "klog", 0))) { 129df8bae1dSRodney W. Grimes splx(s); 130df8bae1dSRodney W. Grimes return (error); 131df8bae1dSRodney W. Grimes } 132df8bae1dSRodney W. Grimes } 133df8bae1dSRodney W. Grimes splx(s); 134df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_RDWAIT; 135df8bae1dSRodney W. Grimes 136df8bae1dSRodney W. Grimes while (uio->uio_resid > 0) { 137df8bae1dSRodney W. Grimes l = mbp->msg_bufx - mbp->msg_bufr; 138df8bae1dSRodney W. Grimes if (l < 0) 139df8bae1dSRodney W. Grimes l = MSG_BSIZE - mbp->msg_bufr; 140df8bae1dSRodney W. Grimes l = min(l, uio->uio_resid); 141df8bae1dSRodney W. Grimes if (l == 0) 142df8bae1dSRodney W. Grimes break; 143df8bae1dSRodney W. Grimes error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr], 144df8bae1dSRodney W. Grimes (int)l, uio); 145df8bae1dSRodney W. Grimes if (error) 146df8bae1dSRodney W. Grimes break; 147df8bae1dSRodney W. Grimes mbp->msg_bufr += l; 1486c8897cfSDavid Greenman if (mbp->msg_bufr >= MSG_BSIZE) 149df8bae1dSRodney W. Grimes mbp->msg_bufr = 0; 150df8bae1dSRodney W. Grimes } 151df8bae1dSRodney W. Grimes return (error); 152df8bae1dSRodney W. Grimes } 153df8bae1dSRodney W. Grimes 154df8bae1dSRodney W. Grimes /*ARGSUSED*/ 15587f6c662SJulian Elischer static int 156df8bae1dSRodney W. Grimes logselect(dev, rw, p) 157df8bae1dSRodney W. Grimes dev_t dev; 158df8bae1dSRodney W. Grimes int rw; 159df8bae1dSRodney W. Grimes struct proc *p; 160df8bae1dSRodney W. Grimes { 161df8bae1dSRodney W. Grimes int s = splhigh(); 162df8bae1dSRodney W. Grimes 163df8bae1dSRodney W. Grimes switch (rw) { 164df8bae1dSRodney W. Grimes 165df8bae1dSRodney W. Grimes case FREAD: 166df8bae1dSRodney W. Grimes if (msgbufp->msg_bufr != msgbufp->msg_bufx) { 167df8bae1dSRodney W. Grimes splx(s); 168df8bae1dSRodney W. Grimes return (1); 169df8bae1dSRodney W. Grimes } 170df8bae1dSRodney W. Grimes selrecord(p, &logsoftc.sc_selp); 171df8bae1dSRodney W. Grimes break; 172df8bae1dSRodney W. Grimes } 173df8bae1dSRodney W. Grimes splx(s); 174df8bae1dSRodney W. Grimes return (0); 175df8bae1dSRodney W. Grimes } 176df8bae1dSRodney W. Grimes 17726f9a767SRodney W. Grimes void 178df8bae1dSRodney W. Grimes logwakeup() 179df8bae1dSRodney W. Grimes { 180df8bae1dSRodney W. Grimes struct proc *p; 181df8bae1dSRodney W. Grimes 182df8bae1dSRodney W. Grimes if (!log_open) 183df8bae1dSRodney W. Grimes return; 184df8bae1dSRodney W. Grimes selwakeup(&logsoftc.sc_selp); 185df8bae1dSRodney W. Grimes if (logsoftc.sc_state & LOG_ASYNC) { 186df8bae1dSRodney W. Grimes if (logsoftc.sc_pgid < 0) 187df8bae1dSRodney W. Grimes gsignal(-logsoftc.sc_pgid, SIGIO); 188bb56ec4aSPoul-Henning Kamp else if ((p = pfind(logsoftc.sc_pgid))) 189df8bae1dSRodney W. Grimes psignal(p, SIGIO); 190df8bae1dSRodney W. Grimes } 191df8bae1dSRodney W. Grimes if (logsoftc.sc_state & LOG_RDWAIT) { 192df8bae1dSRodney W. Grimes wakeup((caddr_t)msgbufp); 193df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_RDWAIT; 194df8bae1dSRodney W. Grimes } 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes 197df8bae1dSRodney W. Grimes /*ARGSUSED*/ 19887f6c662SJulian Elischer static int 199df8bae1dSRodney W. Grimes logioctl(dev, com, data, flag, p) 200df8bae1dSRodney W. Grimes dev_t dev; 201df8bae1dSRodney W. Grimes int com; 202df8bae1dSRodney W. Grimes caddr_t data; 203df8bae1dSRodney W. Grimes int flag; 204df8bae1dSRodney W. Grimes struct proc *p; 205df8bae1dSRodney W. Grimes { 206df8bae1dSRodney W. Grimes long l; 207df8bae1dSRodney W. Grimes int s; 208df8bae1dSRodney W. Grimes 209df8bae1dSRodney W. Grimes switch (com) { 210df8bae1dSRodney W. Grimes 211df8bae1dSRodney W. Grimes /* return number of characters immediately available */ 212df8bae1dSRodney W. Grimes case FIONREAD: 213df8bae1dSRodney W. Grimes s = splhigh(); 214df8bae1dSRodney W. Grimes l = msgbufp->msg_bufx - msgbufp->msg_bufr; 215df8bae1dSRodney W. Grimes splx(s); 216df8bae1dSRodney W. Grimes if (l < 0) 217df8bae1dSRodney W. Grimes l += MSG_BSIZE; 218df8bae1dSRodney W. Grimes *(int *)data = l; 219df8bae1dSRodney W. Grimes break; 220df8bae1dSRodney W. Grimes 221df8bae1dSRodney W. Grimes case FIONBIO: 222df8bae1dSRodney W. Grimes break; 223df8bae1dSRodney W. Grimes 224df8bae1dSRodney W. Grimes case FIOASYNC: 225df8bae1dSRodney W. Grimes if (*(int *)data) 226df8bae1dSRodney W. Grimes logsoftc.sc_state |= LOG_ASYNC; 227df8bae1dSRodney W. Grimes else 228df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_ASYNC; 229df8bae1dSRodney W. Grimes break; 230df8bae1dSRodney W. Grimes 231df8bae1dSRodney W. Grimes case TIOCSPGRP: 232df8bae1dSRodney W. Grimes logsoftc.sc_pgid = *(int *)data; 233df8bae1dSRodney W. Grimes break; 234df8bae1dSRodney W. Grimes 235df8bae1dSRodney W. Grimes case TIOCGPGRP: 236df8bae1dSRodney W. Grimes *(int *)data = logsoftc.sc_pgid; 237df8bae1dSRodney W. Grimes break; 238df8bae1dSRodney W. Grimes 239df8bae1dSRodney W. Grimes default: 240bcac5617SJordan K. Hubbard return (ENOTTY); 241df8bae1dSRodney W. Grimes } 242df8bae1dSRodney W. Grimes return (0); 243df8bae1dSRodney W. Grimes } 24453ac6efbSJulian Elischer 24553ac6efbSJulian Elischer static log_devsw_installed = 0; 2465c17ec63SGarrett Wollman #ifdef DEVFS 24787f6c662SJulian Elischer static void *log_devfs_token; 2485c17ec63SGarrett Wollman #endif 24953ac6efbSJulian Elischer 25087f6c662SJulian Elischer static void 25187f6c662SJulian Elischer log_drvinit(void *unused) 25253ac6efbSJulian Elischer { 25353ac6efbSJulian Elischer dev_t dev; 25453ac6efbSJulian Elischer 25553ac6efbSJulian Elischer if( ! log_devsw_installed ) { 25653ac6efbSJulian Elischer dev = makedev(CDEV_MAJOR,0); 25753ac6efbSJulian Elischer cdevsw_add(&dev,&log_cdevsw,NULL); 25853ac6efbSJulian Elischer log_devsw_installed = 1; 25953ac6efbSJulian Elischer #ifdef DEVFS 26027d02c98SBruce Evans log_devfs_token = devfs_add_devswf(&log_cdevsw, 0, DV_CHR, 26127d02c98SBruce Evans UID_ROOT, GID_WHEEL, 0600, 26227d02c98SBruce Evans "klog"); 26353ac6efbSJulian Elischer #endif 26453ac6efbSJulian Elischer } 2657198bf47SJulian Elischer } 26653ac6efbSJulian Elischer 26753ac6efbSJulian Elischer SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL) 26853ac6efbSJulian Elischer 26953ac6efbSJulian Elischer 270