Make sure we use rstat's protocol's values of FSCALE. We were picking up
[unix-history] / libexec / rpc.rstatd / rstat_proc.c
CommitLineData
43b57156
C
1/*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
8 *
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12 *
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
16 *
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
20 *
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
24 *
25 * Sun Microsystems, Inc.
26 * 2550 Garcia Avenue
27 * Mountain View, California 94043
28 */
29#ifndef lint
30/*static char sccsid[] = "from: @(#)rpc.rstatd.c 1.1 86/09/25 Copyr 1984 Sun Micro";*/
31/*static char sccsid[] = "from: @(#)rstat_proc.c 2.2 88/08/01 4.0 RPCSRC";*/
90ba5b2c 32static char rcsid[] = "$Id: rstat_proc.c,v 1.4 1993/09/23 18:42:39 jtc Exp $";
43b57156
C
33#endif
34
35/*
36 * rstat service: built with rstat.x and derived from rpc.rstatd.c
37 *
38 * Copyright (c) 1984 by Sun Microsystems, Inc.
39 */
40
43b57156 41#include <stdio.h>
90ba5b2c
C
42#include <stdlib.h>
43#include <string.h>
44#include <signal.h>
43b57156
C
45#include <rpc/rpc.h>
46#include <sys/socket.h>
47#include <nlist.h>
48#include <syslog.h>
49#include <sys/errno.h>
50#include <sys/param.h>
51#ifdef BSD
52#include <sys/vmmeter.h>
53#include <sys/dkstat.h>
54#else
55#include <sys/dk.h>
56#endif
57#include <net/if.h>
90ba5b2c
C
58
59#undef FSHIFT /* Use protocol's shift and scale values */
60#undef FSCALE
43b57156
C
61#include <rpcsvc/rstat.h>
62
63struct nlist nl[] = {
64#define X_CPTIME 0
65 { "_cp_time" },
66#define X_SUM 1
67 { "_sum" },
68#define X_IFNET 2
69 { "_ifnet" },
70#define X_DKXFER 3
71 { "_dk_xfer" },
72#define X_BOOTTIME 4
73 { "_boottime" },
74#define X_HZ 5
75 { "_hz" },
76#ifdef vax
77#define X_AVENRUN 6
78 { "_avenrun" },
79#endif
80 "",
81};
82int firstifnet, numintfs; /* chain of ethernet interfaces */
83int stats_service();
84
85extern int from_inetd;
86int sincelastreq = 0; /* number of alarms since last request */
87extern int closedown;
88
89union {
90 struct stats s1;
91 struct statsswtch s2;
92 struct statstime s3;
93} stats_all;
94
95void updatestat();
96static stat_is_init = 0;
97extern int errno;
98
99#ifndef FSCALE
100#define FSCALE (1 << 8)
101#endif
102
103#ifndef BSD
104/*
105 * BSD has the kvm facility for getting info from the
106 * kernel. If you aren't on BSD, this surfices.
107 */
108int kmem;
109
110kvm_read(off, addr, size)
111 unsigned long off, size;
112 char *addr;
113{
114 int len;
115 if (lseek(kmem, (long)off, 0) == -1)
116 return(-1);
117 return(read(kmem, addr, size));
118}
119
120kvm_nlist(nl)
121 struct nlist *nl;
122{
123 int n = nlist("/vmunix", nl);
124 if (nl[0].n_value == 0)
125 return(n);
126
127 if ((kmem = open("/dev/kmem", 0)) < 0)
128 return(-1);
129 return(0);
130}
131#endif
132
133stat_init()
134{
135 stat_is_init = 1;
136 setup();
137 updatestat();
138 (void) signal(SIGALRM, updatestat);
139 alarm(1);
140}
141
142statstime *
143rstatproc_stats_3()
144{
145 if (! stat_is_init)
146 stat_init();
147 sincelastreq = 0;
148 return(&stats_all.s3);
149}
150
151statsswtch *
152rstatproc_stats_2()
153{
154 if (! stat_is_init)
155 stat_init();
156 sincelastreq = 0;
157 return(&stats_all.s2);
158}
159
160stats *
161rstatproc_stats_1()
162{
163 if (! stat_is_init)
164 stat_init();
165 sincelastreq = 0;
166 return(&stats_all.s1);
167}
168
169u_int *
170rstatproc_havedisk_3()
171{
172 static u_int have;
173
174 if (! stat_is_init)
175 stat_init();
176 sincelastreq = 0;
177 have = havedisk();
178 return(&have);
179}
180
181u_int *
182rstatproc_havedisk_2()
183{
184 return(rstatproc_havedisk_3());
185}
186
187u_int *
188rstatproc_havedisk_1()
189{
190 return(rstatproc_havedisk_3());
191}
192
193void
194updatestat()
195{
196 int off, i, hz;
197 struct vmmeter sum;
198 struct ifnet ifnet;
199 double avrun[3];
200 struct timeval tm, btm;
201
202#ifdef DEBUG
203 fprintf(stderr, "entering updatestat\n");
204#endif
205 if (sincelastreq >= closedown) {
206#ifdef DEBUG
207 fprintf(stderr, "about to closedown\n");
208#endif
209 if (from_inetd)
210 exit(0);
211 else {
212 stat_is_init = 0;
213 return;
214 }
215 }
216 sincelastreq++;
217
218 if (kvm_read((long)nl[X_HZ].n_value, (char *)&hz, sizeof hz) != sizeof hz) {
219 syslog(LOG_ERR, "rstat: can't read hz from kmem\n");
220 exit(1);
221 }
222 if (kvm_read((long)nl[X_CPTIME].n_value, (char *)stats_all.s1.cp_time, sizeof (stats_all.s1.cp_time))
223 != sizeof (stats_all.s1.cp_time)) {
224 syslog(LOG_ERR, "rstat: can't read cp_time from kmem\n");
225 exit(1);
226 }
227#ifdef vax
228 if (kvm_read((long)nl[X_AVENRUN].n_value, (char *)avrun, sizeof (avrun)) != sizeof (avrun)) {
229 syslog(LOG_ERR, "rstat: can't read avenrun from kmem\n");
230 exit(1);
231 }
232#endif
233#ifdef BSD
234 (void)getloadavg(avrun, sizeof(avrun) / sizeof(avrun[0]));
235#endif
236 stats_all.s2.avenrun[0] = avrun[0] * FSCALE;
237 stats_all.s2.avenrun[1] = avrun[1] * FSCALE;
238 stats_all.s2.avenrun[2] = avrun[2] * FSCALE;
239 if (kvm_read((long)nl[X_BOOTTIME].n_value, (char *)&btm, sizeof (stats_all.s2.boottime))
240 != sizeof (stats_all.s2.boottime)) {
241 syslog(LOG_ERR, "rstat: can't read boottime from kmem\n");
242 exit(1);
243 }
244 stats_all.s2.boottime.tv_sec = btm.tv_sec;
245 stats_all.s2.boottime.tv_usec = btm.tv_usec;
246
247
248#ifdef DEBUG
249 fprintf(stderr, "%d %d %d %d\n", stats_all.s1.cp_time[0],
250 stats_all.s1.cp_time[1], stats_all.s1.cp_time[2], stats_all.s1.cp_time[3]);
251#endif
252
253 if (kvm_read((long)nl[X_SUM].n_value, (char *)&sum, sizeof sum) != sizeof sum) {
254 syslog(LOG_ERR, "rstat: can't read sum from kmem\n");
255 exit(1);
256 }
257 stats_all.s1.v_pgpgin = sum.v_pgpgin;
258 stats_all.s1.v_pgpgout = sum.v_pgpgout;
259 stats_all.s1.v_pswpin = sum.v_pswpin;
260 stats_all.s1.v_pswpout = sum.v_pswpout;
261 stats_all.s1.v_intr = sum.v_intr;
262 gettimeofday(&tm, (struct timezone *) 0);
263 stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
264 hz*(tm.tv_usec - btm.tv_usec)/1000000;
265 stats_all.s2.v_swtch = sum.v_swtch;
266
267 if (kvm_read((long)nl[X_DKXFER].n_value, (char *)stats_all.s1.dk_xfer, sizeof (stats_all.s1.dk_xfer))
268 != sizeof (stats_all.s1.dk_xfer)) {
269 syslog(LOG_ERR, "rstat: can't read dk_xfer from kmem\n");
270 exit(1);
271 }
272
273 stats_all.s1.if_ipackets = 0;
274 stats_all.s1.if_opackets = 0;
275 stats_all.s1.if_ierrors = 0;
276 stats_all.s1.if_oerrors = 0;
277 stats_all.s1.if_collisions = 0;
278 for (off = firstifnet, i = 0; off && i < numintfs; i++) {
279 if (kvm_read(off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
280 syslog(LOG_ERR, "rstat: can't read ifnet from kmem\n");
281 exit(1);
282 }
283 stats_all.s1.if_ipackets += ifnet.if_ipackets;
284 stats_all.s1.if_opackets += ifnet.if_opackets;
285 stats_all.s1.if_ierrors += ifnet.if_ierrors;
286 stats_all.s1.if_oerrors += ifnet.if_oerrors;
287 stats_all.s1.if_collisions += ifnet.if_collisions;
288 off = (int) ifnet.if_next;
289 }
290 gettimeofday((struct timeval *)&stats_all.s3.curtime,
291 (struct timezone *) 0);
292 alarm(1);
293}
294
295setup()
296{
297 struct ifnet ifnet;
298 int off;
299
300 if (kvm_nlist(nl) != 0) {
301 syslog(LOG_ERR, "rstatd: Can't get namelist.");
302 exit (1);
303 }
304
305 if (kvm_read((long)nl[X_IFNET].n_value, &firstifnet,
306 sizeof(int)) != sizeof(int)) {
307 syslog(LOG_ERR, "rstat: can't read firstifnet from kmem\n");
308 exit(1);
309 }
310
311 numintfs = 0;
312 for (off = firstifnet; off;) {
313 if (kvm_read(off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
314 syslog(LOG_ERR, "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 */
325havedisk()
326{
327 int i, cnt;
328 long xfer[DK_NDRIVE];
329
330 if (kvm_nlist(nl) != 0) {
331 syslog(LOG_ERR, "rstatd: Can't get namelist.");
332 exit (1);
333 }
334
335 if (kvm_read((long)nl[X_DKXFER].n_value, (char *)xfer, sizeof xfer)!= sizeof xfer) {
336 syslog(LOG_ERR, "rstat: can't read kmem\n");
337 exit(1);
338 }
339 cnt = 0;
340 for (i=0; i < DK_NDRIVE; i++)
341 cnt += xfer[i];
342 return (cnt != 0);
343}
344
345void
346rstat_service(rqstp, transp)
347 struct svc_req *rqstp;
348 SVCXPRT *transp;
349{
350 union {
351 int fill;
352 } argument;
353 char *result;
354 bool_t (*xdr_argument)(), (*xdr_result)();
355 char *(*local)();
356
357 switch (rqstp->rq_proc) {
358 case NULLPROC:
359 (void)svc_sendreply(transp, xdr_void, (char *)NULL);
360 goto leave;
361
362 case RSTATPROC_STATS:
363 xdr_argument = xdr_void;
364 xdr_result = xdr_statstime;
365 switch (rqstp->rq_vers) {
366 case RSTATVERS_ORIG:
367 local = (char *(*)()) rstatproc_stats_1;
368 break;
369 case RSTATVERS_SWTCH:
370 local = (char *(*)()) rstatproc_stats_2;
371 break;
372 case RSTATVERS_TIME:
373 local = (char *(*)()) rstatproc_stats_3;
374 break;
375 default:
376 svcerr_progvers(transp, RSTATVERS_ORIG, RSTATVERS_TIME);
377 goto leave;
378 /*NOTREACHED*/
379 }
380 break;
381
382 case RSTATPROC_HAVEDISK:
383 xdr_argument = xdr_void;
384 xdr_result = xdr_u_int;
385 switch (rqstp->rq_vers) {
386 case RSTATVERS_ORIG:
387 local = (char *(*)()) rstatproc_havedisk_1;
388 break;
389 case RSTATVERS_SWTCH:
390 local = (char *(*)()) rstatproc_havedisk_2;
391 break;
392 case RSTATVERS_TIME:
393 local = (char *(*)()) rstatproc_havedisk_3;
394 break;
395 default:
396 svcerr_progvers(transp, RSTATVERS_ORIG, RSTATVERS_TIME);
397 goto leave;
398 /*NOTREACHED*/
399 }
400 break;
401
402 default:
403 svcerr_noproc(transp);
404 goto leave;
405 }
406 bzero((char *)&argument, sizeof(argument));
407 if (!svc_getargs(transp, xdr_argument, &argument)) {
408 svcerr_decode(transp);
409 goto leave;
410 }
411 result = (*local)(&argument, rqstp);
412 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
413 svcerr_systemerr(transp);
414 }
415 if (!svc_freeargs(transp, xdr_argument, &argument)) {
416 (void)fprintf(stderr, "unable to free arguments\n");
417 exit(1);
418 }
419leave:
420 if (from_inetd)
421 exit(0);
422}