Subject: v26i083: xwhosup - X11 R5 program to graphically display "rwho" activity, Part01/01
From: [email-masked] (Boyd Roberts)
Newsgroups: comp.sources.unix

Submitted-By: [email-masked] (Boyd Roberts)
Posting-Number: Volume 26, Issue 84
Archive-Name: xwhosup/part01

[ i totally blew it on this one the first time out.  "findsrc" doesn't seem
  to like files with names like "s.h" because it left it out of the previous
  kit.  also, i used the wrong name in the title.  sorry, boyd..   --vix ]

Originally:

    A snapshot performance monitor. Originally written to watch the load
    distribution on the CPU's on an Silicon Graphics Iris4d/240, it can be
    adapted to display a large variety of changing system statistics.
    
    	- [email-masked] (Mark Moraes)

Modified to snoop for rwhod(8) packets using Jeff Mogul's packetfilter(4)
and display the 5 minute load average on a log scale, or alternating 
yellow/black diagonal stripes if a host hasn't been heard from.

I have some grander plan to turn it into a general purpose resource
monitor, but that'll have to wait.  For the moment I just want have
some rough idea of what our machines are doing.

The X knowledgable will realise that the X code in this is pretty naive
because I hate X and _refuse_ to learn about it -- what a disaster.  I just
want the bits on the screen, without having to read through a pile of overly
verbose and tedious documentation.  The (original) X code is Mark Moreas' work.

    - Boyd Roberts <[email-masked]>
      December '91
      Digital PRL

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  BUGS Bar.c Bar.h BarP.h COPYRIGHT MANIFEST Makefile README
#   csu.diffs s-pfilt-rwho.c s.h xwhosup.1 xwhosup.c
# Wrapped by [email-masked] on Thu Dec 31 13:11:40 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'BUGS' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'BUGS'\"
else
echo shar: Extracting \"'BUGS'\" \(55 characters\)
sed "s/^X//" >'BUGS' <<'END_OF_FILE'
Resizing it vertically causes havoc, I'm not sure why.
END_OF_FILE
if test 55 -ne `wc -c <'BUGS'`; then
    echo shar: \"'BUGS'\" unpacked with wrong size!
