[comp.sources.x] v06i038: xnetload, Patch1

stolcke@icsib12.Berkeley.EDU (Andreas Stolcke) (03/21/90)

Submitted-by: stolcke@icsib12.Berkeley.EDU (Andreas Stolcke)
Posting-number: Volume 6, Issue 38
Archive-name: xnetld/patch1

[ xnetload has appeared in this newsgroup before, but not the R4 version.
  this patch brings the R4 version up to date, but can't be applied to
  the previous version, so we're resetting to patch 1 (I guess)  --dan ]


The following is a patch to xnetload, patchlevel 0 (from the R4 distribution).
It allows the Sun RPC mechanism to be used to get the load from remote
machines, instead of the rwho database.

The patch contains a README file, a patch to be applied to the original
xnetload source, and a copy of the R3 Load widget, which is required
for compilation under R4, but wasn't included in the original distribution.

This patch is not official, but its posting was suggested by the original
author, J. Michael Berkley <jmberkey@watnow.waterloo.edu>.  It will probably
be incorporated in a future update, not to expected too soon, according to
the author.

Have fun!

Andreas

#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README.RUPRPC
#	RUPRPC.patch
#	X11/Load.c
#	X11/Load.c.dist
#	X11/Load.h
#	X11/LoadP.h
# This archive created: Mon Mar 19 17:07:43 1990
export PATH; PATH=/bin:$PATH
if test -f 'README.RUPRPC'
then
	echo shar: over-writing existing file "'README.RUPRPC'"
fi
cat << \SHAR_EOF > 'README.RUPRPC'

Changes to xnetload to use rup-like RPC for remote load:
=====================================================a=

By defining RUPRPC at compile time the getload function uses Sun's RPC
mechanism to obtain remote loads from rstatd(8). This is likely to be the
better alternative on systems where this service is available, since rwhod(8)
may have prohibitive impact on network load and is not run at
many sites for this reason.

Patches:

getload.c:

	With RUPRPC defined, getload uses a simple callrpc(). The details
	of the mechanism are gleaned from the rup(1) source.
	Note that xnetload expects getload to return the load value in
	rwhod format, hence the actual load value is multiplied by 100
	and truncated to a integer.

xnetload.c:

	Allow defining DEFREMUPDATE in the Makefile.

Imakefile:

	When compiling on Suns, the RPC-based remote load mechanism is
	enabled and the default update interval set to 5 seconds (same as
	for local load).

	A little recursive-make hack ensures that getload.c is compiled with
	Sun's cc compiler. gcc doesn't like some of the syntax in
	header files in /usr/include/rpc and /usr/include/rpcsvc.
	The CCOPTIONS definition in the recursive call to make may have to
	be patched to match the CCOPTIONS used for gcc (e.g., put in
	-f68881 if gcc uses -m68881).

	The old X11R3 Load widget code and header files are in subdirectory
	X11, and the Imakefile takes that into account.

Bugs:
	Still uses R3 Load widget.

	The callrpc() function used to perform the RPC does not allow
	timeout specification.  So when a machine is down or not running
	rstatd, xnetload will discover that only after a delay of several
	(tens of) seconds.  When monitoring more than one machine,
	all the displays will be slowed down by this delay.

					Andreas Stolcke
					stolcke@icsi.berkeley.edu
					2/21/90

SHAR_EOF
if test -f 'RUPRPC.patch'
then
	echo shar: over-writing existing file "'RUPRPC.patch'"
fi
cat << \SHAR_EOF > 'RUPRPC.patch'
*** Imakefile.dist	Tue Oct 10 08:06:25 1989
--- Imakefile	Wed Feb 21 12:27:04 1990
***************
*** 22,47 ****
  # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  #
  
  #
  # Since xnetload finds the local machine's load using the standard Load
  # widget stuff, it needs to be able to read kmem, i.e.  setgid kmem.  If
  # you do not want this, then define NOLOCAL
! #        DEFINES = -O -DNOLOCAL
  
!        INCLUDES = -I$(TOP) -I$(TOP)/X11
  
  # Dynix doesn't have -L option on load, but I have left changing the
  # XLIB specification up to individual sites.  Dynix and our Sun 3.5
  # don't come with a memcpy, so you'll have to add in whichever library
  # has memcpy.
! /* LOCAL_LIBRARIES = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB) */
! LOCAL_LIBRARIES = -L/usr/software/X11/lib -lXaw -lXmu -lXt -lX11
  
!            SRCS = xnetload.c getload.o
!            OBJS = xnetload.o getload.o
  
     INSTALLFLAGS = $(INSTKMEMFLAGS)
  
! all: xnetload
  
! SingleProgramTarget(xnetload,$(OBJS),,$(LOCAL_LIBRARIES))
--- 22,63 ----
  # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  #
  
+      COMPATFLAGS = -DXAW_BC
+ 
  #
  # Since xnetload finds the local machine's load using the standard Load
  # widget stuff, it needs to be able to read kmem, i.e.  setgid kmem.  If
  # you do not want this, then define NOLOCAL
! #if SunOSPlatform
!       RUPDEFINES = -DRUPRPC -DDEFREMUPDATE=5 /* -DDEBUGGING */
!    SYS_LIBRARIES = -lrpcsvc
! #endif
!          DEFINES = /* -DNOLOCAL */ $(RUPDEFINES)
  
! #       INCLUDES = -I$(TOP) -I$(TOP)/X11
  
  # Dynix doesn't have -L option on load, but I have left changing the
  # XLIB specification up to individual sites.  Dynix and our Sun 3.5
  # don't come with a memcpy, so you'll have to add in whichever library
  # has memcpy.
! LOCAL_LIBRARIES = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
  
!            SRCS = xnetload.c getload.c X11/Load.c
!            OBJS = xnetload.o getload.o Load.o
  
     INSTALLFLAGS = $(INSTKMEMFLAGS)
  
! ComplexProgramTarget(xnetload)
  
! Load.o:		X11/Load.c
! 		$(CC) -c $(CFLAGS) X11/Load.c
! 
! #if SunOSPlatform
! #if HasGcc	/* GCC is too picky about syntax in Sun RPC header files */
! getload.o:	getload.c
! 		@if [ "$(CC)" != cc ] ;\
! 		then $(MAKE) CC=cc CCOPTIONS= getload.o ;\
! 		else cmd="$(CC) -c $(CFLAGS) getload.c"; echo $$cmd; $$cmd ;\
! 		fi
! #endif
! #endif
*** getload.c.dist	Tue Oct 10 08:06:26 1989
--- getload.c	Wed Feb 21 13:21:55 1990
***************
*** 32,37 ****
--- 32,87 ----
  #include <sys/types.h>
  #include <sys/time.h>
  
+ #ifdef RUPRPC
+ #include <sys/param.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ #include <rpcsvc/rstat.h>
+ #include <rpc/rpc.h>
+ #include <rpc/pmap_clnt.h>
+ 
+ int
+ getload(host)
+ 	char *host;
+ {
+ 	enum clnt_stat err;
+ 	struct statstime sw;
+     
+ #ifdef DEBUGGING
+ 	fprintf(stderr, "xnetload: %s: ", host);
+ 	fflush(stderr);
+ #endif
+ 	err = (enum clnt_stat)callrpc(host, RSTATPROG, RSTATVERS_TIME,
+ 	    RSTATPROC_STATS, xdr_void, 0, xdr_statstime, &sw);
+ 	if (err != RPC_SUCCESS)
+ 	     if (err == RPC_PROGVERSMISMATCH) {
+ 		if (err = (enum clnt_stat)callrpc(host, RSTATPROG,
+ 		    RSTATVERS_SWTCH, RSTATPROC_STATS, xdr_void, 0,
+ 		    xdr_statsswtch, &sw)) {
+ #ifndef DEBUGGING
+ 			fprintf(stderr, "xnetload: %s: ", host);
+ #endif
+ 			clnt_perrno(err);
+ 			fprintf(stderr, "\n");
+ 			return( -1 );
+ 		}
+ 	}
+ 	else {
+ #ifndef DEBUGGING
+ 		fprintf(stderr, "xnetload: %s: ", host);
+ #endif
+ 		clnt_perrno(err);
+ 		fprintf(stderr, "\n");
+ 		return( -1 );
+ 	}
+ 
+ #ifdef DEBUGGING
+ 	fprintf(stderr, "%lf\n", (double)sw.avenrun[0]/FSCALE);
+ #endif
+ 	return( (double)sw.avenrun[0]/FSCALE * 100.0);
+ }
+ 
+ #else /* no RUPRPC */
  /* Dynix doesn't have an rwhod.h file, so here's the struct for that system */
  #ifdef sequent
  struct  outmp {
***************
*** 113,115 ****
--- 163,166 ----
      }
      return(0);		/* couldn't read load if here */
  }
