summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>1997-10-06 23:26:57 (GMT)
committerH. Peter Anvin <hpa@zytor.com>1997-10-06 23:26:57 (GMT)
commit9239d7adb724b6b2c54727ee211baf71b9f4e442 (patch)
treebfa1452e3d9cd81b2adb35683270516df8721a2a
downloadrxload-9239d7adb724b6b2c54727ee211baf71b9f4e442.zip
rxload-9239d7adb724b6b2c54727ee211baf71b9f4e442.tar.gz
rxload-9239d7adb724b6b2c54727ee211baf71b9f4e442.tar.bz2
rxload-9239d7adb724b6b2c54727ee211baf71b9f4e442.tar.xz
Initial revision
-rw-r--r--Imakefile58
-rw-r--r--XLoad.ad6
-rw-r--r--get_load.c1005
-rw-r--r--loadavgd.c154
-rw-r--r--query_load.c169
-rw-r--r--rxload_inet.h31
-rw-r--r--xload.bit16
-rw-r--r--xload.c416
-rw-r--r--xload.man113
9 files changed, 1968 insertions, 0 deletions
diff --git a/Imakefile b/Imakefile
new file mode 100644
index 0000000..10f8ead
--- /dev/null
+++ b/Imakefile
@@ -0,0 +1,58 @@
+XCOMM $XConsortium: Imakefile /main/30 1996/03/09 09:37:57 kaleb $
+XCOMM $XFree86: contrib/programs/xload/Imakefile,v 3.4 1996/10/26 08:19:55 dawes Exp $
+ DEPLIBS = XawClientDepLibs
+LOCAL_LIBRARIES = XawClientLibs
+#ifdef i386MachArchitecture
+ SYS_LIBRARIES = -lsys
+#endif
+#ifdef SVR4Architecture
+#ifdef SGIArchitecture
+ SYS_LIBRARIES = -lmld
+#else
+#ifdef SonyArchitecture
+ SYS_LIBRARIES = -lmld
+#else
+ SYS_LIBRARIES = -lelf
+#endif
+#endif
+#endif
+#if defined(SunArchitecture) && defined(SystemV4)
+#if OSMINORVERSION >= 5
+ SYS_LIBRARIES = -lresolv -lkstat
+#else
+ SYS_LIBRARIES = -lkvm -lelf
+#endif
+#endif
+#ifdef SGIArchitecture
+ SYS_LIBRARIES = -lmld
+#endif
+#ifdef OsfArchitecture
+ SYS_LIBRARIES = -lld
+#endif
+#ifdef i386BsdArchitecture
+ SYS_LIBRARIES = -lutil -lkvm
+#endif
+ SRCS = xload.c query_load.c get_load.c loadavgd.c
+ COBJS = xload.o query_load.o get_load.o
+ DOBJS = loadavgd.o get_load.o
+ OSMAJORVERSION = OSMajorVersion
+ OSMINORVERSION = OSMinorVersion
+ DEFINES = -DOSMAJORVERSION=$(OSMAJORVERSION) -DOSMINORVERSION=$(OSMINORVERSION)
+
+AllTarget(xload in.loadavgd)
+NormalProgramTarget(xload,$(COBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),NullParameter)
+NormalProgramTarget(in.loadavgd,$(DOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),NullParameter)
+
+#if defined(OSF1Architecture) || defined(NetBSDArchitecture) || (defined(FreeBSDArchitecture) && OSMajorVersion > 1) || defined(LinuxArchitecture)
+InstallProgram(xload,$(BINDIR))
+InstallProgram(in.loadavdg,$(BINDIR))
+#else
+InstallProgramWithFlags(xload,$(BINDIR),$(INSTKMEMFLAGS))
+InstallProgramWithFlags(in.loadavgd,$(BINDIR),$(INSTKMEMFLAGS))
+#endif
+
+InstallAppDefaults(XLoad)
+
+InstallManPage(xload,$(MANDIR))
+
+DependTarget()
diff --git a/XLoad.ad b/XLoad.ad
new file mode 100644
index 0000000..3d4c978
--- /dev/null
+++ b/XLoad.ad
@@ -0,0 +1,6 @@
+XLoad.input: false
+*Label*Justify: left
+*JumpScroll: 1
+*internalBorderWidth: 0
+*showGrip: FALSE
+
diff --git a/get_load.c b/get_load.c
new file mode 100644
index 0000000..86b057d
--- /dev/null
+++ b/get_load.c
@@ -0,0 +1,1005 @@
+/* $XConsortium: get_load.c /main/37 1996/03/09 09:38:04 kaleb $ */
+/* $XFree86: contrib/programs/xload/get_load.c,v 3.5 1996/10/26 08:19:56 dawes Exp $ */
+/*
+
+Copyright (c) 1989 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+/*
+ * get_load - get system load
+ *
+ * Authors: Many and varied...
+ *
+ * Call InitLoadPoint() to initialize.
+ * GetLoadPoint() is a callback for the StripChart widget.
+ */
+
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+#include <stdio.h>
+
+#ifdef att
+#define LOADSTUB
+#endif
+
+#ifndef macII
+#ifndef apollo
+#ifndef LOADSTUB
+#if !defined(linux) && !defined(AMOEBA)
+#include <nlist.h>
+#endif /* linux || AMOEBA */
+#endif /* LOADSTUB */
+#endif /* apollo */
+#endif /* macII */
+
+#if defined(MOTOROLA) && defined(SYSV)
+#include <sys/sysinfo.h>
+#endif
+
+#ifdef sun
+# include <sys/param.h>
+# if defined(i386) && !defined(SVR4)
+# include <kvm.h>
+# define KVM_ROUTINES
+# elif defined(SVR4) && OSMINORVERSION > 4
+# include <kstat.h>
+# define KSTAT_ROUTINES
+# endif
+#endif
+
+#ifdef CSRG_BASED
+#include <sys/param.h>
+#endif
+
+#if defined(umips) || (defined(ultrix) && defined(mips))
+#include <sys/fixpoint.h>
+#endif
+
+#if defined(CRAY) || defined(AIXV3)
+#include <sys/param.h>
+#define word word_t
+#include <sys/sysinfo.h>
+#undef word
+#undef n_type
+#define n_type n_value
+#endif /* CRAY */
+
+#ifdef sequent
+#include <sys/vm.h>
+#endif /* sequent */
+
+#ifdef macII
+#include <a.out.h>
+#include <sys/var.h>
+#define X_AVENRUN 0
+#define fxtod(i) (vec[i].high+(vec[i].low/65536.0))
+struct lavnum {
+ unsigned short high;
+ unsigned short low;
+};
+#endif /* macII */
+
+#ifdef hcx
+#include <sys/param.h>
+#endif /* hcx */
+
+#if defined(UTEK) || defined(alliant) || (defined(MOTOROLA) && defined(SVR4))
+#define FSCALE 100.0
+#endif
+
+#ifdef sequent
+#define FSCALE 1000.0
+#endif
+
+#ifdef sgi
+#define FSCALE 1024.0
+#endif
+
+#if defined(sony) && OSMAJORVERSION == 4
+#ifdef mips
+#include <sys/fixpoint.h>
+#else
+#include <sys/param.h>
+#endif
+#endif
+
+#ifdef __osf__
+/*
+ * Use the table(2) interface; it doesn't require setuid root.
+ *
+ * Select 0, 1, or 2 for 5, 30, or 60 second load averages.
+ */
+#ifndef WHICH_AVG
+#define WHICH_AVG 1
+#endif
+#include <sys/table.h>
+#endif
+
+#ifdef SVR4
+#ifndef FSCALE
+#define FSCALE (1 << 8)
+#endif
+#endif
+
+#ifdef X_NOT_POSIX
+extern long lseek();
+#endif
+extern void exit();
+
+static xload_error();
+
+/*
+ * LOCAL QUERY ROUTINES
+ */
+
+#ifdef apollo
+#include <apollo/base.h>
+#include <apollo/time.h>
+typedef struct {
+ short state; /* ready, waiting, etc. */
+ pinteger usr; /* user sr */
+ linteger upc; /* user pc */
+ linteger usp; /* user stack pointer */
+ linteger usb; /* user sb ptr (A6) */
+ time_$clock_t cpu_total; /* cumulative cpu used by process */
+ unsigned short priority; /* process priority */
+ } proc1_$info_t;
+
+void proc1_$get_cput(
+ time_$clock_t *cput
+);
+
+void proc1_$get_info(
+ short &pid,
+ proc1_$info_t *info,
+ status_$t *sts
+);
+
+static int lastNullCpu;
+static int lastClock;
+
+void init_loadavg() /* Apollo version */
+{
+ time_$clock_t timeNow;
+ proc1_$info_t info;
+ status_$t st;
+
+ proc1_$get_info( (short) 2, &info, &st );
+ time_$clock( &timeNow );
+
+ lastClock = timeNow.low32;
+ lastNullCpu = info.cpu_total.low32;
+}
+
+/* ARGSUSED */
+double get_loadavg() /* Apollo version */
+{
+ time_$clock_t timeNow;
+ double temp;
+ proc1_$info_t info;
+ status_$t st;
+
+ proc1_$get_info( (short) 2, &info, &st );
+ time_$clock( &timeNow );
+
+ temp = info.cpu_total.low32 - lastNullCpu;
+ temp = 1.0 - temp / (timeNow.low32 - lastClock);
+
+ lastClock = timeNow.low32;
+ lastNullCpu = info.cpu_total.low32;
+
+ return temp;
+}
+#else /* not apollo */
+#if defined(SYSV) && defined(SYSV386)
+/*
+ * inspired by 'avgload' by John F. Haugh II
+ */
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/immu.h>
+#include <sys/region.h>
+#include <sys/var.h>
+#include <sys/proc.h>
+#define KERNEL_FILE "/unix"
+#define KMEM_FILE "/dev/kmem"
+#define VAR_NAME "v"
+#define PROC_NAME "proc"
+#define BUF_NAME "buf"
+#define DECAY 0.8
+struct nlist namelist[] = {
+ {VAR_NAME},
+ {PROC_NAME},
+ {BUF_NAME},
+ {0},
+};
+
+static int kmem;
+static struct var v;
+static struct proc *p;
+static caddr_t first_buf, last_buf;
+
+void init_loadavg() /* SYSV386 version */
+{
+ int i;
+
+ nlist( KERNEL_FILE, namelist);
+
+ for (i=0; namelist[i].n_name; i++)
+ if (namelist[i].n_value == 0)
+ xload_error("cannot get name list from", KERNEL_FILE);
+
+ if ((kmem = open(KMEM_FILE, O_RDONLY)) < 0)
+ xload_error("cannot open", KMEM_FILE);
+
+ if (lseek(kmem, namelist[0].n_value, 0) == -1)
+ xload_error("cannot seek", VAR_NAME);
+
+ if (read(kmem, &v, sizeof(v)) != sizeof(v))
+ xload_error("cannot read", VAR_NAME);
+
+ if ((p=(struct proc *)malloc(v.v_proc*sizeof(*p))) == NULL)
+ xload_error("cannot allocat space for", PROC_NAME);
+
+ first_buf = (caddr_t) namelist[2].n_value;
+ last_buf = first_buf + v.v_buf * sizeof(struct buf);
+}
+
+double get_loadavg() /* SYSV386 version */
+{
+ static double avenrun = 0.0;
+ int i, nproc, size;
+
+ (void) lseek(kmem, namelist[0].n_value, 0);
+ (void) read(kmem, &v, sizeof(v));
+
+ size = (struct proc *)v.ve_proc - (struct proc *)namelist[1].n_value;
+
+ (void) lseek(kmem, namelist[1].n_value, 0);
+ (void) read(kmem, p, size * sizeof(struct proc));
+
+ for (nproc = 0, i=0; i<size; i++)
+ if ((p[i].p_stat == SRUN) ||
+ (p[i].p_stat == SIDL) ||
+ (p[i].p_stat == SXBRK) ||
+ (p[i].p_stat == SSLEEP && (p[i].p_pri < PZERO) &&
+ (p[i].p_wchan >= first_buf) && (p[i].p_wchan < last_buf)))
+ nproc++;
+
+ /* update the load average using a decay filter */
+ avenrun = DECAY * avenrun + nproc * (1.0 - DECAY);
+ return avenrun;
+}
+#else /* not (SYSV && SYSV386) */
+#ifdef KVM_ROUTINES
+/*
+ * Sun 386i Code - abstracted to see the wood for the trees
+ */
+
+static struct nlist nl[2];
+static kvm_t *kd;
+
+void
+init_loadavg() /* Sun 386i version */
+{
+ kd = kvm_open("/vmunix", NULL, NULL, O_RDONLY, "Load Widget");
+ if (kd == (kvm_t *)0) {
+ xload_error("cannot get access to kernel address space");
+ }
+
+ nl[0].n_name = "avenrun";
+ nl[1].n_name = NULL;
+
+ if (kvm_nlist(kd, nl) != 0) {
+ xload_error("cannot get name list");
+ }
+
+ if (nl[0].n_value == 0) {
+ xload_error("Cannot find address for avenrun in the kernel\n");
+ }
+}
+
+/* ARGSUSED */
+double
+get_loadavg()
+{
+ long temp;
+
+ if (kvm_read(kd, nl[0].n_value, (char *)&temp, sizeof (temp)) !=
+ sizeof (temp)) {
+ xload_error("Kernel read error");
+ }
+ return (double)temp/FSCALE;
+}
+#else /* not KVM_ROUTINES */
+
+#ifdef AMOEBA
+#include <amoeba.h>
+#include <cmdreg.h>
+#include <stderr.h>
+#include <ampolicy.h>
+
+static capability pooldircap;
+extern char *getenv();
+
+void
+init_loadavg()
+{
+ register char *s;
+
+ if ((s = getenv("XLOAD_HOST")) != NULL) {
+ /* do an xload of a single host */
+ if (host_lookup(s, &pooldircap) != STD_OK)
+ xload_error("cannot lookup run server", s);
+ if (dir_lookup(&pooldircap, "proc", &pooldircap) != STD_OK)
+ xload_error("cannot lookup run server", s);
+ } else {
+ /* Else we do an xload of a pool.
+ * Environment variable RUN_SERVER overrides the default one.
+ */
+ if ((s = getenv("RUN_SERVER")) == NULL)
+ s = DEF_RUNSVR_POOL;
+ if (name_lookup(s, &pooldircap) != STD_OK)
+ xload_error("cannot lookup run server", s);
+ }
+}
+
+/* ARGSUSED */
+double
+get_loadavg()
+{
+ long ips, loadav, mfree;
+
+ if (pro_getload(&pooldircap, &ips, &loadav, &mfree) != STD_OK) {
+ /*
+ * No run server. We don't want to crash, though:
+ * it will probably come up again.
+ */
+ init_loadavg();
+ loadav = 0;
+ }
+ return (double)loadav / 1024.0;
+}
+#else /* AMOEBA */
+
+#ifdef linux
+
+void init_loadavg()
+{
+ return;
+}
+
+double get_loadavg()
+{
+ double loadavg;
+ static int fd = -1;
+ int n;
+ char buf[10];
+
+ if (fd < 0)
+ {
+ if (fd == -2 ||
+ (fd = open("/proc/loadavg", O_RDONLY)) < 0)
+ {
+ fd = -2;
+ loadavg = -1.0;
+ return;
+ }
+ }
+ else
+ lseek(fd, 0, 0);
+
+ if ((n = read(fd, buf, sizeof(buf)-1)) > 0 &&
+ sscanf(buf, "%lf", &loadavg) == 1)
+ return loadavg;
+
+ return -1.0;
+}
+
+#else /* linux */
+
+#ifdef LOADSTUB
+
+void init_loadavg()
+{
+}
+
+double get_loadavg()
+{
+ return 1.0; /* Bogus */
+}
+
+#else /* not LOADSTUB */
+
+#ifdef __osf__
+
+void init_loadavg()
+{
+}
+
+double get_loadavg()
+{
+ double loadavg = -1.0;
+ struct tbl_loadavg load_data;
+
+ if (table(TBL_LOADAVG, 0, (char *)&load_data, 1, sizeof(load_data)) < 0)
+ xload_error("error reading load average", "");
+ loadavg = (load_data.tl_lscale == 0) ?
+ load_data.tl_avenrun.d[WHICH_AVG] :
+ load_data.tl_avenrun.l[WHICH_AVG] / (double)load_data.tl_lscale;
+ return loadavg;
+}
+
+#else /* not __osf__ */
+
+#ifdef CSRG_BASED
+#include <kvm.h>
+
+static struct nlist nl[] = {
+ { "_averunnable" },
+#define X_AVERUNNABLE 0
+ { "_fscale" },
+#define X_FSCALE 1
+ { "" },
+};
+static kvm_t *kd;
+static int fscale;
+
+void init_loadavg()
+{
+ fixpt_t averunnable[3]; /* unused really */
+
+ if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
+ xload_error("can't open kvm files");
+
+ if (kvm_nlist(kd, nl) != 0)
+ xload_error("can't read name list");
+
+ if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)averunnable,
+ sizeof(averunnable)) != sizeof(averunnable))
+ xload_error("couldn't obtain _averunnable variable");
+
+ if (kvm_read(kd, (off_t)nl[X_FSCALE].n_value, (char *)&fscale,
+ sizeof(fscale)) != sizeof(fscale))
+ xload_error("couldn't obtain _fscale variable");
+
+ return;
+}
+
+double get_loadavg()
+{
+ fixpt_t t;
+
+ if (kvm_read(kd, (off_t)nl[X_AVERUNNABLE].n_value, (char *)&t,
+ sizeof(t)) != sizeof(t))
+ xload_error("couldn't obtain load average");
+
+ return (double)t/fscale;
+}
+#else /* not __bsdi__ */
+
+#if BSD >= 199306
+
+void init_loadavg()
+{
+}
+
+double get_loadavg()
+{
+ double loadavg;
+
+ if (getloadavg(&loadavg, 1) < 0)
+ xload_error("couldn't obtain load average");
+ return loadavg;
+}
+
+#else /* not BSD >= 199306 */
+#ifdef KSTAT_ROUTINES
+
+/* kstat() interface -- as far as I know unique to Solaris 2.5 and higher */
+/* hpa 1997-08-13 based on code from Sendmail 8.8.7 */
+
+static kstat_ctl_t *kc = NULL;
+static kstat_t *ksp = NULL;
+
+void init_loadavg()
+{
+ kc = kstat_open();
+ if ( !kc )
+ xload_error("kstat_open() failure");
+ ksp = kstat_lookup(kc, "unix", 0, "system_misc");
+ if ( !ksp )
+ xload_error("kstat_lookup() failure");
+}
+
+double get_loadavg()
+{
+ kstat_named_t *ksn;
+ double la;
+
+ if ( kstat_read(kc, ksp, NULL) < 0 )
+ return -1.0;
+
+ ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
+ return ((double) ksn->value.ul + FSCALE/2) / FSCALE;
+}
+
+#else /* not KSTAT_ROUTINES */
+
+#ifndef KMEM_FILE
+#define KMEM_FILE "/dev/kmem"
+#endif
+
+#ifndef KERNEL_FILE
+
+#ifdef alliant
+#define KERNEL_FILE "/vmunix"
+#endif /* alliant */
+
+#ifdef CRAY
+#define KERNEL_FILE "/unicos"
+#endif /* CRAY */
+
+#ifdef hpux
+#define KERNEL_FILE "/hp-ux"
+#endif /* hpux */
+
+#ifdef macII
+#define KERNEL_FILE "/unix"
+#endif /* macII */
+
+#ifdef umips
+# ifdef SYSTYPE_SYSV
+# define KERNEL_FILE "/unix"
+# else
+# define KERNEL_FILE "/vmunix"
+# endif /* SYSTYPE_SYSV */
+#endif /* umips */
+
+#ifdef sequent
+#define KERNEL_FILE "/dynix"
+#endif /* sequent */
+
+#ifdef hcx
+#define KERNEL_FILE "/unix"
+#endif /* hcx */
+
+#ifdef MOTOROLA
+#if defined(SYSV) && defined(m68k)
+#define KERNEL_FILE "/sysV68"
+#endif
+#if defined(SYSV) && defined(m88k)
+#define KERNEL_FILE "/unix"
+#endif
+#ifdef SVR4
+#define KERNEL_FILE "/unix"
+#endif
+#endif /* MOTOROLA */
+
+#if defined(sun) && defined(SVR4)
+#define KERNEL_FILE "/kernel/genunix"
+#endif
+
+#ifdef MINIX
+#define KERNEL_FILE "/sys/kernel"
+#endif /* MINIX */
+
+#ifdef sgi
+#if (OSMAJORVERSION > 4)
+#define KERNEL_FILE "/unix"
+#endif
+#endif
+
+/*
+ * provide default for everyone else
+ */
+#ifndef KERNEL_FILE
+#ifdef SVR4
+#define KERNEL_FILE "/stand/unix"
+#else
+#ifdef SYSV
+#define KERNEL_FILE "/unix"
+#else
+/* If a BSD system, check in <paths.h> */
+# ifdef BSD
+# include <paths.h>
+# ifdef _PATH_UNIX
+# define KERNEL_FILE _PATH_UNIX
+# else
+# ifdef _PATH_KERNEL
+# define KERNEL_FILE _PATH_KERNEL
+# else
+# define KERNEL_FILE "/vmunix"
+# endif
+# endif
+# else /* BSD */
+# define KERNEL_FILE "/vmunix"
+# endif /* BSD */
+#endif /* SYSV */
+#endif /* SVR4 */
+#endif /* KERNEL_FILE */
+#endif /* KERNEL_FILE */
+
+
+#ifndef KERNEL_LOAD_VARIABLE
+# if (BSD >= 199103)
+# define KERNEL_LOAD_VARIABLE "_averunnable"
+# endif /* BSD >= 199103 */
+
+# ifdef alliant
+# define KERNEL_LOAD_VARIABLE "_Loadavg"
+# endif /* alliant */
+
+# ifdef CRAY
+# if defined(CRAY2) && OSMAJORVERSION == 4
+# define KERNEL_LOAD_VARIABLE "avenrun"
+# else
+# define KERNEL_LOAD_VARIABLE "sysinfo"
+# define SYSINFO
+# endif /* defined(CRAY2) && OSMAJORVERSION == 4 */
+# endif /* CRAY */
+
+# ifdef hpux
+# ifdef __hp9000s800
+# define KERNEL_LOAD_VARIABLE "avenrun"
+# endif /* hp9000s800 */
+# endif /* hpux */
+
+# ifdef umips
+# ifdef SYSTYPE_SYSV
+# define KERNEL_LOAD_VARIABLE "avenrun"
+# else
+# define KERNEL_LOAD_VARIABLE "_avenrun"
+# endif /* SYSTYPE_SYSV */
+# endif /* umips */
+
+# ifdef sgi
+# define KERNEL_LOAD_VARIABLE "avenrun"
+# endif /* sgi */
+
+# ifdef AIXV3
+# define KERNEL_LOAD_VARIABLE "sysinfo"
+# endif /* AIXV3 */
+
+# ifdef MOTOROLA
+# if defined(SYSV) && defined(m68k)
+# define KERNEL_LOAD_VARIABLE "sysinfo"
+# endif
+# if defined(SYSV) && defined(m88k)
+# define KERNEL_LOAD_VARIABLE "_sysinfo"
+# endif
+# ifdef SVR4
+# define KERNEL_LOAD_VARIABLE "avenrun"
+# endif
+# endif /* MOTOROLA */
+
+# ifdef MINIX
+# define KERNEL_LOAD_VARIABLE "_loadav"
+# endif /* MINIX */
+
+#endif /* KERNEL_LOAD_VARIABLE */
+
+/*
+ * provide default for everyone else
+ */
+
+#ifndef KERNEL_LOAD_VARIABLE
+# ifdef USG
+# define KERNEL_LOAD_VARIABLE "sysinfo"
+# define SYSINFO
+# else
+# ifdef SVR4
+# define KERNEL_LOAD_VARIABLE "avenrun"
+# else
+# define KERNEL_LOAD_VARIABLE "_avenrun"
+# endif
+# endif
+#endif /* KERNEL_LOAD_VARIABLE */
+
+#ifdef macII
+static struct var v;
+static int pad[2]; /* This padding is needed if xload compiled on */
+ /* a/ux 1.1 is executed on a/ux 1.0, because */
+ /* the var structure had too much padding in 1.0, */
+ /* so the 1.0 kernel writes past the end of the 1.1 */
+ /* var structure in the uvar() call. */
+static struct nlist nl[2];
+static struct lavnum vec[3];
+#else /* not macII */
+static struct nlist namelist[] = { /* namelist for vmunix grubbing */
+#define LOADAV 0
+ {KERNEL_LOAD_VARIABLE},
+ {0}
+};
+#endif /* macII */
+
+static kmem;
+static long loadavg_seek;
+
+init_loadavg()
+{
+#ifdef macII
+ extern nlist();
+
+ int i;
+
+ strcpy(nl[0].n_name, "avenrun");
+ nl[1].n_name[0] = '\0';
+
+ kmem = open(KMEM_FILE, O_RDONLY);
+ if (kmem < 0) {
+ xload_error("cannot open", KMEM_FILE);
+ }
+
+ uvar(&v);
+
+ if (nlist( KERNEL_FILE, nl) != 0) {
+ xload_error("cannot get name list from", KERNEL_FILE);
+ }
+ for (i = 0; i < 2; i++) {
+ nl[i].n_value = (int)nl[i].n_value - v.v_kvoffset;
+ }
+#else /* not macII */
+#if (!defined(SVR4) || !defined(__STDC__)) && !defined(sgi) && !defined(MOTOROLA) && !(BSD >= 199103) && !defined(MINIX)
+ extern void nlist();
+#endif
+
+#ifdef AIXV3
+ knlist( namelist, 1, sizeof(struct nlist));
+#else
+ nlist( KERNEL_FILE, namelist);
+#endif
+ /*
+ * Some systems appear to set only one of these to Zero if the entry could
+ * not be found, I hope no_one returns Zero as a good value, or bad things
+ * will happen to you. (I have a hard time believing the value will
+ * ever really be zero anyway). CDP 5/17/89.
+ */
+#ifdef hcx
+ if (namelist[LOADAV].n_type == 0 &&
+#else
+ if (namelist[LOADAV].n_type == 0 ||
+#endif /* hcx */
+ namelist[LOADAV].n_value == 0) {
+ xload_error("cannot get name list from", KERNEL_FILE);
+ exit(-1);
+ }
+ loadavg_seek = namelist[LOADAV].n_value;
+#if defined(umips) && defined(SYSTYPE_SYSV)
+ loadavg_seek &= 0x7fffffff;
+#endif /* umips && SYSTYPE_SYSV */
+#if (defined(CRAY) && defined(SYSINFO))
+ loadavg_seek += ((char *) (((struct sysinfo *)NULL)->avenrun)) -
+ ((char *) NULL);
+#endif /* CRAY && SYSINFO */
+
+ kmem = open(KMEM_FILE, O_RDONLY);
+ if (kmem < 0) xload_error("cannot open", KMEM_FILE);
+#endif /* macII else */
+}
+
+double get_loadavg()
+{
+ double loadavg = -1.0;
+
+#ifdef macII
+ lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
+#else
+ (void) lseek(kmem, loadavg_seek, 0);
+#endif
+
+#if defined(sun) || defined (UTEK) || defined(sequent) || defined(alliant) || defined(SVR4) || defined(sgi) || defined(hcx) || (BSD >= 199103)
+ {
+ long temp;
+ (void) read(kmem, (char *)&temp, sizeof(long));
+ loadavg = (double)temp/FSCALE;
+ }
+#else /* else not sun or UTEK or sequent or alliant or SVR4 or sgi or hcx */
+# ifdef macII
+ {
+ read(kmem, vec, 3*sizeof(struct lavnum));
+ loadavg = fxtod(0);
+ }
+# else /* else not macII */
+# if defined(umips) || (defined(ultrix) && defined(mips))
+ {
+ fix temp;
+ (void) read(kmem, (char *)&temp, sizeof(fix));
+ loadavg = FIX_TO_DBL(temp);
+ }
+# else /* not umips or ultrix risc */
+# ifdef AIXV3
+ {
+ struct sysinfo sysinfo_now;
+ struct sysinfo sysinfo_last;
+ static firsttime = TRUE;
+ static double runavg = 0.0, swpavg = 0.0;
+
+ (void) lseek(kmem, loadavg_seek, 0);
+ (void) read(kmem, (char *)&sysinfo_last, sizeof(struct sysinfo));
+ if (firsttime)
+ {
+ loadavg = 0.0;
+ firsttime = FALSE;
+ }
+ else
+ {
+ sleep(1);
+ (void) lseek(kmem, loadavg_seek, 0);
+ (void) read(kmem, (char *)&sysinfo_now, sizeof(struct sysinfo));
+ runavg *= 0.8; swpavg *= 0.8;
+ if (sysinfo_now.runocc != sysinfo_last.runocc)
+ runavg += 0.2*((sysinfo_now.runque - sysinfo_last.runque - 1)
+ /(double)(sysinfo_now.runocc - sysinfo_last.runocc));
+ if (sysinfo_now.swpocc != sysinfo_last.swpocc)
+ swpavg += 0.2*((sysinfo_now.swpque - sysinfo_last.swpque)
+ /(double)(sysinfo_now.swpocc - sysinfo_last.swpocc));
+ loadavg = runavg + swpavg;
+ sysinfo_last = sysinfo_now;
+ }
+ /* otherwise we leave load alone. */
+ }
+# else /* not AIXV3 */
+# if defined(MOTOROLA) && defined(SYSV)
+ {
+ static int init = 0;
+ static kmem;
+ static long loadavg_seek;
+ static xload_error();
+
+#define CEXP 0.25 /* Constant used for load averaging */
+
+ struct sysinfo sysinfod;
+ static double oldloadavg;
+ static double cexp = CEXP;
+ static long sv_rq, sv_oc; /* save old values */
+ double rq, oc; /* amount values have changed */
+
+ if (!init)
+ {
+ if (nlist(KERNEL_FILE,namelist) == -1)
+ {
+ perror("xload: nlist()");
+ xload_error("cannot get name list from", KERNEL_FILE);
+ }
+ loadavg_seek = namelist[0].n_value;
+
+ kmem = open(KMEM_FILE, O_RDONLY);
+ if (kmem < 0)
+ {
+ perror("xload: open()");
+ xload_error("cannot open", KMEM_FILE);
+ }
+ }
+
+ lseek(kmem, loadavg_seek, 0);
+ if (read(kmem, &sysinfod, (int) sizeof (struct sysinfo)) == -1)
+ {
+ perror("xload: read() SYSINFONL");
+ xload_error("read failed from", KMEM_FILE);
+ }
+
+ if (!init)
+ {
+ init = 1;
+ sv_rq = sysinfod.runque;
+ sv_oc = sysinfod.runocc;
+ oldloadavg = loadavg = 0.0;
+ return;
+ }
+ /*
+ * calculate the amount the values have
+ * changed since last update
+ */
+ rq = (double) sysinfod.runque - sv_rq;
+ oc = (double) sysinfod.runocc - sv_oc;
+
+ /*
+ * save old values for next time
+ */
+ sv_rq = sysinfod.runque;
+ sv_oc = sysinfod.runocc;
+
+ if (oc == 0.0) /* avoid divide by zero */
+ {
+ loadavg = (1.0 - cexp) * oldloadavg;
+
+ }
+ else
+ {
+ loadavg = ((1.0 - cexp) * oldloadavg) + ((rq / oc) * cexp);
+ }
+ oldloadavg = loadavg;
+ }
+# else /* not MOTOROLA */
+# if defined(sony) && OSMAJORVERSION == 4
+# ifdef mips
+ {
+ fix temp;
+ (void) read(kmem, (char *)&temp, sizeof(fix));
+ loadavg = FIX_TO_DBL(temp);
+ }
+# else /* not mips */
+ {
+ long temp;
+ (void) read(kmem, (char *)&temp, sizeof(long));
+ loadavg = (double)temp/FSCALE;
+ }
+# endif /* mips */
+# else /* not sony NEWSOS4 */
+# ifdef MINIX
+ {
+/* Indices in the loadav array */
+#define LDAV_CURR 0 /* run queue lenght at this moment */
+#define LDAV_6 1 /* av. run q len over 64 ticks (1s) */
+#define LDAV_12 2 /* av. run q len over 4096 ticks */
+#define LDAV_16 3 /* av. run q len over 65536 tick */
+#define LDAV_TOT 4 /* cummulative run q lenght */
+#define LDAV_NR 5 /* size of the loadav array */
+#define LDAV_SCALE_SHFT 8 /* values are scaled by 256 */
+
+ unsigned long loadav[LDAV_NR]; /* load avarage array */
+
+ (void) read(kmem, (char *)loadav, sizeof(loadav));
+ loadavg = (double)loadav[LDAV_12]/0x1000;
+ }
+# else /* !MINIX */
+ (void) read(kmem, (char *)loadavg, sizeof(double));
+# endif /* MINIX */
+# endif /* sony NEWOS4 */
+# endif /* MOTOROLA else */
+# endif /* AIXV3 else */
+# endif /* umips else */
+# endif /* macII else */
+#endif /* sun else */
+ return loadavg;
+}
+#endif /* KSTAT_ROUTINES else */
+#endif /* BSD >= 199306 else */
+#endif /* CSRG_BASED else */
+#endif /* __osf__ else */
+#endif /* LOADSTUB else */
+#endif /* linux else */
+#endif /* AMOEBA else */
+#endif /* KVM_ROUTINES else */
+#endif /* SYSV && SYSV386 else */
+
+static xload_error(str1, str2)
+char *str1, *str2;
+{
+ extern char *ProgramName;
+
+ (void) fprintf(stderr,"%s: %s %s\n", ProgramName, str1, str2);
+#ifdef CSRG_BASED
+ if (kd)
+ kvm_close(kd);
+#endif
+ exit(-1);
+}
+
+#endif /* apollo else */
diff --git a/loadavgd.c b/loadavgd.c
new file mode 100644
index 0000000..f9cffff
--- /dev/null
+++ b/loadavgd.c
@@ -0,0 +1,154 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1997 Transmeta Corporation - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* loadavgd.c - load average reporting daemon (UDP) */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include "rxload_inet.h"
+
+void init_loadavg();
+double get_loadavg();
+
+char *ProgramName;
+
+void server(port,timeout)
+ char *port;
+ int timeout;
+{
+ struct sockaddr_in saddr;
+ struct sockaddr fromaddr;
+ struct servent *serv;
+ int sockfd, addrlen;
+ int socktype, typelen;
+ char buffer[64];
+ double loadavg;
+ int inet_flag;
+
+ /* First find out if we were spawned by inetd. If so, we should have
+ a datagram socket on stdin. */
+ typelen = sizeof(int);
+ if ( getsockopt(0, SOL_SOCKET, SO_TYPE, &socktype, &typelen) == 0
+ /* && typelen == sizeof(int) && socktype == SOCK_DGRAM */ ) {
+ inet_flag = 1;
+ sockfd = 0; /* This was easy */
+ close(1);
+ close(2);
+ } else {
+ inet_flag = 0;
+
+ bzero((char *) &saddr, sizeof(saddr));
+
+ if ( port ) {
+ serv = getservbyname(port, "udp");
+ if ( serv )
+ saddr.sin_port = serv->s_port;
+ else
+ saddr.sin_port = htons(atoi(port));
+ } else {
+ serv = getservbyname(DEFAULT_SERVICE, "udp");
+ if ( serv )
+ saddr.sin_port = serv->s_port;
+ else
+ saddr.sin_port = htons(DEFAULT_PORT);
+ }
+
+ if ( !saddr.sin_port ) {
+ fprintf(stderr, "%s: bad port\n", ProgramName);
+ exit(12);
+ }
+
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
+ perror(ProgramName);
+ exit(13);
+ }
+ if ( bind(sockfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0 ) {
+ fprintf(stderr, "%s: cannot bind to server port\n", ProgramName);
+ exit(14);
+ }
+ }
+
+ while(1) {
+ if ( inet_flag && timeout > 0 ) {
+ struct timeval tv;
+ fd_set sockset;
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_ZERO(&sockset);
+ FD_SET(sockfd,&sockset);
+
+ if ( select(sockfd+1, &sockset, NULL, NULL, &tv) < 0 &&
+ errno == EINTR )
+ continue;
+
+ if ( !FD_ISSET(sockfd,&sockset) )
+ break;
+ }
+
+ addrlen = sizeof(struct sockaddr);
+ if ( recvfrom(sockfd, buffer, 64, 0, &fromaddr, &addrlen) < 0 )
+ break;
+
+ /* The first 8 bytes of the packet are returned in the reply;
+ reserved for client matching requests with replies */
+
+ bzero(buffer+8, 64-8);
+ loadavg = get_loadavg();
+ if ( loadavg >= 0.0 ) {
+ sprintf(buffer+8, "%g", loadavg);
+ sendto(sockfd, buffer, 64, 0, &fromaddr, addrlen);
+ }
+ }
+
+ close(sockfd);
+}
+
+
+int main(argc,argv)
+ int argc;
+ char *argv[];
+{
+ char *port = NULL;
+ int timeout = 900;
+ int i;
+
+ ProgramName = argv[0];
+
+ for ( i = 1 ; i < argc ; i++ ) {
+ if ( !strcmp("-port", argv[i]) && i != argc-1 ) {
+ port = argv[++i];
+ } else if ( !strcmp("-timeout", argv[i]) && i != argc-1 ) {
+ timeout = atoi(argv[++i]);
+ } else {
+ fprintf(stderr, "Usage: %s [-port port] [-timeout timeout]\n", argv[0]);
+ exit(15);
+ }
+ }
+
+ init_loadavg();
+ server(port,timeout);
+ exit(0);
+}
diff --git a/query_load.c b/query_load.c
new file mode 100644
index 0000000..584246f
--- /dev/null
+++ b/query_load.c
@@ -0,0 +1,169 @@
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Cardinals.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "rxload_inet.h"
+
+extern char *ProgramName;
+extern char *remote_host, *remote_port;
+
+extern void setbadcolor(), setgoodcolor();
+
+extern void init_loadavg();
+extern double get_loadavg();
+
+void LocalInitLoadPoint() {
+ init_loadavg();
+}
+
+void RemoteInitLoadPoint();
+
+void LocalGetLoadPoint(w, closure, call_data)
+ Widget w;
+ caddr_t closure;
+ caddr_t call_data;
+{
+ double loadavg;
+
+ loadavg = get_loadavg();
+ *(double *)call_data = (loadavg < 0.0) ? 0.0 : loadavg;
+}
+
+void RemoteGetLoadPoint();
+
+void (*GetLoadPoint)();
+
+void InitLoadPoint()
+{
+ if ( remote_host ) {
+ GetLoadPoint = RemoteGetLoadPoint;
+ RemoteInitLoadPoint();
+ } else {
+ GetLoadPoint = LocalGetLoadPoint;
+ /* LocalInitLoadPoint() is done anyway just-in-case */
+ }
+}
+
+int sock = -1;
+
+void RemoteInitLoadPoint()
+{
+ struct sockaddr_in remote_host_addr;
+ struct servent *serv;
+ struct hostent *host;
+
+ bzero(&remote_host_addr, sizeof(remote_host_addr));
+
+ if ( remote_port ) {
+ serv = getservbyname(remote_port, "udp");
+ if ( serv )
+ remote_host_addr.sin_port = serv->s_port;
+ else
+ remote_host_addr.sin_port = htons(atoi(remote_port));
+ } else {
+ serv = getservbyname(DEFAULT_SERVICE, "udp");
+ if ( serv )
+ remote_host_addr.sin_port = serv->s_port;
+ else
+ remote_host_addr.sin_port = htons(DEFAULT_PORT);
+ }
+
+ host = gethostbyname(remote_host);
+ if ( !host ) {
+ herror(ProgramName);
+ exit(1);
+ }
+
+ remote_host_addr.sin_family = AF_INET;
+ bcopy(host->h_addr, &remote_host_addr.sin_addr, host->h_length);
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if ( sock < 0 ) {
+ fprintf(stderr, "%s: could not create socket\n", ProgramName);
+ exit(1);
+ }
+ if ( connect(sock, (struct sockaddr *) &remote_host_addr, sizeof(remote_host_addr)) < 0 ) {
+ fprintf(stderr, "%s: could not connect socket\n", ProgramName);
+ exit(1);
+ }
+}
+
+void RemoteGetLoadPoint( w, closure, call_data )
+ Widget w; /* unused */
+ caddr_t closure; /* unused */
+ caddr_t call_data; /* pointer to (double) return value */
+{
+ char buffer[65], seqid[9], *p;
+ int i, j, n;
+ long fdflags;
+ double v;
+ fd_set sockset;
+ struct timeval timeout;
+ Arg args[1];
+
+ static int sequence = 100; /* Start a little bit away from zero */
+
+ *((double *)call_data) = 0.0; /* In case of error */
+
+ sprintf(seqid, "%08x", (sequence++) & 0xffffffff);
+
+ /* Flush any already waiting packets */
+ fdflags = fcntl(sock, F_GETFL);
+ fdflags |= O_NDELAY;
+ fcntl(sock, F_SETFL, fdflags);
+ while ( recv(sock, buffer, 64, 0) > 0 );
+ fdflags &= ~O_NDELAY;
+ fcntl(sock, F_SETFL, fdflags);
+
+ for ( i = 0 ; i < SOCK_TRIES ; i++ ) {
+ for ( j = 0 ; j < DGRAM_TRIES ; j++ ) {
+ /* Send polling packet */
+ bzero(buffer, 64);
+ bcopy(seqid, buffer, 8);
+ send(sock, buffer, 64, 0);
+
+ /* Wait for reply */
+ wait_for_packet:
+ FD_ZERO(&sockset);
+ FD_SET(sock, &sockset);
+ timeout.tv_sec = DGRAM_TIMEOUT;
+ timeout.tv_usec = 0;
+ while ( select(sock+1, &sockset, NULL, NULL, &timeout) < 0 &&
+ errno == EINTR );
+
+ /* Proces reply if available */
+ if ( FD_ISSET(sock, &sockset) &&
+ (n = recv(sock, buffer, 64, 0)) > 8 ) {
+ if ( bcmp(buffer, seqid, 8) ) {
+ /* We received a bogus packet, probably reply to a previously
+ abandoned query. We discard this packet, but if we send out
+ a new query we may cause a packet storm on the network. */
+ goto wait_for_packet;
+ }
+
+ buffer[n] = '\0';
+
+ if ( sscanf(buffer+8, "%lf", &v) == 1 ) {
+ *((double *)call_data) = v;
+ setgoodcolor();
+ return;
+ }
+ }
+ }
+
+ /* Consider the possibility the address may have changed: get the address
+ anew and create a new socket */
+ close(sock);
+ RemoteInitLoadPoint();
+ }
+
+ setbadcolor();
+ return;
+}
diff --git a/rxload_inet.h b/rxload_inet.h
new file mode 100644
index 0000000..15f2a60
--- /dev/null
+++ b/rxload_inet.h
@@ -0,0 +1,31 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1997 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* rxload_inet.h - common definitions for inet protocol family */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#define DEFAULT_SERVICE "loadavg" /* Default service name */
+#define DEFAULT_PORT 8216 /* Port number if service unknown */
+
+#define SOCK_TRIES 2 /* Outer-trial loop (new socket) */
+#define DGRAM_TRIES 3 /* Inner-trial loop (same socket) */
+#define DGRAM_TIMEOUT 5 /* Time between requests */
diff --git a/xload.bit b/xload.bit
new file mode 100644
index 0000000..b4b038a
--- /dev/null
+++ b/xload.bit
@@ -0,0 +1,16 @@
+#define xload_width 32
+#define xload_height 32
+#define xload_x_hot 15
+#define xload_y_hot 16
+static unsigned char xload_bits[] = {
+ 0x00, 0x00, 0xc0, 0x03, 0x1e, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf8, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfe, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0xff, 0x03, 0x00, 0xc0, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0x03, 0x00, 0xf0, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xf8, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfc, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x03, 0x00, 0xfe, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0x80, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03};
diff --git a/xload.c b/xload.c
new file mode 100644
index 0000000..7af489d
--- /dev/null
+++ b/xload.c
@@ -0,0 +1,416 @@
+/* $XConsortium: xload.c,v 1.37 94/04/17 20:43:44 converse Exp $ */
+/* $XFree86: contrib/programs/xload/xload.c,v 3.0 1994/06/05 08:00:09 dawes Exp $ */
+/*
+
+Copyright (c) 1989 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+/*
+ * xload - display system load average in a window
+ */
+
+#include <stdio.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xatom.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+
+#include <X11/Xaw/Cardinals.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/StripChart.h>
+#include <X11/Xmu/SysUtil.h>
+
+#include "xload.bit"
+
+char *ProgramName;
+
+char *remote_host, *remote_port;
+static int switch_color = 0;
+struct switch_widget_struct {
+ Widget w;
+ Pixel reach_color;
+ Pixel unreach_color;
+};
+static struct switch_widget_struct switch_widget[2];
+static int switch_count;
+
+extern void exit(), (*GetLoadPoint)();
+extern void InitLoadPoint(), LocalInitLoadPoint();
+static void quit();
+static void ClearLights();
+static void SetLights();
+
+/*
+ * Definition of the Application resources structure.
+ */
+
+typedef struct _XLoadResources {
+ Boolean show_label;
+ Boolean use_lights;
+ char *remote_host;
+ char *remote_port;
+ Pixel unreach_color;
+} XLoadResources;
+
+/*
+ * Command line options table. Only resources are entered here...there is a
+ * pass over the remaining options after XtParseCommand is let loose.
+ */
+
+static XrmOptionDescRec options[] = {
+ {"-scale", "*load.minScale", XrmoptionSepArg, NULL},
+ {"-update", "*load.update", XrmoptionSepArg, NULL},
+ {"-hl", "*load.highlight", XrmoptionSepArg, NULL},
+ {"-highlight", "*load.highlight", XrmoptionSepArg, NULL},
+ {"-label", "*label.label", XrmoptionSepArg, NULL},
+ {"-nolabel", "*showLabel", XrmoptionNoArg, "False"},
+ {"-lights", "*useLights", XrmoptionNoArg, "True"},
+ {"-jumpscroll", "*load.jumpScroll", XrmoptionSepArg, NULL},
+ {"-remotehost", "*remoteHost", XrmoptionSepArg, NULL},
+ {"-remoteport", "*remotePort", XrmoptionSepArg, NULL},
+ {"-unreach", "*unreachColor", XrmoptionSepArg, NULL},
+};
+
+/*
+ * The structure containing the resource information for the
+ * Xload application resources.
+ */
+
+#define Offset(field) (XtOffsetOf(XLoadResources, field))
+
+static XtResource my_resources[] = {
+ {"showLabel", XtCBoolean, XtRBoolean, sizeof(Boolean),
+ Offset(show_label), XtRImmediate, (XtPointer) TRUE},
+ {"useLights", XtCBoolean, XtRBoolean, sizeof(Boolean),
+ Offset(use_lights), XtRImmediate, (XtPointer) FALSE},
+ {"remoteHost", "RemoteHost", XtRString, sizeof(char *),
+ Offset(remote_host), XtRString, (XtPointer) NULL},
+ {"remotePort", "RemotePort", XtRString, sizeof(char *),
+ Offset(remote_port), XtRString, (XtPointer) NULL},
+ {"unreachColor", "UnreachColor", XtRPixel, sizeof(Pixel),
+ Offset(unreach_color), XtRPixel, XtDefaultBackground}
+};
+
+#undef Offset
+
+static XLoadResources resources;
+
+static XtActionsRec xload_actions[] = {
+ { "quit", quit },
+};
+static Atom wm_delete_window;
+static int light_update = 10 * 1000;
+
+/*
+ * Exit with message describing command line format.
+ */
+
+void usage()
+{
+ fprintf (stderr, "usage: %s [-options ...]\n\n", ProgramName);
+ fprintf (stderr, "where options include:\n");
+ fprintf (stderr,
+ " -display dpy X server on which to display\n");
+ fprintf (stderr,
+ " -geometry geom size and location of window\n");
+ fprintf (stderr,
+ " -fn font font to use in label\n");
+ fprintf (stderr,
+ " -scale number minimum number of scale lines\n");
+ fprintf (stderr,
+ " -update seconds interval between updates\n");
+ fprintf (stderr,
+ " -label string annotation text\n");
+ fprintf (stderr,
+ " -bg color background color\n");
+ fprintf (stderr,
+ " -fg color graph color\n");
+ fprintf (stderr,
+ " -hl color scale and text color\n");
+ fprintf (stderr,
+ " -unreach color background color while host unreachable\n");
+ fprintf (stderr,
+ " -nolabel removes the label from above the chart\n");
+ fprintf (stderr,
+ " -jumpscroll value number of pixels to scroll on overflow\n");
+ fprintf (stderr,
+ " -remotehost hostname read the load average from a remote host\n");
+ fprintf (stderr,
+ " -remoteport port specify port to read load average from\n");
+
+ fprintf (stderr, "\n");
+ exit(1);
+}
+
+void main(argc, argv)
+ int argc;
+ char **argv;
+{
+ XtAppContext app_con;
+ Widget toplevel, load, pane, label_wid, load_parent;
+ Arg args[1];
+ Pixmap icon_pixmap = None;
+ char *label, host[256];
+ int i;
+
+ ProgramName = argv[0];
+
+ /* For security reasons, we ought to reset our uid/gid after doing
+ the necessary system initialization and before calling any X
+ routines. Therefore we do the local init even if we don't really
+ need it. Buggy, yes... blame the ones who designed their system so
+ reading the load average is a privileged operation... */
+ LocalInitLoadPoint();
+ setgid(getgid()); /* reset gid first while still (maybe) root */
+ setuid(getuid());
+
+ toplevel = XtAppInitialize(&app_con, "XLoad", options, XtNumber(options),
+ &argc, argv, NULL, NULL, (Cardinal) 0);
+ if (argc != 1) usage();
+
+ XtGetApplicationResources( toplevel, (XtPointer) &resources,
+ my_resources, XtNumber(my_resources),
+ NULL, (Cardinal) 0);
+
+ remote_host = resources.remote_host;
+ remote_port = resources.remote_port;
+
+ InitLoadPoint();
+
+ if (resources.use_lights)
+ {
+ char name[1024];
+ XrmString type;
+ XrmValue db_value;
+ XrmValue int_value;
+ Bool found = False;
+
+ (void) sprintf (name, "%s.paned.load.update", XtName(toplevel));
+ found = XrmGetResource (XtScreenDatabase(XtScreen(toplevel)),
+ name, "XLoad.Paned.StripChart.Interval",
+ &type, &db_value);
+ if (found) {
+ int_value.size = sizeof(int);
+ int_value.addr = (XPointer) &light_update;
+ found = XtConvertAndStore(toplevel, type, &db_value, XtRInt,
+ &int_value);
+ if (found) light_update *= 1000;
+ }
+ ClearLights (XtDisplay (toplevel));
+ SetLights ((XtPointer) toplevel, (XtIntervalId *) 0);
+ }
+ else
+ {
+ /*
+ * This is a hack so that f.delete will do something useful in this
+ * single-window application.
+ */
+ XtAppAddActions (app_con, xload_actions, XtNumber(xload_actions));
+ XtOverrideTranslations(toplevel,
+ XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()"));
+
+ XtSetArg (args[0], XtNiconPixmap, &icon_pixmap);
+ XtGetValues(toplevel, args, ONE);
+ if (icon_pixmap == None) {
+ XtSetArg(args[0], XtNiconPixmap,
+ XCreateBitmapFromData(XtDisplay(toplevel),
+ XtScreen(toplevel)->root,
+ (char *)xload_bits,
+ xload_width, xload_height));
+ XtSetValues (toplevel, args, ONE);
+ }
+
+ if (resources.show_label) {
+ pane = XtCreateManagedWidget ("paned", panedWidgetClass,
+ toplevel, NULL, ZERO);
+
+ label_wid = XtCreateManagedWidget ("label", labelWidgetClass,
+ pane, NULL, ZERO);
+
+ switch_widget[1].w = label_wid;
+ switch_count = 2;
+
+ XtSetArg (args[0], XtNlabel, &label);
+ XtGetValues(label_wid, args, ONE);
+
+ if ( strcmp("label", label) == 0 ) {
+ if ( remote_host ) {
+ strcpy(host, remote_host);
+ } else {
+#ifdef AMOEBA
+ char *s;
+ char *getenv();
+
+ host[255] = '\0';
+ if ((s = getenv("XLOAD_HOST")) != NULL) {
+ strncpy(host, s, 255);
+ } else if ((s = getenv("RUN_SERVER")) != NULL) {
+ /* specific runserver specified; use its name */
+ strncpy(host, s, 255);
+
+ { /* if the last component is ".run", remove it */
+ char *slash = strrchr(host, '/');
+ if (slash != NULL && strcmp(slash + 1, ".run") == 0) {
+ *slash = '\0';
+ }
+ }
+ } else {
+ (void) XmuGetHostname (host, 255); /* "amoeba" */
+ }
+#else
+ (void) XmuGetHostname (host, 255);
+#endif
+ }
+ XtSetArg (args[0], XtNlabel, host);
+ XtSetValues (label_wid, args, ONE);
+ }
+
+ load_parent = pane;
+ }
+ else {
+ load_parent = toplevel;
+ switch_count = 1;
+ }
+
+ load = XtCreateManagedWidget ("load", stripChartWidgetClass,
+ load_parent, NULL, ZERO);
+
+ switch_widget[0].w = load;
+
+ XtAddCallback(load, XtNgetValue, GetLoadPoint, NULL);
+
+ for ( i = 0 ; i < switch_count ; i++ ) {
+ XtSetArg (args[0], XtNbackground, &switch_widget[i].reach_color);
+ XtGetValues(switch_widget[i].w, args, ONE);
+ switch_widget[i].unreach_color = resources.unreach_color;
+ if ( switch_widget[i].reach_color != switch_widget[i].unreach_color )
+ switch_color = 1;
+ }
+
+ XtRealizeWidget (toplevel);
+ wm_delete_window = XInternAtom (XtDisplay(toplevel), "WM_DELETE_WINDOW",
+ False);
+ (void) XSetWMProtocols (XtDisplay(toplevel), XtWindow(toplevel),
+ &wm_delete_window, 1);
+ }
+ XtAppMainLoop(app_con);
+}
+
+static unsigned long current_leds;
+
+static void
+ClearLights (dpy)
+ Display *dpy;
+{
+ XKeyboardControl cntrl;
+
+ cntrl.led_mode = LedModeOff;
+ XChangeKeyboardControl (dpy, KBLedMode, &cntrl);
+ current_leds = 0;
+}
+
+static void
+SetLights (data, timer)
+ XtPointer data;
+ XtIntervalId *timer;
+{
+ Widget toplevel;
+ Display *dpy;
+ double value;
+ unsigned long new_leds, change, bit;
+ int i;
+ XKeyboardControl cntrl;
+
+ toplevel = (Widget) data;
+ dpy = XtDisplay (toplevel);
+ GetLoadPoint (toplevel, (XtPointer) 0, (XtPointer) &value);
+ new_leds = (1 << (int) (value + 0.1)) - 1;
+ change = new_leds ^ current_leds;
+ i = 1;
+ bit = 1;
+ while (current_leds != new_leds)
+ {
+ if (change & bit)
+ {
+ cntrl.led = i;
+ cntrl.led_mode = new_leds & bit ? LedModeOn : LedModeOff;
+ XChangeKeyboardControl (dpy, KBLed|KBLedMode, &cntrl);
+ current_leds ^= bit;
+ }
+ i++;
+ bit <<= 1;
+ }
+ XtAppAddTimeOut(XtWidgetToApplicationContext(toplevel), light_update,
+ SetLights, data);
+}
+
+static void quit (w, event, params, num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ Cardinal *num_params;
+{
+ if (event->type == ClientMessage &&
+ event->xclient.data.l[0] != wm_delete_window) {
+ XBell (XtDisplay(w), 0);
+ return;
+ }
+ if (resources.use_lights)
+ ClearLights (XtDisplay (w));
+ XtDestroyApplicationContext(XtWidgetToApplicationContext(w));
+ exit (0);
+}
+
+void setgoodcolor()
+{
+ int i;
+ Arg args[1];
+
+ if ( switch_color == 2 ) {
+ for ( i = 0 ; i < switch_count ; i++ ) {
+ XtSetArg(args[0], XtNbackground, switch_widget[i].reach_color);
+ XtSetValues(switch_widget[i].w, args, ONE);
+ }
+ switch_color = 1;
+ }
+}
+
+void setbadcolor()
+{
+ int i;
+ Arg args[1];
+
+ if ( switch_color == 1 ) {
+ for ( i = 0 ; i < switch_count ; i++ ) {
+ XtSetArg(args[0], XtNbackground, switch_widget[i].unreach_color);
+ XtSetValues(switch_widget[i].w, args, ONE);
+ }
+ switch_color = 2;
+ }
+}
diff --git a/xload.man b/xload.man
new file mode 100644
index 0000000..1544497
--- /dev/null
+++ b/xload.man
@@ -0,0 +1,113 @@
+.\" $XConsortium: xload.man,v 1.29 94/04/17 20:43:44 matt Exp $
+.TH XLOAD 1 "Release 6" "X Version 11"
+.SH NAME
+xload \- system load average display for X
+.SH SYNOPSIS
+.ta 6n
+\fBxload\fP [-\fItoolkitoption\fP ...] [-scale \fIinteger\fP] [-update \fIseconds\fP] [-hl \fIcolor\fP] [-highlight \fIcolor\fP]
+.br
+ [-remotehost \fIhost\fP] [-remoteport \fIport\fP]
+.br
+ [-jumpscroll \fIpixels\fP] [-label \fIstring\fP] [-nolabel] [-lights]
+.SH DESCRIPTION
+The
+.I xload
+program displays a periodically updating histogram of the system load average.
+.SH OPTIONS
+.PP
+.I Xload
+accepts all of the standard X Toolkit command line options (see \fIX(1)\fP).
+The order of the options in unimportant. \fIxload also accepts the
+following additional options:
+.PP
+.TP 8
+.B \-hl \fIcolor\fP or \-highlight \fIcolor\fP
+This option specifies the color of the scale lines.
+.TP 8
+.B \-jumpscroll \fPnumber of pixels\fP
+The number of pixels to shift the graph to the left when the graph
+reaches the right edge of the window. The default value is 1/2 the width
+of the current window. Smooth scrolling can be achieved by setting it to 1.
+.TP 8
+.B \-label \fIstring\fP
+The string to put into the label above the load average.
+.TP 8
+.B \-nolabel
+If this command line option is specified then no label will be
+displayed above the load graph.
+.TP 8
+.B \-lights
+When specified, this option causes
+.I xload
+to display the current load average by using the keyboard leds; for
+a load average of \fIn\fP, xload lights the first \fIn\fP keyboard leds.
+This option turns off the usual screen display.
+.TP 8
+.B \-scale \fIinteger\fP
+This option specifies the minimum number of tick marks in the histogram,
+where one division represents one load average point. If the load goes
+above this number, \fIxload\fP will create more divisions, but it will never
+use fewer than this number. The default is 1.
+.PP
+.TP 8
+.B \-update \fIseconds\fP
+This option specifies the interval in seconds at which \fIxload\fP
+updates its display. The minimum amount of time allowed between updates
+is 1 second. The default is 10.
+.TP 8
+.B \-remotehost \fIhostname\fP
+Try to get the load average from a remote host. The remote host must
+be running \fBloadavgd\fP.
+.TP 8
+.B \-remoteport \fIport\fP
+Specify which port \fBloadavgd\fP is running on on the remote host.
+.SH RESOURCES
+In addition to the resources available to each of the widgets used by
+\fIxload\fP there is one resource defined by the application itself.
+.TP 8
+.B showLabel (\fPclass\fB Boolean)
+If False then no label will be displayed.
+.SH WIDGETS
+In order to specify resources, it is useful to know the hierarchy of
+the widgets which compose \fIxload\fR. In the notation below,
+indentation indicates hierarchical structure. The widget class name
+is given first, followed by the widget instance name.
+.sp
+.nf
+.ta .5i 1.0i 1.5i 2.0i
+XLoad xload
+ Paned paned
+ Label label
+ StripChart load
+.fi
+.sp
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH FILES
+<XRoot>/lib/X11/app-defaults/XLoad - specifies required resources
+.SH SEE ALSO
+X(1), xrdb(1), mem(4), Athena StripChart Widget.
+.SH BUGS
+This program requires the ability to open and read the special system
+file \fI/dev/kmem\fP. Sites that do not allow general access to this file
+should make \fIxload\fP belong to the same group as \fI/dev/kmem\fP and
+turn on the \fIset group id\fP permission flag.
+.PP
+Reading /dev/kmem is inherently non-portable. Therefore, the routine
+used to read it (get_load.c) must be ported to each new operating system.
+.SH COPYRIGHT
+Copyright ([\d,\s]*) X Consortium
+.br
+See \fIX(1)\fP for a full statement of rights and permissions.
+.SH AUTHORS
+K. Shane Hartman (MIT-LCS) and Stuart A. Malone (MIT-LCS);
+.br
+with features added by Jim Gettys (MIT-Athena), Bob Scheifler (MIT-LCS),
+Tony Della Fera (MIT-Athena), and Chris Peterson (MIT-LCS).