fi
# end of 'BUGS'
fi
if test -f 'Bar.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Bar.c'\"
else
echo shar: Extracting \"'Bar.c'\" \(10785 characters\)
sed "s/^X//" >'Bar.c' <<'END_OF_FILE'
X#include <X11/copyright.h>
X
X/* $XConsortium: Bar.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
X/* Copyright	Massachusetts Institute of Technology	1987, 1988 */
X
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#include "BarP.h"
X
static Dimension def_dimension	= ~0;
static XtOrientation def_orient = XtorientHorizontal;
X#define DEF_LENGTH  ((Dimension) 200)
X#define DEF_THICKNESS	((Dimension) 15)
X
static XtResource resources[] = {
X#define offset(field) XtOffset(BarWidget, bar.field)
X#define Offset(field) XtOffset(BarWidget, field)
X    /* {name, class, type, size, offset, default_type, default_addr}, */
X    /*
X     * We define these core class values to set defaults, so we can
X     * initialize correctly
X     */
X    {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
X	Offset(core.width), XtRDimension, (caddr_t)&def_dimension},
X    {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
X	Offset(core.height), XtRDimension, (caddr_t)&def_dimension},
X    /* Private bar widget resources */
X    {XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
X	offset(length), XtRDimension, (caddr_t) &def_dimension},
X    {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
X	offset(thickness), XtRDimension, (caddr_t) &def_dimension},
X    {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
X	offset(orientation), XtROrientation, (caddr_t) &def_orient},
X#undef offset
X#undef Offset
X};
X
static void ClassInitialize();
static void Initialize();
static void Resize();
static void Redisplay();
X
BarClassRec barClassRec = {
X  { /* core fields */
X    /* superclass		*/	(WidgetClass) &widgetClassRec,
X    /* class_name		*/	"Bar",
X    /* widget_size		*/	sizeof(BarRec),
X    /* class_initialize		*/	ClassInitialize,
X    /* class_part_initialize	*/	NULL,
X    /* class_inited		*/	FALSE,
X    /* initialize		*/	Initialize,
X    /* initialize_hook		*/	NULL,
X    /* realize			*/	XtInheritRealize,
X    /* actions			*/	NULL,
X    /* num_actions		*/	0,
X    /* resources		*/	resources,
X    /* num_resources		*/	XtNumber(resources),
X    /* xrm_class		*/	NULLQUARK,
X    /* compress_motion		*/	TRUE,
X    /* compress_exposure	*/	TRUE,
X    /* compress_enterleave	*/	TRUE,
X    /* visible_interest		*/	FALSE,
X    /* destroy			*/	NULL,
X    /* resize			*/	Resize,
X    /* expose			*/	Redisplay,
X    /* set_values		*/	NULL,
X    /* set_values_hook		*/	NULL,
X    /* set_values_almost	*/	XtInheritSetValuesAlmost,
X    /* get_values_hook		*/	NULL,
X    /* accept_focus		*/	NULL,
X    /* version			*/	XtVersion,
X    /* callback_private		*/	NULL,
X    /* tm_table			*/	NULL,
X    /* query_geometry		*/	XtInheritQueryGeometry,
X    /* display_accelerator	*/	XtInheritDisplayAccelerator,
X    /* extension		*/	NULL
X  },
X  { /* bar fields */
X    /* gray			*/	NULL
X  }
X};
X
WidgetClass barWidgetClass = (WidgetClass)&barClassRec;
X
X#ifdef	UGLY_GRAYS
static char gray0_bits[] = {
X   0x00, 0x00, 0x00};
static char gray1_bits[] = {
X   0x00, 0x02, 0x00};
static char gray2_bits[] = {
X   0x00, 0x03, 0x00};
static char gray3_bits[] = {
X   0x00, 0x03, 0x02};
static char gray4_bits[] = {
X   0x00, 0x07, 0x02};
static char gray5_bits[] = {
X   0x04, 0x07, 0x02};
static char gray6_bits[] = {
X   0x04, 0x07, 0x03};
static char gray7_bits[] = {
X   0x05, 0x07, 0x03};
static char gray8_bits[] = {
X   0x05, 0x07, 0x07};
static char gray9_bits[] = {
X   0xff, 0xff, 0xff};
X
static char *gray_bits[MAXGRAY] = {
X    gray0_bits,
X    gray1_bits,
X    gray2_bits,
X    gray3_bits,
X    gray4_bits,
X    gray5_bits,
X    gray6_bits,
X    gray7_bits,
X    gray8_bits,
X    gray9_bits,
X};
X#else
static char gray0_bits[] = {
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static char gray1_bits[] = {
X   0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
X   0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88,
X   0x22, 0x22, 0x88, 0x88, 0x22, 0x22, 0x88, 0x88};
static char gray2_bits[] = {
X   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
X   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55,
X   0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55};
static char gray3_bits[] = {
X   0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77,
X   0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77,
X   0xdd, 0xdd, 0x77, 0x77, 0xdd, 0xdd, 0x77, 0x77};
static char gray4_bits[] = {
X   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
X   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
X   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
X
static char *gray_bits[MAXGRAY] = {
X    gray0_bits,
X    gray1_bits,
X    gray2_bits,
X    gray3_bits,
X    gray4_bits,
X};
X#endif
X
X#define stripe_width 14
X#define stripe_height 14
static char stripe_bits[] = {
X   0x0f, 0x3c, 0x07, 0x3e, 0x03, 0x3f, 0x81, 0x3f, 0xc0, 0x3f, 0xe0, 0x1f,
X   0xf0, 0x0f, 0xf8, 0x07, 0xfc, 0x03, 0xfe, 0x01, 0xff, 0x00, 0x7f, 0x20,
X   0x3f, 0x30, 0x1f, 0x38};
X
static void
ClassInitialize()
X{
X    XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
X		    NULL, (Cardinal)0 );
X}
X
static void
SetDimensions(w)
BarWidget w;
X{
X    if (w->bar.orientation == XtorientVertical) {
X	w->bar.length = w->core.height;
X	w->bar.thickness = w->core.width;
X    }
X    else {
X	w->bar.length = w->core.width;
X	w->bar.thickness = w->core.height;
X    }
X}
X
X/* ARGSUSED */
static void
Initialize(request, new)
Widget request;		/* what the client asked for */
Widget new;		/* what we're going to give him */
X{
X    BarWidget w = (BarWidget) new;
X    XGCValues gcValues;
X    BarClassPart *bcp = &(barClassRec.bar_class);
X    int i;
X    XColor color, exact;
X
X    if (bcp->gray == (Pixmap *) NULL) {
X	/*
X	 *  We initialize this here instead of ClassInitialize because
X	 *  we need a window to initialize this in. A cleaner way to do
X	 *  this would be to use a separate set of Pixmaps for each
X	 *  widget, so that widgets can be on different screen/visuals.
X	 *  But then we'd have to fix it so this thing understood
X	 *  colours, visuals, more resources...  Laziness wins.
X	 */
X	bcp->gray = (Pixmap *) XtMalloc(MAXGRAY * sizeof(Pixmap));
X	for(i = 0; i < MAXGRAY; i++) {
X	    bcp->gray[i] = XCreatePixmapFromBitmapData(XtDisplay(new),
X	     DefaultRootWindow(XtDisplay(new)), gray_bits[i],
X#ifdef	UGLY_GRAYS
X							      3, 3,
X#else
X							      16, 16,
X#endif
X	     WhitePixelOfScreen(XtScreen(new)),
X	     BlackPixelOfScreen(XtScreen(new)), 1);
X	}
X	XAllocNamedColor(XtDisplay(new),
X			 DefaultColormap(XtDisplay(new), DefaultScreen(XtDisplay(new))),
X			 "Yellow", &color, &exact);
X	bcp->stripe = XCreatePixmapFromBitmapData(XtDisplay(new),
X	     DefaultRootWindow(XtDisplay(new)), stripe_bits, stripe_width,
X	     stripe_height, color.pixel,
X	     BlackPixelOfScreen(XtScreen(new)),
X	     DefaultDepth(XtDisplay(new), DefaultScreen(XtDisplay(new))));
X    }
X    gcValues.stipple = bcp->gray[0];
X    gcValues.fill_style = FillOpaqueStippled;
X    w->bar.gc = XCreateGC(XtDisplay(new), DefaultRootWindow(XtDisplay(new)),
X     GCFillStyle | GCStipple, &gcValues);
X    /* Width and height override length and thickness */
X    if (w->bar.length == def_dimension)
X	w->bar.length = DEF_LENGTH;
X	
X    if (w->bar.thickness == def_dimension)
X	w->bar.thickness = DEF_THICKNESS;
X	
X    if (w->core.width == def_dimension)
X	w->core.width = (w->bar.orientation == XtorientVertical)
X	    ? w->bar.thickness : w->bar.length;
X
X    if (w->core.height == def_dimension)
X	w->core.height = (w->bar.orientation == XtorientHorizontal)
X	    ? w->bar.thickness : w->bar.length;
X    w->bar.striped = 0;
X    w->bar.values = NULL;
X    w->bar.nvalues = 0;
X
X    SetDimensions(w);
X}
X
X/* ARGSUSED */
static void
Resize(gw)
Widget gw;
X{
X    SetDimensions((BarWidget)gw);
X    Redisplay(gw, (XEvent*)NULL, (Region)NULL);
X}
X
X/* ARGSUSED */
static void
Redisplay(gw, event, region)
Widget gw;
XXEvent *event;
Region region;
X{
X    BarWidget w = (BarWidget) gw;
X    int x, y;
X    unsigned int width, height;
X    int maxvalue, i;
X    int inc_gray;
X    int igray; 
X    int vertical = (w->bar.orientation == XtorientVertical);;
X
X    if (! XtIsRealized(gw))
X	return;
X
X    if (w->bar.striped)
X    {
X	if(vertical) {
X	    width = w->bar.thickness;
X	    height = w->core.height;
X	}
X	else {
X	    height = w->bar.thickness;
X	    width = w->core.width;
X	}
X	XSetTile(XtDisplay(gw), w->bar.gc, barClassRec.bar_class.stripe);
X	XSetFillStyle(XtDisplay(gw), w->bar.gc, FillTiled);
X	XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
X		   0, 0, width, height);
X	XSetFillStyle(XtDisplay(gw), w->bar.gc, FillOpaqueStippled);
X	return;
X    }
X
X    for(maxvalue = 0, i = 0; i < w->bar.nvalues; i++)
X	maxvalue += w->bar.values[i];
X    if(maxvalue <= 0)
X	return;
X    x = y = 0;
X    if(vertical)
X	width = w->bar.thickness;
X    else
X	height = w->bar.thickness;
X    inc_gray = (w->bar.nvalues > 1) ? (MAXGRAY - 1) / (w->bar.nvalues - 1) :
X	MAXGRAY - 1;
X    for(igray = 0, i = 0; i < w->bar.nvalues; i++, igray += inc_gray) {
X	unsigned int rectlen = (w->bar.length * w->bar.values[i] +
X				maxvalue / 2) / maxvalue;
X	if (rectlen == 0)
X	    continue;
X	if (i == w->bar.nvalues - 1) {
X	    if (vertical)
X		rectlen = w->core.height - y;
X	    else
X		rectlen = w->core.width - x;
X#ifndef	UGLY_GRAYS
X	    igray = MAXGRAY - 1;
X#endif
X	}
X	XSetStipple(XtDisplay(gw), w->bar.gc, barClassRec.bar_class.gray[igray]);
X	if(vertical) {
X	    XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
X	     x, y, width, rectlen);
X	    y += rectlen;
X	} else {
X	    XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
X	     x, y, rectlen, height);
X	    x += rectlen;
X	}
X    }
X}
X
X/* Public routines. */
void
SetBarValues(gw, values, nvalues)
Widget gw;
int *values;
int nvalues;
X{
X    BarWidget w = (BarWidget) gw;
X    int i;
X
X    if (nvalues > MAXGRAY) {
X#define ERRFMT "Tried to set %d values for bar - maximum is %d\n"
X	char errbuf[sizeof(ERRFMT) + 32];
X	(void) sprintf(errbuf, ERRFMT, nvalues, MAXGRAY);
X#undef ERRFMT
X	XtWarning(errbuf);
X	nvalues = MAXGRAY;
X    }
X    if (nvalues < 0) {
X#define ERRFMT "Tried to set %d values for bar - it must be > 0\n"
X	char errbuf[sizeof(ERRFMT) + 32];
X	(void) sprintf(errbuf, ERRFMT, nvalues);
X	XtWarning(errbuf);
X#undef ERRFMT
X	return;
X    }
X    w->bar.nvalues = nvalues;
X    if (w->bar.values != NULL)
X	XtFree((char *) w->bar.values);
X    if (nvalues != 0)
X	w->bar.values = (int *) XtMalloc(nvalues * sizeof(int));
X    for(i = 0; i < nvalues; i++)
X	w->bar.values[i] = values[i];
X    w->bar.striped = 0;
X    Redisplay( gw, (XEvent*)NULL, (Region)NULL );
X}
X
void
SetBarStripe(gw)
Widget gw;
X{
X    BarWidget w = (BarWidget) gw;
X    int i;
X
X    w->bar.striped = 1;
X    Redisplay( gw, (XEvent*)NULL, (Region)NULL );
X}
END_OF_FILE
if test 10785 -ne `wc -c <'Bar.c'`; then
    echo shar: \"'Bar.c'\" unpacked with wrong size!