+ #endif
SHAR_EOF
if test -f 'X11/Load.c'
then
	echo shar: over-writing existing file "'X11/Load.c'"
fi
cat << \SHAR_EOF > 'X11/Load.c'
#ifndef lint
static char Xrcsid[] = "$XConsortium: Load.c,v 1.44 88/10/17 15:11:38 jim Exp $";
#endif

/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#ifdef apollo
#include "/sys/ins/base.ins.c"
#include "/sys/ins/time.ins.c"
typedef struct {
	short		proc2_$state_t; /* 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;

std_$call void proc1_$get_cput();
std_$call void proc1_$get_info();
#endif /* apollo */

#include <X11/IntrinsicP.h>
#include <X11/Xos.h>
#include <X11/StringDefs.h>
#include <X11/Xmu.h>
#include <stdio.h>

#ifndef macII
#ifndef apollo
#ifndef LOADSTUB
#include <nlist.h>
#endif /* LOADSTUB */
#endif /* apollo */
#endif /* macII */

#ifdef sun
#include <sys/param.h>
#endif
#ifdef NeXT
#include <sys/param.h>
#endif
#ifdef mips
#include <sys/fixpoint.h>
#endif
#ifdef sequent
#include <sys/vm.h>
#endif /* sequent */
#include <X11/LoadP.h>
#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 UTEK
#define FSCALE	100.0
#endif
#ifdef sequent
#define FSCALE	1000.0
#endif

extern long lseek();
extern void exit();

/* Private Data */

static void GetLoadPoint();
static XtCallbackProc getLoadProc = GetLoadPoint;

#define offset(field) XtOffset(LoadWidget,load.field)
#define goffset(field) XtOffset(Widget,core.field)

static Dimension defDim = 120;
static int defInterval = 5;
static int defScale = 1;

static XtResource resources[] = {
    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
	goffset(width), XtRDimension, (caddr_t)&defDim},
    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
	goffset(height), XtRDimension, (caddr_t)&defDim},
    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
	goffset(background_pixel), XtRString, "White"},
    {XtNupdate, XtCInterval, XtRInt, sizeof(int),
        offset(update), XtRInt, (caddr_t)&defInterval},
    {XtNscale, XtCScale, XtRInt, sizeof(int),
        offset(scale), XtRInt, (caddr_t)&defScale},
    {XtNminScale, XtCScale, XtRInt, sizeof(int),
        offset(min_scale), XtRInt, (caddr_t)&defScale},
    {XtNlabel, XtCLabel, XtRString, sizeof(char *),
        offset(text), XtRString, NULL},
    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
        offset(fgpixel), XtRString, "Black"},
    {XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel),
        offset(hipixel), XtRString, "Black"},
    {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
        offset(font), XtRString, XtDefaultFont},
    {XtNgetLoadProc, XtCCallback, XtRCallback, sizeof(caddr_t),
        offset(get_load), XtRFunction, (caddr_t)&getLoadProc},
    {XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
	offset (reverse_video), XtRString, "FALSE"},
};

#undef offset
#undef goffset

