Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)subr_log.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
c45816fa RC |
8 | |
9 | /* | |
10 | * Error log buffer for kernel printf's. | |
11 | */ | |
12 | ||
94368568 JB |
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" | |
c45816fa RC |
21 | |
22 | #define LOG_RDPRI (PZERO + 1) | |
23 | ||
c45816fa RC |
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 | ||
bd10af3f MK |
34 | int log_open; /* also used in log() */ |
35 | ||
0b355a6e | 36 | /*ARGSUSED*/ |
c45816fa RC |
37 | logopen(dev) |
38 | dev_t dev; | |
39 | { | |
40 | ||
bd10af3f | 41 | if (log_open) |
18c9b20d | 42 | return (EBUSY); |
bd10af3f | 43 | log_open = 1; |
c45816fa RC |
44 | logsoftc.sc_selp = 0; |
45 | logsoftc.sc_pgrp = u.u_procp->p_pgrp; | |
46 | /* | |
47 | * Potential race here with putchar() but since putchar should be | |
48 | * called by autoconf, msg_magic should be initialized by the time | |
49 | * we get here. | |
50 | */ | |
51 | if (msgbuf.msg_magic != MSG_MAGIC) { | |
52 | register int i; | |
53 | ||
54 | msgbuf.msg_magic = MSG_MAGIC; | |
55 | msgbuf.msg_bufx = msgbuf.msg_bufr = 0; | |
56 | for (i=0; i < MSG_BSIZE; i++) | |
57 | msgbuf.msg_bufc[i] = 0; | |
58 | } | |
18c9b20d | 59 | return (0); |
c45816fa RC |
60 | } |
61 | ||
0b355a6e | 62 | /*ARGSUSED*/ |
c45816fa RC |
63 | logclose(dev, flag) |
64 | dev_t dev; | |
65 | { | |
bd10af3f | 66 | log_open = 0; |
c45816fa RC |
67 | logsoftc.sc_state = 0; |
68 | logsoftc.sc_selp = 0; | |
69 | logsoftc.sc_pgrp = 0; | |
c45816fa RC |
70 | } |
71 | ||
0b355a6e | 72 | /*ARGSUSED*/ |
c45816fa RC |
73 | logread(dev, uio) |
74 | dev_t dev; | |
75 | struct uio *uio; | |
76 | { | |
77 | register long l; | |
c45816fa RC |
78 | register int s; |
79 | int error = 0; | |
80 | ||
c45816fa RC |
81 | s = splhigh(); |
82 | while (msgbuf.msg_bufr == msgbuf.msg_bufx) { | |
83 | if (logsoftc.sc_state & LOG_NBIO) { | |
84 | splx(s); | |
18c9b20d | 85 | return (EWOULDBLOCK); |
c45816fa RC |
86 | } |
87 | logsoftc.sc_state |= LOG_RDWAIT; | |
88 | sleep((caddr_t)&msgbuf, LOG_RDPRI); | |
89 | } | |
90 | splx(s); | |
91 | logsoftc.sc_state &= ~LOG_RDWAIT; | |
92 | ||
93 | while (uio->uio_resid > 0) { | |
94 | l = msgbuf.msg_bufx - msgbuf.msg_bufr; | |
95 | if (l < 0) | |
96 | l = MSG_BSIZE - msgbuf.msg_bufr; | |
8011f5df | 97 | l = MIN(l, uio->uio_resid); |
b52a4e53 | 98 | if (l == 0) |
18c9b20d | 99 | break; |
c45816fa | 100 | error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr], |
b52a4e53 | 101 | (int)l, UIO_READ, uio); |
c45816fa RC |
102 | if (error) |
103 | break; | |
b52a4e53 | 104 | msgbuf.msg_bufr += l; |
c45816fa RC |
105 | if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE) |
106 | msgbuf.msg_bufr = 0; | |
107 | } | |
18c9b20d | 108 | return (error); |
c45816fa RC |
109 | } |
110 | ||
0b355a6e | 111 | /*ARGSUSED*/ |
c45816fa RC |
112 | logselect(dev, rw) |
113 | dev_t dev; | |
114 | int rw; | |
115 | { | |
116 | int s = splhigh(); | |
117 | ||
118 | switch (rw) { | |
119 | ||
120 | case FREAD: | |
b52a4e53 MK |
121 | if (msgbuf.msg_bufr != msgbuf.msg_bufx) { |
122 | splx(s); | |
123 | return (1); | |
124 | } | |
c45816fa RC |
125 | logsoftc.sc_selp = u.u_procp; |
126 | break; | |
c45816fa RC |
127 | } |
128 | splx(s); | |
18c9b20d | 129 | return (0); |
c45816fa RC |
130 | } |
131 | ||
132 | logwakeup() | |
133 | { | |
134 | ||
bd10af3f MK |
135 | if (!log_open) |
136 | return; | |
c45816fa RC |
137 | if (logsoftc.sc_selp) { |
138 | selwakeup(logsoftc.sc_selp, 0); | |
139 | logsoftc.sc_selp = 0; | |
140 | } | |
141 | if (logsoftc.sc_state & LOG_ASYNC) | |
142 | gsignal(logsoftc.sc_pgrp, SIGIO); | |
143 | if (logsoftc.sc_state & LOG_RDWAIT) { | |
144 | wakeup((caddr_t)&msgbuf); | |
145 | logsoftc.sc_state &= ~LOG_RDWAIT; | |
146 | } | |
147 | } | |
148 | ||
149 | /*ARGSUSED*/ | |
150 | logioctl(com, data, flag) | |
151 | caddr_t data; | |
152 | { | |
153 | long l; | |
154 | int s; | |
155 | ||
156 | switch (com) { | |
157 | ||
158 | /* return number of characters immediately available */ | |
159 | case FIONREAD: | |
160 | s = splhigh(); | |
161 | l = msgbuf.msg_bufx - msgbuf.msg_bufr; | |
162 | splx(s); | |
163 | if (l < 0) | |
164 | l += MSG_BSIZE; | |
165 | *(off_t *)data = l; | |
166 | break; | |
167 | ||
168 | case FIONBIO: | |
169 | if (*(int *)data) | |
170 | logsoftc.sc_state |= LOG_NBIO; | |
171 | else | |
172 | logsoftc.sc_state &= ~LOG_NBIO; | |
173 | break; | |
174 | ||
175 | case FIOASYNC: | |
176 | if (*(int *)data) | |
177 | logsoftc.sc_state |= LOG_ASYNC; | |
178 | else | |
179 | logsoftc.sc_state &= ~LOG_ASYNC; | |
180 | break; | |
181 | ||
182 | case TIOCSPGRP: | |
183 | logsoftc.sc_pgrp = *(int *)data; | |
184 | break; | |
185 | ||
186 | case TIOCGPGRP: | |
187 | *(int *)data = logsoftc.sc_pgrp; | |
188 | break; | |
189 | ||
190 | default: | |
18c9b20d | 191 | return (-1); |
c45816fa | 192 | } |
18c9b20d | 193 | return (0); |
c45816fa | 194 | } |