fi
# end of 'Bar.c'
fi
if test -f 'Bar.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Bar.h'\"
else
echo shar: Extracting \"'Bar.h'\" \(1187 characters\)
sed "s/^X//" >'Bar.h' <<'END_OF_FILE'
X#include <X11/copyright.h>
X
X/* $XConsortium: Bar.h,v 1.2 88/10/25 17:22:09 swick Exp $ */
X/* Copyright	Massachusetts Institute of Technology	1987, 1988 */
X
X#ifndef _Bar_h
X#define _Bar_h
X
X/****************************************************************
X *
X * Bar widget
X *
X ****************************************************************/
X
X/* Resources:
X
X Name		     Class		RepType		Default Value
X ----		     -----		-------		-------------
X background	     Background		Pixel		XtDefaultBackground
X border		     BorderColor	Pixel		XtDefaultForeground
X borderWidth	     BorderWidth	Dimension	1
X destroyCallback     Callback		Pointer		NULL
X height		     Height		Dimension	0
X mappedWhenManaged   MappedWhenManaged	Boolean		True
X sensitive	     Sensitive		Boolean		True
X width		     Width		Dimension	0
X x		     Position		Position	0
X y		     Position		Position	0
X
X*/
X
X/* declare specific BarWidget class and instance datatypes */
X
typedef struct _BarClassRec*	BarWidgetClass;
typedef struct _BarRec*		BarWidget;
X
X/* declare the class constant */
X
extern WidgetClass barWidgetClass;
X
X/* Public procedures */
extern void SetBarValues(/* BarWidget w, int *values, int nvalues */);
X
X#endif  _Bar_h
END_OF_FILE
if test 1187 -ne `wc -c <'Bar.h'`; then
    echo shar: \"'Bar.h'\" unpacked with wrong size!
fi
# end of 'Bar.h'
fi
if test -f 'BarP.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'BarP.h'\"
else
echo shar: Extracting \"'BarP.h'\" \(1160 characters\)
sed "s/^X//" >'BarP.h' <<'END_OF_FILE'
X#include <X11/copyright.h>
X
X/* $XConsortium: BarP.h,v 1.2 88/10/25 17:37:59 swick Exp $ */
X/* Copyright	Massachusetts Institute of Technology	1987, 1988 */
X
X#ifndef _BarP_h
X#define _BarP_h
X
X#include <X11/Xmu/Xmu.h>
X#include "Bar.h"
X/* include superclass private header file */
X#include <X11/CoreP.h>
X
X/* define unique representation types not found in <X11/StringDefs.h> */
X
X#ifdef UGLY_GRAYS
X#define MAXGRAY 10
X#else
X#define MAXGRAY 5
X#endif
X
typedef struct {
X    Pixmap *gray;
X    Pixmap stripe;
X} BarClassPart;
X
typedef struct _BarClassRec {
X    CoreClassPart	core_class;
X    BarClassPart	bar_class;
X} BarClassRec;
X
extern BarClassRec barClassRec;
X
typedef struct {
X    /* private state */
X    int striped;		/* In the striped state? */
X    int *values;		/* Array of values displayed in bar */
X    int nvalues;		/* Number of elements in values */
X    XtOrientation orientation;	/* XtorientHorizontal or XtorientVertical */
X    Dimension	  length;	/* either height or width */
X    Dimension	  thickness;	/* either width or height */
X    GC		  gc;		/* a gc */
X} BarPart;
X
typedef struct _BarRec {
X    CorePart	core;
X    BarPart	bar;
X} BarRec;
X
X#endif  _BarP_h
END_OF_FILE
if test 1160 -ne `wc -c <'BarP.h'`; then
    echo shar: \"'BarP.h'\" unpacked with wrong size!
fi
# end of 'BarP.h'
fi
if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'COPYRIGHT'\"
else
echo shar: Extracting \"'COPYRIGHT'\" \(915 characters\)
sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
X/*
X * Copyright University of Toronto 1988, 1989.
X * Written by Mark Moraes
X *
X * Permission is granted to anyone to use this software for any purpose on
X * any computer system, and to alter it and redistribute it freely, subject
X * to the following restrictions:
X *
X * 1. The author and the University of Toronto are not responsible 
X *    for the consequences of use of this software, no matter how awful, 
X *    even if they arise from flaws in it.
X *
X * 2. The origin of this software must not be misrepresented, either by
X *    explicit claim or by omission.  Since few users ever read sources,
X *    credits must appear in the documentation.
X *
X * 3. Altered versions must be plainly marked as such, and must not be
X *    misrepresented as being the original software.  Since few users
X *    ever read sources, credits must appear in the documentation.
X *
X * 4. This notice may not be removed or altered.
X */
END_OF_FILE
if test 915 -ne `wc -c <'COPYRIGHT'`; then
    echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