static void ClassInitialize();
static void Initialize(), Realize(), Destroy(), Redisplay();
static Boolean SetValues();
static int repaint_window();

LoadClassRec loadClassRec = {
    { /* core fields */
    /* superclass		*/	&widgetClassRec,
    /* class_name		*/	"Load",
    /* size			*/	sizeof(LoadRec),
    /* class_initialize		*/	ClassInitialize,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	FALSE,
    /* initialize		*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	Realize,
    /* actions			*/	NULL,
    /* num_actions		*/	0,
    /* resources		*/	resources,
    /* num_resources		*/	XtNumber(resources),
    /* xrm_class		*/	NULL,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	Destroy,
    /* resize			*/	NULL,
    /* expose			*/	Redisplay,
    /* set_values		*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	NULL,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	NULL,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	NULL,
    /* query_geometry		*/	XtInheritQueryGeometry,
    /* display_accelerator	*/	XtInheritDisplayAccelerator,
    /* extension		*/	NULL
    }
};

WidgetClass loadWidgetClass = (WidgetClass) &loadClassRec;

/****************************************************************
 *
 * Private Procedures
 *
 ****************************************************************/

static void draw_it();

static void ClassInitialize()
{
    XtAddConverter( XtRFunction, XtRCallback, XmuCvtFunctionToCallback,
		    NULL, 0 );
}

/* ARGSUSED */
static void Initialize (greq, gnew)
    Widget greq, gnew;
{
    LoadWidget w = (LoadWidget)gnew;
    XtGCMask	valuemask;
    XGCValues	myXGCV;

    /*
     * set the colors if reverse video; these are the colors used:
     *
     *     background - paper		white
     *     foreground - text, ticks	black
     *     border - border		black (foreground)
     *
     * This doesn't completely work since the parent has already made up a 
     * border.  Sigh.
     */
    if (w->load.reverse_video) {
	Pixel fg = w->load.fgpixel;
	Pixel bg = w->core.background_pixel;

	if (w->core.border_pixel == fg) w->core.border_pixel = bg;
	if (w->load.hipixel == w->load.fgpixel) w->load.hipixel = bg;
	w->load.fgpixel = bg;
	w->core.background_pixel = fg;
    }

    valuemask = GCForeground | GCBackground;
    myXGCV.foreground = w->load.fgpixel;
    if (w->load.font) {
      myXGCV.font = w->load.font->fid;
      valuemask |= GCFont;
    }
    myXGCV.background = w->core.background_pixel;
    w->load.fgGC = XtGetGC(gnew, valuemask, &myXGCV);
    myXGCV.foreground = w->load.hipixel;
    w->load.hiGC = XtGetGC(gnew, valuemask, &myXGCV);

    /*
     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
     * returns the curently contained font.
     */
    if (w->load.font == NULL)
      w->load.font = XQueryFont (XtDisplay (w),
      			XGContextFromGC (DefaultGCOfScreen (XtScreen (w))));

    if (w->load.update > 0)
        w->load.interval_id =
	    XtAddTimeOut(w->load.update*1000, draw_it, (caddr_t)gnew);
    else
        w->load.interval_id = 0;

    w->load.interval = 0;
    w->load.max_value = 0.0;
}
 
static void Realize (gw, valueMask, attrs)
     Widget gw;
     XtValueMask *valueMask;
     XSetWindowAttributes *attrs;
{
     XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
		     *valueMask, attrs );
}

static void Destroy (gw)
     Widget gw;
{
     LoadWidget w = (LoadWidget)gw;
     if (w->load.interval_id) XtRemoveTimeOut (w->load.interval_id);
     XtDestroyGC (w->load.fgGC);
     XtDestroyGC (w->load.hiGC);
}

/* ARGSUSED */
static void Redisplay(gw, event, region)
     Widget gw;
     XEvent *event;
     Region region;
{
     (void) repaint_window ((LoadWidget)gw, event->xexpose.x,
			    event->xexpose.width);
}

/* ARGSUSED */
static void draw_it(client_data, id)
     caddr_t client_data;
     XtIntervalId id;		/* unused */
{
        LoadWidget w = (LoadWidget)client_data;
	double value;

	if (w->load.update > 0)
	    w->load.interval_id =
		XtAddTimeOut(w->load.update*1000, draw_it, (caddr_t)w);

	if (w->load.interval >= w->core.width) {
	    XClearWindow(XtDisplay(w), XtWindow(w));
	    w->load.interval = repaint_window(w, 0, w->core.width);
	}

	/* Get the value, stash the point and draw corresponding line. */

	XtCallCallbacks( (Widget)w, XtNgetLoadProc, (caddr_t)&value );

	/* Keep w->load.max_value up to date, and if this data point is off the
	   graph, change the scale to make it fit. */
	if (value > w->load.max_value) {
	    w->load.max_value = value;
	    if (w->load.max_value > w->load.scale) {
		w->load.scale = ((int)w->load.max_value) + 1;
		XClearWindow(XtDisplay(w), XtWindow(w));
		w->load.interval = repaint_window(w, 0, w->core.width);
	    }
	}

	w->load.valuedata[w->load.interval] = value;
	if (XtIsRealized((Widget)w)) {
	    XDrawLine(XtDisplay(w), XtWindow(w), w->load.fgGC,
		  w->load.interval, w->core.height, w->load.interval, 
		    (int)(w->core.height - (w->core.height * value)
/w->load.scale));
	    XFlush(XtDisplay(w));		    /* Flush output buffers */
	}
	w->load.interval++;		    /* Next point */
} /* draw_it */

/* Blts data according to current size, then redraws the load average window.
 * Next represents the number of valid points in data.  Returns the (possibly)
 * adjusted value of next.  If next is 0, this routine draws an empty window
 * (scale - 1 lines for graph).  If next is less than the current window width,
 * the returned value is identical to the initial value of next and data is
 * unchanged.  Otherwise keeps half a window's worth of data.  If data is
 * changed, then w->load.max_value is updated to reflect the largest data point.
 */

