Annotation of sys/kern/subr_log.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: subr_log.c,v 1.14 2005/12/09 09:09:52 jsg Exp $ */
! 2: /* $NetBSD: subr_log.c,v 1.11 1996/03/30 22:24:44 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1982, 1986, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. Neither the name of the University nor the names of its contributors
! 17: * may be used to endorse or promote products derived from this software
! 18: * without specific prior written permission.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 30: * SUCH DAMAGE.
! 31: *
! 32: * @(#)subr_log.c 8.1 (Berkeley) 6/10/93
! 33: */
! 34:
! 35: /*
! 36: * Error log buffer for kernel printf's.
! 37: */
! 38:
! 39: #include <sys/param.h>
! 40: #include <sys/systm.h>
! 41: #include <sys/proc.h>
! 42: #include <sys/vnode.h>
! 43: #include <sys/ioctl.h>
! 44: #include <sys/msgbuf.h>
! 45: #include <sys/file.h>
! 46: #include <sys/signalvar.h>
! 47: #include <sys/syslog.h>
! 48: #include <sys/conf.h>
! 49: #include <sys/poll.h>
! 50:
! 51: #define LOG_RDPRI (PZERO + 1)
! 52:
! 53: #define LOG_ASYNC 0x04
! 54: #define LOG_RDWAIT 0x08
! 55:
! 56: struct logsoftc {
! 57: int sc_state; /* see above for possibilities */
! 58: struct selinfo sc_selp; /* process waiting on select call */
! 59: int sc_pgid; /* process/group for async I/O */
! 60: uid_t sc_siguid; /* uid for process that set sc_pgid */
! 61: uid_t sc_sigeuid; /* euid for process that set sc_pgid */
! 62: } logsoftc;
! 63:
! 64: int log_open; /* also used in log() */
! 65: int msgbufmapped; /* is the message buffer mapped */
! 66: int msgbufenabled; /* is logging to the buffer enabled */
! 67: struct msgbuf *msgbufp; /* the mapped buffer, itself. */
! 68:
! 69: void filt_logrdetach(struct knote *kn);
! 70: int filt_logread(struct knote *kn, long hint);
! 71:
! 72: struct filterops logread_filtops =
! 73: { 1, NULL, filt_logrdetach, filt_logread};
! 74:
! 75: void
! 76: initmsgbuf(caddr_t buf, size_t bufsize)
! 77: {
! 78: struct msgbuf *mbp;
! 79: long new_bufs;
! 80:
! 81: /* Sanity-check the given size. */
! 82: if (bufsize < sizeof(struct msgbuf))
! 83: return;
! 84:
! 85: mbp = msgbufp = (struct msgbuf *)buf;
! 86:
! 87: new_bufs = bufsize - offsetof(struct msgbuf, msg_bufc);
! 88: if ((mbp->msg_magic != MSG_MAGIC) || (mbp->msg_bufs != new_bufs) ||
! 89: (mbp->msg_bufr < 0) || (mbp->msg_bufr >= mbp->msg_bufs) ||
! 90: (mbp->msg_bufx < 0) || (mbp->msg_bufx >= mbp->msg_bufs)) {
! 91: /*
! 92: * If the buffer magic number is wrong, has changed
! 93: * size (which shouldn't happen often), or is
! 94: * internally inconsistent, initialize it.
! 95: */
! 96:
! 97: bzero(buf, bufsize);
! 98: mbp->msg_magic = MSG_MAGIC;
! 99: mbp->msg_bufs = new_bufs;
! 100: }
! 101:
! 102: /* Always start new buffer data on a new line. */
! 103: if (mbp->msg_bufx > 0 && mbp->msg_bufc[mbp->msg_bufx - 1] != '\n')
! 104: msgbuf_putchar('\n');
! 105:
! 106: /* mark it as ready for use. */
! 107: msgbufmapped = msgbufenabled = 1;
! 108: }
! 109:
! 110: void
! 111: msgbuf_putchar(const char c)
! 112: {
! 113: struct msgbuf *mbp = msgbufp;
! 114:
! 115: if (mbp->msg_magic != MSG_MAGIC)
! 116: /* Nothing we can do */
! 117: return;
! 118:
! 119: mbp->msg_bufc[mbp->msg_bufx++] = c;
! 120: mbp->msg_bufl = min(mbp->msg_bufl+1, mbp->msg_bufs);
! 121: if (mbp->msg_bufx < 0 || mbp->msg_bufx >= mbp->msg_bufs)
! 122: mbp->msg_bufx = 0;
! 123: /* If the buffer is full, keep the most recent data. */
! 124: if (mbp->msg_bufr == mbp->msg_bufx) {
! 125: if (++mbp->msg_bufr >= mbp->msg_bufs)
! 126: mbp->msg_bufr = 0;
! 127: }
! 128: }
! 129:
! 130: /*ARGSUSED*/
! 131: int
! 132: logopen(dev_t dev, int flags, int mode, struct proc *p)
! 133: {
! 134: if (log_open)
! 135: return (EBUSY);
! 136: log_open = 1;
! 137: return (0);
! 138: }
! 139:
! 140: /*ARGSUSED*/
! 141: int
! 142: logclose(dev_t dev, int flag, int mode, struct proc *p)
! 143: {
! 144:
! 145: log_open = 0;
! 146: logsoftc.sc_state = 0;
! 147: return (0);
! 148: }
! 149:
! 150: /*ARGSUSED*/
! 151: int
! 152: logread(dev_t dev, struct uio *uio, int flag)
! 153: {
! 154: struct msgbuf *mbp = msgbufp;
! 155: long l;
! 156: int s;
! 157: int error = 0;
! 158:
! 159: s = splhigh();
! 160: while (mbp->msg_bufr == mbp->msg_bufx) {
! 161: if (flag & IO_NDELAY) {
! 162: splx(s);
! 163: return (EWOULDBLOCK);
! 164: }
! 165: logsoftc.sc_state |= LOG_RDWAIT;
! 166: error = tsleep(mbp, LOG_RDPRI | PCATCH,
! 167: "klog", 0);
! 168: if (error) {
! 169: splx(s);
! 170: return (error);
! 171: }
! 172: }
! 173: splx(s);
! 174: logsoftc.sc_state &= ~LOG_RDWAIT;
! 175:
! 176: while (uio->uio_resid > 0) {
! 177: l = mbp->msg_bufx - mbp->msg_bufr;
! 178: if (l < 0)
! 179: l = mbp->msg_bufs - mbp->msg_bufr;
! 180: l = min(l, uio->uio_resid);
! 181: if (l == 0)
! 182: break;
! 183: error = uiomove(&mbp->msg_bufc[mbp->msg_bufr], (int)l, uio);
! 184: if (error)
! 185: break;
! 186: mbp->msg_bufr += l;
! 187: if (mbp->msg_bufr < 0 || mbp->msg_bufr >= mbp->msg_bufs)
! 188: mbp->msg_bufr = 0;
! 189: }
! 190: return (error);
! 191: }
! 192:
! 193: /*ARGSUSED*/
! 194: int
! 195: logpoll(dev_t dev, int events, struct proc *p)
! 196: {
! 197: int revents = 0;
! 198: int s = splhigh();
! 199:
! 200: if (events & (POLLIN | POLLRDNORM)) {
! 201: if (msgbufp->msg_bufr != msgbufp->msg_bufx)
! 202: revents |= events & (POLLIN | POLLRDNORM);
! 203: else
! 204: selrecord(p, &logsoftc.sc_selp);
! 205: }
! 206: splx(s);
! 207: return (revents);
! 208: }
! 209:
! 210: int
! 211: logkqfilter(dev_t dev, struct knote *kn)
! 212: {
! 213: struct klist *klist;
! 214: int s;
! 215:
! 216: switch (kn->kn_filter) {
! 217: case EVFILT_READ:
! 218: klist = &logsoftc.sc_selp.si_note;
! 219: kn->kn_fop = &logread_filtops;
! 220: break;
! 221: default:
! 222: return (1);
! 223: }
! 224:
! 225: kn->kn_hook = (void *)msgbufp;
! 226:
! 227: s = splhigh();
! 228: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
! 229: splx(s);
! 230:
! 231: return (0);
! 232: }
! 233:
! 234: void
! 235: filt_logrdetach(struct knote *kn)
! 236: {
! 237: int s = splhigh();
! 238:
! 239: SLIST_REMOVE(&logsoftc.sc_selp.si_note, kn, knote, kn_selnext);
! 240: splx(s);
! 241: }
! 242:
! 243: int
! 244: filt_logread(struct knote *kn, long hint)
! 245: {
! 246: struct msgbuf *p = (struct msgbuf *)kn->kn_hook;
! 247:
! 248: kn->kn_data = (int)(p->msg_bufx - p->msg_bufr);
! 249:
! 250: return (p->msg_bufx != p->msg_bufr);
! 251: }
! 252:
! 253: void
! 254: logwakeup(void)
! 255: {
! 256: if (!log_open)
! 257: return;
! 258: selwakeup(&logsoftc.sc_selp);
! 259: if (logsoftc.sc_state & LOG_ASYNC)
! 260: csignal(logsoftc.sc_pgid, SIGIO,
! 261: logsoftc.sc_siguid, logsoftc.sc_sigeuid);
! 262: if (logsoftc.sc_state & LOG_RDWAIT) {
! 263: wakeup(msgbufp);
! 264: logsoftc.sc_state &= ~LOG_RDWAIT;
! 265: }
! 266: KNOTE(&logsoftc.sc_selp.si_note, 0);
! 267: }
! 268:
! 269: /*ARGSUSED*/
! 270: int
! 271: logioctl(dev_t dev, u_long com, caddr_t data, int flag, struct proc *p)
! 272: {
! 273: long l;
! 274: int s;
! 275:
! 276: switch (com) {
! 277:
! 278: /* return number of characters immediately available */
! 279: case FIONREAD:
! 280: s = splhigh();
! 281: l = msgbufp->msg_bufx - msgbufp->msg_bufr;
! 282: splx(s);
! 283: if (l < 0)
! 284: l += msgbufp->msg_bufs;
! 285: *(int *)data = l;
! 286: break;
! 287:
! 288: case FIONBIO:
! 289: break;
! 290:
! 291: case FIOASYNC:
! 292: if (*(int *)data)
! 293: logsoftc.sc_state |= LOG_ASYNC;
! 294: else
! 295: logsoftc.sc_state &= ~LOG_ASYNC;
! 296: break;
! 297:
! 298: case TIOCSPGRP:
! 299: logsoftc.sc_pgid = *(int *)data;
! 300: logsoftc.sc_siguid = p->p_cred->p_ruid;
! 301: logsoftc.sc_sigeuid = p->p_ucred->cr_uid;
! 302: break;
! 303:
! 304: case TIOCGPGRP:
! 305: *(int *)data = logsoftc.sc_pgid;
! 306: break;
! 307:
! 308: default:
! 309: return (-1);
! 310: }
! 311: return (0);
! 312: }
CVSweb