"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 }