static int repaint_window(w, left, width)
    LoadWidget w;
    int left, width;
{
    register int i, j;
    register int next = w->load.interval;
    int scale = w->load.scale;
    extern void bcopy();

    if (next >= w->core.width) {
	j = w->core.width >> 1;
	bcopy((char *)(w->load.valuedata + next - j),
	      (char *)(w->load.valuedata), j * sizeof(double));
	next = j;
	/* Since we just lost some data, recompute the w->load.max_value. */
	w->load.max_value = 0.0;
	for (i = 0; i < next; i++) {
	    if (w->load.valuedata[i] > w->load.max_value) 
	      w->load.max_value = w->load.valuedata[i];
	}
	left = 0;
	width = next; 
    }

    /* Compute the minimum scale required to graph the data, but don't go
       lower than min_scale. */
    if (w->load.interval != 0 || scale <= (int)w->load.max_value)
      scale = ((int) (w->load.max_value)) + 1;
    if (scale < w->load.min_scale)
      scale = w->load.min_scale;
    if (scale != w->load.scale) {
      w->load.scale = scale;
      left = 0;
      width = next;
      if (XtIsRealized ((Widget) w)) {
	XClearWindow (XtDisplay (w), XtWindow (w));
      }
    }

    if (XtIsRealized((Widget)w)) {
	Display *dpy = XtDisplay(w);
	Window win = XtWindow(w);

	if (w->load.text) {
	    /* Print hostname */
	    XDrawString(dpy, win, w->load.hiGC, 2, 
	         2 + w->load.font->ascent, w->load.text, strlen(w->load.text));
	}

	/* Draw graph reference lines */
	for (i = 1; i < w->load.scale; i++) {
	    j = (i * w->core.height) / w->load.scale;
	    XDrawLine(dpy, win, w->load.hiGC, 0, j,
		      (int)w->core.width, j);
	}

	if (next < (width += left)) width = next;
	/* Draw data point lines. */
	for (i = left; i < width; i++)
	    XDrawLine(dpy, win, w->load.fgGC, i, w->core.height,
		  i, (int)(w->core.height-(w->load.valuedata[i] * w->core.height)
			  /w->load.scale));
        }

    return(next);
}

#if apollo
/* ARGSUSED */
static void GetLoadPoint( w, closure, call_data )
     Widget	w;		/* unused */
     caddr_t	closure;	/* unused */
     caddr_t	call_data;	/* pointer to (double) return value */
{
     static Bool    firstTime = TRUE;
     static int     lastNullCpu;
     static int     lastClock;
     time_$clock_t  timeNow;
     double         temp;
     proc1_$info_t  info;
     status_$t      st;

     proc1_$get_info( (short) 2, info, st );
     time_$clock( timeNow );

     if (firstTime)
     {
     	*(double *)call_data = 1.0;
         firstTime = FALSE;
     }
     else {
         temp = info.cpu_total.low32 - lastNullCpu;
     	*(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock);
     }

     lastClock = timeNow.low32;
     lastNullCpu = info.cpu_total.low32;
}
#else
#ifdef LOADSTUB

/* ARGSUSED */
static void GetLoadPoint( w, closure, call_data )
     Widget	w;		/* unused */
     caddr_t	closure;	/* unused */
     caddr_t	call_data;	/* pointer to (double) return value */
{
	*(double *)call_data = 1.0;
}

#else /* LOADSTUB */

#ifndef KMEM_FILE
#define KMEM_FILE "/dev/kmem"
#endif

#ifndef KERNEL_FILE
#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 mips
# ifdef SYSTYPE_SYSV
# define KERNEL_FILE "/unix"
# else
# define KERNEL_FILE "/vmunix"
# endif /* SYSTYPE_SYSV */
#endif /* mips */
#ifdef sequent
#define KERNEL_FILE "/dynix"
#endif /* sequent */

/*
 * provide default for everyone else
 */
#ifndef KERNEL_FILE
#define KERNEL_FILE "/vmunix"
#endif /* KERNEL_FILE */
#endif /* KERNEL_FILE */


#ifndef KERNEL_LOAD_VARIABLE
#ifdef CRAY
#define KERNEL_LOAD_VARIABLE "avenrun"
#undef n_type
#define n_type n_value
#endif /* CRAY */
#ifdef hpux
#ifdef hp9000s800
#define KERNEL_LOAD_VARIABLE "avenrun"
#endif /* hp9000s800 */
#endif /* hpux */
#ifdef mips
# ifdef SYSTYPE_SYSV
# define KERNEL_LOAD_VARIABLE "avenrun"
# else
# define KERNEL_LOAD_VARIABLE "_avenrun"
# endif /* SYSTYPE_SYSV */
#endif /* mips */
#ifdef sequent
#define KERNEL_FILE "/dynix"
#endif /* sequent */
/*
 * provide default for everyone else
 */
#ifndef KERNEL_LOAD_VARIABLE
#define KERNEL_LOAD_VARIABLE "_avenrun"
#endif /* KERNEL_LOAD_VARIABLE */
#endif /* KERNEL_LOAD_VARIABLE */

#ifdef macII
static struct var v;
static struct nlist nl[2];
static struct lavnum vec[3];
#else /* not macII */
#ifdef NeXT
static struct nlist namelist[] = {	    /* namelist for vmunix grubbing */
#define LOADAV 0
    {{KERNEL_LOAD_VARIABLE}},
    {{0}}
};
#else
static struct nlist namelist[] = {	    /* namelist for vmunix grubbing */
#define LOADAV 0
    {KERNEL_LOAD_VARIABLE},
    {0}
};
#endif
#endif /* macII */


/* ARGSUSED */
static void GetLoadPoint( w, closure, call_data )
     Widget	w;		/* unused */
     caddr_t	closure;	/* unused */
     caddr_t	call_data;	/* pointer to (double) return value */
{
  	double *loadavg = (double *)call_data;
	static int init = 0;
	static kmem;
	static long loadavg_seek;
#ifdef macII
        extern nlist();

        if(!init)   {
            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;
            }
            init = 1;
        }
