|
|
1.1 root 1: /*
2: * Copyright (c) 1993 Christopher G. Demetriou
3: * Copyright (c) 1982, 1986 Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by the University of
17: * California, Berkeley and its contributors.
18: * 4. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * from: @(#)subr_log.c 7.11 (Berkeley) 3/17/91
35: * subr_acct.c,v 1.4 1993/06/30 13:43:03 mycroft Exp
36: */
37:
38: /*
39: * acct buffer for accounting information
40: */
41:
42: #include "param.h"
43: #include "systm.h"
44: #include "proc.h"
45: #include "vnode.h"
46: #include "ioctl.h"
47: #include "file.h"
48: #include "malloc.h"
49: #include "acct.h"
50: #include "acctbuf.h"
51: #include "select.h"
52:
53: #define ACCT_RDPRI (PZERO + 1)
54:
55: #define ACCT_ASYNC 0x04
56: #define ACCT_RDWAIT 0x08
57:
58: struct acctsoftc {
59: int sc_state; /* see above for possibilities */
60: struct selinfo sc_selp; /* process waiting on select call */
61: int sc_pgid; /* process/group for async I/O */
62: } acctsoftc;
63:
64: int acct_open; /* also used in acct() */
65: struct acctbuf *acctbufp; /* the accounting buffer pointer */
66:
67: /*ARGSUSED*/
68: int
69: #ifdef __STDC__
70: acctopen(dev_t dev, int flags, int mode, struct proc *p)
71: /* gcc 1.x doesn't like non-ansi def for this */
72: #else
73: acctopen()
74: dev_t dev;
75: int flags, mode;
76: struct proc *p;
77: #endif
78: {
79: if (acct_open)
80: return (EBUSY);
81: acct_open = 1;
82: acctsoftc.sc_pgid = p->p_pid; /* signal process only */
83:
84: if (acctbufp == NULL)
85: acctbuf_init();
86: #ifdef ACCT_DEBUG
87: acctbuf_checkbuf("acctopen");
88: #endif
89:
90: return (0);
91: }
92:
93: /*ARGSUSED*/
94: int
95: #ifdef __STDC__
96: acctclose(dev_t dev, int flag)
97: /* gcc 1.x doesn't like non-ansi def for this */
98: #else
99: acctclose()
100: dev_t dev;
101: int flag;
102: #endif
103: {
104: acct_open = 0;
105: acctsoftc.sc_state = 0;
106: bzero(&acctsoftc.sc_selp,sizeof(acctsoftc.sc_selp));
107:
108: return 0;
109: }
110:
111: /*ARGSUSED*/
112: int
113: #ifdef __STDC__
114: acctread(dev_t dev, struct uio *uio, int flag)
115: /* gcc 1.x doesn't like non-ansi def for this */
116: #else
117: acctread()
118: dev_t dev;
119: struct uio *uio;
120: int flag;
121: #endif
122: {
123: register struct acctbuf *abp = acctbufp;
124: register long l;
125: int error = 0;
126:
127: #ifdef ACCT_DEBUG
128: acctbuf_checkbuf("acctread 1");
129: #endif
130: while (abp->ab_rind == abp->ab_wind) {
131: if (flag & IO_NDELAY) {
132: return (EWOULDBLOCK);
133: }
134: acctsoftc.sc_state |= ACCT_RDWAIT;
135: if (error = tsleep((caddr_t)abp, ACCT_RDPRI | PCATCH,
136: "acct", 0)) {
137: return (error);
138: }
139: }
140: acctsoftc.sc_state &= ~ACCT_RDWAIT;
141:
142: while (uio->uio_resid > 0) {
143: l = abp->ab_wind - abp->ab_rind;
144: if (l < 0)
145: l = ACCT_NBRECS - abp->ab_rind;
146: l = MIN(l, uio->uio_resid / sizeof(struct acct));
147: if (l == 0)
148: break;
149: error = uiomove((caddr_t)&abp->recs[abp->ab_rind],
150: (int)(l * sizeof(struct acct)), uio);
151: if (error)
152: break;
153: abp->ab_rind += l;
154: if (abp->ab_rind < 0 || abp->ab_rind >= ACCT_NBRECS)
155: abp->ab_rind = 0;
156: }
157: #ifdef ACCT_DEBUG
158: acctbuf_checkbuf("acctread 2");
159: #endif
160: return (error);
161: }
162:
163: /*ARGSUSED*/
164: int
165: #ifdef __STDC__
166: acctselect(dev_t dev, int rw, struct proc *p)
167: /* gcc 1.x doesn't like non-ansi def for this */
168: #else
169: acctselect()
170: dev_t dev;
171: int rw;
172: struct proc *p;
173: #endif
174: {
175: switch (rw) {
176:
177: case FREAD:
178: #ifdef ACCT_DEBUG
179: acctbuf_checkbuf("acctselect");
180: #endif
181: if (acctbufp->ab_rind != acctbufp->ab_wind) {
182: return (1);
183: }
184: selrecord(p, &acctsoftc.sc_selp);
185: break;
186: }
187: return (0);
188: }
189:
190: void
191: acctwakeup()
192: {
193: struct proc *p;
194:
195: if (!acct_open)
196: return;
197: selwakeup(&acctsoftc.sc_selp);
198: if (acctsoftc.sc_state & ACCT_ASYNC) {
199: if (acctsoftc.sc_pgid < 0)
200: gsignal(-acctsoftc.sc_pgid, SIGIO);
201: else if (p = pfind(acctsoftc.sc_pgid))
202: psignal(p, SIGIO);
203: }
204: if (acctsoftc.sc_state & ACCT_RDWAIT) {
205: wakeup((caddr_t)acctbufp);
206: acctsoftc.sc_state &= ~ACCT_RDWAIT;
207: }
208: }
209:
210: /*ARGSUSED*/
211: int
212: #ifdef __STDC__
213: acctioctl(dev_t dev, int com, caddr_t data, int flag)
214: /* gcc 1.x doesn't like non-ansi def for this */
215: #else
216: acctioctl()
217: dev_t dev;
218: int com;
219: caddr_t data;
220: int flag;
221: #endif
222: {
223: long l;
224:
225: switch (com) {
226:
227: /* return number of characters immediately available */
228: case FIONREAD:
229: #ifdef ACCT_DEBUG
230: acctbuf_checkbuf("acctioctl");
231: #endif
232: l = acctbufp->ab_wind - acctbufp->ab_rind;
233: if (l < 0)
234: l += ACCT_NBRECS;
235: *(off_t *)data = l * sizeof(struct acct);
236: break;
237:
238: case FIONBIO:
239: break;
240:
241: case FIOASYNC:
242: if (*(int *)data)
243: acctsoftc.sc_state |= ACCT_ASYNC;
244: else
245: acctsoftc.sc_state &= ~ACCT_ASYNC;
246: break;
247:
248: case TIOCSPGRP:
249: acctsoftc.sc_pgid = *(int *)data;
250: break;
251:
252: case TIOCGPGRP:
253: *(int *)data = acctsoftc.sc_pgid;
254: break;
255:
256: default:
257: return (-1);
258: }
259: return (0);
260: }
261:
262: void
263: acctbuf_init()
264: {
265: if (acctbufp != NULL)
266: panic("acctbuf reinit\n");
267:
268: acctbufp = malloc(ACCT_BSIZE, M_DEVBUF, M_WAITOK);
269: if (acctbufp == NULL)
270: panic("acctbuf_init: couldn't allocate accounting buffer\n");
271:
272: bzero(acctbufp, ACCT_BSIZE);
273: acctbufp->ab_magic = ACCT_MAGIC;
274: }
275:
276: #ifdef ACCT_DEBUG
277: void
278: acctbuf_checkbuf(char *from)
279: {
280: char *str;
281: int dopanic = 0;
282:
283: if (acctbufp == NULL) {
284: str = "accounting buffer pointer null";
285: dopanic = 1;
286: }
287: if (acctbufp->ab_magic != ACCT_MAGIC) {
288: str = "accounting buffer magic bad";
289: dopanic = 1;
290: }
291: if (acctbufp->ab_rind < 0 || acctbufp->ab_rind >= ACCT_NBRECS) {
292: str = "accounting buffer read index out of range";
293: dopanic = 1;
294: }
295: if (acctbufp->ab_wind < 0 || acctbufp->ab_wind >= ACCT_NBRECS) {
296: str = "accounting buffer write index out of range";
297: dopanic = 1;
298: }
299: if (dopanic) {
300: printf("acctbuf_checkbuf: from %s\n", from);
301: panic(str);
302: }
303: }
304: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.