fi
# end of 'COPYRIGHT'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(499 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X BUGS                       1	
X Bar.c                      1	
X Bar.h                      1	
X BarP.h                     1	
X COPYRIGHT                  1	
X MANIFEST                   1	
X Makefile                   1	
X README                     1	
X csu.diffs                  1	
X s-pfilt-rwho.c             1	
X s.h                        1	
X xwhosup.1                  1	
X xwhosup.c                  1	
END_OF_FILE
if test 499 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1165 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
DESTROOT =
DESTPATH = $(DESTROOT)/contrib
DESTSHR = $(DESTPATH)/share
DESTSYS = $(DESTPATH)/system
MAND = $(DESTSHR)/man
BIND = $(DESTSYS)/bin
X
SRCROOT =
SRCPATH = $(SRCROOT)/contrib
SRCSHR = $(SRCPATH)/share
SRCSYS = $(SRCPATH)/system
INCD = $(SRCSHR)/include
LIBD = $(SRCSYS)/lib
X
X#(decnet needed by xlib?)
XXLIB = -lX11 -ldnet
X#(nope)
X#XLIB = -lX11
X
PROGRAM		= xwhosup
MANPAGE		= xwhosup.1
X
H		= \
X		Bar.h \
X		BarP.h \
X		s.h
X
SRC		= \
X		BUGS \
X		COPYRIGHT \
X		Makefile \
X		README \
X		$(MANPAGE) \
X		$(H) \
X		Bar.c \
X		s-pfilt-rwho.c \
X		xwhosup.c
X
OBJS 		= \
X		Bar.o \
X		s-pfilt-rwho.o \
X		xwhosup.o
X
X#(gcc)
CC		= gcc
CDEBUG		= -O -g
X#(other)
CC		= cc
CDEBUG		= -O
X
INC		= -I$(INCD)
CFLAGS		= $(INC) $(CDEBUG)
LIBS		= -L$(LIBD) -lXaw -lXmu -lXt -lXext $(XLIB) -lm
X
all		: $(PROGRAM)
X
X$(PROGRAM)	: $(OBJS)
X		$(CC) -o $(PROGRAM) $(OBJS) $(LIBS)
X
install		: $(PROGRAM) $(MANPAGE)
X		install -c -s $(PROGRAM) $(BIND)/$(PROGRAM)
X		install -c    $(MANPAGE) $(MAND)/man1/$(MANPAGE)
X
shar		:
X		shar $(SRC) > $(PROGRAM).shar
X
clean		:
X		-rm -f $(OBJS) $(PROGRAM).shar $(PROGRAM)
X
Bar.o		: Bar.c BarP.h Bar.h
xwhosup.o	: xwhosup.c Bar.h s.h
s-pfilt-rwho.o	: s-pfilt-rwho.c 
END_OF_FILE
if test 1165 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1056 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Originally:
X
X    A snapshot performance monitor. Originally written to watch the load
X    distribution on the CPU's on an Silicon Graphics Iris4d/240, it can be
X    adapted to display a large variety of changing system statistics.
X    
X    	- [email-masked] (Mark Moraes)
X
Modified to snoop for rwhod(8) packets using Jeff Mogul's packetfilter(4)
and display the 5 minute load average on a log scale, or alternating 
yellow/black diagonal stripes if a host hasn't been heard from.
X
I have some grander plan to turn it into a general purpose resource
monitor, but that'll have to wait.  For the moment I just want have
some rough idea of what our machines are doing.
X
The X knowledgable will realise that the X code in this is pretty naive
because I hate X and _refuse_ to learn about it -- what a disaster.  I just
want the bits on the screen, without having to read through a pile of overly
verbose and tedious documentation.  The (original) X code is Mark Moreas' work.
X
X
X    - Boyd Roberts <[email-masked]>
X      December '91
X      Digital PRL
END_OF_FILE
if test 1056 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'csu.diffs' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'csu.diffs'\"
else
echo shar: Extracting \"'csu.diffs'\" \(1465 characters\)
sed "s/^X//" >'csu.diffs' <<'END_OF_FILE'
X*** Makefile.orig	Wed Dec 30 10:19:09 1992
X--- Makefile	Wed Dec 30 11:01:00 1992
X***************
X*** 1,2 ****
X--- 1,21 ----
X+ DESTROOT =
X+ DESTPATH = $(DESTROOT)/contrib
X+ DESTSHR = $(DESTPATH)/share
X+ DESTSYS = $(DESTPATH)/system
X+ MAND = $(DESTSHR)/man
X+ BIND = $(DESTSYS)/bin
X+ 
X+ SRCROOT =
X+ SRCPATH = $(SRCROOT)/contrib
X+ SRCSHR = $(SRCPATH)/share
X+ SRCSYS = $(SRCPATH)/system
X+ INCD = $(SRCSHR)/include
X+ LIBD = $(SRCSYS)/lib
X+ 
X+ #(decnet needed by xlib?)
X+ XLIB = -lX11 -ldnet
X+ #(nope)
X+ #XLIB = -lX11
X+ 
X  PROGRAM		= xwhosup
X  MANPAGE		= xwhosup.1
X***************
X*** 23,30 ****
X  		xwhosup.o
X  
X! INC		= -I/usr/local/include
X! CFLAGS		= $(INC) -O -g
X! LIBS		= -lXaw -lXmu -lXt -lXext -lX11 -lm
X  
X  all		: $(PROGRAM)
X  
X--- 42,56 ----
X  		xwhosup.o
X  
X! #(gcc)
X! CC		= gcc
X! CDEBUG		= -O -g
X! #(other)
X! CC		= cc
X! CDEBUG		= -O
X  
X+ INC		= -I$(INCD)
X+ CFLAGS		= $(INC) $(CDEBUG)
X+ LIBS		= -L$(LIBD) -lXaw -lXmu -lXt -lXext $(XLIB) -lm
X+ 
X  all		: $(PROGRAM)
X  
X***************
X*** 32,35 ****
X--- 58,65 ----
X  		$(CC) -o $(PROGRAM) $(OBJS) $(LIBS)
X  
X+ install		: $(PROGRAM) $(MANPAGE)
X+ 		install -c -s $(PROGRAM) $(BIND)/$(PROGRAM)
X+ 		install -c    $(MANPAGE) $(MAND)/man1/$(MANPAGE)
X+ 
X  shar		:
X  		shar $(SRC) > $(PROGRAM).shar
X***************
X*** 36,40 ****
X  
X  clean		:
X! 		-rm -f $(OBJS) $(PROGRAM).shar
X  
X  Bar.o		: Bar.c BarP.h Bar.h
X--- 66,70 ----
X  
X  clean		:
X! 		-rm -f $(OBJS) $(PROGRAM).shar $(PROGRAM)
X  
X  Bar.o		: Bar.c BarP.h Bar.h
END_OF_FILE
if test 1465 -ne `wc -c <'csu.diffs'`; then
    echo shar: \"'csu.diffs'\" unpacked with wrong size!
