xref: /csrg-svn/sys/kern/subr_log.c (revision 24524)
1 /*
2  * Copyright (c) 1982 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)subr_log.c	6.6 (Berkeley) 09/04/85
7  */
8 
9 /*
10  * Error log buffer for kernel printf's.
11  */
12 
13 #include "param.h"
14 #include "dir.h"
15 #include "user.h"
16 #include "proc.h"
17 #include "ioctl.h"
18 #include "msgbuf.h"
19 #include "file.h"
20 #include "errno.h"
21 
22 #define LOG_RDPRI	(PZERO + 1)
23 
24 #define LOG_NBIO	0x02
25 #define LOG_ASYNC	0x04
26 #define LOG_RDWAIT	0x08
27 
28 struct logsoftc {
29 	int	sc_state;		/* see above for possibilities */
30 	struct	proc *sc_selp;		/* process waiting on select call */
31 	int	sc_pgrp;		/* process group for async I/O */
32 } logsoftc;
33 
34 int	log_open;			/* also used in log() */
35 
36 #ifdef LOGDEBUG
37 /*VARARGS1*/
38 xprintf(fmt, x1)
39 	char *fmt;
40 	unsigned x1;
41 {
42 
43 	prf(fmt, &x1, 1, (struct tty *)0);
44 }
45 #endif
46 
47 /*ARGSUSED*/
48 logopen(dev)
49 	dev_t dev;
50 {
51 
52 #ifdef LOGDEBUG
53 	xprintf("logopen: dev=0x%x\n", dev);
54 #endif
55 	if (log_open)
56 		return (EBUSY);
57 	log_open = 1;
58 	logsoftc.sc_selp = 0;
59 	logsoftc.sc_pgrp = u.u_procp->p_pgrp;
60 	/*
61 	 * Potential race here with putchar() but since putchar should be
62 	 * called by autoconf, msg_magic should be initialized by the time
63 	 * we get here.
64 	 */
65 	if (msgbuf.msg_magic != MSG_MAGIC) {
66 		register int i;
67 
68 		msgbuf.msg_magic = MSG_MAGIC;
69 		msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
70 		for (i=0; i < MSG_BSIZE; i++)
71 			msgbuf.msg_bufc[i] = 0;
72 	}
73 #ifdef LOGDEBUG
74 	xprintf("logopen: bufx=%d, bufr=%d\n", msgbuf.msg_bufx, msgbuf.msg_bufr);
75 #endif
76 	return (0);
77 }
78 
79 /*ARGSUSED*/
80 logclose(dev, flag)
81 	dev_t dev;
82 {
83 	log_open = 0;
84 	logsoftc.sc_state = 0;
85 	logsoftc.sc_selp = 0;
86 	logsoftc.sc_pgrp = 0;
87 #ifdef LOGDEBUG
88 	xprintf("logclose: dev=0x%x\n", dev);
89 #endif
90 }
91 
92 /*ARGSUSED*/
93 logread(dev, uio)
94 	dev_t dev;
95 	struct uio *uio;
96 {
97 	register long l;
98 	register u_int c;
99 	register int s;
100 	int error = 0;
101 
102 #ifdef LOGDEBUG
103 	xprintf("logread: dev=0x%x\n", dev);
104 #endif
105 
106 	s = splhigh();
107 	while (msgbuf.msg_bufr == msgbuf.msg_bufx) {
108 		if (logsoftc.sc_state & LOG_NBIO) {
109 			splx(s);
110 			return (EWOULDBLOCK);
111 		}
112 		logsoftc.sc_state |= LOG_RDWAIT;
113 		sleep((caddr_t)&msgbuf, LOG_RDPRI);
114 	}
115 	splx(s);
116 	logsoftc.sc_state &= ~LOG_RDWAIT;
117 
118 	while (uio->uio_resid > 0) {
119 		l = msgbuf.msg_bufx - msgbuf.msg_bufr;
120 		if (l < 0)
121 			l = MSG_BSIZE - msgbuf.msg_bufr;
122 		c = min((u_int) l, (u_int)uio->uio_resid);
123 #ifdef LOGDEBUG
124 		xprintf("logread: bufx=%d, bufr=%d, l=%d, c=%d\n",
125 			msgbuf.msg_bufx, msgbuf.msg_bufr, l, c);
126 #endif
127 		if (c <= 0)
128 			break;
129 		error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr],
130 			(int)c, UIO_READ, uio);
131 		if (error)
132 			break;
133 		msgbuf.msg_bufr += c;
134 		if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE)
135 			msgbuf.msg_bufr = 0;
136 	}
137 	return (error);
138 }
139 
140 /*ARGSUSED*/
141 logselect(dev, rw)
142 	dev_t dev;
143 	int rw;
144 {
145 	int s = splhigh();
146 
147 	switch (rw) {
148 
149 	case FREAD:
150 		if (msgbuf.msg_bufr != msgbuf.msg_bufx)
151 			goto win;
152 #ifdef LOGDEBUG
153 		if (logsoftc.sc_selp)
154 			xprintf("logselect: collision\n");
155 #endif
156 		logsoftc.sc_selp = u.u_procp;
157 		break;
158 
159 	case FWRITE:
160 #ifdef LOGDEBUG
161 		xprintf("logselect: FWRITE\n");
162 #endif
163 		break;
164 	}
165 	splx(s);
166 	return (0);
167 win:
168 	splx(s);
169 	return (1);
170 }
171 
172 logwakeup()
173 {
174 
175 	if (!log_open)
176 		return;
177 	if (logsoftc.sc_selp) {
178 		selwakeup(logsoftc.sc_selp, 0);
179 		logsoftc.sc_selp = 0;
180 	}
181 	if (logsoftc.sc_state & LOG_ASYNC)
182 		gsignal(logsoftc.sc_pgrp, SIGIO);
183 	if (logsoftc.sc_state & LOG_RDWAIT) {
184 		wakeup((caddr_t)&msgbuf);
185 		logsoftc.sc_state &= ~LOG_RDWAIT;
186 	}
187 }
188 
189 /*ARGSUSED*/
190 logioctl(com, data, flag)
191 	caddr_t data;
192 {
193 	long l;
194 	int s;
195 
196 	switch (com) {
197 
198 	/* return number of characters immediately available */
199 	case FIONREAD:
200 		s = splhigh();
201 		l = msgbuf.msg_bufx - msgbuf.msg_bufr;
202 		splx(s);
203 		if (l < 0)
204 			l += MSG_BSIZE;
205 		*(off_t *)data = l;
206 		break;
207 
208 	case FIONBIO:
209 		if (*(int *)data)
210 			logsoftc.sc_state |= LOG_NBIO;
211 		else
212 			logsoftc.sc_state &= ~LOG_NBIO;
213 		break;
214 
215 	case FIOASYNC:
216 		if (*(int *)data)
217 			logsoftc.sc_state |= LOG_ASYNC;
218 		else
219 			logsoftc.sc_state &= ~LOG_ASYNC;
220 		break;
221 
222 	case TIOCSPGRP:
223 		logsoftc.sc_pgrp = *(int *)data;
224 		break;
225 
226 	case TIOCGPGRP:
227 		*(int *)data = logsoftc.sc_pgrp;
228 		break;
229 
230 	default:
231 		return (-1);
232 	}
233 	return (0);
234 }
235