#else /* not macII */
	extern void nlist();
	
	if(!init)   {
	    nlist( KERNEL_FILE, namelist);
	    if (namelist[LOADAV].n_type == 0){
		xload_error("cannot get name list from", KERNEL_FILE);
		exit(-1);
	    }
	    loadavg_seek = namelist[LOADAV].n_value;
# if defined(mips) && defined(SYSTYPE_SYSV)
	    loadavg_seek &= 0x7fffffff;
# endif /* mips && SYSTYPE_SYSV */
	    kmem = open(KMEM_FILE, O_RDONLY);
	    if (kmem < 0) xload_error("cannot open", KMEM_FILE);
	    init = 1;
	}
	

	(void) lseek(kmem, loadavg_seek, 0);
#endif /* macII */
#if defined(sun) || defined (UTEK) || defined(sequent) || defined(NeXT)
	{
		long temp;
		(void) read(kmem, (char *)&temp, sizeof(long));
		*loadavg = (double)temp/FSCALE;
	}
#else /* else not sun */
# ifdef macII
        {
                lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
                read(kmem, vec, 3*sizeof(struct lavnum));
                *loadavg = fxtod(0);
        }
# else /* else not macII */
#  ifdef mips
	{
		fix temp;
		(void) read(kmem, (char *)&temp, sizeof(fix));
		*loadavg = FIX_TO_DBL(temp);
	}
#  else /* not mips */
	(void) read(kmem, (char *)loadavg, sizeof(double));
#  endif /* mips */
# endif /* macII */
#endif /* sun */
	return;
}
#endif /* LOADSTUB */
#endif /* apollo */

static xload_error(str1, str2)
char *str1, *str2;
{
    (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
    exit(-1);
}

/* ARGSUSED */
static Boolean SetValues (current, request, new)
    Widget current, request, new;
{
    LoadWidget old = (LoadWidget)current;
    LoadWidget w = (LoadWidget)new;
    if (w->load.update != old->load.update) {
	XtRemoveTimeOut (old->load.interval_id);
	w->load.interval_id =
	    XtAddTimeOut(w->load.update*1000, draw_it, (caddr_t)w);
    }

    return( FALSE );
}
SHAR_EOF
if test -f 'X11/Load.c.dist'
then
	echo shar: over-writing existing file "'X11/Load.c.dist'"
fi
cat << \SHAR_EOF > 'X11/Load.c.dist'
#ifndef lint
static char Xrcsid[] = "$XConsortium: Load.c,v 1.44 88/10/17 15:11:38 jim Exp $";
#endif

/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#ifdef apollo
#include "/sys/ins/base.ins.c"
#include "/sys/ins/time.ins.c"
typedef struct {
	short		proc2_$state_t; /* 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;

std_$call void proc1_$get_cput();
std_$call void proc1_$get_info();
#endif /* apollo */

#include <X11/IntrinsicP.h>
#include <X11/Xos.h>
#include <X11/StringDefs.h>
#include <X11/Xmu.h>
#include <stdio.h>

#ifndef macII
#ifndef apollo
#ifndef LOADSTUB
#include <nlist.h>
#endif /* LOADSTUB */
#endif /* apollo */
#endif /* macII */

#ifdef sun
#include <sys/param.h>
#endif
#ifdef mips
#include <sys/fixpoint.h>
#endif
#ifdef sequent
#include <sys/vm.h>
#endif /* sequent */
#include <X11/LoadP.h>
#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 UTEK
#define FSCALE	100.0
#endif
#ifdef sequent
#define FSCALE	1000.0
#endif

extern long lseek();
extern void exit();

/* Private Data */

static void GetLoadPoint();
static XtCallbackProc getLoadProc = GetLoadPoint;

#define offset(field) XtOffset(LoadWidget,load.field)
#define goffset(field) XtOffset(Widget,core.field)

static Dimension defDim = 120;
static int defInterval = 5;
static int defScale = 1;

static XtResource resources[] = {
    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
	goffset(width), XtRDimension, (caddr_t)&defDim},
    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
	goffset(height), XtRDimension, (caddr_t)&defDim},
    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
	goffset(background_pixel), XtRString, "White"},
    {XtNupdate, XtCInterval, XtRInt, sizeof(int),
        offset(update), XtRInt, (caddr_t)&defInterval},
    {XtNscale, XtCScale, XtRInt, sizeof(int),
        offset(scale), XtRInt, (caddr_t)&defScale},
    {XtNminScale, XtCScale, XtRInt, sizeof(int),
        offset(min_scale), XtRInt, (caddr_t)&defScale},
    {XtNlabel, XtCLabel, XtRString, sizeof(char *),
        offset(text), XtRString, NULL},
    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
        offset(fgpixel), XtRString, "Black"},
    {XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel),
        offset(hipixel), XtRString, "Black"},
    {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
        offset(font), XtRString, XtDefaultFont},
    {XtNgetLoadProc, XtCCallback, XtRCallback, sizeof(caddr_t),
        offset(get_load), XtRFunction, (caddr_t)&getLoadProc},
    {XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean),
	offset (reverse_video), XtRString, "FALSE"},
};

#undef offset
#undef goffset

static void ClassInitialize();
static void Initialize(), Realize(), Destroy(), Redisplay();
static Boolean SetValues();
static int repaint_window();

LoadClassRec loadClassRec = {
    { /* core fields */
    /* superclass		*/	&widgetClassRec,
    /* class_name		*/	"Load",
    /* size			*/	sizeof(LoadRec),
    /* class_initialize		*/	ClassInitialize,
    /* class_part_initialize	*/	NULL,
    /* class_inited		*/	FALSE,
    /* initialize		*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	Realize,
    /* actions			*/	NULL,
    /* num_actions		*/	0,
    /* resources		*/	resources,
    /* num_resources		*/	XtNumber(resources),
    /* xrm_class		*/	NULL,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	Destroy,
    /* resize			*/	NULL,
    /* expose			*/	Redisplay,
    /* set_values		*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	NULL,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	NULL,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	NULL,
    /* query_geometry		*/	XtInheritQueryGeometry,
    /* display_accelerator	*/	XtInheritDisplayAccelerator,
    /* extension		*/	NULL
    }
};