fi
# end of 'csu.diffs'
fi
if test -f 's-pfilt-rwho.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'s-pfilt-rwho.c'\"
else
echo shar: Extracting \"'s-pfilt-rwho.c'\" \(11679 characters\)
sed "s/^X//" >'s-pfilt-rwho.c' <<'END_OF_FILE'
X/*
X *	packetfilter(4) support for rwhod(8) packets in the style of
X *	the original `system dependant' s.c file.
X *
X *	Boyd Roberts <[email-masked]>
X *	December '91
X *	Digital PRL
X */
X
X#include        <stdio.h>
X#include        <sys/types.h>
X#include        <sys/socket.h>
X#include        <fcntl.h>
X#include	<netdb.h>
X#include	<time.h>
X#include        <net/pfilt.h>
X#include        <net/if.h>
X#include        <netinet/in_systm.h>
X#include        <netinet/in.h>
X#include        <netinet/if_ether.h>
X#include        <netinet/ip.h>
X#include        <netinet/udp.h>
X#include	<protocols/rwhod.h>
X#include	<ctype.h>
X#include	<math.h>
X
X#include	<X11/Xos.h>
X#include	<X11/StringDefs.h>
X#include	<X11/Intrinsic.h>
X#include	<X11/Xaw/Form.h>
X#include	<X11/Xaw/Label.h>
X#include	<X11/Xmu/Xmu.h>
X
X/*
X *	rwho strings for getservbyname(3).
X */
X#define 	RWHO_SERVICE	"who"
X#define 	RWHO_PROTOCOL	"udp"
X
X/*
X *	Number of load average ints.
X */
X#define		NLOADAV		3
X
X/*
X *	Timeout (in seconds) for marking a host dead.
X */
X#define		HOSTTIMEUP	(2 * 60)
X
X/*
X *	Simple host data structure.
X */
struct host
X{
X	char		*h_name;
X	time_t		h_when;
X	int		h_loadav[NLOADAV];
X	int		h_state;
X};
X
X/*
X *	Host states.
X */
X#define HS_INIT		0		/* not heard from yet */
X#define HS_UP		1		/* heard from */
X#define HS_DOWN		2		/* not heard from for HOSTIMEUP */
X
X/*
X *	Host array and number.
X *
X *	I could add a hashtable here to point into the host array,
X *	but the search of the table (on receipt of a packet) will
X *	probably be quick because there will only be a small
X *	number of hosts; how much screen real estate have you got?
X */
static struct host	*hosts;
static int		nhosts;
X
X/*
X *	packetfilter(4) file descriptor.
X */
int			Clnt_multi_sock;
X
X/*
X *	Highest bar value and the value of one point on the bar.
X */
X#define BAREND		1000
X#define BARPOINT	250
X
extern char		*progname;
X
X/*
X *	System error message.
X */
char	*
sysmess()
X{
X	extern int	errno;
X	extern int	sys_nerr;
X	extern char	*sys_errlist[];
X
X	return errno <= 0 || errno > sys_nerr ? "Unknown error" : sys_errlist[errno];
X}
X
X/*
X *	Add a packetfilter(4) expression.
X */
X#define add(x)	f.enf_Filter[i++] = (x)
X
X
X/*
X *	Set up a packetfilter(4) filter for rwhod(8) packets.
X */
int
rwho_filter()
X{
X	int		fd;
X	u_short		bits;
X	int		i;
X	struct servent	*rwho;
X	struct enfilter	f;
X
X	if ((fd = pfopen((char *)0, O_RDONLY)) == -1)
X	{
X		fprintf(stderr, "%s: Could not open packetfilter.", progname, sysmess());
X		exit(1);
X		/* NOTREACHED */
X	}
X
X	/*
X	 *	Match promiscuoslsy received packets non-exclusively
X	 *	and return them prepended by a `struct enstamp'.
X	 */
X	bits = ENPROMISC | ENNONEXCL | ENTSTAMP;
X
X	if (ioctl(fd, EIOCMBIS, (char *)&bits) == -1)
X	{
X		fprintf(stderr, "%s: Could not ioctl packetfilter. %s", progname, sysmess());
X		exit(1);
X		/* NOTREACHED */
X	}
X
X	/*
X	 *	Grab the rwhod(8) service info.
X	 */
X	if ((rwho = getservbyname(RWHO_SERVICE, RWHO_PROTOCOL)) == (struct servent *)0)
X	{
X		fprintf(stderr, "%s: No rwho UDP service. %s", progname, sysmess());
X		exit(1);
X		/* NOTREACHED */
X	}
X
X	/*
X	 *	Build and ioctl(2) the filter.
X	 */
X	f.enf_Priority = 0;
X	i = 0;
X
X	add(ENF_PUSHWORD + 6);		/* packet type */
X	add(ENF_PUSHLIT);
X	add(htons((u_short)ETHERTYPE_IP));
X	add(ENF_EQ);			/* IP? */
X
X	add(ENF_PUSHWORD + 11);		/* protocol type */
X	add(ENF_PUSHLIT);
X	add(htons((u_short)0x00FF));
X	add(ENF_AND);			/* in low byte */
X	add(ENF_PUSHLIT);
X	add(htons((u_short)IPPROTO_UDP));
X	add(ENF_EQ);			/* UDP? */
X
X	add(ENF_CAND);			/* IP && UDP ? */
X
X	add(ENF_PUSHWORD + 17);		/* src port */
X	add(ENF_PUSHLIT);
X	add((u_short)rwho->s_port);
X
X	add(ENF_EQ);			/* rwho? */
X
X	f.enf_FilterLen = i;
X
X	if (ioctl(fd, EIOCSETF, &f) == -1)
X	{
X		fprintf(stderr, "%s: Could not ioctl packetfilter. %s", progname, sysmess());
X		exit(1);
X		/* NOTREACHED */
X	}
X
X	return fd;
X}
X
X/*
X *	Return the ASCII representation of an Ethernet address.
X */
char	*
ether_addr(a)
u_char	*a;
X{
X	static char	buf[18];
X
X	sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", a[0], a[1], a[2], a[3], a[4], a[5]);
X
X	return buf;
X}
X
X/*
X *	Process a rwhod(8) packet.  Do _a lot_ of sanity checking, trashing
X *	any packets that look weird.  Various extraneous IP structs are
X *	initialised here for debugging.
X */
static struct whod	*
rwho(fd)
X{
X	unsigned char		*p;
X	int			n;
X	int			i;
X	struct ether_header	*ether;
X	struct ip		*ip;
X	struct udphdr		*udp;
X	static struct whod	whop;
X	struct enstamp		stamp;
X	unsigned char		buf[4096];
X	extern Bool		noisy;
X	int			true_length;
X	extern char		*progname;
X
X	switch (n = read(fd, (char *)buf, sizeof buf))
X	{
X	case 0:
X		if (noisy)
X			fprintf(stderr, "%s: End of file on packetfilter.\n", progname);
X
X		return (struct whod *)0;
X
X	case -1:
X		if (noisy)
X			fprintf(stderr, "%s: Could not read packetfilter. %s\n", progname, sysmess());
X
X		return (struct whod *)0;
X	
X	default:
X		break;
X	}
X
X	p = buf;
X
X	/* peek at the stamp and copy it */
X
X	if (n <= sizeof(stamp.ens_stamplen) || n <= ((struct enstamp *)p)->ens_stamplen)
X	{
X		if (noisy)
X			fprintf(stderr, "%s: Short packetfilter read of %d bytes.\n", progname, n);
X
X		return (struct whod *)0;
X	}
X
X	bcopy((char *)p, (char *)&stamp, (int)((struct enstamp *)p)->ens_stamplen);
X
X	n -= stamp.ens_stamplen;
X	true_length = n;
X
X	if (n < 0)
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte packet missing enstamp.\n", progname, true_length);
X
X		return (struct whod *)0;
X	}
X
X	p += stamp.ens_stamplen;
X	n -= sizeof (struct ether_header);
X
X	if (n < 0)
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte packet missing Ethernet header.\n", progname, true_length);
X
X		return (struct whod *)0;
X	}
X
X	/* now we have an ethernet packet */
X
X	ether = (struct ether_header *)p;
X	p += sizeof (struct ether_header);
X
X	n -= sizeof (struct ip);
X
X	if (n < 0)
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte packet from %s missing IP header.\n", progname, true_length, ether_addr(ether->ether_shost));
X
X		return (struct whod *)0;
X	}
X
X	/* now we have an IP packet */
X
X	ip = (struct ip *)p;
X	p += sizeof (struct ip);
X
X	if (n <= sizeof (struct udphdr))
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte packet from %s missing UDP header.\n", progname, true_length, inet_ntoa(ip->ip_src));
X
X		return (struct whod *)0;
X	}
X
X	/* now we have a UDP packet */
X
X	udp = (struct udphdr *)p;
X
X	/* check the UDP datalength with the length returned by read(2) */
X
X	if (n != ntohs(udp->uh_ulen))
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte packet from %s UDP length %d, should be %d.\n", progname, true_length, inet_ntoa(ip->ip_src), ntohs(udp->uh_ulen), n);
X
X		return (struct whod *)0;
X	}
X
X	p += sizeof (struct udphdr);		/* rwho packet */
X	n -= sizeof (struct udphdr);		/* rwho packet length */
X
X        /* make _sure_ that we have the bits of the rwho we want */
X
X	if ((unsigned char *)&((struct whod *)p)->wd_we[0] - p > n)
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte rwho packet from %s truncated.\n", progname, true_length, inet_ntoa(ip->ip_src));
X
X		return (struct whod *)0;
X	}
X
X	bcopy((char *)p, (char *)&whop, n);		/* rwho packet */
X
X	/*
X	 *	Verify and turn into host byte order.
X	 */
X	if (whop.wd_vers != WHODVERSION)
X	{
X		if (noisy)
X			fprintf(stderr, "%s: %d byte rwho packet version %d from %s should be version %d.\n", progname, true_length, whop.wd_vers, inet_ntoa(ip->ip_src), WHODVERSION);
X
X		return (struct whod *)0;
X	}
X
X	whop.wd_sendtime = (int)ntohl(whop.wd_sendtime);
X
X	/* use the receive time in the packet stamp */
X	whop.wd_recvtime = stamp.ens_tstamp.tv_sec;
X
X	for (i = 0; i < sizeof(whop.wd_hostname); i++)
X	{
X		unsigned char	c;
X
X		if ((c = whop.wd_hostname[i]) == '\0')
X			break;
X
X		if (!isprint(c))
X		{
X			if (noisy)
X				fprintf(stderr, "%s: Unprintable hostname character 0%03o in rwho packet from %s.\n", progname, c, inet_ntoa(ip->ip_src));
X
X			return (struct whod *)0;
X		}
X	}
X
X	if (noisy)
X	{
X		for (i = 0; i < sizeof(whop.wd_hostname); i++)
X		{
X			unsigned char	c;
X
X			if ((c = whop.wd_hostname[i]) == '\0')
X				break;
X
X			putchar(c);
X		}
X	}
X
X	for (i = 0; i < NLOADAV; i++)
X	{
X		whop.wd_loadav[i] = (int)ntohl(whop.wd_loadav[i]);
X
X		if (noisy)
X			printf(" %.3f", (double)whop.wd_loadav[i] / 100.0);
X	}
X
X	whop.wd_boottime = (int)ntohl(whop.wd_boottime);
X
X	if (noisy)
X		printf("\n");
X
X	/* forget about the utmp data -- it's too ugly */
X
X	return &whop;
X}
X
X/*
X *	Called when XtMainLoop gets seltrue on the packetfilter descriptor.
X */
X
X/* ARGSUSED */
XXtInputCallbackProc
get_socket_msg(client_data, source, id)
caddr_t client_data;
int *source;
XXtInputId *id;
X{
X	int		i;
X	struct whod	*whop;
X
X	/*
X	 *	Grab packet in host byte order.
X	 */
X	if ((whop = rwho(Clnt_multi_sock)) == (struct whod *)0)
X		return;
X
X	/*
X	 *	Find host slot in table and update it.  A linear search,
X	 *	but I could add a hashtable.
X	 */
X	for (i = 0; i < nhosts; i++)
X	{
X		int		j;
X		struct host	*hp;
X		double		d;
X		int		bars[4];
X
X		hp = &hosts[i];
X
X		if (strncmp(whop->wd_hostname, hp->h_name, sizeof (whop->wd_hostname)) != 0)
X			continue;
X
X		/* copy load averages and mark up */
X		for (j = 0; j < NLOADAV; j++)
X			hp->h_loadav[j] = whop->wd_loadav[j];
X
X		hp->h_when = whop->wd_recvtime;
X		hp->h_state = HS_UP;
X
X		/*
X		 *	Logarithmic bar display from 1..BAREND but linear from 0..1
X		 */
X		bars[0] = 0;
X
X		if ((d = (double)hp->h_loadav[0] / 100.0) > 1.0)
X			bars[1] = log10(d) * BARPOINT + BARPOINT;
X		else
X			bars[1] = d * BARPOINT;
X
X		if (bars[1] > BAREND)
X			bars[1] = BAREND;
X
X		bars[2] = BAREND - bars[1];
X		bars[3] = 0;
X
X		draw_bar(i, &bars[0], sizeof bars / sizeof bars[0]);
X		break;
X	}
X}
X
X/*
X *	Called every HOSTTIMEUP seconds to scan for dead hosts.
X */
X/* ARGSUSED */
XXtTimerCallbackProc
host_down(closure, id)
caddr_t closure;
XXtIntervalId *id;
X{
X	int		i;
X	struct timeval	t;
X	struct timezone	tz;
X
X	if (gettimeofday(&t, &tz) == -1)
X		t.tv_sec = 0x7FFFFFFF;		/* cannot happen */
X
X	for (i = 0; i < nhosts; i++)
X	{
X		struct host	*hp;
X
X		hp = &hosts[i];
X
X		switch (hp->h_state)
X		{
X		case HS_INIT:
X		case HS_UP:
X			if (t.tv_sec > hp->h_when + HOSTTIMEUP)
X			{
X				extern Widget *bar;
X
X				hp->h_state = HS_DOWN;
X
X#if	DEBUG
X				printf("%s DOWN\n", hp->h_name);
X#endif
X
X				SetBarStripe(bar[i]);
X			}
X			break;
X
X		case HS_DOWN:
X			break;
X		}
X	}
X
X	/* set up next call */
X	XtAddTimeOut((unsigned long)(HOSTTIMEUP * 1000), host_down, (caddr_t)0);
X}
X
X/*
X *	Look at argv for the number of hosts (bars).
X */
X/* ARGSUSED */
int
num_bars(argc, argv)
int	argc;
char	*argv[];
X{
X	if (argc < 2)
X	{
X		extern void	usage();
X
X		usage();
X		/* NOTREACHED */
X	}
X
X	return argc - 1;
X}
X
X/*
X *	Initialise (in some sense).
X */
X/* ARGSUSED */
void
init_bars(n)
int	n;
X{
X	Clnt_multi_sock = rwho_filter();
X
X	XtAddTimeOut((unsigned long)(HOSTTIMEUP * 1000), host_down, (caddr_t)0);
X}
X
X/*
X *	Called after num_bars to ask for the bar names.
X *
X *	I use a naive algorithm to match hostnames without the domain part.
X *	If the domain is present, it's stripped.  Use of /etc/hosts or any
X *	form of nameserver is explicitly avoided; it's simpler and more
X *	robust just to use strcmp(3) to match/verify hostnames.
X */
X/* ARGSUSED */
char **
label_bars(nbars, argc, argv)
int nbars;
int argc;
char **argv;
X{
X	int		i;
X	char		**hostv;
X	char		**n;
X	extern char	*xmalloc();
X
X	nhosts = nbars;
X	hosts = (struct host *)xmalloc(nhosts * sizeof (struct host));
X	argv++;
X
X	n = hostv = (char **)xmalloc(nhosts * sizeof (char *));
X
X	for (i = 0; i < nhosts; i++)
X	{
X		char		*p;
X		int		j;
X		struct host	*hp;
X		extern char	*strchr();
X		extern char	*strncpy();
X
X		hp = &hosts[i];
X
X		/* hack off domain part */
X		if ((p = strchr(argv[i], '.')) != (char *)0)
X			j = p - argv[i];
X		else
X			j = strlen(argv[i]);
X
X		hp->h_name = *n++ = strncpy(xmalloc(j + 1), argv[i], j);
X		hp->h_name[j] = '\0';
X		hp->h_when = 0;
X
X		for (j = 0; j < NLOADAV; j++)
X			hp->h_loadav[j] = 0;
X	
X		hp->h_state = HS_INIT;	
X	}
X
X	return hostv;
X}
END_OF_FILE
if test 11679 -ne `wc -c <'s-pfilt-rwho.c'`; then
    echo shar: \"'s-pfilt-rwho.c'\" unpacked with wrong size!
