BSD 4_4 release
[unix-history] / usr / src / lib / librpc / rpcsvc / rstat_proc.c
CommitLineData
ad787160
C
1/* @(#)rstat_proc.c 2.2 88/08/01 4.0 RPCSRC */
2#ifndef lint
3static char sccsid[] = "@(#)rpc.rstatd.c 1.1 86/09/25 Copyr 1984 Sun Micro";
4#endif
5
6/*
7 * Copyright (c) 1984 by Sun Microsystems, Inc.
8 */
9
10/*
11 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
12 * unrestricted use provided that this legend is included on all tape
13 * media and as a part of the software program in whole or part. Users
14 * may copy or modify Sun RPC without charge, but are not authorized
15 * to license or distribute it to anyone else except as part of a product or
16 * program developed by the user.
17 *
18 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
19 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
21 *
22 * Sun RPC is provided with no support and without any obligation on the
23 * part of Sun Microsystems, Inc. to assist in its use, correction,
24 * modification or enhancement.
25 *
26 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
27 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
28 * OR ANY PART THEREOF.
29 *
30 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
31 * or profits or other special, indirect and consequential damages, even if
32 * Sun has been advised of the possibility of such damages.
33 *
34 * Sun Microsystems, Inc.
35 * 2550 Garcia Avenue
36 * Mountain View, California 94043
37 */
38
39/*
40 * rstat service: built with rstat.x and derived from rpc.rstatd.c
41 */
42
43#include <signal.h>
44#include <stdio.h>
45#include <rpc/rpc.h>
46#include <sys/socket.h>
47#include <nlist.h>
48#include <sys/dk.h>
49#include <sys/errno.h>
50#include <sys/vmmeter.h>
51#include <net/if.h>
52#include "rstat.h"
53
54struct nlist nl[] = {
55#define X_CPTIME 0
56 { "_cp_time" },
57#define X_SUM 1
58 { "_sum" },
59#define X_IFNET 2
60 { "_ifnet" },
61#define X_DKXFER 3
62 { "_dk_xfer" },
63#define X_BOOTTIME 4
64 { "_boottime" },
65#define X_AVENRUN 5
66 { "_avenrun" },
67#define X_HZ 6
68 { "_hz" },
69 "",
70};
71int kmem;
72int firstifnet, numintfs; /* chain of ethernet interfaces */
73int stats_service();
74
75/*
76 * Define EXIT_WHEN_IDLE if you are able to have this program invoked
77 * automatically on demand (as from inetd). When defined, the service
78 * will terminated after being idle for 20 seconds.
79 */
80int sincelastreq = 0; /* number of alarms since last request */
81#ifdef EXIT_WHEN_IDLE
82#define CLOSEDOWN 20 /* how long to wait before exiting */
83#endif /* def EXIT_WHEN_IDLE */
84
85union {
86 struct stats s1;
87 struct statsswtch s2;
88 struct statstime s3;
89} stats_all;
90
91int updatestat();
92static stat_is_init = 0;
93extern int errno;
94
95#ifndef FSCALE
96#define FSCALE (1 << 8)
97#endif
98
99stat_init()
100{
101 stat_is_init = 1;
102 setup();
103 updatestat();
104 alarm(1);
105 signal(SIGALRM, updatestat);
106 sleep(1); /* allow for one wake-up */
107}
108
109statstime *
110rstatproc_stats_3()
111{
112 if (! stat_is_init)
113 stat_init();
114 sincelastreq = 0;
115 return(&stats_all.s3);
116}
117
118statsswtch *
119rstatproc_stats_2()
120{
121 if (! stat_is_init)
122 stat_init();
123 sincelastreq = 0;
124 return(&stats_all.s2);
125}
126
127stats *
128rstatproc_stats_1()
129{
130 if (! stat_is_init)
131 stat_init();
132 sincelastreq = 0;
133 return(&stats_all.s1);
134}
135
136u_int *
137rstatproc_havedisk_3()
138{
139 static u_int have;
140
141 if (! stat_is_init)
142 stat_init();
143 sincelastreq = 0;
144 have = havedisk();
145 return(&have);
146}
147
148u_int *
149rstatproc_havedisk_2()
150{
151 return(rstatproc_havedisk_3());
152}
153
154u_int *
155rstatproc_havedisk_1()
156{
157 return(rstatproc_havedisk_3());
158}
159
160updatestat()
161{
162 int off, i, hz;
163 struct vmmeter sum;
164 struct ifnet ifnet;
165 double avrun[3];
166 struct timeval tm, btm;
167
168#ifdef DEBUG
169 fprintf(stderr, "entering updatestat\n");
170#endif
171#ifdef EXIT_WHEN_IDLE
172 if (sincelastreq >= CLOSEDOWN) {
173#ifdef DEBUG
174 fprintf(stderr, "about to closedown\n");
175#endif
176 exit(0);
177 }
178 sincelastreq++;
179#endif /* def EXIT_WHEN_IDLE */
180 if (lseek(kmem, (long)nl[X_HZ].n_value, 0) == -1) {
181 fprintf(stderr, "rstat: can't seek in kmem\n");
182 exit(1);
183 }
184 if (read(kmem, (char *)&hz, sizeof hz) != sizeof hz) {
185 fprintf(stderr, "rstat: can't read hz from kmem\n");
186 exit(1);
187 }
188 if (lseek(kmem, (long)nl[X_CPTIME].n_value, 0) == -1) {
189 fprintf(stderr, "rstat: can't seek in kmem\n");
190 exit(1);
191 }
192 if (read(kmem, (char *)stats_all.s1.cp_time, sizeof (stats_all.s1.cp_time))
193 != sizeof (stats_all.s1.cp_time)) {
194 fprintf(stderr, "rstat: can't read cp_time from kmem\n");
195 exit(1);
196 }
197 if (lseek(kmem, (long)nl[X_AVENRUN].n_value, 0) ==-1) {
198 fprintf(stderr, "rstat: can't seek in kmem\n");
199 exit(1);
200 }
201#ifdef vax
202 if (read(kmem, (char *)avrun, sizeof (avrun)) != sizeof (avrun)) {
203 fprintf(stderr, "rstat: can't read avenrun from kmem\n");
204 exit(1);
205 }
206 stats_all.s2.avenrun[0] = avrun[0] * FSCALE;
207 stats_all.s2.avenrun[1] = avrun[1] * FSCALE;
208 stats_all.s2.avenrun[2] = avrun[2] * FSCALE;
209#endif
210 if (lseek(kmem, (long)nl[X_BOOTTIME].n_value, 0) == -1) {
211 fprintf(stderr, "rstat: can't seek in kmem\n");
212 exit(1);
213 }
214 if (read(kmem, (char *)&btm, sizeof (stats_all.s2.boottime))
215 != sizeof (stats_all.s2.boottime)) {
216 fprintf(stderr, "rstat: can't read boottime from kmem\n");
217 exit(1);
218 }
219 stats_all.s2.boottime.tv_sec = btm.tv_sec;
220 stats_all.s2.boottime.tv_usec = btm.tv_usec;
221
222
223#ifdef DEBUG
224 fprintf(stderr, "%d %d %d %d\n", stats_all.s1.cp_time[0],
225 stats_all.s1.cp_time[1], stats_all.s1.cp_time[2], stats_all.s1.cp_time[3]);
226#endif
227
228 if (lseek(kmem, (long)nl[X_SUM].n_value, 0) ==-1) {
229 fprintf(stderr, "rstat: can't seek in kmem\n");
230 exit(1);
231 }
232 if (read(kmem, (char *)&sum, sizeof sum) != sizeof sum) {
233 fprintf(stderr, "rstat: can't read sum from kmem\n");
234 exit(1);
235 }
236 stats_all.s1.v_pgpgin = sum.v_pgpgin;
237 stats_all.s1.v_pgpgout = sum.v_pgpgout;
238 stats_all.s1.v_pswpin = sum.v_pswpin;
239 stats_all.s1.v_pswpout = sum.v_pswpout;
240 stats_all.s1.v_intr = sum.v_intr;
241 gettimeofday(&tm, (struct timezone *) 0);
242 stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
243 hz*(tm.tv_usec - btm.tv_usec)/1000000;
244 stats_all.s2.v_swtch = sum.v_swtch;
245
246 if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) {
247 fprintf(stderr, "rstat: can't seek in kmem\n");
248 exit(1);
249 }
250 if (read(kmem, (char *)stats_all.s1.dk_xfer, sizeof (stats_all.s1.dk_xfer))
251 != sizeof (stats_all.s1.dk_xfer)) {
252 fprintf(stderr, "rstat: can't read dk_xfer from kmem\n");
253 exit(1);
254 }
255
256 stats_all.s1.if_ipackets = 0;
257 stats_all.s1.if_opackets = 0;
258 stats_all.s1.if_ierrors = 0;
259 stats_all.s1.if_oerrors = 0;
260 stats_all.s1.if_collisions = 0;
261 for (off = firstifnet, i = 0; off && i < numintfs; i++) {
262 if (lseek(kmem, (long)off, 0) == -1) {
263 fprintf(stderr, "rstat: can't seek in kmem\n");
264 exit(1);
265 }
266 if (read(kmem, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
267 fprintf(stderr, "rstat: can't read ifnet from kmem\n");
268 exit(1);
269 }
270 stats_all.s1.if_ipackets += ifnet.if_ipackets;
271 stats_all.s1.if_opackets += ifnet.if_opackets;
272 stats_all.s1.if_ierrors += ifnet.if_ierrors;
273 stats_all.s1.if_oerrors += ifnet.if_oerrors;
274 stats_all.s1.if_collisions += ifnet.if_collisions;
275 off = (int) ifnet.if_next;
276 }
277 gettimeofday((struct timeval *)&stats_all.s3.curtime,
278 (struct timezone *) 0);
279 alarm(1);
280}
281
282static
283setup()
284{
285 struct ifnet ifnet;
286 int off;
287
288 nlist("/vmunix", nl);
289 if (nl[0].n_value == 0) {
290 fprintf(stderr, "rstat: Variables missing from namelist\n");
291 exit (1);
292 }
293 if ((kmem = open("/dev/kmem", 0)) < 0) {
294 fprintf(stderr, "rstat: can't open kmem\n");
295 exit(1);
296 }
297
298 off = nl[X_IFNET].n_value;
299 if (lseek(kmem, (long)off, 0) == -1) {
300 fprintf(stderr, "rstat: can't seek in kmem\n");
301 exit(1);
302 }
303 if (read(kmem, (char *)&firstifnet, sizeof(int)) != sizeof (int)) {
304 fprintf(stderr, "rstat: can't read firstifnet from kmem\n");
305 exit(1);
306 }
307 numintfs = 0;
308 for (off = firstifnet; off;) {
309 if (lseek(kmem, (long)off, 0) == -1) {
310 fprintf(stderr, "rstat: can't seek in kmem\n");
311 exit(1);
312 }
313 if (read(kmem, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
314 fprintf(stderr, "rstat: can't read ifnet from kmem\n");
315 exit(1);
316 }
317 numintfs++;
318 off = (int) ifnet.if_next;
319 }
320}
321
322/*
323 * returns true if have a disk
324 */
325static
326havedisk()
327{
328 int i, cnt;
329 long xfer[DK_NDRIVE];
330
331 nlist("/vmunix", nl);
332 if (nl[X_DKXFER].n_value == 0) {
333 fprintf(stderr, "rstat: Variables missing from namelist\n");
334 exit (1);
335 }
336 if ((kmem = open("/dev/kmem", 0)) < 0) {
337 fprintf(stderr, "rstat: can't open kmem\n");
338 exit(1);
339 }
340 if (lseek(kmem, (long)nl[X_DKXFER].n_value, 0) == -1) {
341 fprintf(stderr, "rstat: can't seek in kmem\n");
342 exit(1);
343 }
344 if (read(kmem, (char *)xfer, sizeof xfer)!= sizeof xfer) {
345 fprintf(stderr, "rstat: can't read kmem\n");
346 exit(1);
347 }
348 cnt = 0;
349 for (i=0; i < DK_NDRIVE; i++)
350 cnt += xfer[i];
351 return (cnt != 0);
352}