"Fossies" - the Fresh Open Source Software Archive 
Member "xload-snmp-0.5/get_load.c" (17 Mar 2003, 30297 Bytes) of package /linux/privat/old/xload-snmp-0.5.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "get_load.c" see the
Fossies "Dox" file reference documentation.
1 /**
2 ** xload-snmp <alh@warhound.org>
3 ** Changes to this software differing from the X Consortium release
4 ** versions below are Copyright (c) 2000 Adrian Hosey. Changes are
5 ** licensed under the X Consortium license as described below.
6 **/
7
8 /* $XConsortium: get_load.c /main/37 1996/03/09 09:38:04 kaleb $ */
9 /* $XFree86: contrib/programs/xload/get_load.c,v 3.6 1996/11/18 12:50:12 dawes Exp $ */
10 /*
11
12 Copyright (c) 1989 X Consortium
13
14 Permission is hereby granted, free of charge, to any person obtaining
15 a copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sublicense, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
21
22 The above copyright notice and this permission notice shall be included
23 in all copies or substantial portions of the Software.
24
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 OTHER DEALINGS IN THE SOFTWARE.
32
33 Except as contained in this notice, the name of the X Consortium shall
34 not be used in advertising or otherwise to promote the sale, use or
35 other dealings in this Software without prior written authorization
36 from the X Consortium.
37
38 */
39
40 /*
41 * get_load - get system load
42 *
43 * Authors: Many and varied...
44 *
45 * Call InitLoadPoint() to initialize.
46 * GetLoadPoint() is a callback for the StripChart widget.
47 */
48
49 #include <X11/Xos.h>
50 #include <X11/Intrinsic.h>
51 #include <stdio.h>
52
53 #include "xload-snmp.h"
54
55 /* These are all for doing SNMP. We'll hold them up here because they
56 * only need to be initialized once in the life of the program.
57 */
58 static struct snmp_session session;
59 static struct snmp_session *ss = NULL;
60 static snmp_params *my_params;
61 static oid anOID[MAX_OID_LEN];
62 static size_t anOID_len = MAX_OID_LEN;
63 /* Need this when using -delta flag */
64 static double prev_real_value = 0.0;
65
66 #define COMMUNITY_STR_LEN 256
67
68 #ifdef att
69 #define LOADSTUB
70 #endif
71
72 #ifndef macII
73 #ifndef apollo
74 #ifndef LOADSTUB
75 #if !defined(linux) && !defined(AMOEBA)
76 #include <nlist.h>
77 #endif /* linux || AMOEBA */
78 #endif /* LOADSTUB */
79 #endif /* apollo */
80 #endif /* macII */
81
82 #if defined(MOTOROLA) && defined(SYSV)
83 #include <sys/sysinfo.h>
84 #endif
85
86 #ifdef sun
87 # include <sys/param.h>
88 # if defined(SVR4) && (OSMAJORVERSION == 5) && (OSMINORVERSION > 3)
89 # include <kvm.h>
90 # endif
91 # if defined(i386) && !defined(SVR4)
92 # include <kvm.h>
93 # define KVM_ROUTINES
94 # endif /* i386 */
95 #endif
96
97 #ifdef CSRG_BASED
98 #include <sys/param.h>
99 #endif
100
101 #if defined(umips) || (defined(ultrix) && defined(mips))
102 #include <sys/fixpoint.h>
103 #endif
104
105 #if defined(CRAY) || defined(AIXV3)
106 #include <sys/param.h>
107 #define word word_t
108 #include <sys/sysinfo.h>
109 #undef word
110 #undef n_type
111 #define n_type n_value
112 #endif /* CRAY */
113
114 #ifdef sequent
115 #include <sys/vm.h>
116 #endif /* sequent */
117
118 #ifdef macII
119 #include <a.out.h>
120 #include <sys/var.h>
121 #define X_AVENRUN 0
122 #define fxtod(i) (vec[i].high+(vec[i].low/65536.0))
123 struct lavnum {
124 unsigned short high;
125 unsigned short low;
126 };
127 #endif /* macII */
128
129 #ifdef hcx
130 #include <sys/param.h>
131 #endif /* hcx */
132
133 #if defined(UTEK) || defined(alliant) || (defined(MOTOROLA) && defined(SVR4))
134 #define FSCALE 100.0
135 #endif
136
137 #ifdef sequent
138 #define FSCALE 1000.0
139 #endif
140
141 #ifdef sgi
142 #define FSCALE 1024.0
143 #endif
144
145 #if defined(sony) && OSMAJORVERSION == 4
146 #ifdef mips
147 #include <sys/fixpoint.h>
148 #else
149 #include <sys/param.h>
150 #endif
151 #endif
152
153 #ifdef __osf__
154 /*
155 * Use the table(2) interface; it doesn't require setuid root.
156 *
157 * Select 0, 1, or 2 for 5, 30, or 60 second load averages.
158 */
159 #ifndef WHICH_AVG
160 #define WHICH_AVG 1
161 #endif
162 #include <sys/table.h>
163 #endif
164
165 #ifdef SVR4
166 #ifndef FSCALE
167 #define FSCALE (1 << 8)
168 #endif
169 #endif
170
171 #ifdef X_NOT_POSIX
172 extern long lseek();
173 #endif
174 extern void exit();
175
176 static xload_error(
177 #if NeedFunctionPrototypes
178 char *, char *
179 #endif
180 );
181
182
183 #ifdef apollo
184 #include <apollo/base.h>
185 #include <apollo/time.h>
186 typedef struct {
187 short state; /* ready, waiting, etc. */
188 pinteger usr; /* user sr */
189 linteger upc; /* user pc */
190 linteger usp; /* user stack pointer */
191 linteger usb; /* user sb ptr (A6) */
192 time_$clock_t cpu_total; /* cumulative cpu used by process */
193 unsigned short priority; /* process priority */
194 } proc1_$info_t;
195
196 void proc1_$get_cput(
197 time_$clock_t *cput
198 );
199
200 void proc1_$get_info(
201 short &pid,
202 proc1_$info_t *info,
203 status_$t *sts
204 );
205
206 static int lastNullCpu;
207 static int lastClock;
208
209 void InitLoadPoint() /* Apollo version */
210 {
211 time_$clock_t timeNow;
212 proc1_$info_t info;
213 status_$t st;
214
215 proc1_$get_info( (short) 2, &info, &st );
216 time_$clock( &timeNow );
217
218 lastClock = timeNow.low32;
219 lastNullCpu = info.cpu_total.low32;
220 }
221
222 /* ARGSUSED */
223 void GetLoadPoint( w, closure, call_data ) /* Apollo version */
224 Widget w; /* unused */
225 caddr_t closure; /* unused */
226 caddr_t call_data; /* pointer to (double) return value */
227 {
228 time_$clock_t timeNow;
229 double temp;
230 proc1_$info_t info;
231 status_$t st;
232
233 proc1_$get_info( (short) 2, &info, &st );
234 time_$clock( &timeNow );
235
236 temp = info.cpu_total.low32 - lastNullCpu;
237 *(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock);
238
239 lastClock = timeNow.low32;
240 lastNullCpu = info.cpu_total.low32;
241 }
242 #else /* not apollo */
243 #if defined(SYSV) && defined(SYSV386)
244 /*
245 * inspired by 'avgload' by John F. Haugh II
246 */
247 #include <sys/param.h>
248 #include <sys/buf.h>
249 #include <sys/immu.h>
250 #include <sys/region.h>
251 #include <sys/var.h>
252 #include <sys/proc.h>
253 #define KERNEL_FILE "/unix"
254 #define KMEM_FILE "/dev/kmem"
255 #define VAR_NAME "v"
256 #define PROC_NAME "proc"
257 #define BUF_NAME "buf"
258 #define DECAY 0.8
259 struct nlist namelist[] = {
260 {VAR_NAME},
261 {PROC_NAME},
262 {BUF_NAME},
263 {0},
264 };
265
266 static int kmem;
267 static struct var v;
268 static struct proc *p;
269 static caddr_t first_buf, last_buf;
270
271 void InitLoadPoint() /* SYSV386 version */
272 {
273 int i;
274
275 nlist( KERNEL_FILE, namelist);
276
277 for (i=0; namelist[i].n_name; i++)
278 if (namelist[i].n_value == 0)
279 xload_error("cannot get name list from", KERNEL_FILE);
280
281 if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0)
282 xload_error("cannot open", KMEM_FILE);
283
284 if (lseek(kmem, namelist[0].n_value, 0) == -1)
285 xload_error("cannot seek", VAR_NAME);
286
287 if (read(kmem, &v, sizeof(v)) != sizeof(v))
288 xload_error("cannot read", VAR_NAME);
289
290 if ((p=(struct proc *)malloc(v.v_proc*sizeof(*p))) == NULL)
291 xload_error("cannot allocat space for", PROC_NAME);
292
293 first_buf = (caddr_t) namelist[2].n_value;
294 last_buf = first_buf + v.v_buf * sizeof(struct buf);
295 }
296
297 /* ARGSUSED */
298 void GetLoadPoint( w, closure, call_data ) /* SYSV386 version */
299 Widget w; /* unused */
300 caddr_t closure; /* unused */
301 caddr_t call_data; /* pointer to (double) return value */
302 {
303 double *loadavg = (double *)call_data;
304 static double avenrun = 0.0;
305 int i, nproc, size;
306
307 (void) lseek(kmem, namelist[0].n_value, 0);
308 (void) read(kmem, &v, sizeof(v));
309
310 size = (struct proc *)v.ve_proc - (struct proc *)namelist[1].n_value;
311
312 (void) lseek(kmem, namelist[1].n_value, 0);
313 (void) read(kmem, p, size * sizeof(struct proc));
314
315 for (nproc = 0, i=0; i<size; i++)
316 if ((p[i].p_stat == SRUN) ||
317 (p[i].p_stat == SIDL) ||
318 (p[i].p_stat == SXBRK) ||
319 (p[i].p_stat == SSLEEP && (p[i].p_pri < PZERO) &&
320 (p[i].p_wchan >= first_buf) && (p[i].p_wchan < last_buf)))
321 nproc++;
322
323 /* update the load average using a decay filter */
324 avenrun = DECAY * avenrun + nproc * (1.0 - DECAY);
325 *loadavg = avenrun;
326
327 return;
328 }
329 #else /* not (SYSV && SYSV386) */
330 #ifdef KVM_ROUTINES
331 /*
332 * Sun 386i Code - abstracted to see the wood for the trees
333 */
334
335 static struct nlist nl[2];
336 static kvm_t *kd;
337
338 void
339 InitLoadPoint() /* Sun 386i version */
340 {
341 kd = kvm_open("/vmunix", NULL, NULL, O_RDONLY, "Load Widget");
342 if (kd == (kvm_t *)0) {
343 xload_error("cannot get access to kernel address space", "");
344 }
345
346 nl[0].n_name = "avenrun";
347 nl[1].n_name = NULL;
348
349 if (kvm_nlist(kd, nl) != 0) {
350 xload_error("cannot get name list", "");
351 }
352
353 if (nl[0].n_value == 0) {
354 xload_error("Cannot find address for avenrun in the kernel\n", "");
355 }
356 }
357
358 /* ARGSUSED */
359 void
360 GetLoadPoint( w, closure, call_data ) /* Sun 386i version */
361 Widget w; /* unused */
362 XtPointer closure; /* unused */
363 XtPointer call_data; /* pointer to (double) return value */
364 {
365 double *loadavg = (double *)call_data;
366 long temp;
367
368 if (kvm_read(kd, nl[0].n_value, (char *)&temp, sizeof (temp)) !=
369 sizeof (temp)) {
370 xload_error("Kernel read error", "");
371 }
372 *loadavg = (double)temp/FSCALE;
373 }
374 #else /* not KVM_ROUTINES */
375
376 #ifdef AMOEBA
377 #include <amoeba.h>
378 #include <cmdreg.h>
379 #include <stderr.h>
380 #include <ampolicy.h>
381
382 static capability pooldircap;
383 extern char *getenv();
384
385 void
386 InitLoadPoint()
387 {
388 register char *s;
389
390 if ((s = getenv("XLOAD_HOST")) != NULL) {
391 /* do an xload of a single host */
392 if (host_lookup(s, &pooldircap) != STD_OK)
393 xload_error("cannot lookup run server", s);
394 if (dir_lookup(&pooldircap, "proc", &pooldircap) != STD_OK)
395 xload_error("cannot lookup run server", s);
396 } else {
397 /* Else we do an xload of a pool.
398 * Environment variable RUN_SERVER overrides the default one.
399 */
400 if ((s = getenv("RUN_SERVER")) == NULL)
401 s = DEF_RUNSVR_POOL;
402 if (name_lookup(s, &pooldircap) != STD_OK)
403 xload_error("cannot lookup run server", s);
404 }
405 }
406
407 /* ARGSUSED */
408 void GetLoadPoint( w, closure, call_data )
409 Widget w; /* unused */
410 caddr_t closure; /* unused */
411 caddr_t call_data; /* pointer to (double) return value */
412 {
413 long ips, loadav, mfree;
414
415 if (pro_getload(&pooldircap, &ips, &loadav, &mfree) != STD_OK) {
416 /*
417 * No run server. We don't want to crash, though:
418 * it will probably come up again.
419 */
420 InitLoadPoint();
421 loadav = 0;
422 }
423 *(double *)call_data = (double)loadav / 1024.0;
424 }
425 #else /* AMOEBA */
426
427 #ifdef linux
428
429 void InitLoadPoint()
430 {
431 return;
432 }
433
434 void GetLoadPoint( w, closure, call_data )
435 Widget w; /* unused */
436 caddr_t closure; /* unused */
437 caddr_t call_data; /* pointer to (double) return value */
438 {
439 static int fd = -1;
440 int n;
441 char buf[10];
442
443 if (fd < 0)
444 {
445 if (fd == -2 ||
446 (fd = open("/proc/loadavg", O_RDONLY)) < 0)
447 {
448 fd = -2;
449 *(double *)call_data = 0.0;
450 return;
451 }
452 }
453 else
454 lseek(fd, 0, 0);
455
456 if ((n = read(fd, buf, sizeof(buf)-1)) > 0 &&
457 sscanf(buf, "%lf", (double *)call_data) == 1)
458 return;
459
460 *(double *)call_data = 0.0; /* temporary hiccup */
461
462 return;
463 }
464
465 #else /* linux */
466
467 #ifdef LOADSTUB
468
469 void InitLoadPoint()
470 {
471 }
472
473 /* ARGSUSED */
474 void GetLoadPoint( w, closure, call_data )
475 Widget w; /* unused */
476 caddr_t closure; /* unused */
477 caddr_t call_data; /* pointer to (double) return value */
478 {
479 *(double *)call_data = 1.0;
480 }
481
482 #else /* not LOADSTUB */
483
484 #ifdef __osf__
485
486 void InitLoadPoint()
487 {
488 }
489
490 /*ARGSUSED*/
491 void GetLoadPoint( w, closure, call_data )
492 Widget w; /* unused */
493 caddr_t closure; /* unused */
494 caddr_t call_data; /* pointer to (double) return value */
495 {
496 double *loadavg = (double *)call_data;
497 struct tbl_loadavg load_data;
498
499 if (table(TBL_LOADAVG, 0, (char *)&load_data, 1, sizeof(load_data)) < 0)
500 xload_error("error reading load average", "");
501 *loadavg = (load_data.tl_lscale == 0) ?
502 load_data.tl_avenrun.d[WHICH_AVG] :
503 load_data.tl_avenrun.l[WHICH_AVG] / (double)load_data.tl_lscale;
504 }
505
506 #else /* not __osf__ */
507
508 #ifdef __bsdi__
509 #include <kvm.h>
510
511 static struct nlist nl[] = {
512 { "_averunnable" },
513 #define X_AVERUNNABLE 0
514 { "_fscale" },
515 #define X_FSCALE 1
516 { "" },
517 };
518 static kvm_t *kd;
519 static int fscale;
520
521 void InitLoadPoint()
522 {
523 fixpt_t averunnable[3]; /* unused really */
524
525 if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
526 xload_error("can't open kvm files", "");
527
528 if (kvm_nlist(kd, nl) != 0)
529 xload_error("can't read name list", "");
530
531 if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)averunnable,
532 sizeof(averunnable)) != sizeof(averunnable))
533 xload_error("couldn't obtain _averunnable variable", "");
534
535 if (kvm_read(kd, (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
536 sizeof(fscale)) != sizeof(fscale))
537 xload_error("couldn't obtain _fscale variable", "");
538
539 return;
540 }
541
542 void GetLoadPoint(w, closure, call_data)
543 Widget w; /* unused */
544 caddr_t closure; /* unused */
545 caddr_t call_data; /* ptr to (double) return value */
546 {
547 double *loadavg = (double *)call_data;
548 fixpt_t t;
549
550 if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)&t,
551 sizeof(t)) != sizeof(t))
552 xload_error("couldn't obtain load average", "");
553
554 *loadavg = (double)t/fscale;
555
556 return;
557 }
558 #else /* not __bsdi__ */
559
560 #if BSD >= 199306
561
562 void InitLoadPoint()
563 {
564 }
565
566 void GetLoadPoint(w, closure, call_data)
567 Widget w; /* unused */
568 caddr_t closure; /* unused */
569 caddr_t call_data; /* ptr to (double) return value */
570 {
571 double *loadavg = (double *)call_data;
572
573 if (getloadavg(loadavg, 1) < 0)
574 xload_error("couldn't obtain load average", "");
575 }
576
577 #else /* not BSD >= 199306 */
578
579 #ifndef KMEM_FILE
580 #define KMEM_FILE "/dev/kmem"
581 #endif
582
583 #ifndef KERNEL_FILE
584
585 #ifdef alliant
586 #define KERNEL_FILE "/vmunix"
587 #endif /* alliant */
588
589 #ifdef CRAY
590 #define KERNEL_FILE "/unicos"
591 #endif /* CRAY */
592
593 #ifdef hpux
594 #define KERNEL_FILE "/hp-ux"
595 #endif /* hpux */
596
597 #ifdef macII
598 #define KERNEL_FILE "/unix"
599 #endif /* macII */
600
601 #ifdef umips
602 # ifdef SYSTYPE_SYSV
603 # define KERNEL_FILE "/unix"
604 # else
605 # define KERNEL_FILE "/vmunix"
606 # endif /* SYSTYPE_SYSV */
607 #endif /* umips */
608
609 #ifdef sequent
610 #define KERNEL_FILE "/dynix"
611 #endif /* sequent */
612
613 #ifdef hcx
614 #define KERNEL_FILE "/unix"
615 #endif /* hcx */
616
617 #ifdef MOTOROLA
618 #if defined(SYSV) && defined(m68k)
619 #define KERNEL_FILE "/sysV68"
620 #endif
621 #if defined(SYSV) && defined(m88k)
622 #define KERNEL_FILE "/unix"
623 #endif
624 #ifdef SVR4
625 #define KERNEL_FILE "/unix"
626 #endif
627 #endif /* MOTOROLA */
628
629 #if defined(sun) && defined(SVR4)
630 #define KERNEL_FILE "/kernel/unix"
631 #endif
632
633 #ifdef MINIX
634 #define KERNEL_FILE "/sys/kernel"
635 #endif /* MINIX */
636
637 #ifdef sgi
638 #if (OSMAJORVERSION > 4)
639 #define KERNEL_FILE "/unix"
640 #endif
641 #endif
642
643 /*
644 * provide default for everyone else
645 */
646 #ifndef KERNEL_FILE
647 #ifdef SVR4
648 #define KERNEL_FILE "/stand/unix"
649 #else
650 #ifdef SYSV
651 #define KERNEL_FILE "/unix"
652 #else
653 /* If a BSD system, check in <paths.h> */
654 # ifdef BSD
655 # include <paths.h>
656 # ifdef _PATH_UNIX
657 # define KERNEL_FILE _PATH_UNIX
658 # else
659 # ifdef _PATH_KERNEL
660 # define KERNEL_FILE _PATH_KERNEL
661 # else
662 # define KERNEL_FILE "/vmunix"
663 # endif
664 # endif
665 # else /* BSD */
666 # define KERNEL_FILE "/vmunix"
667 # endif /* BSD */
668 #endif /* SYSV */
669 #endif /* SVR4 */
670 #endif /* KERNEL_FILE */
671 #endif /* KERNEL_FILE */
672
673
674 #ifndef KERNEL_LOAD_VARIABLE
675 # if (BSD >= 199103)
676 # define KERNEL_LOAD_VARIABLE "_averunnable"
677 # endif /* BSD >= 199103 */
678
679 # ifdef alliant
680 # define KERNEL_LOAD_VARIABLE "_Loadavg"
681 # endif /* alliant */
682
683 # ifdef CRAY
684 # if defined(CRAY2) && OSMAJORVERSION == 4
685 # define KERNEL_LOAD_VARIABLE "avenrun"
686 # else
687 # define KERNEL_LOAD_VARIABLE "sysinfo"
688 # define SYSINFO
689 # endif /* defined(CRAY2) && OSMAJORVERSION == 4 */
690 # endif /* CRAY */
691
692 # ifdef hpux
693 # ifdef __hp9000s800
694 # define KERNEL_LOAD_VARIABLE "avenrun"
695 # endif /* hp9000s800 */
696 # endif /* hpux */
697
698 # ifdef umips
699 # ifdef SYSTYPE_SYSV
700 # define KERNEL_LOAD_VARIABLE "avenrun"
701 # else
702 # define KERNEL_LOAD_VARIABLE "_avenrun"
703 # endif /* SYSTYPE_SYSV */
704 # endif /* umips */
705
706 # ifdef sgi
707 # define KERNEL_LOAD_VARIABLE "avenrun"
708 # endif /* sgi */
709
710 # ifdef AIXV3
711 # define KERNEL_LOAD_VARIABLE "sysinfo"
712 # endif /* AIXV3 */
713
714 # ifdef MOTOROLA
715 # if defined(SYSV) && defined(m68k)
716 # define KERNEL_LOAD_VARIABLE "sysinfo"
717 # endif
718 # if defined(SYSV) && defined(m88k)
719 # define KERNEL_LOAD_VARIABLE "_sysinfo"
720 # endif
721 # ifdef SVR4
722 # define KERNEL_LOAD_VARIABLE "avenrun"
723 # endif
724 # endif /* MOTOROLA */
725
726 # ifdef MINIX
727 # define KERNEL_LOAD_VARIABLE "_loadav"
728 # endif /* MINIX */
729
730 #endif /* KERNEL_LOAD_VARIABLE */
731
732 /*
733 * provide default for everyone else
734 */
735
736 #ifndef KERNEL_LOAD_VARIABLE
737 # ifdef USG
738 # define KERNEL_LOAD_VARIABLE "sysinfo"
739 # define SYSINFO
740 # else
741 # ifdef SVR4
742 # define KERNEL_LOAD_VARIABLE "avenrun"
743 # else
744 # define KERNEL_LOAD_VARIABLE "_avenrun"
745 # endif
746 # endif
747 #endif /* KERNEL_LOAD_VARIABLE */
748
749 #ifdef macII
750 static struct var v;
751 static int pad[2]; /* This padding is needed if xload compiled on */
752 /* a/ux 1.1 is executed on a/ux 1.0, because */
753 /* the var structure had too much padding in 1.0, */
754 /* so the 1.0 kernel writes past the end of the 1.1 */
755 /* var structure in the uvar() call. */
756 static struct nlist nl[2];
757 static struct lavnum vec[3];
758 #else /* not macII */
759 static struct nlist namelist[] = { /* namelist for vmunix grubbing */
760 #define LOADAV 0
761 {KERNEL_LOAD_VARIABLE},
762 {0}
763 };
764 #endif /* macII */
765
766 static kmem;
767 static long loadavg_seek;
768
769 InitLoadPoint()
770 {
771 #ifdef macII
772 extern nlist();
773
774 int i;
775
776 strcpy(nl[0].n_name, "avenrun");
777 nl[1].n_name[0] = '\0';
778
779 kmem = open(KMEM_FILE, O_RDONLY);
780 if (kmem < 0) {
781 xload_error("cannot open", KMEM_FILE);
782 }
783
784 uvar(&v);
785
786 if (nlist( KERNEL_FILE, nl) != 0) {
787 xload_error("cannot get name list from", KERNEL_FILE);
788 }
789 for (i = 0; i < 2; i++) {
790 nl[i].n_value = (int)nl[i].n_value - v.v_kvoffset;
791 }
792 #else /* not macII */
793 #if defined(sun) && defined(SVR4) && (OSMAJORVERSION == 5) && (OSMINORVERSION > 3)
794 {
795 kvm_t *kd;
796
797 kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "xload");
798 if (kd == NULL)
799 {
800 xload_error("cannot get name list from", "kernel");
801 exit(-1);
802 }
803 if (kvm_nlist (kd, namelist) < 0 )
804 {
805 xload_error("cannot get name list from", "kernel");
806 exit(-1);
807 }
808 if (namelist[LOADAV].n_type == 0 ||
809 namelist[LOADAV].n_value == 0) {
810 xload_error("cannot get name list from", "kernel");
811 exit(-1);
812 }
813 loadavg_seek = namelist[LOADAV].n_value;
814 }
815 #else /* sun svr4 5.5 or later */
816
817 #if (!defined(SVR4) || !defined(__STDC__)) && !defined(sgi) && !defined(MOTOROLA) && !(BSD >= 199103) && !defined(MINIX)
818 extern void nlist();
819 #endif
820
821 #ifdef AIXV3
822 knlist( namelist, 1, sizeof(struct nlist));
823 #else
824 nlist( KERNEL_FILE, namelist);
825 #endif
826 /*
827 * Some systems appear to set only one of these to Zero if the entry could
828 * not be found, I hope no_one returns Zero as a good value, or bad things
829 * will happen to you. (I have a hard time believing the value will
830 * ever really be zero anyway). CDP 5/17/89.
831 */
832 #ifdef hcx
833 if (namelist[LOADAV].n_type == 0 &&
834 #else
835 if (namelist[LOADAV].n_type == 0 ||
836 #endif /* hcx */
837 namelist[LOADAV].n_value == 0) {
838 xload_error("cannot get name list from", KERNEL_FILE);
839 exit(-1);
840 }
841 loadavg_seek = namelist[LOADAV].n_value;
842 #if defined(umips) && defined(SYSTYPE_SYSV)
843 loadavg_seek &= 0x7fffffff;
844 #endif /* umips && SYSTYPE_SYSV */
845 #if (defined(CRAY) && defined(SYSINFO))
846 loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) -
847 ((char *) NULL);
848 #endif /* CRAY && SYSINFO */
849 #endif /* sun svr4 5.5 or later */
850 kmem = open(KMEM_FILE, O_RDONLY);
851 if (kmem < 0) xload_error("cannot open", KMEM_FILE);
852 #endif /* macII else */
853 }
854
855 /* ARGSUSED */
856 void GetLoadPoint( w, closure, call_data )
857 Widget w; /* unused */
858 caddr_t closure; /* unused */
859 caddr_t call_data; /* pointer to (double) return value */
860 {
861 double *loadavg = (double *)call_data;
862
863 #ifdef macII
864 lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
865 #else
866 (void) lseek(kmem, loadavg_seek, 0);
867 #endif
868
869 #if defined(sun) || defined (UTEK) || defined(sequent) || defined(alliant) || defined(SVR4) || defined(sgi) || defined(hcx) || (BSD >= 199103)
870 {
871 long temp;
872 (void) read(kmem, (char *)&temp, sizeof(long));
873 *loadavg = (double)temp/FSCALE;
874 }
875 #else /* else not sun or UTEK or sequent or alliant or SVR4 or sgi or hcx */
876 # ifdef macII
877 {
878 read(kmem, vec, 3*sizeof(struct lavnum));
879 *loadavg = fxtod(0);
880 }
881 # else /* else not macII */
882 # if defined(umips) || (defined(ultrix) && defined(mips))
883 {
884 fix temp;
885 (void) read(kmem, (char *)&temp, sizeof(fix));
886 *loadavg = FIX_TO_DBL(temp);
887 }
888 # else /* not umips or ultrix risc */
889 # ifdef AIXV3
890 {
891 struct sysinfo sysinfo_now;
892 struct sysinfo sysinfo_last;
893 static firsttime = TRUE;
894 static double runavg = 0.0, swpavg = 0.0;
895
896 (void) lseek(kmem, loadavg_seek, 0);
897 (void) read(kmem, (char *)&sysinfo_last, sizeof(struct sysinfo));
898 if (firsttime)
899 {
900 *loadavg = 0.0;
901 firsttime = FALSE;
902 }
903 else
904 {
905 sleep(1);
906 (void) lseek(kmem, loadavg_seek, 0);
907 (void) read(kmem, (char *)&sysinfo_now, sizeof(struct sysinfo));
908 runavg *= 0.8; swpavg *= 0.8;
909 if (sysinfo_now.runocc != sysinfo_last.runocc)
910 runavg += 0.2*((sysinfo_now.runque - sysinfo_last.runque - 1)
911 /(double)(sysinfo_now.runocc - sysinfo_last.runocc));
912 if (sysinfo_now.swpocc != sysinfo_last.swpocc)
913 swpavg += 0.2*((sysinfo_now.swpque - sysinfo_last.swpque)
914 /(double)(sysinfo_now.swpocc - sysinfo_last.swpocc));
915 *loadavg = runavg + swpavg;
916 sysinfo_last = sysinfo_now;
917 }
918 /* otherwise we leave load alone. */
919 }
920 # else /* not AIXV3 */
921 # if defined(MOTOROLA) && defined(SYSV)
922 {
923 static int init = 0;
924 static kmem;
925 static long loadavg_seek;
926
927 #define CEXP 0.25 /* Constant used for load averaging */
928
929 struct sysinfo sysinfod;
930 static double oldloadavg;
931 static double cexp = CEXP;
932 static long sv_rq, sv_oc; /* save old values */
933 double rq, oc; /* amount values have changed */
934
935 if (!init)
936 {
937 if (nlist(KERNEL_FILE,namelist) == -1)
938 {
939 perror("xload: nlist()");
940 xload_error("cannot get name list from", KERNEL_FILE);
941 }
942 loadavg_seek = namelist[0].n_value;
943
944 kmem = open(KMEM_FILE, O_RDONLY);
945 if (kmem < 0)
946 {
947 perror("xload: open()");
948 xload_error("cannot open", KMEM_FILE);
949 }
950 }
951
952 lseek(kmem, loadavg_seek, 0);
953 if (read(kmem, &sysinfod, (int) sizeof (struct sysinfo)) == -1)
954 {
955 perror("xload: read() SYSINFONL");
956 xload_error("read failed from", KMEM_FILE);
957 }
958
959 if (!init)
960 {
961 init = 1;
962 sv_rq = sysinfod.runque;
963 sv_oc = sysinfod.runocc;
964 oldloadavg = *loadavg = 0.0;
965 return;
966 }
967 /*
968 * calculate the amount the values have
969 * changed since last update
970 */
971 rq = (double) sysinfod.runque - sv_rq;
972 oc = (double) sysinfod.runocc - sv_oc;
973
974 /*
975 * save old values for next time
976 */
977 sv_rq = sysinfod.runque;
978 sv_oc = sysinfod.runocc;
979
980 if (oc == 0.0) /* avoid divide by zero */
981 {
982 *loadavg = (1.0 - cexp) * oldloadavg;
983
984 }
985 else
986 {
987 *loadavg = ((1.0 - cexp) * oldloadavg) + ((rq / oc) * cexp);
988 }
989 oldloadavg = *loadavg;
990 }
991 # else /* not MOTOROLA */
992 # if defined(sony) && OSMAJORVERSION == 4
993 # ifdef mips
994 {
995 fix temp;
996 (void) read(kmem, (char *)&temp, sizeof(fix));
997 *loadavg = FIX_TO_DBL(temp);
998 }
999 # else /* not mips */
1000 {
1001 long temp;
1002 (void) read(kmem, (char *)&temp, sizeof(long));
1003 *loadavg = (double)temp/FSCALE;
1004 }
1005 # endif /* mips */
1006 # else /* not sony NEWSOS4 */
1007 # ifdef MINIX
1008 {
1009 /* Indices in the loadav array */
1010 #define LDAV_CURR 0 /* run queue lenght at this moment */
1011 #define LDAV_6 1 /* av. run q len over 64 ticks (1s) */
1012 #define LDAV_12 2 /* av. run q len over 4096 ticks */
1013 #define LDAV_16 3 /* av. run q len over 65536 tick */
1014 #define LDAV_TOT 4 /* cummulative run q lenght */
1015 #define LDAV_NR 5 /* size of the loadav array */
1016 #define LDAV_SCALE_SHFT 8 /* values are scaled by 256 */
1017
1018 unsigned long loadav[LDAV_NR]; /* load avarage array */
1019
1020 (void) read(kmem, (char *)loadav, sizeof(loadav));
1021 *loadavg = (double)loadav[LDAV_12]/0x1000;
1022 }
1023 # else /* !MINIX */
1024 (void) read(kmem, (char *)loadavg, sizeof(double));
1025 # endif /* MINIX */
1026 # endif /* sony NEWOS4 */
1027 # endif /* MOTOROLA else */
1028 # endif /* AIXV3 else */
1029 # endif /* umips else */
1030 # endif /* macII else */
1031 #endif /* sun else */
1032 return;
1033 }
1034 #endif /* BSD >= 199306 else */
1035 #endif /* __bsdi__ else */
1036 #endif /* __osf__ else */
1037 #endif /* LOADSTUB else */
1038 #endif /* linux else */
1039 #endif /* AMOEBA else */
1040 #endif /* KVM_ROUTINES else */
1041 #endif /* SYSV && SYSV386 else */
1042
1043 static xload_error(str1, str2)
1044 char *str1, *str2;
1045 {
1046 (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
1047 #ifdef __bsdi__
1048 if (kd)
1049 kvm_close(kd);
1050 #endif
1051 exit(-1);
1052 }
1053
1054 #endif /* apollo else */
1055
1056 /** And finally, the SNMP version **/
1057
1058 /* Read the community string out of the given filename. */
1059 char* slurp_community_string(char* filename) {
1060 char* stringbuf;
1061 FILE* fp = NULL;
1062 int i;
1063
1064 if ((stringbuf = (char*)malloc(sizeof(char) * (COMMUNITY_STR_LEN + 1)))
1065 == NULL) {
1066 xload_error("Couldn't allocate memory for community", "string");
1067 exit(-1);
1068 }
1069 if ((fp = fopen(filename, "r")) == NULL) {
1070 xload_error("Couldn't read community string from", filename);
1071 exit(-1);
1072 }
1073 while (fgets(stringbuf, COMMUNITY_STR_LEN + 1, fp))
1074 if (stringbuf[0] != '#')
1075 break;
1076
1077 for (i = 0; i < COMMUNITY_STR_LEN + 1; i++)
1078 if (stringbuf[i] == '\n') {
1079 stringbuf[i] = '\0';
1080 break;
1081 }
1082
1083 return stringbuf;
1084 }
1085
1086
1087
1088
1089 /* This should return something other than void. We're being rather
1090 * blithe about error checking right now. */
1091 void initialize_xload_snmp(snmp_params *closure) {
1092
1093 /* Initialize the library */
1094 init_snmp("xload-snmp");
1095
1096 /* Set up some defaults for the session */
1097 my_params = closure;
1098 snmp_sess_init(&session);
1099 session.version = SNMP_VERSION_1;
1100 session.peername = my_params->peername;
1101 session.community = slurp_community_string(my_params->community);
1102 session.community_len = strlen(session.community);
1103 get_node(my_params->oid, anOID, &anOID_len);
1104
1105 ss = snmp_open(&session);
1106 return;
1107 }
1108
1109
1110 void GetLoadPoint_SNMP( w, closure, call_data)
1111 Widget w; /* unused */
1112 caddr_t closure; /* pointer to snmp_params struct */
1113 caddr_t call_data; /* pointer to (double) return value */
1114 {
1115 struct snmp_pdu *pdu, *response;
1116 struct variable_list *vars;
1117 int status;
1118 float scale_factor;
1119 double prevprev_real_value;
1120
1121 if (ss == NULL) initialize_xload_snmp((snmp_params*)closure);
1122 scale_factor = ((snmp_params*)closure)->factor;
1123
1124 pdu = snmp_pdu_create(SNMP_MSG_GET);
1125 snmp_add_null_var(pdu, anOID, anOID_len);
1126
1127 status = snmp_synch_response(ss, pdu, &response);
1128 if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
1129 vars = response->variables;
1130 if (vars->type == ASN_OPAQUE_FLOAT)
1131 *(double*)call_data = *(vars->val.floatVal) / scale_factor;
1132 /* _Most_ of the other times treating the value as an int is
1133 * the right thing. Cases where this is not true will be
1134 * determined by experience. Lucky call_data points to a
1135 * double so we have lots of storage. */
1136 else
1137 *(double*)call_data = *(vars->val.integer) / scale_factor;
1138
1139 /* If we're doing -delta make that calculation now. */
1140 if (((snmp_params*)closure)->delta) {
1141 if (prev_real_value == 0.0) {
1142 /* But we need at least two values to take a delta. */
1143 prev_real_value = *(double*)call_data;
1144 *(double*)call_data = 0.0;
1145 }
1146 else {
1147 prevprev_real_value = prev_real_value;
1148 /* Save the results of this calculation for the next
1149 * calculation */
1150 prev_real_value = *(double*)call_data;
1151 *(double*)call_data = prev_real_value - prevprev_real_value;
1152 /* Negative number means the counter went down, perhaps
1153 * it was reset. So let's start over. */
1154 if (*(double*)call_data < 0.0) {
1155 *(double*)call_data = prev_real_value = 0.0;
1156 }
1157 }
1158 }
1159 }
1160 else {
1161 if (status == STAT_SUCCESS)
1162 fprintf(stderr, "Error in packet\nReason: %s\n",
1163 snmp_errstring(response->errstat));
1164 else
1165 snmp_sess_perror("snmpget", ss);
1166 *(double*)call_data = 0.0; /* There was a problem, so plot 0.0 */
1167 }
1168
1169 if (response)
1170 snmp_free_pdu(response);
1171 /* Since we don't want snmp_close() here in the callback, where do
1172 * we want it? Back in main()? Pudoo. */
1173 return;
1174 }