fi
# end of 's-pfilt-rwho.c'
fi
if test -f 's.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'s.h'\"
else
echo shar: Extracting \"'s.h'\" \(262 characters\)
sed "s/^X//" >'s.h' <<'END_OF_FILE'
X/*
X *  Any system dependent file must implement these routines. See s-bsd.c
X *  and s-iris4d.c for examples.
X */
extern int num_bars();
extern char **label_bars(/* int nbars */);
extern void init_bars(/* int nbars */);
extern void display_bars(/* int nbars */);
END_OF_FILE
if test 262 -ne `wc -c <'s.h'`; then
    echo shar: \"'s.h'\" unpacked with wrong size!
fi
# end of 's.h'
fi
if test -f 'xwhosup.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xwhosup.1'\"
else
echo shar: Extracting \"'xwhosup.1'\" \(2136 characters\)
sed "s/^X//" >'xwhosup.1' <<'END_OF_FILE'
X.TH XWHOSUP 1
X.SH NAME
xwhosup - display rwho based host up/down status
X.SH SYNTAX
X\fBxwhosup\fP [\fI\-toolkitoption\fP ...] [\fI-noisy\fP] host ...
X.SH DESCRIPTION
X.I Xwhosup
displays a logarithmic bar graph showing
X.I host
load average.  This data is gathered from network
X.IR rwhod (8)
broadcasts collected via
X.IR packetfilter (4).
Hosts can be specified by either their hostname, or by their fully qualified
domain name.  If the domain is supplied it is stripped and ignored.
X.PP
Initially no bar graph is displayed until either a packet is received or the
host alive timer expires.  The bar graph displays the 5 minute load average
for a host.  The scale is logarithmic with a maximum value of 1000.  For values
between 0 to 1 the scale is linear.
X.PP
If a host has not been heard from after some interval it is as marked down.
This is indicated by a bar consisting of alternating yellow/black diagonal
stripes.
X.PP
If the
X.I -noisy
option is specified
X.I xwhosup
prints a one line summary (hostname and load averages) for each
X.IR rwho (8)
broadcast received.  If a corrupted packet is received this option
causes debugging information to be written to standard error.
X.SH SEE ALSO
X.IR ruptime (1),
X.IR rwho (1),
X.IR xcpustate (1),
X.IR packetfilter (4),
X.IR rwhod (8).
X.SH BUGS
Vertical re-sizing doesn't work well and horizontal re-sizing is
X.IR interesting .
X.PP
More concern has been placed on network snooping than X programming, as the
later does not interest the author.
X.PP
The linear 0 to 1 scale is provided so that the graph is more interesting
because most of our hosts are basically idle.
X.SH AUTHOR
Boyd Roberts <[email-masked]>
X.PP
X.I Xwhosup
is based on the code from Mark Moraes' 
X.IR xcpustate (1)
X.SM CPU
user/system/idle time monitor.  This 
X.IR packetfilter (4)
interface was written to provide a simple indication of the
status of network host(s).
X.PP
Originally authored by Mark Moraes, University of Toronto.
Thanks to Chris Siebenmann for the code for BSD systems.
Thanks to Walter D. Poxon from Cray Research for the code for Cray X/MP and
Y/MPs.
X.SH "LOCAL PROPRIETOR"
Boyd Roberts <[email-masked]>
END_OF_FILE
if test 2136 -ne `wc -c <'xwhosup.1'`; then
    echo shar: \"'xwhosup.1'\" unpacked with wrong size!