WidgetClass loadWidgetClass = (WidgetClass) &loadClassRec;

/****************************************************************
 *
 * Private Procedures
 *
 ****************************************************************/

static void draw_it();

static void ClassInitialize()
{
    XtAddConverter( XtRFunction, XtRCallback, XmuCvtFunctionToCallback,
		    NULL, 0 );
}

/* ARGSUSED */
static void Initialize (greq, gnew)
    Widget greq, gnew;
{
    LoadWidget w = (LoadWidget)gnew;
    XtGCMask	valuemask;
    XGCValues	myXGCV;

    /*
     * set the colors if reverse video; these are the colors used:
     *
     *     background - paper		white
     *     foreground - text, ticks	black
     *     border - border		black (foreground)
     *
     * This doesn't completely work since the parent has already made up a 
     * border.  Sigh.
     */
    if (w->load.reverse_video) {
	Pixel fg = w->load.fgpixel;
	Pixel bg = w->core.background_pixel;

	if (w->core.border_pixel == fg) w->core.border_pixel = bg;
	if (w->load.hipixel == w->load.fgpixel) w->load.hipixel = bg;
	w->load.fgpixel = bg;
	w->core.background_pixel = fg;
    }

    valuemask = GCForeground | GCBackground;
    myXGCV.foreground = w->load.fgpixel;
    if (w->load.font) {
      myXGCV.font = w->load.font->fid;
      valuemask |= GCFont;
    }
    myXGCV.background = w->core.background_pixel;
    w->load.fgGC = XtGetGC(gnew, valuemask, &myXGCV);
    myXGCV.foreground = w->load.hipixel;
    w->load.hiGC = XtGetGC(gnew, valuemask, &myXGCV);

    /*
     * Note that the second argument is a GCid -- QueryFont accepts a GCid and
     * returns the curently contained font.
     */
    if (w->load.font == NULL)
      w->load.font = XQueryFont (XtDisplay (w),
      			XGContextFromGC (DefaultGCOfScreen (XtScreen (w))));

    if (w->load.update > 0)
        w->load.interval_id =
	    XtAddTimeOut(w->load.update*1000, draw_it, (caddr_t)gnew);
    else
        w->load.interval_id = 0;

    w->load.interval = 0;
    w->load.max_value = 0.0;
}
 
static void Realize (gw, valueMask, attrs)
     Widget gw;
     XtValueMask *valueMask;
     XSetWindowAttributes *attrs;
{
     XtCreateWindow( gw, (unsigned)InputOutput, (Visual *)CopyFromParent,
		     *valueMask, attrs );
}

static void Destroy (gw)
     Widget gw;
{
     LoadWidget w = (LoadWidget)gw;
     if (w->load.interval_id) XtRemoveTimeOut (w->load.interval_id);
     XtDestroyGC (w->load.fgGC);
     XtDestroyGC (w->load.hiGC);
}

/* ARGSUSED */
static void Redisplay(gw, event, region)
     Widget gw;
     XEvent *event;
     Region region;
{
     (void) repaint_window ((LoadWidget)gw, event->xexpose.x,
			    event->xexpose.width);
}

/* ARGSUSED */
static void draw_it(client_data, id)
     caddr_t client_data;
     XtIntervalId id;		/* unused */
{
        LoadWidget w = (LoadWidget)client_data;
	double value;

	if (w->load.update > 0)
	    w->load.interval_id =
		XtAddTimeOut(w->load.update*1000, draw_it, (caddr_t)w);

	if (w->load.interval >= w->core.width) {
	    XClearWindow(XtDisplay(w), XtWindow(w));
	    w->load.interval = repaint_window(w, 0, w->core.width);
	}

	/* Get the value, stash the point and draw corresponding line. */

	XtCallCallbacks( (Widget)w, XtNgetLoadProc, (caddr_t)&value );

	/* Keep w->load.max_value up to date, and if this data point is off the
	   graph, change the scale to make it fit. */
	if (value > w->load.max_value) {
	    w->load.max_value = value;
	    if (w->load.max_value > w->load.scale) {
		w->load.scale = ((int)w->load.max_value) + 1;
		XClearWindow(XtDisplay(w), XtWindow(w));
		w->load.interval = repaint_window(w, 0, w->core.width);
	    }
	}

	w->load.valuedata[w->load.interval] = value;
	if (XtIsRealized((Widget)w)) {
	    XDrawLine(XtDisplay(w), XtWindow(w), w->load.fgGC,
		  w->load.interval, w->core.height, w->load.interval, 
		    (int)(w->core.height - (w->core.height * value)
/w->load.scale));
	    XFlush(XtDisplay(w));		    /* Flush output buffers */
	}
	w->load.interval++;		    /* Next point */
} /* draw_it */

/* Blts data according to current size, then redraws the load average window.
 * Next represents the number of valid points in data.  Returns the (possibly)
 * adjusted value of next.  If next is 0, this routine draws an empty window
 * (scale - 1 lines for graph).  If next is less than the current window width,
 * the returned value is identical to the initial value of next and data is
 * unchanged.  Otherwise keeps half a window's worth of data.  If data is
 * changed, then w->load.max_value is updated to reflect the largest data point.
 */

