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 344e2f199eSPoul-Henning Kamp * $Id: subr_log.c,v 1.34 1999/05/06 18:12:46 peter 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 417b778b5eSEivind Eklund #include "opt_devfs.h" 427b778b5eSEivind Eklund 43df8bae1dSRodney W. Grimes #include <sys/param.h> 44df8bae1dSRodney W. Grimes #include <sys/systm.h> 4598d93822SBruce Evans #include <sys/conf.h> 46df8bae1dSRodney W. Grimes #include <sys/proc.h> 47df8bae1dSRodney W. Grimes #include <sys/vnode.h> 4820982410SBruce Evans #include <sys/filio.h> 4920982410SBruce Evans #include <sys/ttycom.h> 50df8bae1dSRodney W. Grimes #include <sys/msgbuf.h> 51797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 5253ac6efbSJulian Elischer #include <sys/kernel.h> 531514b90fSPeter Wemm #include <sys/poll.h> 54831d27a9SDon Lewis #include <sys/filedesc.h> 5553ac6efbSJulian Elischer #ifdef DEVFS 5653ac6efbSJulian Elischer #include <sys/devfsext.h> 5753ac6efbSJulian Elischer #endif /*DEVFS*/ 5853ac6efbSJulian Elischer 59df8bae1dSRodney W. Grimes #define LOG_RDPRI (PZERO + 1) 60df8bae1dSRodney W. Grimes 61df8bae1dSRodney W. Grimes #define LOG_ASYNC 0x04 62df8bae1dSRodney W. Grimes #define LOG_RDWAIT 0x08 63df8bae1dSRodney W. Grimes 6487f6c662SJulian Elischer static d_open_t logopen; 6587f6c662SJulian Elischer static d_close_t logclose; 6687f6c662SJulian Elischer static d_read_t logread; 6787f6c662SJulian Elischer static d_ioctl_t logioctl; 681514b90fSPeter Wemm static d_poll_t logpoll; 6987f6c662SJulian Elischer 7087f6c662SJulian Elischer #define CDEV_MAJOR 7 714e2f199eSPoul-Henning Kamp static struct cdevsw log_cdevsw = { 724e2f199eSPoul-Henning Kamp /* open */ logopen, 734e2f199eSPoul-Henning Kamp /* close */ logclose, 744e2f199eSPoul-Henning Kamp /* read */ logread, 754e2f199eSPoul-Henning Kamp /* write */ nowrite, 764e2f199eSPoul-Henning Kamp /* ioctl */ logioctl, 774e2f199eSPoul-Henning Kamp /* stop */ nostop, 784e2f199eSPoul-Henning Kamp /* reset */ noreset, 794e2f199eSPoul-Henning Kamp /* devtotty */ nodevtotty, 804e2f199eSPoul-Henning Kamp /* poll */ logpoll, 814e2f199eSPoul-Henning Kamp /* mmap */ nommap, 824e2f199eSPoul-Henning Kamp /* strategy */ nostrategy, 834e2f199eSPoul-Henning Kamp /* name */ "log", 844e2f199eSPoul-Henning Kamp /* parms */ noparms, 854e2f199eSPoul-Henning Kamp /* maj */ CDEV_MAJOR, 864e2f199eSPoul-Henning Kamp /* dump */ nodump, 874e2f199eSPoul-Henning Kamp /* psize */ nopsize, 884e2f199eSPoul-Henning Kamp /* flags */ 0, 894e2f199eSPoul-Henning Kamp /* maxio */ 0, 904e2f199eSPoul-Henning Kamp /* bmaj */ -1 914e2f199eSPoul-Henning Kamp }; 9287f6c662SJulian Elischer 9387b6de2bSPoul-Henning Kamp static struct logsoftc { 94df8bae1dSRodney W. Grimes int sc_state; /* see above for possibilities */ 95df8bae1dSRodney W. Grimes struct selinfo sc_selp; /* process waiting on select call */ 9662d6ce3aSDon Lewis struct sigio *sc_sigio; /* information for async I/O */ 97df8bae1dSRodney W. Grimes } logsoftc; 98df8bae1dSRodney W. Grimes 99df8bae1dSRodney W. Grimes int log_open; /* also used in log() */ 100df8bae1dSRodney W. Grimes 101df8bae1dSRodney W. Grimes /*ARGSUSED*/ 10287f6c662SJulian Elischer static int 103df8bae1dSRodney W. Grimes logopen(dev, flags, mode, p) 104df8bae1dSRodney W. Grimes dev_t dev; 105df8bae1dSRodney W. Grimes int flags, mode; 106df8bae1dSRodney W. Grimes struct proc *p; 107df8bae1dSRodney W. Grimes { 108df8bae1dSRodney W. Grimes if (log_open) 109df8bae1dSRodney W. Grimes return (EBUSY); 110df8bae1dSRodney W. Grimes log_open = 1; 111831d27a9SDon Lewis fsetown(p->p_pid, &logsoftc.sc_sigio); /* signal process only */ 112df8bae1dSRodney W. Grimes return (0); 113df8bae1dSRodney W. Grimes } 114df8bae1dSRodney W. Grimes 115df8bae1dSRodney W. Grimes /*ARGSUSED*/ 11687f6c662SJulian Elischer static int 117df8bae1dSRodney W. Grimes logclose(dev, flag, mode, p) 118df8bae1dSRodney W. Grimes dev_t dev; 119df8bae1dSRodney W. Grimes int flag, mode; 120df8bae1dSRodney W. Grimes struct proc *p; 121df8bae1dSRodney W. Grimes { 122df8bae1dSRodney W. Grimes 123df8bae1dSRodney W. Grimes log_open = 0; 124df8bae1dSRodney W. Grimes logsoftc.sc_state = 0; 125831d27a9SDon Lewis funsetown(logsoftc.sc_sigio); 126df8bae1dSRodney W. Grimes return (0); 127df8bae1dSRodney W. Grimes } 128df8bae1dSRodney W. Grimes 129df8bae1dSRodney W. Grimes /*ARGSUSED*/ 13087f6c662SJulian Elischer static int 131df8bae1dSRodney W. Grimes logread(dev, uio, flag) 132df8bae1dSRodney W. Grimes dev_t dev; 133df8bae1dSRodney W. Grimes struct uio *uio; 134df8bae1dSRodney W. Grimes int flag; 135df8bae1dSRodney W. Grimes { 136df8bae1dSRodney W. Grimes register struct msgbuf *mbp = msgbufp; 137df8bae1dSRodney W. Grimes register long l; 138df8bae1dSRodney W. Grimes register int s; 139df8bae1dSRodney W. Grimes int error = 0; 140df8bae1dSRodney W. Grimes 141df8bae1dSRodney W. Grimes s = splhigh(); 142df8bae1dSRodney W. Grimes while (mbp->msg_bufr == mbp->msg_bufx) { 143df8bae1dSRodney W. Grimes if (flag & IO_NDELAY) { 144df8bae1dSRodney W. Grimes splx(s); 145df8bae1dSRodney W. Grimes return (EWOULDBLOCK); 146df8bae1dSRodney W. Grimes } 147df8bae1dSRodney W. Grimes logsoftc.sc_state |= LOG_RDWAIT; 148bb56ec4aSPoul-Henning Kamp if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 149bb56ec4aSPoul-Henning Kamp "klog", 0))) { 150df8bae1dSRodney W. Grimes splx(s); 151df8bae1dSRodney W. Grimes return (error); 152df8bae1dSRodney W. Grimes } 153df8bae1dSRodney W. Grimes } 154df8bae1dSRodney W. Grimes splx(s); 155df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_RDWAIT; 156df8bae1dSRodney W. Grimes 157df8bae1dSRodney W. Grimes while (uio->uio_resid > 0) { 158df8bae1dSRodney W. Grimes l = mbp->msg_bufx - mbp->msg_bufr; 159df8bae1dSRodney W. Grimes if (l < 0) 16058067a99SPoul-Henning Kamp l = mbp->msg_size - mbp->msg_bufr; 161df8bae1dSRodney W. Grimes l = min(l, uio->uio_resid); 162df8bae1dSRodney W. Grimes if (l == 0) 163df8bae1dSRodney W. Grimes break; 16458067a99SPoul-Henning Kamp error = uiomove((caddr_t)msgbufp->msg_ptr + mbp->msg_bufr, 165df8bae1dSRodney W. Grimes (int)l, uio); 166df8bae1dSRodney W. Grimes if (error) 167df8bae1dSRodney W. Grimes break; 168df8bae1dSRodney W. Grimes mbp->msg_bufr += l; 16958067a99SPoul-Henning Kamp if (mbp->msg_bufr >= mbp->msg_size) 170df8bae1dSRodney W. Grimes mbp->msg_bufr = 0; 171df8bae1dSRodney W. Grimes } 172df8bae1dSRodney W. Grimes return (error); 173df8bae1dSRodney W. Grimes } 174df8bae1dSRodney W. Grimes 175df8bae1dSRodney W. Grimes /*ARGSUSED*/ 17687f6c662SJulian Elischer static int 1771514b90fSPeter Wemm logpoll(dev, events, p) 178df8bae1dSRodney W. Grimes dev_t dev; 1791514b90fSPeter Wemm int events; 180df8bae1dSRodney W. Grimes struct proc *p; 181df8bae1dSRodney W. Grimes { 1821514b90fSPeter Wemm int s; 1831514b90fSPeter Wemm int revents = 0; 184df8bae1dSRodney W. Grimes 1851514b90fSPeter Wemm s = splhigh(); 186df8bae1dSRodney W. Grimes 187dfd5dee1SPeter Wemm if (events & (POLLIN | POLLRDNORM)) { 1881514b90fSPeter Wemm if (msgbufp->msg_bufr != msgbufp->msg_bufx) 1891514b90fSPeter Wemm revents |= events & (POLLIN | POLLRDNORM); 1901514b90fSPeter Wemm else 191df8bae1dSRodney W. Grimes selrecord(p, &logsoftc.sc_selp); 192dfd5dee1SPeter Wemm } 193df8bae1dSRodney W. Grimes splx(s); 1941514b90fSPeter Wemm return (revents); 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes 19726f9a767SRodney W. Grimes void 198df8bae1dSRodney W. Grimes logwakeup() 199df8bae1dSRodney W. Grimes { 200df8bae1dSRodney W. Grimes if (!log_open) 201df8bae1dSRodney W. Grimes return; 202df8bae1dSRodney W. Grimes selwakeup(&logsoftc.sc_selp); 203831d27a9SDon Lewis if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL) 204831d27a9SDon Lewis pgsigio(logsoftc.sc_sigio, SIGIO, 0); 205df8bae1dSRodney W. Grimes if (logsoftc.sc_state & LOG_RDWAIT) { 206df8bae1dSRodney W. Grimes wakeup((caddr_t)msgbufp); 207df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_RDWAIT; 208df8bae1dSRodney W. Grimes } 209df8bae1dSRodney W. Grimes } 210df8bae1dSRodney W. Grimes 211df8bae1dSRodney W. Grimes /*ARGSUSED*/ 21287f6c662SJulian Elischer static int 213df8bae1dSRodney W. Grimes logioctl(dev, com, data, flag, p) 214df8bae1dSRodney W. Grimes dev_t dev; 215ecbb00a2SDoug Rabson u_long com; 216df8bae1dSRodney W. Grimes caddr_t data; 217df8bae1dSRodney W. Grimes int flag; 218df8bae1dSRodney W. Grimes struct proc *p; 219df8bae1dSRodney W. Grimes { 220df8bae1dSRodney W. Grimes long l; 221df8bae1dSRodney W. Grimes int s; 222df8bae1dSRodney W. Grimes 223df8bae1dSRodney W. Grimes switch (com) { 224df8bae1dSRodney W. Grimes 225df8bae1dSRodney W. Grimes /* return number of characters immediately available */ 226df8bae1dSRodney W. Grimes case FIONREAD: 227df8bae1dSRodney W. Grimes s = splhigh(); 228df8bae1dSRodney W. Grimes l = msgbufp->msg_bufx - msgbufp->msg_bufr; 229df8bae1dSRodney W. Grimes splx(s); 230df8bae1dSRodney W. Grimes if (l < 0) 23158067a99SPoul-Henning Kamp l += msgbufp->msg_size; 232df8bae1dSRodney W. Grimes *(int *)data = l; 233df8bae1dSRodney W. Grimes break; 234df8bae1dSRodney W. Grimes 235df8bae1dSRodney W. Grimes case FIONBIO: 236df8bae1dSRodney W. Grimes break; 237df8bae1dSRodney W. Grimes 238df8bae1dSRodney W. Grimes case FIOASYNC: 239df8bae1dSRodney W. Grimes if (*(int *)data) 240df8bae1dSRodney W. Grimes logsoftc.sc_state |= LOG_ASYNC; 241df8bae1dSRodney W. Grimes else 242df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_ASYNC; 243df8bae1dSRodney W. Grimes break; 244df8bae1dSRodney W. Grimes 245831d27a9SDon Lewis case FIOSETOWN: 246831d27a9SDon Lewis return (fsetown(*(int *)data, &logsoftc.sc_sigio)); 247831d27a9SDon Lewis 248831d27a9SDon Lewis case FIOGETOWN: 249831d27a9SDon Lewis *(int *)data = fgetown(logsoftc.sc_sigio); 250df8bae1dSRodney W. Grimes break; 251df8bae1dSRodney W. Grimes 252831d27a9SDon Lewis /* This is deprecated, FIOSETOWN should be used instead. */ 253831d27a9SDon Lewis case TIOCSPGRP: 254831d27a9SDon Lewis return (fsetown(-(*(int *)data), &logsoftc.sc_sigio)); 255831d27a9SDon Lewis 256831d27a9SDon Lewis /* This is deprecated, FIOGETOWN should be used instead */ 257df8bae1dSRodney W. Grimes case TIOCGPGRP: 258831d27a9SDon Lewis *(int *)data = -fgetown(logsoftc.sc_sigio); 259df8bae1dSRodney W. Grimes break; 260df8bae1dSRodney W. Grimes 261df8bae1dSRodney W. Grimes default: 262bcac5617SJordan K. Hubbard return (ENOTTY); 263df8bae1dSRodney W. Grimes } 264df8bae1dSRodney W. Grimes return (0); 265df8bae1dSRodney W. Grimes } 26653ac6efbSJulian Elischer 267e31abedeSBruce Evans static int log_devsw_installed; 2685c17ec63SGarrett Wollman #ifdef DEVFS 26987f6c662SJulian Elischer static void *log_devfs_token; 2705c17ec63SGarrett Wollman #endif 27153ac6efbSJulian Elischer 272514ede09SBruce Evans static void log_drvinit __P((void *unused)); 27387f6c662SJulian Elischer static void 274514ede09SBruce Evans log_drvinit(unused) 275514ede09SBruce Evans void *unused; 27653ac6efbSJulian Elischer { 27753ac6efbSJulian Elischer dev_t dev; 27853ac6efbSJulian Elischer 27953ac6efbSJulian Elischer if( ! log_devsw_installed ) { 28053ac6efbSJulian Elischer dev = makedev(CDEV_MAJOR,0); 28153ac6efbSJulian Elischer cdevsw_add(&dev,&log_cdevsw,NULL); 28253ac6efbSJulian Elischer log_devsw_installed = 1; 28353ac6efbSJulian Elischer #ifdef DEVFS 28427d02c98SBruce Evans log_devfs_token = devfs_add_devswf(&log_cdevsw, 0, DV_CHR, 28527d02c98SBruce Evans UID_ROOT, GID_WHEEL, 0600, 28627d02c98SBruce Evans "klog"); 28753ac6efbSJulian Elischer #endif 28853ac6efbSJulian Elischer } 2897198bf47SJulian Elischer } 29053ac6efbSJulian Elischer 29153ac6efbSJulian Elischer SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL) 292