subr_log.c revision 1.1.1.2 1 /*
2 * Copyright (c) 1982, 1986, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)subr_log.c 8.1 (Berkeley) 6/10/93
34 */
35
36 /*
37 * Error log buffer for kernel printf's.
38 */
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/vnode.h>
44 #include <sys/ioctl.h>
45 #include <sys/msgbuf.h>
46 #include <sys/file.h>
47
48 #define LOG_RDPRI (PZERO + 1)
49
50 #define LOG_ASYNC 0x04
51 #define LOG_RDWAIT 0x08
52
53 struct logsoftc {
54 int sc_state; /* see above for possibilities */
55 struct selinfo sc_selp; /* process waiting on select call */
56 int sc_pgid; /* process/group for async I/O */
57 } logsoftc;
58
59 int log_open; /* also used in log() */
60
61 /*ARGSUSED*/
62 logopen(dev, flags, mode, p)
63 dev_t dev;
64 int flags, mode;
65 struct proc *p;
66 {
67 register struct msgbuf *mbp = msgbufp;
68
69 if (log_open)
70 return (EBUSY);
71 log_open = 1;
72 logsoftc.sc_pgid = p->p_pid; /* signal process only */
73 /*
74 * Potential race here with putchar() but since putchar should be
75 * called by autoconf, msg_magic should be initialized by the time
76 * we get here.
77 */
78 if (mbp->msg_magic != MSG_MAGIC) {
79 register int i;
80
81 mbp->msg_magic = MSG_MAGIC;
82 mbp->msg_bufx = mbp->msg_bufr = 0;
83 for (i=0; i < MSG_BSIZE; i++)
84 mbp->msg_bufc[i] = 0;
85 }
86 return (0);
87 }
88
89 /*ARGSUSED*/
90 logclose(dev, flag, mode, p)
91 dev_t dev;
92 int flag, mode;
93 struct proc *p;
94 {
95
96 log_open = 0;
97 logsoftc.sc_state = 0;
98 return (0);
99 }
100
101 /*ARGSUSED*/
102 logread(dev, uio, flag)
103 dev_t dev;
104 struct uio *uio;
105 int flag;
106 {
107 register struct msgbuf *mbp = msgbufp;
108 register long l;
109 register int s;
110 int error = 0;
111
112 s = splhigh();
113 while (mbp->msg_bufr == mbp->msg_bufx) {
114 if (flag & IO_NDELAY) {
115 splx(s);
116 return (EWOULDBLOCK);
117 }
118 logsoftc.sc_state |= LOG_RDWAIT;
119 if (error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH,
120 "klog", 0)) {
121 splx(s);
122 return (error);
123 }
124 }
125 splx(s);
126 logsoftc.sc_state &= ~LOG_RDWAIT;
127
128 while (uio->uio_resid > 0) {
129 l = mbp->msg_bufx - mbp->msg_bufr;
130 if (l < 0)
131 l = MSG_BSIZE - mbp->msg_bufr;
132 l = min(l, uio->uio_resid);
133 if (l == 0)
134 break;
135 error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr],
136 (int)l, uio);
137 if (error)
138 break;
139 mbp->msg_bufr += l;
140 if (mbp->msg_bufr < 0 || mbp->msg_bufr >= MSG_BSIZE)
141 mbp->msg_bufr = 0;
142 }
143 return (error);
144 }
145
146 /*ARGSUSED*/
147 logselect(dev, rw, p)
148 dev_t dev;
149 int rw;
150 struct proc *p;
151 {
152 int s = splhigh();
153
154 switch (rw) {
155
156 case FREAD:
157 if (msgbufp->msg_bufr != msgbufp->msg_bufx) {
158 splx(s);
159 return (1);
160 }
161 selrecord(p, &logsoftc.sc_selp);
162 break;
163 }
164 splx(s);
165 return (0);
166 }
167
168 logwakeup()
169 {
170 struct proc *p;
171
172 if (!log_open)
173 return;
174 selwakeup(&logsoftc.sc_selp);
175 if (logsoftc.sc_state & LOG_ASYNC) {
176 if (logsoftc.sc_pgid < 0)
177 gsignal(-logsoftc.sc_pgid, SIGIO);
178 else if (p = pfind(logsoftc.sc_pgid))
179 psignal(p, SIGIO);
180 }
181 if (logsoftc.sc_state & LOG_RDWAIT) {
182 wakeup((caddr_t)msgbufp);
183 logsoftc.sc_state &= ~LOG_RDWAIT;
184 }
185 }
186
187 /*ARGSUSED*/
188 logioctl(dev, com, data, flag, p)
189 dev_t dev;
190 int com;
191 caddr_t data;
192 int flag;
193 struct proc *p;
194 {
195 long l;
196 int s;
197
198 switch (com) {
199
200 /* return number of characters immediately available */
201 case FIONREAD:
202 s = splhigh();
203 l = msgbufp->msg_bufx - msgbufp->msg_bufr;
204 splx(s);
205 if (l < 0)
206 l += MSG_BSIZE;
207 *(int *)data = l;
208 break;
209
210 case FIONBIO:
211 break;
212
213 case FIOASYNC:
214 if (*(int *)data)
215 logsoftc.sc_state |= LOG_ASYNC;
216 else
217 logsoftc.sc_state &= ~LOG_ASYNC;
218 break;
219
220 case TIOCSPGRP:
221 logsoftc.sc_pgid = *(int *)data;
222 break;
223
224 case TIOCGPGRP:
225 *(int *)data = logsoftc.sc_pgid;
226 break;
227
228 default:
229 return (-1);
230 }
231 return (0);
232 }
233