Annotation of sys/kern/subr_log.c, Revision 1.1.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