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 | * | |
fa1aff05 | 6 | * @(#)subr_log.c 7.9 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
c45816fa RC |
8 | |
9 | /* | |
10 | * Error log buffer for kernel printf's. | |
11 | */ | |
12 | ||
94368568 | 13 | #include "param.h" |
94368568 JB |
14 | #include "user.h" |
15 | #include "proc.h" | |
0a23a89f | 16 | #include "vnode.h" |
94368568 JB |
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_ASYNC 0x04 |
25 | #define LOG_RDWAIT 0x08 | |
26 | ||
27 | struct logsoftc { | |
28 | int sc_state; /* see above for possibilities */ | |
29 | struct proc *sc_selp; /* process waiting on select call */ | |
f9b02bae | 30 | int sc_pgid; /* process/group for async I/O */ |
c45816fa RC |
31 | } logsoftc; |
32 | ||
bd10af3f MK |
33 | int log_open; /* also used in log() */ |
34 | ||
0b355a6e | 35 | /*ARGSUSED*/ |
c45816fa RC |
36 | logopen(dev) |
37 | dev_t dev; | |
38 | { | |
39 | ||
bd10af3f | 40 | if (log_open) |
18c9b20d | 41 | return (EBUSY); |
bd10af3f | 42 | log_open = 1; |
f9b02bae | 43 | logsoftc.sc_pgid = u.u_procp->p_pid; /* signal process only */ |
c45816fa RC |
44 | /* |
45 | * Potential race here with putchar() but since putchar should be | |
46 | * called by autoconf, msg_magic should be initialized by the time | |
47 | * we get here. | |
48 | */ | |
49 | if (msgbuf.msg_magic != MSG_MAGIC) { | |
50 | register int i; | |
51 | ||
52 | msgbuf.msg_magic = MSG_MAGIC; | |
53 | msgbuf.msg_bufx = msgbuf.msg_bufr = 0; | |
54 | for (i=0; i < MSG_BSIZE; i++) | |
55 | msgbuf.msg_bufc[i] = 0; | |
56 | } | |
18c9b20d | 57 | return (0); |
c45816fa RC |
58 | } |
59 | ||
0b355a6e | 60 | /*ARGSUSED*/ |
c45816fa RC |
61 | logclose(dev, flag) |
62 | dev_t dev; | |
63 | { | |
bd10af3f | 64 | log_open = 0; |
c45816fa RC |
65 | logsoftc.sc_state = 0; |
66 | logsoftc.sc_selp = 0; | |
c45816fa RC |
67 | } |
68 | ||
0b355a6e | 69 | /*ARGSUSED*/ |
f9b02bae | 70 | logread(dev, uio, flag) |
c45816fa RC |
71 | dev_t dev; |
72 | struct uio *uio; | |
f9b02bae | 73 | int flag; |
c45816fa RC |
74 | { |
75 | register long l; | |
c45816fa RC |
76 | register int s; |
77 | int error = 0; | |
78 | ||
c45816fa RC |
79 | s = splhigh(); |
80 | while (msgbuf.msg_bufr == msgbuf.msg_bufx) { | |
f9b02bae | 81 | if (flag & IO_NDELAY) { |
c45816fa | 82 | splx(s); |
18c9b20d | 83 | return (EWOULDBLOCK); |
c45816fa RC |
84 | } |
85 | logsoftc.sc_state |= LOG_RDWAIT; | |
86f4eb6e MT |
86 | if (error = tsleep((caddr_t)&msgbuf, LOG_RDPRI | PCATCH, |
87 | "klog", 0)) { | |
88 | splx(s); | |
89 | return (error); | |
90 | } | |
c45816fa RC |
91 | } |
92 | splx(s); | |
93 | logsoftc.sc_state &= ~LOG_RDWAIT; | |
94 | ||
95 | while (uio->uio_resid > 0) { | |
96 | l = msgbuf.msg_bufx - msgbuf.msg_bufr; | |
97 | if (l < 0) | |
98 | l = MSG_BSIZE - msgbuf.msg_bufr; | |
8011f5df | 99 | l = MIN(l, uio->uio_resid); |
b52a4e53 | 100 | if (l == 0) |
18c9b20d | 101 | break; |
c45816fa | 102 | error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr], |
c4ec2128 | 103 | (int)l, uio); |
c45816fa RC |
104 | if (error) |
105 | break; | |
b52a4e53 | 106 | msgbuf.msg_bufr += l; |
c45816fa RC |
107 | if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE) |
108 | msgbuf.msg_bufr = 0; | |
109 | } | |
18c9b20d | 110 | return (error); |
c45816fa RC |
111 | } |
112 | ||
0b355a6e | 113 | /*ARGSUSED*/ |
c45816fa RC |
114 | logselect(dev, rw) |
115 | dev_t dev; | |
116 | int rw; | |
117 | { | |
118 | int s = splhigh(); | |
119 | ||
120 | switch (rw) { | |
121 | ||
122 | case FREAD: | |
b52a4e53 MK |
123 | if (msgbuf.msg_bufr != msgbuf.msg_bufx) { |
124 | splx(s); | |
125 | return (1); | |
126 | } | |
c45816fa RC |
127 | logsoftc.sc_selp = u.u_procp; |
128 | break; | |
c45816fa RC |
129 | } |
130 | splx(s); | |
18c9b20d | 131 | return (0); |
c45816fa RC |
132 | } |
133 | ||
134 | logwakeup() | |
135 | { | |
f9b02bae | 136 | struct proc *p; |
c45816fa | 137 | |
bd10af3f MK |
138 | if (!log_open) |
139 | return; | |
c45816fa RC |
140 | if (logsoftc.sc_selp) { |
141 | selwakeup(logsoftc.sc_selp, 0); | |
142 | logsoftc.sc_selp = 0; | |
143 | } | |
f9b02bae MK |
144 | if (logsoftc.sc_state & LOG_ASYNC) { |
145 | if (logsoftc.sc_pgid < 0) | |
fa1aff05 | 146 | gsignal(-logsoftc.sc_pgid, SIGIO); |
f9b02bae MK |
147 | else if (p = pfind(logsoftc.sc_pgid)) |
148 | psignal(p, SIGIO); | |
149 | } | |
c45816fa RC |
150 | if (logsoftc.sc_state & LOG_RDWAIT) { |
151 | wakeup((caddr_t)&msgbuf); | |
152 | logsoftc.sc_state &= ~LOG_RDWAIT; | |
153 | } | |
154 | } | |
155 | ||
156 | /*ARGSUSED*/ | |
f9b02bae | 157 | logioctl(dev, com, data, flag) |
c45816fa RC |
158 | caddr_t data; |
159 | { | |
160 | long l; | |
161 | int s; | |
162 | ||
163 | switch (com) { | |
164 | ||
165 | /* return number of characters immediately available */ | |
166 | case FIONREAD: | |
167 | s = splhigh(); | |
168 | l = msgbuf.msg_bufx - msgbuf.msg_bufr; | |
169 | splx(s); | |
170 | if (l < 0) | |
171 | l += MSG_BSIZE; | |
172 | *(off_t *)data = l; | |
173 | break; | |
174 | ||
175 | case FIONBIO: | |
c45816fa RC |
176 | break; |
177 | ||
178 | case FIOASYNC: | |
179 | if (*(int *)data) | |
180 | logsoftc.sc_state |= LOG_ASYNC; | |
181 | else | |
182 | logsoftc.sc_state &= ~LOG_ASYNC; | |
183 | break; | |
184 | ||
f9b02bae | 185 | case TIOCSPGRP: |
8fe87cbb | 186 | logsoftc.sc_pgid = *(int *)data; |
c45816fa RC |
187 | break; |
188 | ||
189 | case TIOCGPGRP: | |
f9b02bae | 190 | *(int *)data = logsoftc.sc_pgid; |
c45816fa RC |
191 | break; |
192 | ||
193 | default: | |
18c9b20d | 194 | return (-1); |
c45816fa | 195 | } |
18c9b20d | 196 | return (0); |
c45816fa | 197 | } |