static int repaint_window(w, left, width)
    LoadWidget w;
    int left, width;
{
    register int i, j;
    register int next = w->load.interval;
    int scale = w->load.scale;
    extern void bcopy();

    if (next >= w->core.width) {
	j = w->core.width >> 1;
	bcopy((char *)(w->load.valuedata + next - j),
	      (char *)(w->load.valuedata), j * sizeof(double));
	next = j;
	/* Since we just lost some data, recompute the w->load.max_value. */
	w->load.max_value = 0.0;
	for (i = 0; i < next; i++) {
	    if (w->load.valuedata[i] > w->load.max_value) 
	      w->load.max_value = w->load.valuedata[i];
	}
	left = 0;
	width = next; 
    }

    /* Compute the minimum scale required to graph the data, but don't go
       lower than min_scale. */
    if (w->load.interval != 0 || scale <= (int)w->load.max_value)
      scale = ((int) (w->load.max_value)) + 1;
    if (scale < w->load.min_scale)
      scale = w->load.min_scale;
    if (scale != w->load.scale) {
      w->load.scale = scale;
      left = 0;
      width = next;
      if (XtIsRealized ((Widget) w)) {
	XClearWindow (XtDisplay (w), XtWindow (w));
      }
    }

    if (XtIsRealized((Widget)w)) {
	Display *dpy = XtDisplay(w);
	Window win = XtWindow(w);

	if (w->load.text) {
	    /* Print hostname */
	    XDrawString(dpy, win, w->load.hiGC, 2, 
	         2 + w->load.font->ascent, w->load.text, strlen(w->load.text));
	}

	/* Draw graph reference lines */
	for (i = 1; i < w->load.scale; i++) {
	    j = (i * w->core.height) / w->load.scale;
	    XDrawLine(dpy, win, w->load.hiGC, 0, j,
		      (int)w->core.width, j);
	}

	if (next < (width += left)) width = next;
	/* Draw data point lines. */
	for (i = left; i < width; i++)
	    XDrawLine(dpy, win, w->load.fgGC, i, w->core.height,
		  i, (int)(w->core.height-(w->load.valuedata[i] * w->core.height)
			  /w->load.scale));
        }

    return(next);
}

#if apollo
/* ARGSUSED */
static void GetLoadPoint( w, closure, call_data )
     Widget	w;		/* unused */
     caddr_t	closure;	/* unused */
     caddr_t	call_data;	/* pointer to (double) return value */
{
     static Bool    firstTime = TRUE;
     static int     lastNullCpu;
     static int     lastClock;
     time_$clock_t  timeNow;
     double         temp;
     proc1_$info_t  info;
     status_$t      st;

     proc1_$get_info( (short) 2, info, st );
     time_$clock( timeNow );

     if (firstTime)
     {
     	*(double *)call_data = 1.0;
         firstTime = FALSE;
     }
     else {
         temp = info.cpu_total.low32 - lastNullCpu;
     	*(double *)call_data = 1.0 - temp / (timeNow.low32 - lastClock);
     }

     lastClock = timeNow.low32;
     lastNullCpu = info.cpu_total.low32;
}
#else
#ifdef LOADSTUB

/* ARGSUSED */
static void GetLoadPoint( w, closure, call_data )
     Widget	w;		/* unused */
     caddr_t	closure;	/* unused */
     caddr_t	call_data;	/* pointer to (double) return value */
{
	*(double *)call_data = 1.0;
}

#else /* LOADSTUB */

#ifndef KMEM_FILE
#define KMEM_FILE "/dev/kmem"
#endif

#ifndef KERNEL_FILE
#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 mips
# ifdef SYSTYPE_SYSV
# define KERNEL_FILE "/unix"
# else
# define KERNEL_FILE "/vmunix"
# endif /* SYSTYPE_SYSV */
#endif /* mips */
#ifdef sequent
#define KERNEL_FILE "/dynix"
#endif /* sequent */

/*
 * provide default for everyone else
 */
#ifndef KERNEL_FILE
#define KERNEL_FILE "/vmunix"
#endif /* KERNEL_FILE */
#endif /* KERNEL_FILE */


#ifndef KERNEL_LOAD_VARIABLE
#ifdef CRAY
#define KERNEL_LOAD_VARIABLE "avenrun"
#undef n_type
#define n_type n_value
#endif /* CRAY */
#ifdef hpux
#ifdef hp9000s800
#define KERNEL_LOAD_VARIABLE "avenrun"
#endif /* hp9000s800 */
#endif /* hpux */
#ifdef mips
# ifdef SYSTYPE_SYSV
# define KERNEL_LOAD_VARIABLE "avenrun"
# else
# define KERNEL_LOAD_VARIABLE "_avenrun"
# endif /* SYSTYPE_SYSV */
#endif /* mips */
#ifdef sequent
#define KERNEL_FILE "/dynix"
#endif /* sequent */
/*
 * provide default for everyone else
 */
#ifndef KERNEL_LOAD_VARIABLE
#define KERNEL_LOAD_VARIABLE "_avenrun"
#endif /* KERNEL_LOAD_VARIABLE */
#endif /* KERNEL_LOAD_VARIABLE */

#ifdef macII
static struct var v;
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 */


/* ARGSUSED */
static void GetLoadPoint( w, closure, call_data )
     Widget	w;		/* unused */
     caddr_t	closure;	/* unused */
     caddr_t	call_data;	/* pointer to (double) return value */
{
  	double *loadavg = (double *)call_data;
	static int init = 0;
	static kmem;
	static long loadavg_seek;
#ifdef macII
        extern nlist();

        if(!init)   {
            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;
            }
            init = 1;
        }
#else /* not macII */
	extern void nlist();
	
	if(!init)   {
	    nlist( KERNEL_FILE, namelist);
	    if (namelist[LOADAV].n_type == 0){
		xload_error("cannot get name list from", KERNEL_FILE);
		exit(-1);
	    }
	    loadavg_seek = namelist[LOADAV].n_value;
# if defined(mips) && defined(SYSTYPE_SYSV)
	    loadavg_seek &= 0x7fffffff;
# endif /* mips && SYSTYPE_SYSV */
	    kmem = open(KMEM_FILE, O_RDONLY);
	    if (kmem < 0) xload_error("cannot open", KMEM_FILE);
	    init = 1;
	}
	

	(void) lseek(kmem, loadavg_seek, 0);