fi
# end of 'xwhosup.1'
fi
if test -f 'xwhosup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xwhosup.c'\"
else
echo shar: Extracting \"'xwhosup.c'\" \(5923 characters\)
sed "s/^X//" >'xwhosup.c' <<'END_OF_FILE'
X/*
X*  Displays CPU state distribution
X*/
X#ifndef lint
static char rcsid[] = "$Header: /ai/lambda/X.V11R4/contrib/clients/xcpustate/RCS/xcpustate.c,v 1.2 90/02/20 00:33:36 xwindows Exp $";
X#endif /*lint*/
X
X#include <stdio.h>
X
X#include <X11/Xos.h>
X#include <X11/StringDefs.h>
X#include <X11/Intrinsic.h>
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xmu/Xmu.h>
X#include "Bar.h"
X#include "s.h"
X
X#define MAXSTR 512
X#define DEF_INTERVAL	1
X#define DEF_COUNT		-1
X
char *progname;
static int defaultInterval = DEF_INTERVAL;
static int defaultCount = DEF_COUNT;
static Bool defaultNoisy = False;
int count, interval;
Bool noisy;
X
X/* Application Resources - no particular widget */
static XtResource application_resources[] = {
X    {"interval", "Interval", XtRInt, sizeof(int),
X	    (Cardinal)&interval, XtRInt, (caddr_t) &defaultInterval},
X    {"count", "Count", XtRInt, sizeof(int),
X	    (Cardinal)&count, XtRInt, (caddr_t) &defaultCount},
X    {"noisy", "Noisy", XtRBoolean, sizeof(Bool),
X	    (Cardinal)&noisy, XtRBoolean, (caddr_t) &defaultNoisy},
X};
X
X/*
X*  Command line options table. The command line is parsed for these,
X*  and it sets/overrides the appropriate values in the resource
X*  database
X*/
static XrmOptionDescRec optionDescList[] = {
X    {"-interval",   ".interval",    XrmoptionSepArg,    (caddr_t) NULL},
X    {"-count",	    ".count",	    XrmoptionSepArg,    (caddr_t) NULL},
X    {"-noisy",	    ".noisy",	    XrmoptionNoArg,     (caddr_t) "True"},
X};
X
X/*
X*  DON'T CHANGE THE ORDER OF THE ARGS IN THE VARIOUS ARG STRUCTS. IF
X*  YOU WANT TO ADD STUFF, ADD IT AT THE END OF THE STRUCT, BECAUSE WE
X*  REFER TO SOME OF THE ELEMENTS BY POSITION IN THE CODE.
X*/
X/* No spacing between the widgets on the Form */
static Arg form_args[] = {
X    {XtNdefaultDistance, (XtArgVal) 0},
X};
X
static Arg subform_args[] = {
X    {XtNfromVert, (XtArgVal) 0},
X    {XtNdefaultDistance, (XtArgVal) 2},
X    {XtNborderWidth, (XtArgVal) 0},
X    {XtNtop, (XtArgVal) XtChainTop},
X    {XtNbottom, (XtArgVal) XtChainTop}, /* ChainBottom causes strange resize */
X    {XtNright, (XtArgVal) XtChainRight},
X    {XtNleft, (XtArgVal) XtChainLeft},
X};
X
static Arg bar_args[] = {
X/*    {XtNfromHoriz, (XtArgVal) 0}, */
X    {XtNorientation, (XtArgVal) XtorientHorizontal},
X    {XtNborderWidth, (XtArgVal) 1},
X    {XtNlength, (XtArgVal) ((Dimension) 200)},
X    {XtNthickness, (XtArgVal) ((Dimension) 20)},
X    {XtNtop, (XtArgVal) XtChainTop},
X    {XtNbottom, (XtArgVal) XtChainTop},
X    {XtNright, (XtArgVal) XtChainRight},
X    {XtNleft, (XtArgVal) XtChainRight},
X    {XtNvertDistance, (XtArgVal) 0},
X/*    {XtNhorizDistance, (XtArgVal) 0}, */
X    {XtNresizable, (XtArgVal) FALSE},
X};
X
static Arg label_args[] = {
X    {XtNlabel, (XtArgVal) 0},
X    {XtNjustify, (XtArgVal) XtJustifyLeft},
X    {XtNborderWidth, (XtArgVal) 0},
X    {XtNtop, (XtArgVal) XtChainTop},
X    {XtNbottom, (XtArgVal) XtChainTop},
X    {XtNright, (XtArgVal) XtChainLeft},
X    {XtNleft, (XtArgVal) XtChainLeft},
X    {XtNvertDistance, (XtArgVal) 0},
X    {XtNhorizDistance, (XtArgVal) 0},
X    {XtNresizable, (XtArgVal) FALSE},
X};
X
static Arg gwid_args[] = {
X    {XtNwidth, (XtArgVal)0},
X};
X
static Arg sx_args[] = {
X    {XtNhorizDistance, (XtArgVal)0},
X};
X
void
usage()
X{
X    (void) fprintf(stderr,
X"usage: %s [Xt options] [-count iterations] [-interval delay_seconds] [-noisy] host ...\n",
X     progname);
X    exit(-1);
X}
X
char *
xmalloc(n)
int n;
X{
X    extern char *malloc();
X    char *cp = malloc((unsigned) n);
X    if (cp == NULL) {
X	    (void) fprintf(stderr, "%s: Ran out of memory.\n", progname);
X	    exit(-1);
X    }
X    return cp;
X}
X
extern XtInputCallbackProc	get_socket_msg();
X
static int nbars;
Widget *bar;
static char **barnames;
X    
main(argc, argv)
int argc;
char **argv;
X{
X    int i;
X    Widget topLevel;
X    Widget form, label;
X    Widget subform = NULL;
X    extern char *strchr(/* const char *, char */);
X    int maxwid;
X    extern int Clnt_multi_sock;
X
X    if ((progname = strchr(argv[0], '/')) == NULL)
X	progname = argv[0];
X    else
X	progname++;
X
X
X    topLevel = XtInitialize(progname, "RWHOHostMonitor",
X			    optionDescList, XtNumber(optionDescList),
X			    &argc, argv);
X
X    nbars = num_bars(argc, argv);
X    if (nbars == 0) {
X	(void) fprintf(stderr, "num_bars returned 0 - something is wrong\n");
X	exit(-1);
X    }
X    bar = (Widget *) xmalloc(nbars * sizeof(Widget));
X    barnames = label_bars(nbars, argc, argv);
X	
X    XtGetApplicationResources(topLevel, 0, application_resources,
X			      XtNumber(application_resources), NULL, 0 );
X
X    form = XtCreateManagedWidget("form", formWidgetClass, topLevel,
X				 form_args, XtNumber(form_args));
X    
X    maxwid = 0;
X    for(i = 0; i < nbars; i++) {
X#define FORMNAMEFMT	"form%d"
X	char formname[sizeof(FORMNAMEFMT) + 32];
X#define BARNAMEFMT	"bar%d"
X	char barname[sizeof(BARNAMEFMT) + 32];
X
X	if (i > 0)
X	    subform_args[0].value = (XtArgVal) subform;
X	(void) sprintf(formname, FORMNAMEFMT, i);
X	subform = XtCreateManagedWidget(formname, formWidgetClass, form,
X				 subform_args, XtNumber(subform_args));
X	label_args[0].value = (XtArgVal) barnames[i];
X	label = XtCreateManagedWidget(barnames[i], labelWidgetClass, subform,
X				      label_args, XtNumber(label_args));
X	XtSetArg(gwid_args[0], XtNwidth, 0);
X	XtGetValues(label, gwid_args, 1);
X	if (gwid_args[0].value > maxwid)
X	    maxwid = gwid_args[0].value;
X	(void) sprintf(barname, BARNAMEFMT, i);
X/*	bar_args[0].value = (XtArgVal) label; */
X	bar[i] = XtCreateManagedWidget(barname, barWidgetClass, subform,
X				    bar_args, XtNumber(bar_args));
X    }
X    sx_args[0].value = (XtArgVal)(maxwid + 2);
X    for(i = 0; i < nbars; i++)
X	XtSetValues(bar[i], sx_args, 1);
X
X    XtRealizeWidget(topLevel);
X
X    init_bars(nbars);
X
X    XtAddInput(Clnt_multi_sock, XtInputReadMask, get_socket_msg, (caddr_t)0);
X
X    XtMainLoop();
X}
X
void
draw_bar(i, states, nstates)
int i;
int states[];
int nstates;
X{
X    SetBarValues((Widget) bar[i], states, nstates);
X}
END_OF_FILE
if test 5923 -ne `wc -c <'xwhosup.c'`; then
    echo shar: \"'xwhosup.c'\" unpacked with wrong size!
fi
# end of 'xwhosup.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0