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 34c3aac50fSPeter Wemm * $FreeBSD$ 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> 49797f2d22SPoul-Henning Kamp #include <sys/signalvar.h> 5053ac6efbSJulian Elischer #include <sys/kernel.h> 511514b90fSPeter Wemm #include <sys/poll.h> 52831d27a9SDon Lewis #include <sys/filedesc.h> 5353ac6efbSJulian Elischer 54df8bae1dSRodney W. Grimes #define LOG_RDPRI (PZERO + 1) 55df8bae1dSRodney W. Grimes 56df8bae1dSRodney W. Grimes #define LOG_ASYNC 0x04 57df8bae1dSRodney W. Grimes #define LOG_RDWAIT 0x08 58df8bae1dSRodney W. Grimes 5987f6c662SJulian Elischer static d_open_t logopen; 6087f6c662SJulian Elischer static d_close_t logclose; 6187f6c662SJulian Elischer static d_read_t logread; 6287f6c662SJulian Elischer static d_ioctl_t logioctl; 631514b90fSPeter Wemm static d_poll_t logpoll; 6487f6c662SJulian Elischer 6587f6c662SJulian Elischer #define CDEV_MAJOR 7 664e2f199eSPoul-Henning Kamp static struct cdevsw log_cdevsw = { 674e2f199eSPoul-Henning Kamp /* open */ logopen, 684e2f199eSPoul-Henning Kamp /* close */ logclose, 694e2f199eSPoul-Henning Kamp /* read */ logread, 704e2f199eSPoul-Henning Kamp /* write */ nowrite, 714e2f199eSPoul-Henning Kamp /* ioctl */ logioctl, 724e2f199eSPoul-Henning Kamp /* poll */ logpoll, 734e2f199eSPoul-Henning Kamp /* mmap */ nommap, 744e2f199eSPoul-Henning Kamp /* strategy */ nostrategy, 754e2f199eSPoul-Henning Kamp /* name */ "log", 764e2f199eSPoul-Henning Kamp /* maj */ CDEV_MAJOR, 774e2f199eSPoul-Henning Kamp /* dump */ nodump, 784e2f199eSPoul-Henning Kamp /* psize */ nopsize, 794e2f199eSPoul-Henning Kamp /* flags */ 0, 804e2f199eSPoul-Henning Kamp /* bmaj */ -1 814e2f199eSPoul-Henning Kamp }; 8287f6c662SJulian Elischer 8387b6de2bSPoul-Henning Kamp static struct logsoftc { 84df8bae1dSRodney W. Grimes int sc_state; /* see above for possibilities */ 85df8bae1dSRodney W. Grimes struct selinfo sc_selp; /* process waiting on select call */ 8662d6ce3aSDon Lewis struct sigio *sc_sigio; /* information for async I/O */ 87df8bae1dSRodney W. Grimes } logsoftc; 88df8bae1dSRodney W. Grimes 89df8bae1dSRodney W. Grimes int log_open; /* also used in log() */ 90df8bae1dSRodney W. Grimes 91df8bae1dSRodney W. Grimes /*ARGSUSED*/ 9287f6c662SJulian Elischer static int 9306b6617eSPoul-Henning Kamp logopen(dev_t dev, int flags, int mode, struct proc *p) 94df8bae1dSRodney W. Grimes { 95df8bae1dSRodney W. Grimes if (log_open) 96df8bae1dSRodney W. Grimes return (EBUSY); 97df8bae1dSRodney W. Grimes log_open = 1; 98831d27a9SDon Lewis fsetown(p->p_pid, &logsoftc.sc_sigio); /* signal process only */ 99df8bae1dSRodney W. Grimes return (0); 100df8bae1dSRodney W. Grimes } 101df8bae1dSRodney W. Grimes 102df8bae1dSRodney W. Grimes /*ARGSUSED*/ 10387f6c662SJulian Elischer static int 10406b6617eSPoul-Henning Kamp logclose(dev_t dev, int flag, int mode, struct proc *p) 105df8bae1dSRodney W. Grimes { 106df8bae1dSRodney W. Grimes 107df8bae1dSRodney W. Grimes log_open = 0; 108df8bae1dSRodney W. Grimes logsoftc.sc_state = 0; 109831d27a9SDon Lewis funsetown(logsoftc.sc_sigio); 110df8bae1dSRodney W. Grimes return (0); 111df8bae1dSRodney W. Grimes } 112df8bae1dSRodney W. Grimes 113df8bae1dSRodney W. Grimes /*ARGSUSED*/ 11487f6c662SJulian Elischer static int 11506b6617eSPoul-Henning Kamp logread(dev_t dev, struct uio *uio, int flag) 116df8bae1dSRodney W. Grimes { 11706b6617eSPoul-Henning Kamp struct msgbuf *mbp = msgbufp; 11806b6617eSPoul-Henning Kamp long l; 11906b6617eSPoul-Henning Kamp int s; 120df8bae1dSRodney W. Grimes int error = 0; 121df8bae1dSRodney W. Grimes 122df8bae1dSRodney W. Grimes s = splhigh(); 123df8bae1dSRodney W. Grimes while (mbp->msg_bufr == mbp->msg_bufx) { 124df8bae1dSRodney W. Grimes if (flag & IO_NDELAY) { 125df8bae1dSRodney W. Grimes splx(s); 126df8bae1dSRodney W. Grimes return (EWOULDBLOCK); 127df8bae1dSRodney W. Grimes } 128df8bae1dSRodney W. Grimes logsoftc.sc_state |= LOG_RDWAIT; 129bb56ec4aSPoul-Henning Kamp if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 130bb56ec4aSPoul-Henning Kamp "klog", 0))) { 131df8bae1dSRodney W. Grimes splx(s); 132df8bae1dSRodney W. Grimes return (error); 133df8bae1dSRodney W. Grimes } 134df8bae1dSRodney W. Grimes } 135df8bae1dSRodney W. Grimes splx(s); 136df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_RDWAIT; 137df8bae1dSRodney W. Grimes 138df8bae1dSRodney W. Grimes while (uio->uio_resid > 0) { 139df8bae1dSRodney W. Grimes l = mbp->msg_bufx - mbp->msg_bufr; 140df8bae1dSRodney W. Grimes if (l < 0) 14158067a99SPoul-Henning Kamp l = mbp->msg_size - mbp->msg_bufr; 142df8bae1dSRodney W. Grimes l = min(l, uio->uio_resid); 143df8bae1dSRodney W. Grimes if (l == 0) 144df8bae1dSRodney W. Grimes break; 14558067a99SPoul-Henning Kamp error = uiomove((caddr_t)msgbufp->msg_ptr + mbp->msg_bufr, 146df8bae1dSRodney W. Grimes (int)l, uio); 147df8bae1dSRodney W. Grimes if (error) 148df8bae1dSRodney W. Grimes break; 149df8bae1dSRodney W. Grimes mbp->msg_bufr += l; 15058067a99SPoul-Henning Kamp if (mbp->msg_bufr >= mbp->msg_size) 151df8bae1dSRodney W. Grimes mbp->msg_bufr = 0; 152df8bae1dSRodney W. Grimes } 153df8bae1dSRodney W. Grimes return (error); 154df8bae1dSRodney W. Grimes } 155df8bae1dSRodney W. Grimes 156df8bae1dSRodney W. Grimes /*ARGSUSED*/ 15787f6c662SJulian Elischer static int 15806b6617eSPoul-Henning Kamp logpoll(dev_t dev, int events, struct proc *p) 159df8bae1dSRodney W. Grimes { 1601514b90fSPeter Wemm int s; 1611514b90fSPeter Wemm int revents = 0; 162df8bae1dSRodney W. Grimes 1631514b90fSPeter Wemm s = splhigh(); 164df8bae1dSRodney W. Grimes 165dfd5dee1SPeter Wemm if (events & (POLLIN | POLLRDNORM)) { 1661514b90fSPeter Wemm if (msgbufp->msg_bufr != msgbufp->msg_bufx) 1671514b90fSPeter Wemm revents |= events & (POLLIN | POLLRDNORM); 1681514b90fSPeter Wemm else 169df8bae1dSRodney W. Grimes selrecord(p, &logsoftc.sc_selp); 170dfd5dee1SPeter Wemm } 171df8bae1dSRodney W. Grimes splx(s); 1721514b90fSPeter Wemm return (revents); 173df8bae1dSRodney W. Grimes } 174df8bae1dSRodney W. Grimes 17526f9a767SRodney W. Grimes void 17606b6617eSPoul-Henning Kamp logwakeup(void) 177df8bae1dSRodney W. Grimes { 178df8bae1dSRodney W. Grimes if (!log_open) 179df8bae1dSRodney W. Grimes return; 180df8bae1dSRodney W. Grimes selwakeup(&logsoftc.sc_selp); 181831d27a9SDon Lewis if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL) 182831d27a9SDon Lewis pgsigio(logsoftc.sc_sigio, SIGIO, 0); 183df8bae1dSRodney W. Grimes if (logsoftc.sc_state & LOG_RDWAIT) { 184df8bae1dSRodney W. Grimes wakeup((caddr_t)msgbufp); 185df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_RDWAIT; 186df8bae1dSRodney W. Grimes } 187df8bae1dSRodney W. Grimes } 188df8bae1dSRodney W. Grimes 189df8bae1dSRodney W. Grimes /*ARGSUSED*/ 19087f6c662SJulian Elischer static int 19106b6617eSPoul-Henning Kamp logioctl(dev_t dev, u_long com, caddr_t data, int flag, struct proc *p) 192df8bae1dSRodney W. Grimes { 193df8bae1dSRodney W. Grimes long l; 194df8bae1dSRodney W. Grimes int s; 195df8bae1dSRodney W. Grimes 196df8bae1dSRodney W. Grimes switch (com) { 197df8bae1dSRodney W. Grimes 198df8bae1dSRodney W. Grimes /* return number of characters immediately available */ 199df8bae1dSRodney W. Grimes case FIONREAD: 200df8bae1dSRodney W. Grimes s = splhigh(); 201df8bae1dSRodney W. Grimes l = msgbufp->msg_bufx - msgbufp->msg_bufr; 202df8bae1dSRodney W. Grimes splx(s); 203df8bae1dSRodney W. Grimes if (l < 0) 20458067a99SPoul-Henning Kamp l += msgbufp->msg_size; 205df8bae1dSRodney W. Grimes *(int *)data = l; 206df8bae1dSRodney W. Grimes break; 207df8bae1dSRodney W. Grimes 208df8bae1dSRodney W. Grimes case FIONBIO: 209df8bae1dSRodney W. Grimes break; 210df8bae1dSRodney W. Grimes 211df8bae1dSRodney W. Grimes case FIOASYNC: 212df8bae1dSRodney W. Grimes if (*(int *)data) 213df8bae1dSRodney W. Grimes logsoftc.sc_state |= LOG_ASYNC; 214df8bae1dSRodney W. Grimes else 215df8bae1dSRodney W. Grimes logsoftc.sc_state &= ~LOG_ASYNC; 216df8bae1dSRodney W. Grimes break; 217df8bae1dSRodney W. Grimes 218831d27a9SDon Lewis case FIOSETOWN: 219831d27a9SDon Lewis return (fsetown(*(int *)data, &logsoftc.sc_sigio)); 220831d27a9SDon Lewis 221831d27a9SDon Lewis case FIOGETOWN: 222831d27a9SDon Lewis *(int *)data = fgetown(logsoftc.sc_sigio); 223df8bae1dSRodney W. Grimes break; 224df8bae1dSRodney W. Grimes 225831d27a9SDon Lewis /* This is deprecated, FIOSETOWN should be used instead. */ 226831d27a9SDon Lewis case TIOCSPGRP: 227831d27a9SDon Lewis return (fsetown(-(*(int *)data), &logsoftc.sc_sigio)); 228831d27a9SDon Lewis 229831d27a9SDon Lewis /* This is deprecated, FIOGETOWN should be used instead */ 230df8bae1dSRodney W. Grimes case TIOCGPGRP: 231831d27a9SDon Lewis *(int *)data = -fgetown(logsoftc.sc_sigio); 232df8bae1dSRodney W. Grimes break; 233df8bae1dSRodney W. Grimes 234df8bae1dSRodney W. Grimes default: 235bcac5617SJordan K. Hubbard return (ENOTTY); 236df8bae1dSRodney W. Grimes } 237df8bae1dSRodney W. Grimes return (0); 238df8bae1dSRodney W. Grimes } 23953ac6efbSJulian Elischer 24087f6c662SJulian Elischer static void 24106b6617eSPoul-Henning Kamp log_drvinit(void *unused) 24253ac6efbSJulian Elischer { 24306b6617eSPoul-Henning Kamp 2449dcbe240SPoul-Henning Kamp make_dev(&log_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "klog"); 2457198bf47SJulian Elischer } 24653ac6efbSJulian Elischer 24753ac6efbSJulian Elischer SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL) 248