#endif /* macII */
#if defined(sun) || defined (UTEK) || defined(sequent)
	{
		long temp;
		(void) read(kmem, (char *)&temp, sizeof(long));
		*loadavg = (double)temp/FSCALE;
	}
#else /* else not sun */
# ifdef macII
        {
                lseek(kmem, (long)nl[X_AVENRUN].n_value, 0);
                read(kmem, vec, 3*sizeof(struct lavnum));
                *loadavg = fxtod(0);
        }
# else /* else not macII */
#  ifdef mips
	{
		fix temp;
		(void) read(kmem, (char *)&temp, sizeof(fix));
		*loadavg = FIX_TO_DBL(temp);
	}
#  else /* not mips */
	(void) read(kmem, (char *)loadavg, sizeof(double));
#  endif /* mips */
# endif /* macII */
#endif /* sun */
	return;
}
#endif /* LOADSTUB */
#endif /* apollo */

static xload_error(str1, str2)
char *str1, *str2;
{
    (void) fprintf(stderr,"xload: %s %s\n", str1, str2);
    exit(-1);
}

/* ARGSUSED */
static Boolean SetValues (current, request, new)
    Widget current, request, new;
{
    LoadWidget old = (LoadWidget)current;
    LoadWidget w = (LoadWidget)new;
    if (w->load.update != old->load.update) {
	XtRemoveTimeOut (old->load.interval_id);
	w->load.interval_id =
	    XtAddTimeOut(w->load.update*1000, draw_it, (caddr_t)w);
    }

    return( FALSE );
}
SHAR_EOF
if test -f 'X11/Load.h'
then
	echo shar: over-writing existing file "'X11/Load.h'"
fi
cat << \SHAR_EOF > 'X11/Load.h'
/*
* $XConsortium: Load.h,v 1.13 88/10/23 14:03:12 swick Exp $
*/


/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#ifndef _XtLoad_h
#define _XtLoad_h

/***********************************************************************
 *
 * Load Widget
 *
 ***********************************************************************/

/* Parameters:

 Name		     Class		RepType		Default Value
 ----		     -----		-------		-------------
 background	     Background		Pixel		White
 border		     BorderColor	Pixel		Black
 borderWidth	     BorderWidth	Dimension	1
 destroyCallback     Callback		Pointer		NULL
 font		     Font		XFontStruct*	XtDefaultFont
 foreground	     Foreground		Pixel		Black
 getLoadProc	     Callback		Callback	(internal)
 height		     Height		Dimension	120
 highlight	     Foreground		Pixel		Black
 label		     Label		String		(empty string)
 mappedWhenManaged   MappedWhenManaged	Boolean		True
 minScale	     Scale		int		1
 reverseVideo	     ReverseVideo	Boolean		False
 scale		     Scale		int		1
 update		     Interval		int		5 (seconds)
 width		     Width		Dimension	120
 x		     Position		Position	0
 y		     Position		Position	0

*/


#define XtNupdate		"update"
#define XtNscale		"scale"
#define XtNvmunix		"vmunix"
#define XtNminScale		"minScale"
#define XtNgetLoadProc		"getLoadProc"
#define XtNhighlight		"highlight"
 
#define XtCScale		"Scale"

typedef struct _LoadRec *LoadWidget;  /* completely defined in LoadPrivate.h */
typedef struct _LoadClassRec *LoadWidgetClass;    /* completely defined
in LoadPrivate.h */

extern WidgetClass loadWidgetClass;

#endif _XtLoad_h
/* DON'T ADD STUFF AFTER THIS #endif */
SHAR_EOF
if test -f 'X11/LoadP.h'
then
	echo shar: over-writing existing file "'X11/LoadP.h'"
fi
cat << \SHAR_EOF > 'X11/LoadP.h'
/*
* $XConsortium: LoadP.h,v 1.11 88/09/06 16:41:56 jim Exp $
*/


/***********************************************************
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.

                        All Rights Reserved

Permission to use, copy, modify, and distribute this software and its 
documentation for any purpose and without fee is hereby granted, 
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in 
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.  

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

******************************************************************/

#ifndef _LoadP_h
#define _LoadP_h

#include <X11/Load.h>
#include <X11/CoreP.h>

#define SEG_BUFF_SIZE		128

/* New fields for the load widget instance record */
typedef struct {
	 Pixel	fgpixel;	/* color index for graph */
	 Pixel	hipixel;	/* color index for text */
	 XFontStruct	*font;	/* font for text */
	 GC	fgGC;		/* graphics context for fgpixel */
	 GC	hiGC;		/* graphics context for hipixel */
/* start of graph stuff */
	 int	update;		/* update frequence */
	 int	scale;		/* scale factor */
	 int	 min_scale;	/* smallest scale factor */
	 int	 interval;	/* data point interval */
	 Boolean reverse_video;		/* display in reverse video */
	 char	*text;		/* label */
	 double max_value;	/* Max Value in window */
	 double valuedata[2048];/* record of data points */
	 XtIntervalId interval_id;
	 XtCallbackList get_load; /* proc to call to fetch load pt */
   } LoadPart;

/* Full instance record declaration */
typedef struct _LoadRec {
   CorePart core;
   LoadPart load;
   } LoadRec;

/* New fields for the Load widget class record */
typedef struct {int dummy;} LoadClassPart;

/* Full class record declaration. */
typedef struct _LoadClassRec {
   CoreClassPart core_class;
   LoadClassPart load_class;
   } LoadClassRec;

/* Class pointer. */
extern LoadClassRec loadClassRec;

#endif _LoadP_h
SHAR_EOF
#	End of shell archive
exit 0

dan
-----------------------------------------------------------
		    O'Reilly && Associates
		argv@sun.com / argv@ora.com
	   632 Petaluma Ave, Sebastopol, CA 95472 
     800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
    Opinions expressed reflect those of the author only.