#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2000-06-23 15:55 EDT by <jdd@allen.cs>.
# Source directory was `/h/20/jdd/src/jdd/released/xcpustate'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#   1005 -rw-r--r-- COPYRIGHT
#   1565 -rw-r----- MANIFEST
#   3337 -rw-r--r-- README
#   8173 -rw-r--r-- Bar.c
#   1700 -rw-r--r-- Bar.h
#   1244 -rw-r--r-- BarP.h
#   2733 -rw-r--r-- Imakefile
#   2389 -rw-r----- Makefile.noimake
#    672 -rw-r----- array.h
#   1361 -rw-r----- levels.h
#    111 -rw-r--r-- patchlevel.h
#   4221 -rw-r--r-- rstat.c
#   3281 -rw-r----- rstat.h
#   4255 -rw-r--r-- rstat.x
#   3122 -rw-r----- rstat_clnt.c
#  21812 -rw-r----- rstat_xdr.c
#   2942 -rw-r--r-- s-bsd.c
#   3550 -rw-r----- s-bsd44.c
#   2829 -rw-r--r-- s-gould-np1.c
#   3883 -rw-r--r-- s-irix.c
#   3827 -rw-r--r-- s-mach.c
#   5043 -rw-r--r-- s-solbourne.c
#  12704 -rw-r--r-- s-sunos4.c
#   7501 -rw-r--r-- s-sunos5.c
#   5822 -rw-r--r-- s-ultrix.c
#   3332 -rw-r--r-- s-unicos.c
#  18420 -rw-r----- s-ncr.c
#  10160 -rw-r----- s-svr4.c
#   2268 -rw------- s-bsdi.c
#   4313 -rw-r--r-- s-aix.c
#   5461 -rw------- s-linux.c
#   1429 -rw-r--r-- s.c
#    315 -rw-r----- s.h
#  20882 -rw-r--r-- xcpustate.c
#   9995 -rw-r--r-- xcpustate.man
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh06559; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= COPYRIGHT ==============
if test -f 'COPYRIGHT' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'COPYRIGHT' '(file already exists)'
else
  $echo 'x -' extracting 'COPYRIGHT' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'COPYRIGHT' &&
/*
X * Copyright University of Toronto 1988, 1989, 1994, 1996, 1997, 1998.
X * (except where indicated otherwise in source file) 
X * by John DiMarco and 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(s) 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 */
SHAR_EOF
  $shar_touch -am 0305162998 'COPYRIGHT' &&
  chmod 0644 'COPYRIGHT' ||
  $echo 'restore of' 'COPYRIGHT' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'COPYRIGHT:' 'MD5 check failed'
d498642b8504a03e4f658b1a4772c101  COPYRIGHT
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'COPYRIGHT'`"
    test 1005 -eq "$shar_count" ||
    $echo 'COPYRIGHT:' 'original size' '1005,' 'current size' "$shar_count!"
  fi
fi
# ============= MANIFEST ==============
if test -f 'MANIFEST' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'MANIFEST' '(file already exists)'
else
  $echo 'x -' extracting 'MANIFEST' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'MANIFEST' &&
COPYRIGHT		Copyright notice
MANIFEST		This file
README			Read this file first
Bar.c			Bar widget routines
Bar.h			Bar widget public header file
BarP.h			Bar widget private header file
Imakefile		Imake configuration file
Makefile.noimake	makefile for sites without imake
array.h			Header file for Array abstract data type
levels.h		Header file defining gray levels 
patchlevel.h		Patch level/version
rstat.c			RSTAT routines
rstat.h			RSTAT header: generated by rpcgen rstat.x
rstat.x			RSTAT rpcgen source
rstat_clnt.c		RSTAT client source: generated by rpcgen rstat.x
rstat_xdr.c		RSTAT XDR structures: generated by rpcgen rstat.x
s-bsd.c			Machine dependent code for BSD 
s-bsd44.c		Machine dependent code for 4.4BSD systems (fooBSD)
s-gould-np1.c		Machine dependent code for Gould NP1
s-irix.c		Machine dependent code for SGI IRIX
s-mach.c		Machine dependent code for Mach
s-solbourne.c		Machine dependent code for Solbourne 4.x
s-sunos4.c		Machine dependent code for suns running SunOS 4.x
s-sunos5.c		Machine dependent code for SunOS 5.x / Solaris 2.x
s-ultrix.c		Machine dependent code for Ultrix multiprocessors
s-unicos.c		Machine dependent code for Cray UNICOS
s-ncr.c			Machine dependent code for NCR systems
s-svr4.c		Machine dependent code for generic SVR4 systems
s-bsdi.c		Machine dependent code for BSDI systems
s-aix.c			Machine dependent code for AIX systems
s-linux.c		Machine dependent code for LINUX systems
s.c			Wrapper for machine-dependent code
s.h			Header file for s.c
xcpustate.c		Main XCPUSTATE code
xcpustate.man		XCPUSTATE manual page
SHAR_EOF
  $shar_touch -am 0315181297 'MANIFEST' &&
  chmod 0640 'MANIFEST' ||
  $echo 'restore of' 'MANIFEST' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'MANIFEST:' 'MD5 check failed'
9f46145b2c09619de293b187b98012c0  MANIFEST
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MANIFEST'`"
    test 1565 -eq "$shar_count" ||
    $echo 'MANIFEST:' 'original size' '1565,' 'current size' "$shar_count!"
  fi
fi
# ============= README ==============
if test -f 'README' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'README' '(file already exists)'
else
  $echo 'x -' extracting 'README' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'README' &&
June 23, 2000
X
XXCPUSTATE is a snapshot performance monitor. It was originally written by
Mark Moraes to watch the load distribution on the CPUs on an Silicon Graphics
Iris 4D/240. It has since been ported to a wide variety of multiprocessors and
uniprocessors.
X
On some systems (eg. Suns),  XCPUSTATE can monitor disk performance, and on
Suns running SunOS 4.x, it can monitor OMNI network coprocessor performance.
It supports the RSTAT RPC protocol, and both tiled/stippled and
color/grayscale bars.
X
Native support for the following systems is included:
X
AIX 3.x and 4.x, BSD 4.3 and earlier, BSD 4.4 and derivitives
(FreeBSD, NetBSD, OpenBSD), BSDI, Gould NP1, SGI IRIX, MACH, NCR SVR4,
Solbourne OS/MP, SunOS 4.x, Solaris 2.x, USL SVR4, Digital Ultrix, Cray
UNICOS, Linux.  
X
If your system is not listed here, RSTAT RPC may still be used.
X
The latest version of xcpustate can be obtained via anonymous ftp from:
X    ftp://ftp.cs.toronto.edu/pub/jdd/xcpustate
X    ftp://ftp.x.org/contrib/utilities/
X
Installation Notes:
X
X	If you have imake, edit the Imakefile, paying special attention
X	to the DEFINES line.  Then generate the makefile using xmkmf and run
X	make to compile the application.
X
X	If you do not have imake, copy Makefile.noimake to Makefile, and
X	modify it for your system, paying special attention to the DEFS
X	line.  
X
X	For most (but not all) architectures, xcpustate must be installed 
X	with read privileges on /dev/kmem or equivalent. This generally 
X	requires that it be installed setgid kmem or setgid sys, or even 
X	setuid root. If xcpustate cannot read the kernel, it will not be able
X	to access the kernel variables it needs. However, xcpustate will
X	still be able to use the RSTAT protocol.
X
X	If you have difficulty compiling the rstat* files, and if you
X	have a functional rpcgen, you can regenerate them for your own
X	architecture by doing a "make veryclean" before typing "make".
X
Architecture-dependant notes:
X
X	For SunOS 4.x, add -DOMNI to MACHDEFS in the Imakefile (or 
X	Makefile.noimake) if you have and use OMNI NC400/NC600 network 
X	co-processors and want to include support for them.
X
X	For SunOS 5.x, xcpustate uses the kstat interface to access kernel
X	data, and thus read access to /dev/kmem is not necessary.
X
X	For AIX 4.x SMP support using Makefile.noimake, add -DSMP to
X	MACHDEFS.
X
X	For Linux, xcpustate uses /proc/stat, so read access to /dev/kmem
X	is not necessary.  To get separate bars per CPU for linux 2.0.x, apply
X	Jerome Forissie's per-cpu usage information patch for /proc/stat, from
X	"http://www-isia.cma.fr/~forissie/smp_kernel_patch/index.html"
X	(not necessary on later kernels). 
X	When this patch is applied, if desired, you can add -DSHOWAVG to
X	Imakefile or Makefile.noimake to show one more bar than the number of
X	CPUS available; the first bar is the average over all CPUs.
X
Porting Notes: 
X
X	It is sufficient to write an s-<machine>.c for the desired system,
X	and include it in s.c.  All system-dependent code is in the
X	appropriate s-<machine>.c file.  Use one of the existing files
X	as a template.
X
Regards,
X
John
--
John DiMarco <jdd@cs.toronto.edu>                         Office: SF2101
CSLab Systems Manager                                     Phone: 416-978-5300
University of Toronto                                     Fax:   416-978-1931
http://www.cs.toronto.edu/~jdd
SHAR_EOF
  $shar_touch -am 06231554100 'README' &&
  chmod 0644 'README' ||
  $echo 'restore of' 'README' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'README:' 'MD5 check failed'
21e50a569fd745ec93d801960bcf5008  README
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'README'`"
    test 3337 -eq "$shar_count" ||
    $echo 'README:' 'original size' '3337,' 'current size' "$shar_count!"
  fi
fi
# ============= Bar.c ==============
if test -f 'Bar.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'Bar.c' '(file already exists)'
else
  $echo 'x -' extracting 'Bar.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Bar.c' &&
/* #include <X11/copyright.h> */
X
/* $XConsortium: Bar.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
/* Copyright	Massachusetts Institute of Technology	1987, 1988 */
X
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include "array.h"
#include "BarP.h"
X
static Dimension def_dimension	= (Dimension)~0;
static XtOrientation def_orient = XtorientHorizontal;
static Boolean def_true = True;
X
#define DEF_LENGTH  ((Dimension) 200)
#define DEF_THICKNESS	((Dimension) 15)
X
/*
X * !! should provide converters for Arrays of some supported types, and
X * for fillstyles
X */
static XtResource resources[] = {
#define offset(field) XtOffset(BarWidget, bar.field)
#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    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X	offset(foreground), XtRString, XtDefaultForeground},
X    {XtNfillStyle, XtCFillStyle, XtRInt, sizeof(int),
X	offset(fillstyle), XtRInt, (caddr_t) 0},
X    {XtNpixmaps, XtCPixmaps, XtRArray, sizeof(Array *),
X	offset(pixmaps), XtRArray, (caddr_t) NULL},
#undef offset
#undef Offset
};
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 class fields */
X    /* extension		*/	NULL
X  }
};
X
WidgetClass barWidgetClass = (WidgetClass)&barClassRec;
X
static void
ClassInitialize()
{
X    XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
X		    NULL, (Cardinal)0 );
}
X
static void
SetDimensions(w)
BarWidget w;
{
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 * We can't use XtGetGC, since we're going to write to the GC, so we use
X * a simple caching scheme to share a gc between Bar widgets of the same
X * fillstyle on the same display.  The first Bar widget in gets to be
X * the GC we cache.  For most applications, all Bars will be on one
X * display and use the same fillStyle, we hope.
X */
static GC gc_cache;
static Display *dpy_cache;
static int fstyle_cache;
X
/* ARGSUSED */
static void
Initialize(request, new)
Widget request;		/* what the client asked for */
Widget new;		/* what we're going to give him */
{
X    BarWidget w = (BarWidget) new;
X    XGCValues gcv;
X    Display *dpy = XtDisplay(new);
X
X    if (dpy_cache == NULL || w->bar.fillstyle != fstyle_cache ||
X	dpy_cache != dpy) {
X	gcv.fill_style = w->bar.fillstyle;
X	gcv.foreground = w->bar.foreground;
X	gcv.background = w->core.background_pixel;
X	w->bar.gc = XCreateGC(dpy, DefaultRootWindow(dpy),
X			      GCFillStyle | GCForeground | GCBackground, &gcv);
X	if (dpy_cache == NULL) {
X	    dpy_cache = dpy;
X	    fstyle_cache = w->bar.fillstyle;
X	    gc_cache = w->bar.gc;
X	}
X    } else {
X	w->bar.gc = gc_cache;
X    }
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.values = NULL;
X    w->bar.nvalues = 0;
X
X    SetDimensions(w);
}
X
/* ARGSUSED */
static void
Resize(gw)
Widget gw;
{
X    SetDimensions((BarWidget)gw);
X    Redisplay(gw, (XEvent*)NULL, (Region)NULL);
}
X
/* ARGSUSED */
static void
Redisplay(gw, event, region)
Widget gw;
XXEvent *event;
Region region;
{
X    BarWidget w = (BarWidget) gw;
X    int x, y;
X    unsigned int width, height;
X    int maxvalue, i;
X    int vertical = (w->bar.orientation == XtorientVertical);;
X
X    if (! XtIsRealized(gw))
X	return;
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    if (w->bar.nvalues > w->bar.pixmaps->nitems) {
X	XtWarning("Too many values to represent in a bar");
X	return;
X    }
X    for(i = 0; i < w->bar.nvalues; i++) {
X	unsigned int rectlen = (w->bar.length * w->bar.values[i] +
X				maxvalue / 2) / (unsigned int)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	}
X	switch (w->bar.fillstyle) {
X	case FillSolid:
X	    XSetForeground(XtDisplay(gw), w->bar.gc,
X			   ((Pixel *) w->bar.pixmaps->items)[i]);
X	    break;
X	case FillTiled:
X	    XSetTile(XtDisplay(gw), w->bar.gc,
X			   ((Pixmap *) w->bar.pixmaps->items)[i]);
X	    break;
X	case FillStippled:
X	case FillOpaqueStippled:
X	    XSetStipple(XtDisplay(gw), w->bar.gc,
X			   ((Pixmap *) w->bar.pixmaps->items)[i]);
X	    break;
X	}
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
/* !! We really should make the widget support Xt{Get,Set}Values fully */
/* Public routines. */
void
SetBarValues(gw, values, nvalues)
Widget gw;
int *values;
int nvalues;
{
X    BarWidget w = (BarWidget) gw;
X    int i;
X
X    if (nvalues > w->bar.pixmaps->nitems) {
#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, w->bar.pixmaps->nitems);
#undef ERRFMT
X	XtWarning(errbuf);
X	nvalues = w->bar.pixmaps->nitems;
X    }
X    if (nvalues <= 0) {
#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);
#undef ERRFMT
X	return;
X    }
X    if (w->bar.values == NULL || w->bar.nvalues < nvalues) {
X	if (w->bar.values) XtFree((char *) w->bar.values);
X	w->bar.values = (int *) XtMalloc(nvalues * sizeof(int));
X    }
X    w->bar.nvalues = nvalues;
X    for(i = 0; i < nvalues; i++)
X	w->bar.values[i] = values[i];
X    Redisplay( gw, (XEvent*)NULL, (Region)NULL );
}
SHAR_EOF
  $shar_touch -am 0708190394 'Bar.c' &&
  chmod 0644 'Bar.c' ||
  $echo 'restore of' 'Bar.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'Bar.c:' 'MD5 check failed'
7b2d76d970a34985a91f7ce600efe235  Bar.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Bar.c'`"
    test 8173 -eq "$shar_count" ||
    $echo 'Bar.c:' 'original size' '8173,' 'current size' "$shar_count!"
  fi
fi
# ============= Bar.h ==============
if test -f 'Bar.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'Bar.h' '(file already exists)'
else
  $echo 'x -' extracting 'Bar.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Bar.h' &&
/* $XConsortium: Bar.h,v 1.2 88/10/25 17:22:09 swick Exp $ */
/* Copyright	Massachusetts Institute of Technology	1987, 1988 */
X
#ifndef _Bar_h
#define _Bar_h
X
/****************************************************************
X *
X * Bar widget
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 fillStyle	     FillStyle		Short		0
X pixmaps	     Pixmaps		Array		0
X
*/
X
/* declare specific BarWidget class and instance datatypes */
X
typedef struct _BarClassRec*	BarWidgetClass;
typedef struct _BarRec*		BarWidget;
X
/* declare barWidget name and class atoms */
/*
X * If FillStyle is solid, the array pixmaps contains the Pixels to use
X * for the display.  If FillStyle is FillTiled, the array contains the
X * Pixmaps to use for tiling, if FillStyle is FillStippled or
X * FillOpaqueStippled, then the array contains the Pixmaps to be used as
X * stipples.
X */
#define XtNfillStyle	"fillStyle"
#define XtCFillStyle	"FillStyle"
#define XtNpixmaps	"pixmaps"
#define XtCPixmaps	"Pixmaps"
X
/* declare the class constant */
X
extern WidgetClass barWidgetClass;
X
/* Public procedures */
extern void SetBarValues(/* BarWidget w, int *values, int nvalues */);
X
#endif  /* _Bar_h */
SHAR_EOF
  $shar_touch -am 0708185994 'Bar.h' &&
  chmod 0644 'Bar.h' ||
  $echo 'restore of' 'Bar.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'Bar.h:' 'MD5 check failed'
39808965b18550dd6f7eaef4eea5c2c4  Bar.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Bar.h'`"
    test 1700 -eq "$shar_count" ||
    $echo 'Bar.h:' 'original size' '1700,' 'current size' "$shar_count!"
  fi
fi
# ============= BarP.h ==============
if test -f 'BarP.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'BarP.h' '(file already exists)'
else
  $echo 'x -' extracting 'BarP.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'BarP.h' &&
/* $XConsortium: BarP.h,v 1.2 88/10/25 17:37:59 swick Exp $ */
/* Copyright	Massachusetts Institute of Technology	1987, 1988 */
X
#ifndef _BarP_h
#define _BarP_h
X
#include <X11/Xmu/Xmu.h>
#include "Bar.h"
X
/* define unique representation types not found in <X11/StringDefs.h> */
X
#define MAXGRAY 10
X
typedef struct {
X    caddr_t	extension;	/* C compiler needs one field at least */
} BarClassPart;
X
typedef struct _BarClassRec {
X    CoreClassPart	core_class;
X    BarClassPart	bar_class;
} BarClassRec;
X
extern BarClassRec barClassRec;
X
typedef struct {
X    /* private state */
X    int *values;		/* Array of values displayed in bar */
X    int nvalues;		/* Number of elements in values */
X    Boolean	  paintTile;	/* if true, use tiling instead of stippling */
X    XtOrientation orientation;	/* XtorientHorizontal or XtorientVertical */
X    Dimension	  length;	/* either height or width */
X    Dimension	  thickness;	/* either width or height */
X    int		  fillstyle;	/* fillstyle to use for XFillRectangle */
X    Pixel	  foreground;	/* foreground colour */
X    Array	  *pixmaps;	/* pixels/tiles/stipples to use */
X    GC		  gc;		/* a gc */
} BarPart;
X
typedef struct _BarRec {
X    CorePart	core;
X    BarPart	bar;
} BarRec;
X
#endif  /* _BarP_h */
SHAR_EOF
  $shar_touch -am 0708200594 'BarP.h' &&
  chmod 0644 'BarP.h' ||
  $echo 'restore of' 'BarP.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'BarP.h:' 'MD5 check failed'
2cb081e55dfeb2dfe1e43f03fd9306f0  BarP.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'BarP.h'`"
    test 1244 -eq "$shar_count" ||
    $echo 'BarP.h:' 'original size' '1244,' 'current size' "$shar_count!"
  fi
fi
# ============= Imakefile ==============
if test -f 'Imakefile' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'Imakefile' '(file already exists)'
else
  $echo 'x -' extracting 'Imakefile' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Imakefile' &&
X        DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
LOCAL_LIBRARIES = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
X           SRCS = xcpustate.c Bar.c s.c rstat.c rstat_clnt.c rstat_xdr.c
X           OBJS = xcpustate.o Bar.o s.o rstat.o rstat_clnt.o rstat_xdr.o
X   INSTPGMFLAGS = InstPgmFlags InstKmemFlags
/*
X *  Things to consider adding to DEFINES:
X *
X *  -DRSTAT -- support the rstat protocol for querying the rstatd running
X *             on remote machines (using the -host option).  There's no harm 
X *             in leaving this in, unless you think your users will query
X *             machines they shouldn't.
X *  -DSHOWAVG -- this has no effect except on Linux machines.  If defined,
X *             a CPU bar showing the "average" CPU will be added.  
X *  -DDEF_FONT -- the default font.  Leave this alone unless you don't want
X *             to use the X default font (XtdefaultFont).  To force
X *             a particular font, e.g. 9x15, -DDEF_FONT=\"9x15" will work.
X *  -DDEF_INTERVAL -- the default update interval, normally 1 second.  This is
X *             used when one isn't specified via the command line or an X 
X *             resource. e.g. -DDEF_INTERVAL=2.5
X *  -DINTERVAL_MIN -- the minimum interval, normally 0 seconds.  Set this
X *             to something greater to keep xcpustate from overloading your
X *             network or x-server with traffic, which it can easily do if
X *             a small interval (e.g. 0.01 seconds) is specified.  For example,
X *             to prevent intervals less than half a second, use 
X *             -DINTERVAL_MIN=0.5
X */
X        DEFINES = $(SYSTYPE) -DRSTAT
X
#if defined(MACH)
X  SYS_LIBRARIES = -lmach
#endif /* MACH */
X
#if defined(SparcArchitecture) && OSMajorVersion == 4
X  SYS_LIBRARIES = -lkvm
X        /* add -DOMNI if you have OMNI nc400s */
X        SYSTYPE = -DSUNOS4
#endif
X
#if defined(SVR4)
X  SYS_LIBRARIES = -lelf
#endif
X
#if defined(SGIArchitecture) 
X        SYSTYPE = -DIRIX
#endif
X
#if ( defined(SunArchitecture) || defined(SparcArchitecture)) && OSMajorVersion == 5
X  SYS_LIBRARIES = -lkstat -lelf
X        SYSTYPE = -DSUNOS5
X   INSTPGMFLAGS = InstPgmFlags 
#endif
X
#if defined(AIXArchitecture) || defined(_AIX) || defined(AIX) || defined(aix)
#if OSMajorVersion > 3
X        SYSTYPE = -DSMP
#endif 
#endif
X
#if defined (FreeBSDArchitecture) || defined(NetBSDArchitecture) || defined(OpenBSDArchitecture)
X    SYS_LIBRARIES = -lkvm
#endif
X
ComplexProgramTarget(xcpustate)
X
rstat.c: rstat.h
X
rstat.h rstat_clnt.c rstat_xdr.c: rstat.x
X	rpcgen rstat.x
X
xcpustate.c: levels.h
X
shar:
X	shar `awk '{print $$1}' MANIFEST` >xcpustate-`awk '{print $$7;exit}' patchlevel.h`.shar
X
veryclean: clean
X	$(RM) rstat_* rstat.h xcpustate-*.shar Makefile
SHAR_EOF
  $shar_touch -am 0305181698 'Imakefile' &&
  chmod 0644 'Imakefile' ||
  $echo 'restore of' 'Imakefile' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'Imakefile:' 'MD5 check failed'
9535d6bb24607472f0f460bc52c02c98  Imakefile
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Imakefile'`"
    test 2733 -eq "$shar_count" ||
    $echo 'Imakefile:' 'original size' '2733,' 'current size' "$shar_count!"
  fi
fi
# ============= Makefile.noimake ==============
if test -f 'Makefile.noimake' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'Makefile.noimake' '(file already exists)'
else
  $echo 'x -' extracting 'Makefile.noimake' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Makefile.noimake' &&
SRCS= xcpustate.c Bar.c s.c rstat.c rstat_clnt.c rstat_xdr.c 
OBJS= $(SRCS:.c=.o)
X
#  Things to consider adding to DEFS:
#
#  -DRSTAT -- support the rstat protocol for querying the rstatd running
#             on remote machines (using the -host option).  There's no harm 
#             in leaving this in, unless you think your users will query
#             machines they shouldn't.
#  -DSHOWAVG -- this has no effect except on Linux machines.  If defined,
#             a CPU bar showing the "average" CPU will be added.  
#  -DDEF_FONT -- the default font.  Leave this alone unless you don't want
#             to use the X default font (XtdefaultFont).  To force
#             a particular font, e.g. 9x15, -DDEF_FONT=\"9x15" will work.
#  -DDEF_INTERVAL -- the default update interval, normally 1 second.  This is
#             used when one isn't specified via the command line or an X 
#             resource. e.g. -DDEF_INTERVAL=2.5
#  -DINTERVAL_MIN -- the minimum interval, normally 0 seconds.  Set this
#             to something greater to keep xcpustate from overloading your
#             network or x-server with traffic, which it can easily do if
#             a small interval (e.g. 0.01 seconds) is specified.  For example,
#             to prevent intervals less than half a second, use 
#             -DINTERVAL_MIN=0.5
X
DEFS= -DRSTAT
CC= cc
RM= rm -f
SHAR= shar
X
# edit the MACH* flags for your architecture
X
# SunOS 4.x/openwin
X
# MACHDEFS= -DSUNOS4 # -DOMNI
# MACHLIBS= -lkvm
# MACHLIBDIR= -L/usr/openwin/lib
# MACHINCDIR= -I/usr/openwin/include
X
# SunOS 5.x/openwin
X
# MACHDEFS= -DSUNOS5
# MACHLIBS= -lkstat -lelf -lsocket -lnsl -lgen
# MACHLIBDIR= -L/usr/openwin/lib -R/usr/openwin/lib
# MACHINCDIR= -I/usr/openwin/include
X
# AIX 4.x
X
# MACHDEFS= -DSMP -DSYSV
# MACHLIBS= 
# MACHLIBDIR=
# MACHINCDIR= 
X
# Put definitions for your own machine here, if necessary.
X
MACHDEFS= 
MACHLIBS= 
MACHLIBDIR=
MACHINCDIR= 
X
CFLAGS = -O $(MACHINCDIR) $(DEFS) $(MACHDEFS)
X
XXLIBS= -lXaw -lXmu -lXt -lXext -lX11
LIBDIR= $(MACHLIBDIR)
X
xcpustate: $(OBJS)
X	$(CC) -o $@ $(OBJS) $(LIBDIR) $(XLIBS) $(MACHLIBS)
X
clean: 
X	$(RM) *.o xcpustate
X
veryclean: clean
X	$(RM) rstat_* rstat.h xcpustate-*.shar Makefile
X
shar:
X	$(SHAR) `awk '{print $$1}' MANIFEST` >xcpustate-`awk '{print $$7;exit}' patchlevel.h`.shar
X
rstat.c: rstat.h
X
rstat.h rstat_clnt.c rstat_xdr.c: rstat.x
X	rpcgen rstat.x
X
SHAR_EOF
  $shar_touch -am 0305181598 'Makefile.noimake' &&
  chmod 0640 'Makefile.noimake' ||
  $echo 'restore of' 'Makefile.noimake' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'Makefile.noimake:' 'MD5 check failed'
fbfc6ff83945f58b1b325a9126cad2e3  Makefile.noimake
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile.noimake'`"
    test 2389 -eq "$shar_count" ||
    $echo 'Makefile.noimake:' 'original size' '2389,' 'current size' "$shar_count!"
  fi
fi
# ============= array.h ==============
if test -f 'array.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'array.h' '(file already exists)'
else
  $echo 'x -' extracting 'array.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'array.h' &&
#ifndef array_h_
#define array_h_
X
/*
X * Structure in which to store counted arrays of fixed size objects.
X * The items element is a pointer to a block of memory, presumably
X * holding nitems.  The user should cast it to the proper type; as with
X * a union, it is the users responsibility to store and retrieve the
X * same type of information -- the itemtype field can be used to store
X * type codes for validation and checking, or the size of the objects.
X */
typedef struct {
X	int itemtype;
X	int nitems;
X	caddr_t items;
} Array;
X
#define XtNarray	"array"
#define XtRArray	"Array"
#define XtCArray	"Array"
X
#endif /* array_h_ */ /* Do not add anything after this line */
SHAR_EOF
  $shar_touch -am 0408190394 'array.h' &&
  chmod 0640 'array.h' ||
  $echo 'restore of' 'array.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'array.h:' 'MD5 check failed'
2004e0d1dce91dfe8c429ca7bb418abf  array.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'array.h'`"
    test 672 -eq "$shar_count" ||
    $echo 'array.h:' 'original size' '672,' 'current size' "$shar_count!"
  fi
fi
# ============= levels.h ==============
if test -f 'levels.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'levels.h' '(file already exists)'
else
  $echo 'x -' extracting 'levels.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'levels.h' &&
/* Levels of bar intensity */
X
#define MAXLEVELS 10 
X
/* mapping of grays to levels; intended to maximize contrast */
static int level_mapping[MAXLEVELS][MAXLEVELS] = {
X	{ 9 },
X	{ 0, 9 },
X	{ 0, 4, 9 },
X	{ 0, 3, 6, 9 },
X	{ 0, 2, 4, 7, 9 },
X	{ 0, 1, 3, 5, 7, 9 },
X	{ 0, 1, 3, 5, 7, 8, 9 },
X	{ 0, 1, 2, 3, 5, 7, 8, 9 },
X	{ 0, 1, 2, 3, 5, 6, 7, 8, 9 },
X	{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
};
X
/* Gray bitmaps */
X
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   ~0x0, ~0x0, ~0x0};
X
static char *gray_bits[] = {
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
/* Gray colors */
static char graycolornames[] = 
"gray99,gray90,gray81,gray72,gray63,gray54,gray45,gray36,gray27,gray18";
X
/* Default non-gray colors */
static char colornames[] = 
"blue,green,yellow,red,cyan,magenta,purple,maroon,navyblue,black";
SHAR_EOF
  $shar_touch -am 0708200494 'levels.h' &&
  chmod 0640 'levels.h' ||
  $echo 'restore of' 'levels.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'levels.h:' 'MD5 check failed'
4a8840bbfd88ba41a41b7a809fbaa763  levels.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'levels.h'`"
    test 1361 -eq "$shar_count" ||
    $echo 'levels.h:' 'original size' '1361,' 'current size' "$shar_count!"
  fi
fi
# ============= patchlevel.h ==============
if test -f 'patchlevel.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'patchlevel.h' '(file already exists)'
else
  $echo 'x -' extracting 'patchlevel.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'patchlevel.h' &&
static char patchlevel[] = "xcpustate Version 2.6beta $Id: patchlevel.h,v 1.15 2000/06/23 19:44:47 jdd Exp $";
SHAR_EOF
  $shar_touch -am 06231544100 'patchlevel.h' &&
  chmod 0644 'patchlevel.h' ||
  $echo 'restore of' 'patchlevel.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'patchlevel.h:' 'MD5 check failed'
684c1eb3d54849137bd183ead10f43cc  patchlevel.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'patchlevel.h'`"
    test 111 -eq "$shar_count" ||
    $echo 'patchlevel.h:' 'original size' '111,' 'current size' "$shar_count!"
  fi
fi
# ============= rstat.c ==============
if test -f 'rstat.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'rstat.c' '(file already exists)'
else
  $echo 'x -' extracting 'rstat.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'rstat.c' &&
/* 
X * rstat RPC code
X */
/* John DiMarco, CSLab, University of Toronto <jdd@cs.toronto.edu> */
X
#ifdef RSTAT
X
/* LINTLIBRARY */
#define MULTIPROCESSOR
X
#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <rpc/rpc.h>
#include "rstat.h"
X
/* most typical cpu states; for BSD systems */
#define CP_USER         0
#define CP_NICE         1
#define CP_SYS          2
#define CP_IDLE         3
X
#ifndef MAXDISKXFER
#define MAXDISKXFER 100
#endif /* MAXDISKXFER */
X
#define DISKSTATES 2 /* idle, transfer */
X
int ncpu;       /* number of CPUs */
int ndisk;      /* number of disks */
X
#define BUFFSIZE 64
X
#ifndef MAXHOSTNAMELEN
X  /* Some U*x deviants managed to not have this in sys/param.h */
# define MAXHOSTNAMELEN 64
#endif
X
static statstime *sts;
X
static CLIENT *cl;
X
extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X
extern char *rstathost;
extern int cpuflag, diskflag;
X
extern char *xmalloc(/* int nbytes */);
extern void shorten(/* char *hname */);
X
/* Called at the beginning to inquire how many bars are needed. */
int
rstat_num_bars()
{
X	int nbars=0;
X
X	if(NULL==(cl=clnt_create(rstathost, RSTATPROG, RSTATVERS_TIME, "udp"))){
X		clnt_pcreateerror(rstathost);
X		exit(1);
X	}
X
X	if(cpuflag){
X		ncpu=1; /* rstat only supports uniprocessors */
X		nbars += ncpu;
X	}
X	if(diskflag){
X		ndisk=RSTAT_DK_NDRIVE;
X		nbars += ndisk;
X	}
X	return(nbars);
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
rstat_bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i, n=0;
X
X    if(cpuflag){
X        for(i=0; i<ncpu; i++,n++){
X                items[n] = RSTAT_CPUSTATES;
X        }
X    }
X    if(diskflag){
X	for(i=0; i<ndisk; i++,n++){
X		items[n] = DISKSTATES;
X	}
X    }
}
X
/* Called after num_bars to ask for the bar names */
char **
rstat_label_bars(nbars)
{
X        char **names;
X        int i, base;
X        static char hname[MAXHOSTNAMELEN + 1];
X	char buf[MAXHOSTNAMELEN + 1 + BUFFSIZE];
X	char *cpname="";
X
X	(void)strcpy(hname, rstathost);
X        shorten(hname);
X        names = (char **) xmalloc(nbars * sizeof(char *));
X
X	base=0; 
X
X	if(cpuflag) {
X		/* do cpu names */
X		for(i=0; i<ncpu; i++) {
X			(void) sprintf(buf, "%s%s%s%d", hname, 
X					hname[0]?" ":"", cpname, i);
X			names[base+i] = xmalloc(strlen(buf) + 1);
X			strcpy(names[base+i], buf);
X		}
X		base+=ncpu;
X	}
X	if(diskflag) {
X		/* do disk names */
X		for(i=0; i <ndisk; i++) {
X			(void) sprintf(buf, "%s%sd%d", hname, hname[0]?" ":"", 
X					i);
X			names[base+i] = xmalloc(strlen(buf) + 1);
X			strcpy(names[base+i], buf);
X		}
X		base+=ndisk;
X        }
X        return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
rstat_init_bars(nbars)
int nbars;
{
}
X
static void
display_cpu(base)
int base;
{
X	int states[RSTAT_CPUSTATES], i;
X	static long old[RSTAT_CPUSTATES];
X
X	states[0] = (long)(sts->cp_time[CP_IDLE] - old[CP_IDLE]);
X	states[1] = (long)(sts->cp_time[CP_NICE] - old[CP_NICE]);
X	states[2] = (long)(sts->cp_time[CP_USER] - old[CP_USER]);
X	states[3] = (long)(sts->cp_time[CP_SYS] - old[CP_SYS]);
X	for(i=0;i<RSTAT_CPUSTATES;i++) old[i]=sts->cp_time[i];
X	draw_bar(base, states, RSTAT_CPUSTATES);
}
X
static void
display_disk(base)
int base;
{
X	int states[2], i;
X	static long old[RSTAT_DK_NDRIVE];
X
X	for(i=0;i<RSTAT_DK_NDRIVE;i++){
X		long xfer;
X
X		xfer = sts->dk_xfer[i]-old[i];
X		if(xfer>MAXDISKXFER) xfer=MAXDISKXFER;
X		states[0] = MAXDISKXFER - xfer;
X		states[1] = xfer;
X		draw_bar(base+i, states, 2);
X		old[i] = sts->dk_xfer[i];
X	}
}
X
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
rstat_display_bars(nbars)
int nbars;
{
X	int n=0;
X	if(NULL==(sts=rstatproc_stats_3((void *)NULL, cl))){
X		clnt_perror(cl, rstathost);
X		exit(1);
X	}
X	if(cpuflag) {
X		display_cpu(n);
X		n+=ncpu;
X	}
X	if(diskflag) {
X		display_disk(n);
X		n+=ndisk;
X	}
}
X
#endif /* RSTAT */
SHAR_EOF
  $shar_touch -am 0728164799 'rstat.c' &&
  chmod 0644 'rstat.c' ||
  $echo 'restore of' 'rstat.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'rstat.c:' 'MD5 check failed'
7d3ea966d439f72a82eca6d915387e35  rstat.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rstat.c'`"
    test 4221 -eq "$shar_count" ||
    $echo 'rstat.c:' 'original size' '4221,' 'current size' "$shar_count!"
  fi
fi
# ============= rstat.h ==============
if test -f 'rstat.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'rstat.h' '(file already exists)'
else
  $echo 'x -' extracting 'rstat.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'rstat.h' &&
/*
X * Please do not edit this file.
X * It was generated using rpcgen.
X */
X
#ifndef _RSTAT_H_RPCGEN
#define	_RSTAT_H_RPCGEN
X
#include <rpc/rpc.h>
/*
X * Copyright (c) 1985, 1990, 1991 by Sun Microsystems, Inc.
X */
/* from rstat.x */
X
#pragma ident	"@(#)rstat.x	1.2	92/07/14 SMI"
X
#ifndef FSCALE
/*
X * Scale factor for scaled integers used to count load averages.
X */
#define FSHIFT  8               /* bits to right of fixed binary point */
#define FSCALE  (1<<FSHIFT)
X
#endif /* ndef FSCALE */
#ifndef DST_NONE
#include <sys/time.h>          /* The time struct defined below is meant to */
#endif                         /* match struct timeval.                     */
X
X
X
X
X
X
#define	RSTAT_CPUSTATES 4
#define	RSTAT_DK_NDRIVE 4
X
struct rstat_timeval {
X	long tv_sec;
X	long tv_usec;
};
typedef struct rstat_timeval rstat_timeval;
X
struct statsvar {
X	struct {
X		u_int cp_time_len;
X		int *cp_time_val;
X	} cp_time;
X	struct {
X		u_int dk_xfer_len;
X		int *dk_xfer_val;
X	} dk_xfer;
X	u_int v_pgpgin;
X	u_int v_pgpgout;
X	u_int v_pswpin;
X	u_int v_pswpout;
X	u_int v_intr;
X	int if_ipackets;
X	int if_ierrors;
X	int if_opackets;
X	int if_oerrors;
X	int if_collisions;
X	u_int v_swtch;
X	long avenrun[3];
X	rstat_timeval boottime;
X	rstat_timeval curtime;
};
typedef struct statsvar statsvar;
X
struct statstime {
X	int cp_time[RSTAT_CPUSTATES];
X	int dk_xfer[RSTAT_DK_NDRIVE];
X	u_int v_pgpgin;
X	u_int v_pgpgout;
X	u_int v_pswpin;
X	u_int v_pswpout;
X	u_int v_intr;
X	int if_ipackets;
X	int if_ierrors;
X	int if_oerrors;
X	int if_collisions;
X	u_int v_swtch;
X	long avenrun[3];
X	rstat_timeval boottime;
X	rstat_timeval curtime;
X	int if_opackets;
};
typedef struct statstime statstime;
X
struct statsswtch {
X	int cp_time[RSTAT_CPUSTATES];
X	int dk_xfer[RSTAT_DK_NDRIVE];
X	u_int v_pgpgin;
X	u_int v_pgpgout;
X	u_int v_pswpin;
X	u_int v_pswpout;
X	u_int v_intr;
X	int if_ipackets;
X	int if_ierrors;
X	int if_oerrors;
X	int if_collisions;
X	u_int v_swtch;
X	u_int avenrun[3];
X	rstat_timeval boottime;
X	int if_opackets;
};
typedef struct statsswtch statsswtch;
X
struct stats {
X	int cp_time[RSTAT_CPUSTATES];
X	int dk_xfer[RSTAT_DK_NDRIVE];
X	u_int v_pgpgin;
X	u_int v_pgpgout;
X	u_int v_pswpin;
X	u_int v_pswpout;
X	u_int v_intr;
X	int if_ipackets;
X	int if_ierrors;
X	int if_oerrors;
X	int if_collisions;
X	int if_opackets;
};
typedef struct stats stats;
X
#define	RSTATPROG ((unsigned long)(100001))
#define	RSTATVERS_VAR ((unsigned long)(4))
#define	RSTATPROC_STATS ((unsigned long)(1))
extern  statsvar * rstatproc_stats_4();
#define	RSTATPROC_HAVEDISK ((unsigned long)(2))
extern  u_int * rstatproc_havedisk_4();
extern int rstatprog_4_freeresult();
#define	RSTATVERS_TIME ((unsigned long)(3))
extern  statstime * rstatproc_stats_3();
extern  u_int * rstatproc_havedisk_3();
extern int rstatprog_3_freeresult();
#define	RSTATVERS_SWTCH ((unsigned long)(2))
extern  statsswtch * rstatproc_stats_2();
extern  u_int * rstatproc_havedisk_2();
extern int rstatprog_2_freeresult();
#define	RSTATVERS_ORIG ((unsigned long)(1))
extern  stats * rstatproc_stats_1();
extern  u_int * rstatproc_havedisk_1();
extern int rstatprog_1_freeresult();
X
/* the xdr functions */
extern bool_t xdr_rstat_timeval();
extern bool_t xdr_statsvar();
extern bool_t xdr_statstime();
extern bool_t xdr_statsswtch();
extern bool_t xdr_stats();
X
#endif /* !_RSTAT_H_RPCGEN */
SHAR_EOF
  $shar_touch -am 0728151499 'rstat.h' &&
  chmod 0640 'rstat.h' ||
  $echo 'restore of' 'rstat.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'rstat.h:' 'MD5 check failed'
6abae9bf8fc9fac7d822b79d82a05fd7  rstat.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rstat.h'`"
    test 3281 -eq "$shar_count" ||
    $echo 'rstat.h:' 'original size' '3281,' 'current size' "$shar_count!"
  fi
fi
# ============= rstat.x ==============
if test -f 'rstat.x' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'rstat.x' '(file already exists)'
else
  $echo 'x -' extracting 'rstat.x' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'rstat.x' &&
%/*
% * Copyright (c) 1985, 1990, 1991 by Sun Microsystems, Inc.
% */
X
%/* from rstat.x */
X
/*
X * Gather statistics on remote machines
X */
X
#ifdef RPC_HDR
%
%#pragma ident	"@(#)rstat.x	1.2	92/07/14 SMI"
%
%#ifndef FSCALE
%/*
% * Scale factor for scaled integers used to count load averages.
% */
%#define FSHIFT  8               /* bits to right of fixed binary point */
%#define FSCALE  (1<<FSHIFT)
%
%#endif /* ndef FSCALE */
X
%#ifndef DST_NONE
%#include <sys/time.h>          /* The time struct defined below is meant to */
%#endif                         /* match struct timeval.                     */
%
%
%
%
%
%
#elif RPC_SVC
%
%/*
% *  Server side stub routines for the rstat daemon
% */
%
#elif RPC_CLNT
%
%/*
% *  Client side stub routines for the rstat daemon
% */
%
#elif RPC_XDR
%/*
% * XDR routines for the rstat daemon, rup and perfmeter.
% */
%
%/*
% * xdr_timeval was used in previous releases.
% */
%
%bool_t
%#ifdef __STDC__
%xdr_timeval(XDR *xdrs, struct timeval *tvp)
%#else /* K&R C */
%xdr_timeval(xdrs, tvp)
%	XDR *xdrs;
%	struct timeval *tvp;
%#endif /* K&R C */
%{
%	return (xdr_rstat_timeval(xdrs, tvp));
%}
X
%
#endif
X
const RSTAT_CPUSTATES = 4;
const RSTAT_DK_NDRIVE = 4;
X
/*
X * GMT since 0:00, January 1, 1970
X */
struct rstat_timeval {
X	long tv_sec;	/* seconds */
X	long tv_usec;	/* and microseconds */
};
X
struct statsvar {				/* RSTATVERS_VAR */
X	int cp_time<>; 		/* variable number of CPU states */
X	int dk_xfer<>;		/* variable number of disks */
X	unsigned v_pgpgin;	/* these are cumulative sum */
X	unsigned v_pgpgout;
X	unsigned v_pswpin;
X	unsigned v_pswpout;
X	unsigned v_intr;
X	int if_ipackets;
X	int if_ierrors;
X	int if_opackets;
X	int if_oerrors;
X	int if_collisions;
X	unsigned v_swtch;
X	long avenrun[3];
X	rstat_timeval boottime;
X	rstat_timeval curtime;
};
X
struct statstime {				/* RSTATVERS_TIME */
X	int cp_time[RSTAT_CPUSTATES];
X	int dk_xfer[RSTAT_DK_NDRIVE];
X	unsigned int v_pgpgin;	/* these are cumulative sum */
X	unsigned int v_pgpgout;
X	unsigned int v_pswpin;
X	unsigned int v_pswpout;
X	unsigned int v_intr;
X	int if_ipackets;
X	int if_ierrors;
X	int if_oerrors;
X	int if_collisions;
X	unsigned int v_swtch;
X	long avenrun[3];
X	rstat_timeval boottime;
X	rstat_timeval curtime;
X	int if_opackets;
};
X
struct statsswtch {                     /* RSTATVERS_SWTCH */
X        int cp_time[RSTAT_CPUSTATES];
X        int dk_xfer[RSTAT_DK_NDRIVE];
X        unsigned int v_pgpgin;  /* these are cumulative sum */
X        unsigned int v_pgpgout;
X        unsigned int v_pswpin;
X        unsigned int v_pswpout;
X        unsigned int v_intr;
X        int if_ipackets;
X        int if_ierrors;
X        int if_oerrors;
X        int if_collisions;
X        unsigned int v_swtch;
X        unsigned int avenrun[3];/* scaled by FSCALE */
X        rstat_timeval boottime;
X        int if_opackets;
};
X
struct stats {                          /* RSTATVERS_ORIG */
X        int cp_time[RSTAT_CPUSTATES];
X        int dk_xfer[RSTAT_DK_NDRIVE];
X        unsigned int v_pgpgin;  /* these are cumulative sum */
X        unsigned int v_pgpgout;
X        unsigned int v_pswpin;
X        unsigned int v_pswpout;
X        unsigned int v_intr;
X        int if_ipackets;
X        int if_ierrors;
X        int if_oerrors;
X        int if_collisions;
X        int if_opackets;
};
X
program RSTATPROG {
X        /*
X         * Version 4 allows for variable number of disk and RSTAT_CPU states.
X         */
X	version RSTATVERS_VAR {
X		statsvar
X		RSTATPROC_STATS (void) = 1;
X		unsigned int
X		RSTATPROC_HAVEDISK (void) = 2;
X	} = 4;
X	/*
X	 * Newest version includes current time and context switching info
X	 */
X	version RSTATVERS_TIME {
X		statstime
X		RSTATPROC_STATS(void) = 1;
X		unsigned int
X		RSTATPROC_HAVEDISK(void) = 2;
X	} = 3;
X        /*
X         * Does not have current time
X         */
X        version RSTATVERS_SWTCH {
X                statsswtch
X                RSTATPROC_STATS(void) = 1;
X  
X                unsigned int
X                RSTATPROC_HAVEDISK(void) = 2;
X        } = 2;
X        /*
X         * Old version has no info about current time or context switching
X         */
X        version RSTATVERS_ORIG {
X                stats
X                RSTATPROC_STATS(void) = 1;
X  
X                unsigned int
X                RSTATPROC_HAVEDISK(void) = 2;
X        } = 1;
} = 100001;
SHAR_EOF
  $shar_touch -am 0728151499 'rstat.x' &&
  chmod 0644 'rstat.x' ||
  $echo 'restore of' 'rstat.x' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'rstat.x:' 'MD5 check failed'
a79d7d2b092a1294095d3d3c88221a23  rstat.x
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rstat.x'`"
    test 4255 -eq "$shar_count" ||
    $echo 'rstat.x:' 'original size' '4255,' 'current size' "$shar_count!"
  fi
fi
# ============= rstat_clnt.c ==============
if test -f 'rstat_clnt.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'rstat_clnt.c' '(file already exists)'
else
  $echo 'x -' extracting 'rstat_clnt.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'rstat_clnt.c' &&
/*
X * Please do not edit this file.
X * It was generated using rpcgen.
X */
X
#include "rstat.h"
/*
X * Copyright (c) 1985, 1990, 1991 by Sun Microsystems, Inc.
X */
/* from rstat.x */
X
/*
X *  Client side stub routines for the rstat daemon
X */
X
X
/* Default timeout can be changed using clnt_control() */
static struct timeval TIMEOUT = { 25, 0 };
X
statsvar *
rstatproc_stats_4(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static statsvar clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_STATS,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_statsvar, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
u_int *
rstatproc_havedisk_4(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static u_int clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_HAVEDISK,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_u_int, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
statstime *
rstatproc_stats_3(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static statstime clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_STATS,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_statstime, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
u_int *
rstatproc_havedisk_3(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static u_int clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_HAVEDISK,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_u_int, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
statsswtch *
rstatproc_stats_2(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static statsswtch clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_STATS,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_statsswtch, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
u_int *
rstatproc_havedisk_2(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static u_int clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_HAVEDISK,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_u_int, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
stats *
rstatproc_stats_1(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static stats clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_STATS,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_stats, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
X
u_int *
rstatproc_havedisk_1(argp, clnt)
X	void *argp;
X	CLIENT *clnt;
{
X	static u_int clnt_res;
X
X	memset((char *)&clnt_res, 0, sizeof (clnt_res));
X	if (clnt_call(clnt, RSTATPROC_HAVEDISK,
X		(xdrproc_t) xdr_void, (caddr_t) argp,
X		(xdrproc_t) xdr_u_int, (caddr_t) &clnt_res,
X		TIMEOUT) != RPC_SUCCESS) {
X		return (NULL);
X	}
X	return (&clnt_res);
}
SHAR_EOF
  $shar_touch -am 0728151499 'rstat_clnt.c' &&
  chmod 0640 'rstat_clnt.c' ||
  $echo 'restore of' 'rstat_clnt.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'rstat_clnt.c:' 'MD5 check failed'
d58893124119d813f30cc70a2b8166eb  rstat_clnt.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rstat_clnt.c'`"
    test 3122 -eq "$shar_count" ||
    $echo 'rstat_clnt.c:' 'original size' '3122,' 'current size' "$shar_count!"
  fi
fi
# ============= rstat_xdr.c ==============
if test -f 'rstat_xdr.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'rstat_xdr.c' '(file already exists)'
else
  $echo 'x -' extracting 'rstat_xdr.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'rstat_xdr.c' &&
/*
X * Please do not edit this file.
X * It was generated using rpcgen.
X */
X
#ifndef CRAY1
#ifndef inline_t 
#define inline_t long
#endif /* !inline_t */
#endif /* !CRAY1 */
X
#include "rstat.h"
/*
X * Copyright (c) 1985, 1990, 1991 by Sun Microsystems, Inc.
X */
/* from rstat.x */
/*
X * XDR routines for the rstat daemon, rup and perfmeter.
X */
X
/*
X * xdr_timeval was used in previous releases.
X */
X
bool_t
#ifdef __STDC__
xdr_timeval(XDR *xdrs, struct timeval *tvp)
#else /* K&R C */
xdr_timeval(xdrs, tvp)
X	XDR *xdrs;
X	struct timeval *tvp;
#endif /* K&R C */
{
X	return (xdr_rstat_timeval(xdrs, tvp));
}
X
X
bool_t
xdr_rstat_timeval(xdrs, objp)
X	register XDR *xdrs;
X	rstat_timeval *objp;
{
X
X	register inline_t *buf;
X
X	if (!xdr_long(xdrs, &objp->tv_sec))
X		return (FALSE);
X	if (!xdr_long(xdrs, &objp->tv_usec))
X		return (FALSE);
X	return (TRUE);
}
X
bool_t
xdr_statsvar(xdrs, objp)
X	register XDR *xdrs;
X	statsvar *objp;
{
X
X	register inline_t *buf;
X
X	int i;
X
X	if (xdrs->x_op == XDR_ENCODE) {
X		if (!xdr_array(xdrs, (char **)&objp->cp_time.cp_time_val, (u_int *) &objp->cp_time.cp_time_len, ~0,
X			sizeof (int), (xdrproc_t) xdr_int))
X			return (FALSE);
X		if (!xdr_array(xdrs, (char **)&objp->dk_xfer.dk_xfer_val, (u_int *) &objp->dk_xfer.dk_xfer_len, ~0,
X			sizeof (int), (xdrproc_t) xdr_int))
X			return (FALSE);
X
X		buf = XDR_INLINE(xdrs, (11 + 3) * BYTES_PER_XDR_UNIT);
X
X		if (buf == NULL) {
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_opackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_swtch))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X				sizeof (long), (xdrproc_t) xdr_long))
X				return (FALSE);
X
X		} else {
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgin);
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgout);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpin);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpout);
X			IXDR_PUT_U_LONG(buf, objp->v_intr);
X			IXDR_PUT_LONG(buf, objp->if_ipackets);
X			IXDR_PUT_LONG(buf, objp->if_ierrors);
X			IXDR_PUT_LONG(buf, objp->if_opackets);
X			IXDR_PUT_LONG(buf, objp->if_oerrors);
X			IXDR_PUT_LONG(buf, objp->if_collisions);
X			IXDR_PUT_U_LONG(buf, objp->v_swtch);
X			{
X				register long *genp;
X
X				for (i = 0, genp = objp->avenrun;
X					i < 3; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X		}
X		if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X			return (FALSE);
X		if (!xdr_rstat_timeval(xdrs, &objp->curtime))
X			return (FALSE);
X		return (TRUE);
X	} else if (xdrs->x_op == XDR_DECODE) {
X		if (!xdr_array(xdrs, (char **)&objp->cp_time.cp_time_val, (u_int *) &objp->cp_time.cp_time_len, ~0,
X			sizeof (int), (xdrproc_t) xdr_int))
X			return (FALSE);
X		if (!xdr_array(xdrs, (char **)&objp->dk_xfer.dk_xfer_val, (u_int *) &objp->dk_xfer.dk_xfer_len, ~0,
X			sizeof (int), (xdrproc_t) xdr_int))
X			return (FALSE);
X
X		buf = XDR_INLINE(xdrs, (11 + 3) * BYTES_PER_XDR_UNIT);
X
X		if (buf == NULL) {
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_opackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_swtch))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X				sizeof (long), (xdrproc_t) xdr_long))
X				return (FALSE);
X
X		} else {
X			objp->v_pgpgin = IXDR_GET_U_LONG(buf);
X			objp->v_pgpgout = IXDR_GET_U_LONG(buf);
X			objp->v_pswpin = IXDR_GET_U_LONG(buf);
X			objp->v_pswpout = IXDR_GET_U_LONG(buf);
X			objp->v_intr = IXDR_GET_U_LONG(buf);
X			objp->if_ipackets = IXDR_GET_LONG(buf);
X			objp->if_ierrors = IXDR_GET_LONG(buf);
X			objp->if_opackets = IXDR_GET_LONG(buf);
X			objp->if_oerrors = IXDR_GET_LONG(buf);
X			objp->if_collisions = IXDR_GET_LONG(buf);
X			objp->v_swtch = IXDR_GET_U_LONG(buf);
X			{
X				register long *genp;
X
X				for (i = 0, genp = objp->avenrun;
X					i < 3; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X		}
X		if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X			return (FALSE);
X		if (!xdr_rstat_timeval(xdrs, &objp->curtime))
X			return (FALSE);
X		return (TRUE);
X	}
X
X	if (!xdr_array(xdrs, (char **)&objp->cp_time.cp_time_val, (u_int *) &objp->cp_time.cp_time_len, ~0,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_array(xdrs, (char **)&objp->dk_xfer.dk_xfer_val, (u_int *) &objp->dk_xfer.dk_xfer_len, ~0,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_intr))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ipackets))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ierrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_opackets))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_oerrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_collisions))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_swtch))
X		return (FALSE);
X	if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X		sizeof (long), (xdrproc_t) xdr_long))
X		return (FALSE);
X	if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X		return (FALSE);
X	if (!xdr_rstat_timeval(xdrs, &objp->curtime))
X		return (FALSE);
X	return (TRUE);
}
X
bool_t
xdr_statstime(xdrs, objp)
X	register XDR *xdrs;
X	statstime *objp;
{
X
X	register inline_t *buf;
X
X	int i;
X
X	if (xdrs->x_op == XDR_ENCODE) {
X		buf = XDR_INLINE(xdrs, (10 + (RSTAT_CPUSTATES + RSTAT_DK_NDRIVE + 3)) * BYTES_PER_XDR_UNIT);
X		if (buf == NULL) {
X			if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_swtch))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X				sizeof (long), (xdrproc_t) xdr_long))
X				return (FALSE);
X
X		} else {
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->cp_time;
X					i < RSTAT_CPUSTATES; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->dk_xfer;
X					i < RSTAT_DK_NDRIVE; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgin);
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgout);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpin);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpout);
X			IXDR_PUT_U_LONG(buf, objp->v_intr);
X			IXDR_PUT_LONG(buf, objp->if_ipackets);
X			IXDR_PUT_LONG(buf, objp->if_ierrors);
X			IXDR_PUT_LONG(buf, objp->if_oerrors);
X			IXDR_PUT_LONG(buf, objp->if_collisions);
X			IXDR_PUT_U_LONG(buf, objp->v_swtch);
X			{
X				register long *genp;
X
X				for (i = 0, genp = objp->avenrun;
X					i < 3; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X		}
X		if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X			return (FALSE);
X		if (!xdr_rstat_timeval(xdrs, &objp->curtime))
X			return (FALSE);
X		if (!xdr_int(xdrs, &objp->if_opackets))
X			return (FALSE);
X		return (TRUE);
X	} else if (xdrs->x_op == XDR_DECODE) {
X		buf = XDR_INLINE(xdrs, (10 + (RSTAT_CPUSTATES + RSTAT_DK_NDRIVE + 3)) * BYTES_PER_XDR_UNIT);
X		if (buf == NULL) {
X			if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_swtch))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X				sizeof (long), (xdrproc_t) xdr_long))
X				return (FALSE);
X
X		} else {
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->cp_time;
X					i < RSTAT_CPUSTATES; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->dk_xfer;
X					i < RSTAT_DK_NDRIVE; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X			objp->v_pgpgin = IXDR_GET_U_LONG(buf);
X			objp->v_pgpgout = IXDR_GET_U_LONG(buf);
X			objp->v_pswpin = IXDR_GET_U_LONG(buf);
X			objp->v_pswpout = IXDR_GET_U_LONG(buf);
X			objp->v_intr = IXDR_GET_U_LONG(buf);
X			objp->if_ipackets = IXDR_GET_LONG(buf);
X			objp->if_ierrors = IXDR_GET_LONG(buf);
X			objp->if_oerrors = IXDR_GET_LONG(buf);
X			objp->if_collisions = IXDR_GET_LONG(buf);
X			objp->v_swtch = IXDR_GET_U_LONG(buf);
X			{
X				register long *genp;
X
X				for (i = 0, genp = objp->avenrun;
X					i < 3; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X		}
X		if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X			return (FALSE);
X		if (!xdr_rstat_timeval(xdrs, &objp->curtime))
X			return (FALSE);
X		if (!xdr_int(xdrs, &objp->if_opackets))
X			return (FALSE);
X		return (TRUE);
X	}
X
X	if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_intr))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ipackets))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ierrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_oerrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_collisions))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_swtch))
X		return (FALSE);
X	if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X		sizeof (long), (xdrproc_t) xdr_long))
X		return (FALSE);
X	if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X		return (FALSE);
X	if (!xdr_rstat_timeval(xdrs, &objp->curtime))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_opackets))
X		return (FALSE);
X	return (TRUE);
}
X
bool_t
xdr_statsswtch(xdrs, objp)
X	register XDR *xdrs;
X	statsswtch *objp;
{
X
X	register inline_t *buf;
X
X	int i;
X
X	if (xdrs->x_op == XDR_ENCODE) {
X		buf = XDR_INLINE(xdrs, (10 + (RSTAT_CPUSTATES + RSTAT_DK_NDRIVE + 3)) * BYTES_PER_XDR_UNIT);
X		if (buf == NULL) {
X			if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_swtch))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X				sizeof (u_int), (xdrproc_t) xdr_u_int))
X				return (FALSE);
X
X		} else {
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->cp_time;
X					i < RSTAT_CPUSTATES; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->dk_xfer;
X					i < RSTAT_DK_NDRIVE; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgin);
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgout);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpin);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpout);
X			IXDR_PUT_U_LONG(buf, objp->v_intr);
X			IXDR_PUT_LONG(buf, objp->if_ipackets);
X			IXDR_PUT_LONG(buf, objp->if_ierrors);
X			IXDR_PUT_LONG(buf, objp->if_oerrors);
X			IXDR_PUT_LONG(buf, objp->if_collisions);
X			IXDR_PUT_U_LONG(buf, objp->v_swtch);
X			{
X				register u_int *genp;
X
X				for (i = 0, genp = objp->avenrun;
X					i < 3; i++) {
X					IXDR_PUT_U_LONG(buf, *genp++);
X				}
X			}
X		}
X		if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X			return (FALSE);
X		if (!xdr_int(xdrs, &objp->if_opackets))
X			return (FALSE);
X		return (TRUE);
X	} else if (xdrs->x_op == XDR_DECODE) {
X		buf = XDR_INLINE(xdrs, (10 + (RSTAT_CPUSTATES + RSTAT_DK_NDRIVE + 3)) * BYTES_PER_XDR_UNIT);
X		if (buf == NULL) {
X			if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_swtch))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X				sizeof (u_int), (xdrproc_t) xdr_u_int))
X				return (FALSE);
X
X		} else {
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->cp_time;
X					i < RSTAT_CPUSTATES; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->dk_xfer;
X					i < RSTAT_DK_NDRIVE; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X			objp->v_pgpgin = IXDR_GET_U_LONG(buf);
X			objp->v_pgpgout = IXDR_GET_U_LONG(buf);
X			objp->v_pswpin = IXDR_GET_U_LONG(buf);
X			objp->v_pswpout = IXDR_GET_U_LONG(buf);
X			objp->v_intr = IXDR_GET_U_LONG(buf);
X			objp->if_ipackets = IXDR_GET_LONG(buf);
X			objp->if_ierrors = IXDR_GET_LONG(buf);
X			objp->if_oerrors = IXDR_GET_LONG(buf);
X			objp->if_collisions = IXDR_GET_LONG(buf);
X			objp->v_swtch = IXDR_GET_U_LONG(buf);
X			{
X				register u_int *genp;
X
X				for (i = 0, genp = objp->avenrun;
X					i < 3; i++) {
X					*genp++ = IXDR_GET_U_LONG(buf);
X				}
X			}
X		}
X		if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X			return (FALSE);
X		if (!xdr_int(xdrs, &objp->if_opackets))
X			return (FALSE);
X		return (TRUE);
X	}
X
X	if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_intr))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ipackets))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ierrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_oerrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_collisions))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_swtch))
X		return (FALSE);
X	if (!xdr_vector(xdrs, (char *)objp->avenrun, 3,
X		sizeof (u_int), (xdrproc_t) xdr_u_int))
X		return (FALSE);
X	if (!xdr_rstat_timeval(xdrs, &objp->boottime))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_opackets))
X		return (FALSE);
X	return (TRUE);
}
X
bool_t
xdr_stats(xdrs, objp)
X	register XDR *xdrs;
X	stats *objp;
{
X
X	register inline_t *buf;
X
X	int i;
X
X	if (xdrs->x_op == XDR_ENCODE) {
X		buf = XDR_INLINE(xdrs, (10 + (RSTAT_CPUSTATES + RSTAT_DK_NDRIVE)) * BYTES_PER_XDR_UNIT);
X		if (buf == NULL) {
X			if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_opackets))
X				return (FALSE);
X		} else {
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->cp_time;
X					i < RSTAT_CPUSTATES; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->dk_xfer;
X					i < RSTAT_DK_NDRIVE; i++) {
X					IXDR_PUT_LONG(buf, *genp++);
X				}
X			}
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgin);
X			IXDR_PUT_U_LONG(buf, objp->v_pgpgout);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpin);
X			IXDR_PUT_U_LONG(buf, objp->v_pswpout);
X			IXDR_PUT_U_LONG(buf, objp->v_intr);
X			IXDR_PUT_LONG(buf, objp->if_ipackets);
X			IXDR_PUT_LONG(buf, objp->if_ierrors);
X			IXDR_PUT_LONG(buf, objp->if_oerrors);
X			IXDR_PUT_LONG(buf, objp->if_collisions);
X			IXDR_PUT_LONG(buf, objp->if_opackets);
X		}
X		return (TRUE);
X	} else if (xdrs->x_op == XDR_DECODE) {
X		buf = XDR_INLINE(xdrs, (10 + (RSTAT_CPUSTATES + RSTAT_DK_NDRIVE)) * BYTES_PER_XDR_UNIT);
X		if (buf == NULL) {
X			if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X				sizeof (int), (xdrproc_t) xdr_int))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpin))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_pswpout))
X				return (FALSE);
X			if (!xdr_u_int(xdrs, &objp->v_intr))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ipackets))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_ierrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_oerrors))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_collisions))
X				return (FALSE);
X			if (!xdr_int(xdrs, &objp->if_opackets))
X				return (FALSE);
X		} else {
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->cp_time;
X					i < RSTAT_CPUSTATES; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X			{
X				register int *genp;
X
X				for (i = 0, genp = objp->dk_xfer;
X					i < RSTAT_DK_NDRIVE; i++) {
X					*genp++ = IXDR_GET_LONG(buf);
X				}
X			}
X			objp->v_pgpgin = IXDR_GET_U_LONG(buf);
X			objp->v_pgpgout = IXDR_GET_U_LONG(buf);
X			objp->v_pswpin = IXDR_GET_U_LONG(buf);
X			objp->v_pswpout = IXDR_GET_U_LONG(buf);
X			objp->v_intr = IXDR_GET_U_LONG(buf);
X			objp->if_ipackets = IXDR_GET_LONG(buf);
X			objp->if_ierrors = IXDR_GET_LONG(buf);
X			objp->if_oerrors = IXDR_GET_LONG(buf);
X			objp->if_collisions = IXDR_GET_LONG(buf);
X			objp->if_opackets = IXDR_GET_LONG(buf);
X		}
X		return (TRUE);
X	}
X
X	if (!xdr_vector(xdrs, (char *)objp->cp_time, RSTAT_CPUSTATES,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_vector(xdrs, (char *)objp->dk_xfer, RSTAT_DK_NDRIVE,
X		sizeof (int), (xdrproc_t) xdr_int))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pgpgout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpin))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_pswpout))
X		return (FALSE);
X	if (!xdr_u_int(xdrs, &objp->v_intr))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ipackets))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_ierrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_oerrors))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_collisions))
X		return (FALSE);
X	if (!xdr_int(xdrs, &objp->if_opackets))
X		return (FALSE);
X	return (TRUE);
}
SHAR_EOF
  $shar_touch -am 0728151499 'rstat_xdr.c' &&
  chmod 0640 'rstat_xdr.c' ||
  $echo 'restore of' 'rstat_xdr.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'rstat_xdr.c:' 'MD5 check failed'
682430f42283a323a48dab6337d2dc87  rstat_xdr.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'rstat_xdr.c'`"
    test 21812 -eq "$shar_count" ||
    $echo 'rstat_xdr.c:' 'original size' '21812,' 'current size' "$shar_count!"
  fi
fi
# ============= s-bsd.c ==============
if test -f 's-bsd.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-bsd.c' '(file already exists)'
else
  $echo 'x -' extracting 's-bsd.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-bsd.c' &&
/*
X * System dependent file for BSD derivatives that have _cp_time in their
X * kernels to hold the CPU states. Seen to work on SunOS and Ultrix.
X */
/* Chris Siebenmann <cks@sys.toronto.edu>, University of Toronto */
/* LINTLIBRARY */
#include <sys/param.h>
#include <sys/dk.h>
#include <nlist.h>
X
#ifndef MAXHOSTNAMELEN
X  /* Some U*x deviants managed to not have this in sys/param.h */
# define MAXHOSTNAMELEN 64
#endif
X
extern char *xmalloc(/* int nbytes */);
extern void shorten(/* char *hname */);
X
extern int open(), read();
extern long lseek();
X
extern char *kernelSymbols;
X
long	cp_time[CPUSTATES];
long	cp_old[CPUSTATES];
int	kmem;			/* file descriptor of /dev/kmem. */
struct nlist	nl[] = {
#define	X_CP_TIME	0
X	{ "_cp_time" },
X	{ "" },
};
X
#define NPROCS 1
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X	return NPROCS;
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    items[0] = CPUSTATES;
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X	static char hname[MAXHOSTNAMELEN + 1];
X	static char *names[NPROCS];
X
X	names[0] = hname;
X	hname[MAXHOSTNAMELEN] = '\0';
X	if (gethostname(hname, MAXHOSTNAMELEN) < 0) {
X		perror("gethostname");
X		*hname = '\0';
X	}
X	shorten(hname);
X	return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	if ((kmem = open("/dev/kmem", 0)) < 0) {
X		perror("/dev/kmem");
X		exit(1);
X	}
X	(void)nlist(kernelSymbols?kernelSymbols:"/vmunix", nl);
X	if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
X	    (long) nl[X_CP_TIME].n_value)
X		perror("lseek");
X	if (read(kmem, (char *) cp_old, sizeof(cp_old)) != sizeof(cp_old))
X		perror("read");
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	states[CPUSTATES];
X	int	nstates;
X	int	i;
X	extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X	
X	if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
X	    (long) nl[X_CP_TIME].n_value)
X		perror("lseek");
X	if (read(kmem, (char *) cp_time, sizeof(cp_time)) !=
X	    sizeof(cp_time))
X		perror("read");
X	
X	
#define delta(cpustate) ((int) (cp_time[(cpustate)] - cp_old[(cpustate)]))
X
X	nstates = 0;
X	states[nstates++] = delta(CP_IDLE);
X	states[nstates++] = delta(CP_USER);
X	states[nstates++] = delta(CP_NICE);
X	states[nstates++] = delta(CP_SYS);
X	draw_bar(0, states, nstates);
X	for (i = 0; i < CPUSTATES; i ++)
X		cp_old[i] = cp_time[i];
}
SHAR_EOF
  $shar_touch -am 0326205297 's-bsd.c' &&
  chmod 0644 's-bsd.c' ||
  $echo 'restore of' 's-bsd.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-bsd.c:' 'MD5 check failed'
4f77ecf99a0251fb04107ad842bde1da  s-bsd.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-bsd.c'`"
    test 2942 -eq "$shar_count" ||
    $echo 's-bsd.c:' 'original size' '2942,' 'current size' "$shar_count!"
  fi
fi
# ============= s-bsd44.c ==============
if test -f 's-bsd44.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-bsd44.c' '(file already exists)'
else
  $echo 'x -' extracting 's-bsd44.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-bsd44.c' &&
/*
X * System dependent file for 4.4BSD derivatives.  Works on FreeBSD 2.x.
X * Should work on NetBSD 1.x and OpenBSD
X * Based on s-bsd.c by Chris Siebenmann <cks@sys.toronto.edu>
X */
/* David O'Brien, University of California at Davis <obrien@cs.ucdavis.edu> */
/*
X * Utilizes the kvm library avalible on BSD 4.4.
X * Binary should be sgid ``kmem''
X */
X
/* LINTLIBRARY */
X
#include <sys/param.h>
#if !(defined(BSD) && (BSD >= 199306)) 	/* ie. BSD 4.4 systems */
#error This is not a 4.4BSD-Lite dervived system.
#endif
X
#include <sys/dkstat.h>
#include <kvm.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>		/* for perror() */
X
#include <nlist.h>
X
X
extern char *xmalloc(/* int nbytes */);
extern void shorten(/* char *hname */);
X
extern char *kernelSymbols;
static kvm_t *kmem;			/* pointer into the kmem */
X
long	cp_time[CPUSTATES];
long	cp_old[CPUSTATES];
X
struct nlist	nl[] = {
#define	X_CP_TIME	0
X	{ "_cp_time" },
X	{ "" },
};
X
#define NPROCS 1
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X	return NPROCS;
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    items[0] = CPUSTATES;
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X	static char hname[MAXHOSTNAMELEN + 1];
X	static char *names[NPROCS];
X
X	names[0] = hname;
X	hname[MAXHOSTNAMELEN] = '\0';
X	if (gethostname(hname, MAXHOSTNAMELEN) < 0) {
X		perror("gethostname");
X		*hname = '\0';
X	}
X	shorten(hname);
X	return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	int j;
X	char errbuf[ 1024 ];
X
X	/* if ((kmem = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) { */
X	if ((kmem = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
X		perror("/dev/kmem");
X		fprintf(stderr, "%s\n", errbuf );
X		exit(1);
X	}
X	/* get the list of symbols we want to access in the kernel */
X	if (kvm_nlist(kmem, nl) == -1) 
X		fprintf( stderr, "kvm error, %s\n", kvm_geterr(kmem));
X		
X	if (nl[0].n_type == 0)
X		fprintf(stderr, "nlist failed\n");
X
X	if ((j=kvm_read(kmem, nl[X_CP_TIME].n_value, (char *) cp_old,
X		sizeof cp_old)) != sizeof cp_old) {
X		perror("kvm_read,1");
X		fprintf( stderr, "kvm_read returns %d\n", j );
X		fprintf( stderr, "kvm error, %s\n", kvm_geterr(kmem));
X	}
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	states[CPUSTATES];
X	int	nstates;
X	int	i;
X	extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X	
X	if ((i=kvm_read(kmem, nl[X_CP_TIME].n_value, (char *) cp_time,
X		sizeof cp_time)) != sizeof cp_time)
X	{
X		perror("kvm_read,2");
X		fprintf( stderr, "kvm_read returns %d\n", i );
X		fprintf( stderr, "kvm error, %s\n", kvm_geterr(kmem));
X	}
X	
#define delta(cpustate) ((int) (cp_time[(cpustate)] - cp_old[(cpustate)]))
X
X	nstates = 0;
X	states[nstates++] = delta(CP_IDLE);
X	states[nstates++] = delta(CP_USER);
X	states[nstates++] = delta(CP_NICE);
X	states[nstates++] = delta(CP_SYS);
X	draw_bar(0, states, nstates);
X	for (i = 0; i < CPUSTATES; i ++)
X		cp_old[i] = cp_time[i];
}
SHAR_EOF
  $shar_touch -am 0326205297 's-bsd44.c' &&
  chmod 0640 's-bsd44.c' ||
  $echo 'restore of' 's-bsd44.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-bsd44.c:' 'MD5 check failed'
001c673cd9884b51fa60b3e052c0fa19  s-bsd44.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-bsd44.c'`"
    test 3550 -eq "$shar_count" ||
    $echo 's-bsd44.c:' 'original size' '3550,' 'current size' "$shar_count!"
  fi
fi
# ============= s-gould-np1.c ==============
if test -f 's-gould-np1.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-gould-np1.c' '(file already exists)'
else
  $echo 'x -' extracting 's-gould-np1.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-gould-np1.c' &&
/* s-gould-np1.c : has _Cptime instead of _cp_time */
X
/*
X * Hugues Leroy, INRIA, RENNES France <Hugues.Leroy@irisa.fr>
X * added support for the Gould NP1
X * based on code by
X * Chris Siebenmann, University of Toronto <cks@sys.toronto.edu>
X * and
X * Salvador P. Abreu, U.Nova de Lisboa, PORTUGAL <spa@fctunl.rccn.pt>
*/
X        
/* LINTLIBRARY */
#include <sys/param.h>
#include <sys/dk.h>
#include <nlist.h>
X
extern int open(), read();
extern long lseek();
X
extern char *kernelSymbols;
X
/* NPROCS is now always 2 */
X
#define NPROCS 2
X
long	cp_time[NPROCS][CPUSTATES];
long	cp_old [NPROCS][CPUSTATES];
int	kmem;			/* file descriptor of /dev/kmem. */
struct nlist	nl[] = {
#define	X_CP_TIME	0
X	{ "_Cptime" },
X	{ "" },
};
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X    return NPROCS;
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i;
X
X    for(i = 0; i < nbars; i++)
X        items[i] = CPUSTATES;
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    static char *name[NPROCS];
X
X    name[0] = "CPU 1";
X    name[1] = "CPU 2";
X    return name;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X    
X    if ((kmem = open("/dev/kmem", 0)) < 0) {
X	    perror("/dev/kmem");
X	    exit(1);
X    }
X    (void)nlist(kernelSymbols?kernelSymbols:"/vmunix", nl);
X    if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
X	(long) nl[X_CP_TIME].n_value)
X	    perror("lseek");
X    if (read(kmem, (char *) cp_old, sizeof(cp_old)) !=
X	sizeof(cp_old))
X	    perror("read");
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	states[CPUSTATES];
X	int	nstates;
X	int	i,j;
X
X	
X	if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
X	    (long) nl[X_CP_TIME].n_value)
X		perror("lseek");
X	if (read(kmem, (char *) cp_time, sizeof(cp_time)) !=
X	    sizeof(cp_time))
X		perror("read");
X
X
#define delta(cpustate) ((int) (cp_time[i][(cpustate)] -
cp_old[i][(cpustate)]))
X
X	for (i=0; i<NPROCS; i++) {
X	nstates = 0;
X	states[nstates++] = delta(CP_IDLE);
X	states[nstates++] = delta(CP_USER);
X	states[nstates++] = delta(CP_NICE);
X	states[nstates++] = delta(CP_SYS);
X	draw_bar(i, states, nstates);
X	}
X	for (i = 0; i < CPUSTATES; i ++)
X	for (j=0; j< NPROCS; j++)
X		cp_old[j][i] = cp_time[j][i];
X
X
}
SHAR_EOF
  $shar_touch -am 0326205297 's-gould-np1.c' &&
  chmod 0644 's-gould-np1.c' ||
  $echo 'restore of' 's-gould-np1.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-gould-np1.c:' 'MD5 check failed'
85dd32e32b4e934e27b3c9b4a64bd142  s-gould-np1.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-gould-np1.c'`"
    test 2829 -eq "$shar_count" ||
    $echo 's-gould-np1.c:' 'original size' '2829,' 'current size' "$shar_count!"
  fi
fi
# ============= s-irix.c ==============
if test -f 's-irix.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-irix.c' '(file already exists)'
else
  $echo 'x -' extracting 's-irix.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-irix.c' &&
/* System dependent file for Silicon Graphics Iris4d systems */
/* Mark Moraes, ANT, University of Toronto <moraes@cs.toronto.edu> */
/* LINTLIBRARY */
#include <stdio.h>
#include <sys/types.h>
#include <sys/sysmp.h>
#include <sys/sysinfo.h>
#include <sys/param.h>
X
#define NSTATES 6
X
extern char *xmalloc(/* int nbytes */);
extern void shorten(/* char *hname */);
X
extern sep_wait;
X
static int *errs;
static struct sysinfo **si;
static struct sysinfo **last_si;
static struct sysinfo **tmp_si;
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X    return sysmp(MP_NPROCS);
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i;
X
X    for(i = 0; i < nbars; i++)
X        if(sep_wait) 
X		items[i] = NSTATES; 
X	else 
X		items[i] = NSTATES-1; 
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    char **names;
X    int i;
X    extern char *strcpy(/* char *, const char * */);
X    static char hname[MAXHOSTNAMELEN + 1];
X
X    hname[MAXHOSTNAMELEN] = '\0';
X    if (gethostname(hname, MAXHOSTNAMELEN) < 0) {
X	perror("gethostname");
X	*hname = '\0';
X    }
X    shorten(hname);
X    names = (char **) xmalloc(nbars * sizeof(char *));
X    for(i = 0; i < nbars; i++) {
#define CPUNAME	"%s %d"
X	char buf[MAXHOSTNAMELEN + 1 + 32];
X
X	(void) sprintf(buf, CPUNAME, hname, i);
X	names[i] = strcpy(xmalloc(strlen(buf) + 1), buf);
X    }
X    return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
void
init_bars(nbars)
int nbars;
{
X    int i;
X    int ret;
X    
X    /* Initialize sysinfo by taking first reading */
X
X    last_si = (struct sysinfo **) xmalloc(nbars * sizeof(struct sysinfo *));
X    si = (struct sysinfo **) xmalloc(nbars * sizeof(struct sysinfo *));
X    errs = (int *) xmalloc(nbars * sizeof(int));
X
X    for(i = 0; i < nbars; i++) {
X	last_si[i] = (struct sysinfo *) xmalloc(sizeof(struct sysinfo));
X	si[i] = (struct sysinfo *) xmalloc(sizeof(struct sysinfo));
X	errs[i] = 0;
X	ret = sysmp(MP_SAGET1, MPSA_SINFO, (int) last_si[i],
X		    sizeof(struct sysinfo), i);
X	if (ret != 0) {
X	    (void) fprintf(stderr,
X	     "sysmp(MP_SAGET1, MPSA_SINFO) returned %d on processor %d\n",
X	     ret, i);
X	    (void) fflush(stderr);
X	    errs[i]++;
X	    continue;
X	}
X    }
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X    struct sysinfo dummy;
X    int states[sizeof(dummy.cpu)/sizeof(time_t)];
X    int nstates;
X    int ret;
X    int i;
X    extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X
X    for(i = 0; i < nbars; i++) {
X	if (errs[i] != 0)
X	    continue;
X	ret = sysmp(MP_SAGET1, MPSA_SINFO, (int) si[i],
X		    sizeof(struct sysinfo), i);
X	if (ret != 0) {
X	    (void) fprintf(stderr,
X	     "sysmp(MP_SAGET1, MPSA_SINFO) returned %d on processor %d\n",
X	      ret, i);
X	    (void) fflush(stderr);
X	    errs[i]++;
X	    continue;
X	}
X	    
#define delta(cpustate) \
((int) (si[i]->cpu[(cpustate)] - last_si[i]->cpu[(cpustate)]))
X
X	nstates = 0;
X	if(sep_wait) {
X	    states[nstates++] = delta(CPU_IDLE);
X	    states[nstates++] = delta(CPU_WAIT);
X	} else {
X	    states[nstates++] = delta(CPU_IDLE) + delta(CPU_WAIT);
X	}
X	states[nstates++] = delta(CPU_USER);
X	states[nstates++] = delta(CPU_KERNEL);
X	states[nstates++] = delta(CPU_SXBRK);
X	states[nstates++] = delta(CPU_INTR);
X	draw_bar(i, states, nstates);
X    }
X    tmp_si = last_si;
X    last_si = si;
X    si = tmp_si;
}
SHAR_EOF
  $shar_touch -am 0429204994 's-irix.c' &&
  chmod 0644 's-irix.c' ||
  $echo 'restore of' 's-irix.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-irix.c:' 'MD5 check failed'
025a979ce37a1531f8af0756014a06bb  s-irix.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-irix.c'`"
    test 3883 -eq "$shar_count" ||
    $echo 's-irix.c:' 'original size' '3883,' 'current size' "$shar_count!"
  fi
fi
# ============= s-mach.c ==============
if test -f 's-mach.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-mach.c' '(file already exists)'
else
  $echo 'x -' extracting 's-mach.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-mach.c' &&
/*
X * System dependent file for Mach
X */
X
/* 
X * Melinda Shore, mt Xinu, 3/21/90 
X */
X
#include <mach.h>
X
#define NSTATES 3
X
extern char *xmalloc(/* int nbytes */);
extern kern_return_t host_info();
extern task_t task_self();
extern kern_return_t slot_info();
int *cpu_ids;
machine_slot_data_t **last_sinfo, **cur_sinfo, **tmp_sinfo;
task_t self;
X
/* 
X * Called at the beginning to enquire how many bars are needed,
X * and to determine which cpu slots are filled
X */
X
int
num_bars()
{
X    machine_info_data_t minfo;
X    machine_slot_data_t sinfo;
X    int i, j = 0, result, ncpus;
X
X    ncpus = 0;
X    self = task_self();
X    if ((result = host_info(self, &minfo)) != KERN_SUCCESS)  {
X        mach_error("xcpustate", result);
X        exit(1);
X    }
X    cpu_ids = (int *)xmalloc(minfo.max_cpus * sizeof (int));
X    for (i = 0 ; i < minfo.max_cpus ; i++)  {
X        if ((result = slot_info(self, i, &sinfo)) != KERN_SUCCESS)
X            mach_error("xcpustate", result);
X        else
X            if (sinfo.is_cpu && sinfo.running)  {
X                ncpus++;
X                cpu_ids[j++] = i;
X            }
X    }
X    return ncpus;
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i;
X
X    for(i = 0; i < nbars; i++)
X        items[i] = NSTATES;
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    char **names;
X    int i;
X
X    names = (char **)xmalloc(nbars * sizeof (char *));
X    for (i = 0 ; i < nbars ; i++)  {
X        names[i] = xmalloc(10);
X        (void) sprintf(names[i], "Slot %d", cpu_ids[i]);
X    }
X    return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X    int i;
X    kern_return_t result;
X
X    cur_sinfo = (machine_slot_data_t **)xmalloc(nbars *
X                                               sizeof (machine_slot_data_t *));
X    last_sinfo = (machine_slot_data_t **)xmalloc(nbars *
X                                               sizeof (machine_slot_data_t *));
X    for (i = 0 ; i < nbars ; i++)  {
X        cur_sinfo[i] = (machine_slot_data_t *)xmalloc(sizeof
X                                                   (machine_slot_data_t));
X        last_sinfo[i] = (machine_slot_data_t *)xmalloc(sizeof
X                                                   (machine_slot_data_t));
X        if ((result = slot_info(self, cpu_ids[i], cur_sinfo[i])) !=
X            KERN_SUCCESS)  {
X            mach_error("xcpustate", result);
X            exit(1);
X        }
X    }            
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X    int states[CPU_STATE_MAX];
X    int nstates;
X    int i;
X    extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X    kern_return_t result;
X    
X    for (i = 0 ; i < nbars ; i++)  {
X        if ((result = slot_info(self, cpu_ids[i], cur_sinfo[i])) != 
X            KERN_SUCCESS)
X            mach_error("xcpustate", result);
#define delta(cpustate) ((int) (cur_sinfo[i]->cpu_ticks[(cpustate)] - \
X    last_sinfo[i]->cpu_ticks[(cpustate)]))
X
X        nstates = 0;
X        states[nstates++] = delta(CPU_STATE_USER);
X        states[nstates++] = delta(CPU_STATE_SYSTEM);
X        states[nstates++] = delta(CPU_STATE_IDLE);
X        draw_bar(i, states, nstates);
X    }
X    tmp_sinfo = last_sinfo;
X    last_sinfo = cur_sinfo;
X    cur_sinfo = tmp_sinfo;
}
SHAR_EOF
  $shar_touch -am 0408190394 's-mach.c' &&
  chmod 0644 's-mach.c' ||
  $echo 'restore of' 's-mach.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-mach.c:' 'MD5 check failed'
733cba59a38d6e1fe7963f8bf7eedd3d  s-mach.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-mach.c'`"
    test 3827 -eq "$shar_count" ||
    $echo 's-mach.c:' 'original size' '3827,' 'current size' "$shar_count!"
  fi
fi
# ============= s-solbourne.c ==============
if test -f 's-solbourne.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-solbourne.c' '(file already exists)'
else
  $echo 'x -' extracting 's-solbourne.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-solbourne.c' &&
/* System dependent file for Solbourne workstations running OS/MP.	*/
/*
X * Copyright 1990 Solbourne Computer, Inc.
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the name of Solbourne not be used in advertising or
X * publicity pertaining to distribution of the software without specific,
X * written prior permission.  Solbourne Computer, Inc. makes no representations 
X * about the suitability of this software for any purpose.  It is provided 
X * "as is" without express or implied warranty.
X *
X * SOLBOURNE COMPUTER, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
X * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 
X * IN NO EVENT SHALL SOLBOURNE COMPUTER, INC. BE LIABLE FOR ANY SPECIAL,
X * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
X * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
X * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X * PERFORMANCE OF THIS SOFTWARE.
X *
X * Author:  William Kucharski, Solbourne Computer, Inc.
X *          kucharsk@Solbourne.COM
X *	    ...!{boulder,sun,uunet}!stan!kucharsk
X */
/* LINTLIBRARY */
X
#include <sys/syscall.h>
#include <sys/param.h>
#include <sys/dk.h>
#include <nlist.h>
X
extern char *xmalloc(/* int nbytes */);
X
extern int open(), read();
extern long lseek();
X
extern char *kernelSymbols();
X
long	cp_time[MAXNCPUS][CPUSTATES];
long	cp_old[MAXNCPUS][CPUSTATES];
int	kmem;			/* file descriptor of /dev/kmem. */
struct nlist	nl[] = {
#define	X_CP_TIME	0
X	{ "_cp_mp_time" },
X	{ "" },
};
X
/* Called at the beginning to inquire how many bars are needed. */
X
int
num_bars()
{
X	unsigned int	status;
X	unsigned int	width;
X	unsigned int	type;
X
X	int	numcpus = 0;
X	int	proc;
X
X	if (syscall(SYS_getcpustatus, &status, &width, &type) < 0) {
X		perror("getcpustatus");
X		exit(1);
X	}
X
X	for (proc = 0; proc < width; proc++)
X		if ((status >> proc) & 1)
X			numcpus++;
X
X	return(numcpus);
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i;
X
X    for(i = 0; i < nbars; i++)
X        items[i] = CPUSTATES;
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    extern char *strcpy(/* char *, const char * */);
X
X    char **names;
X    int i;
X
X    static char hname[MAXHOSTNAMELEN];
X
X    if (gethostname(hname, MAXHOSTNAMELEN) < 0) {
X        perror("gethostname");
X        hname[0] = '\0';
X    }
X
X    names = (char **) xmalloc(nbars * sizeof(char *));
X    if (nbars == 1) {
X	    char buf[MAXHOSTNAMELEN + 3];
X	    (void) sprintf(buf, "%s: ", hname);
X	    names[0] = strcpy(xmalloc(strlen(buf) + 1), buf);
X    } else {
X    for(i = 0; i < nbars; i++) {
X        char buf[MAXHOSTNAMELEN + 6];
X
X		    /* 
X		     * Use bar number % 10 in case someone someday can stuff
X		     * more than 9 CPUs into a Solbourne box...
X		     */
X
X		    (void) sprintf(buf, "%s(%d): ", hname, (i % 10));
X        names[i] = strcpy(xmalloc(strlen(buf) + 1), buf);
X	    }
X    }
X    return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X    
X    if ((kmem = open("/dev/kmem", 0)) < 0) {
X	    perror("/dev/kmem");
X	    exit(1);
X    }
X    (void)nlist(kernelSymbols?kernelSymbols:"/vmunix", nl);
X    if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
X	(long) nl[X_CP_TIME].n_value)
X	    perror("lseek");
X    if (read(kmem, (char *) cp_old, sizeof(cp_old)) !=
X	sizeof(cp_old))
X	    perror("read");
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	nstates;
X	int	states[CPUSTATES];
X	int	i;
X	int	proc;
X
X	extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X	
X	if (lseek(kmem, (long) nl[X_CP_TIME].n_value, 0) !=
X	    (long) nl[X_CP_TIME].n_value)
X		perror("lseek");
X	if (read(kmem, (char *) cp_time, sizeof(cp_time)) !=
X	    sizeof(cp_time))
X		perror("read");
X	
#define delta(cpu, cpustate) ((int) (cp_time[cpu][(cpustate)] - \
X	cp_old[cpu][(cpustate)]))
X
X	for (proc = 0; proc < nbars; proc++) {
X		nstates = 0;
X		states[nstates++] = delta(proc, CP_IDLE);
X		states[nstates++] = delta(proc, CP_USER);
X		states[nstates++] = delta(proc, CP_NICE);
X		states[nstates++] = delta(proc, CP_SYS);
X		draw_bar(proc, states, nstates);
X		for (i = 0; i < CPUSTATES; i ++)
X			cp_old[proc][i] = cp_time[proc][i];
X	}
}
SHAR_EOF
  $shar_touch -am 0721162794 's-solbourne.c' &&
  chmod 0644 's-solbourne.c' ||
  $echo 'restore of' 's-solbourne.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-solbourne.c:' 'MD5 check failed'
75157ff7d5024d8bd55dd0de2e58ff48  s-solbourne.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-solbourne.c'`"
    test 5043 -eq "$shar_count" ||
    $echo 's-solbourne.c:' 'original size' '5043,' 'current size' "$shar_count!"
  fi
fi
# ============= s-sunos4.c ==============
if test -f 's-sunos4.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-sunos4.c' '(file already exists)'
else
  $echo 'x -' extracting 's-sunos4.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-sunos4.c' &&
/* 
X * System dependent file for SunOS4.x machines, using the kvm library.
/* John DiMarco, CSLab, University of Toronto <jdd@cs.toronto.edu> */
X
/* LINTLIBRARY */
#define MULTIPROCESSOR
X
#include <sys/types.h>
#include <sys/file.h>
#include <sys/dk.h>
#include <nlist.h>
#include <kvm.h>
#include <sundev/mbvar.h>
X
#ifdef OMNI
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/buf.h>
#include <sys/filio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <sundev/mbvar.h>
#include "/usr/sys/sundev/nereg.h"
X
#define OMNICPU ns_st.nst_cpu_cur
#define OMNISTATES 2 /* system, idle */
X
static int nomni = 0;
#define NEMAX 16
#define NEBASE "/dev/ne"
static int omfd[NEMAX];
static int omnum[NEMAX];
extern int omniflag;
extern int open();
X
#endif
X
#ifndef MAXHOSTNAMELEN
X  /* Some U*x deviants managed to not have this in sys/param.h */
# define MAXHOSTNAMELEN 64
#endif
X
/* define some extended processor states here, in case they're not defined
X   in sys/dk.h (which is the case for 4.1.1 and below). */
#ifndef XPSTATES
#define XPSTATES 8
#define XP_SPIN 0
#define XP_DISK 1
#define XP_SERV 2
#endif /* XPSTATES */
X
static int x_cp_time;
X
static char *dk_name[DK_NDRIVE];
static int hz;
static long dk_bps[DK_NDRIVE];
X
extern char *xmalloc(/* int nbytes */);
extern void shorten(/* char *hname */);
X
extern int diskflag;
extern int cpuflag;
extern char *kernelSymbols;
X
#define NCPU 4  /* maximum possible number of CPUs. This isn't likely to   */
X                /* change under SunOS4.x. SunOS5.x will require a new port */
X                /* of xcpustate anyways, so no need to think ahead here.   */
X
#define DISKSTATES 3 /* idle, seek, transfer */
#define MPSTATES 6 /* idle, user, nice, system, spin, serv */
X
#define NULL (char *)0
X
static kvm_t *kd;
X
int ncpu;       /* number of CPUs */
int ndisk;      /* number of disks */
int procset;    /* flag of CPUs */
X
struct nlist	nl[] = {
#define N_NCPU          0
X        { "_ncpu" },
#define N_DK_BPS        1
X        { "_dk_bps" },
#define N_CP_TIME       2
X        { "_cp_time" },
#define N_DK_TIME       3
X        { "_dk_time" },
#define N_DK_WDS        4
X        { "_dk_wds" },
#define N_MP_TIME       5
X        { "_mp_time" },
#define N_XP_TIME       6
X        { "_xp_time" },
#define N_MBDINIT       7
X        { "_mbdinit" },
#define N_DK_IVEC       8
X        { "_dk_ivec" },
#define N_HZ            9
X        { "_hz" },
#define N_PROCSET      10
X        { "_procset" },
X	{ "" },
};
X
#define DK_WDS_SIZE 64.0
#define BUFFSIZE 64
X
extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X
static char *kernel_getstring(address, info)
char *address;
char *info;
{
X        static char buff[BUFFSIZE];
X
X        if(kvm_read(kd, (u_long)address, (char *)buff, 
X		sizeof(buff)) != sizeof(buff)){
X                perror(info);
X        }
X        buff[BUFFSIZE-1]='\0'; /* just in case it's not null-terminated */
X        return(buff);
}
X
static void kernel_get(addr, dest, size, info)
u_long addr;
char *dest;
u_int size;
char *info;
{
X	/* get something from the kernel */
X	if(kvm_read(kd, addr, dest, size)!=size){
X		perror(info);
X		exit(1);
X	}
}
X
static void kernel_init(name)
char *name;
{
X	/* initialize kernel */
X	if((kvm_t *)NULL==(kd=kvm_open(kernelSymbols, NULL, NULL, O_RDONLY, 
X			name))){
X		perror("kvm_open");
X		exit(1);
X	}
X
X	/* read namelist */
X	if(-1==kvm_nlist(kd, nl)){
X		perror("kvm_nlist");
X		exit(1);
X	}
}
X
#ifdef OMNI
static int omni_init()
{
X	/* count OMNI network coprocessors, initialize omfd/num tables */
X
X	char buff[BUFFSIZE];
X	int fd, there=0, i, n=0;
X
X	/* probe /dev/ne0../dev/ne16, check if present */
X	for(i=0;i<NEMAX;i++){
X		(void) sprintf(buff, "%s%d", NEBASE, i);
X		if(-1!=(fd=open(buff, O_RDONLY))){
X			if(-1!=ioctl(fd, NIOISTHERE, &there)) {
X				if(there) {
X					omfd[n]=fd;
X					omnum[n]=i;
X					n++;
X				}
X			}
X		}
X	}
X	return(n);
}
#endif /* OMNI */
X
static int cpu_init()
{
X	/* count cpus */
X
X	int n=1; /* assume uniprocessor by default */
X
X	if(N_UNDF!=nl[N_NCPU].n_type) {
X		kernel_get(nl[N_NCPU].n_value, (char *)&n, sizeof(n), "ncpu");
X		if(NCPU<n || n<1){
X			/* if n is unreasonable, assume uniprocessor */
X			n=1;
X		}
X		procset = 1;
X		kernel_get(nl[N_PROCSET].n_value, (char *)&procset, sizeof(procset), "procset");
X	} 
X	return(n);
}
X
static int disk_init()
{
X	/* count disks, initialize dk_name table */
X
X	int n=0;
X	if(N_UNDF!=nl[N_DK_IVEC].n_type){
X		/* devinfo machine (openboot prom) */
X		struct dk_ivec div, *div_p;
X
X		for(div_p=(struct dk_ivec *)nl[N_DK_IVEC].n_value;
X			n<DK_NDRIVE;div_p++){
X			char *name;
X
X			kernel_get((u_long)div_p, (char *)&div, sizeof(div),
X					"div");
X			if(NULL==div.dk_name) break;
X			name=kernel_getstring(div.dk_name, "div.dk_name");
X			if('\0'==*name) continue; 
X
X			dk_name[n]=xmalloc(BUFFSIZE);
X			(void) sprintf(dk_name[n], "%s%d", name, div.dk_unit);
X			n++;
X		}
X	} else {
X		/* mainbus machine */
X		struct mb_device mbd, *mbd_p;
X		struct mb_driver mdr;
X
X		for(mbd_p=(struct mb_device *)nl[N_MBDINIT].n_value;
X			n<DK_NDRIVE;mbd_p++){
X			kernel_get((u_long)mbd_p, (char *)&mbd, sizeof(mbd),
X					 "mbd");
X
X			if(NULL==(char *)mbd.md_driver) break; 
X
X			if(mbd.md_dk<0 || 0==mbd.md_alive) continue; 
X
X			kernel_get((u_long)mbd.md_driver, (char *)&mdr, 
X					sizeof(mdr), "mdr");
X			dk_name[mbd.md_dk]=xmalloc(BUFFSIZE);
X			(void) sprintf(dk_name[mbd.md_dk],
X				"%s%d", kernel_getstring(mdr.mdr_dname, 
X							 "mdr_dname"),
X				mbd.md_unit);
X			n++;
X		}
X	}
X
#if 0
X	/* pad names so that they're the same length */
X	for(i=0;i<n;i++){
X		tmp=strlen(dk_name[i]);	
X		if(tmp>maxlen) maxlen=tmp;
X	}
X	for(i=0;i<n;i++){
X		tmp=strlen(dk_name[i]);
X		for(j=tmp;j<maxlen;j++){
X			*(dk_name[i]+j)=' ';
X		}
X		*(dk_name[i]+maxlen)='\0';
X	}
#endif /* 0 */
X
X	return(n);
}
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X
X	int nbars=0; 
X
X	/* Open the kernel interface */
X	kernel_init("xcpustate");
X
X	if(cpuflag){
X		ncpu=cpu_init();
X		if(ncpu>0) {
X			nbars += ncpu;
X		} else {
X			cpuflag=0;
X		}
X	}
#ifdef OMNI
X	if(omniflag){
X		nomni=omni_init();
X		if(nomni>0) {
X			nbars += nomni;
X		} else {
X			omniflag=0;
X		}
X	}
#endif /* OMNI */
X	if(diskflag){
X		ndisk=disk_init();
X		if(ndisk>0) {
X			nbars += ndisk;
X		} else {
X			diskflag=0;
X		}
X	}
X	return(nbars);
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i, n=0;
X
X    if(cpuflag){
X	for(i=0; i<ncpu; i++,n++){
X		items[n] = (ncpu>1)?MPSTATES:CPUSTATES;
X	}
X    }
#ifdef OMNI
X    if(omniflag){
X	for(i=0; i<nomni; i++,n++){
X		items[n] = OMNISTATES;
X	}
X    }
#endif /* OMNI */
X    if(diskflag){
X	for(i=0; i<ndisk; i++,n++){
X		items[n] = DISKSTATES;
X	}
X    }
}
X
/* Called after num_bars to ask for the bar names */
char **
label_bars(nbars)
{
X        char **names;
X        int i, j, base;
X        extern char *strcpy();
X        static char hname[MAXHOSTNAMELEN + 1];
X	char buf[MAXHOSTNAMELEN + 1 + BUFFSIZE];
X	char *cpname="";
X
X        hname[MAXHOSTNAMELEN] = '\0';
X        if (0 >gethostname(hname, MAXHOSTNAMELEN)) {
X                perror("gethostname");
X                *hname = '\0';
X        }
X        shorten(hname);
X        names = (char **) xmalloc(nbars * sizeof(char *));
X
X	base=0; 
X
#ifdef OMNI
X	if(omniflag) cpname="CP"; /* to distinguish main CPU(s) from nc400s */
#endif /* OMNI */
X
X	if(cpuflag) {
X		/* do cpu names */
X		for(i=0, j=0; j<NCPU; j++) {
X		    if ((procset >> j) & 0x01) {
X			(void) sprintf(buf, "%s%s%s%d", hname, 
X					hname[0]?" ":"", cpname, j);
X			names[base+i] = strcpy(xmalloc(strlen(buf) + 1), buf);
X			i++;
X		    }
X		}
X		base+=ncpu;
X	}
#ifdef OMNI
X	if(omniflag) {
X		/* do NC400 names */
X		for(i=0; i<nomni; i++) {
X			(void) sprintf(buf, "%s%s%s%d", hname, 
X					hname[0]?" ":"", "NE", omnum[i]);
X			names[base+i] = strcpy(xmalloc(strlen(buf) + 1), buf);
X		}
X		base+=nomni;
X	}
#endif /* OMNI */
X	if(diskflag) {
X		/* do disk names */
X		for(i=0; i <ndisk; i++) {
X			(void) sprintf(buf, "%s%s%s", hname, hname[0]?" ":"", 
X					dk_name[i]);
X			names[base+i] = strcpy(xmalloc(strlen(buf) + 1), buf);
X		}
X		base+=ndisk;
X        }
X        return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	if(diskflag){
X		kernel_get(nl[N_HZ].n_value, (char *)&hz, sizeof(hz), "hz");
X		kernel_get(nl[N_DK_BPS].n_value, (char *)dk_bps, 
X			sizeof(dk_bps), "dk_bps");
X	}
X	if(cpuflag){
X		if(ncpu>1){
X			x_cp_time=N_MP_TIME;
X		} else {
X			x_cp_time=N_CP_TIME;
X		}
X	}
}
X
#ifdef OMNI
static void
display_omni(base)
int base;
{
X	/* display OMNI bars */
X	int states[OMNISTATES], nstates, i;
X	struct ne_usrstat u;
X	struct iovec iov;
X
X	iov.iov_base=(char *)&u;
X	iov.iov_len=sizeof(u);
X
X	for(i=0;i<nomni;i++){
X		nstates=0;
X
X		u.OMNICPU = 0; /* in case the ioctl fails */
X		(void)ioctl(omfd[i], NIOGETSTAT, &iov);
X
X		states[nstates++] = 100-u.OMNICPU;
X		states[nstates++] = u.OMNICPU;
X		draw_bar(i+base, states, nstates);
X	}
}
#endif /* OMNI */
X
static void
display_cpu(base)
int base;
{
X	int states[CPUSTATES+XPSTATES], nstates, i, j, p;
X	long cp_time[NCPU][CPUSTATES], xp_time[NCPU][XPSTATES];
X	static long cp_old[NCPU][CPUSTATES], xp_old[NCPU][XPSTATES];
X
X	kernel_get(nl[x_cp_time].n_value, (char *)cp_time, sizeof(cp_time), 
X			"cp_time");
X	if(ncpu>1){
X		kernel_get(nl[N_XP_TIME].n_value, (char *)xp_time, 
X				sizeof(xp_time), "xp_time");
X	}
#define xdelta(cpu, cpustate) ((int) (xp_time[cpu][(cpustate)] - \
X        xp_old[cpu][(cpustate)]))
X
#define delta(cpu, cpustate) ((int) (cp_time[cpu][(cpustate)] - \
X        cp_old[cpu][(cpustate)]))
X
X
X	for(p=0,i=0; i<NCPU; i++){
X	    if ((procset >> i) & 0x01) {
X		nstates=0;
X		states[nstates++] = delta(i, CP_IDLE);
X		states[nstates++] = delta(i, CP_USER);
X		states[nstates++] = delta(i, CP_NICE);
X		if(ncpu>1){
X			long sys, spin, serv;
X			
X			sys = delta(i, CP_SYS);
X			spin = xdelta(i, XP_SPIN);
X			serv = xdelta(i, XP_SERV);
X			
X			states[nstates++] = sys - (spin + serv);
X			states[nstates++] = spin;
X			states[nstates++] = serv;
X		} else {
X			states[nstates++] = delta(i, CP_SYS);
X		}
X		draw_bar(p+base, states, nstates);
X
X		/* save old values */
X		for (j = 0; j < XPSTATES; j++){
X			xp_old[i][j] = xp_time[i][j];
X		}
X		for (j = 0; j < CPUSTATES; j ++){
X			cp_old[i][j] = cp_time[i][j];
X		}
X		p++;
X	    }
X	}
}
X
static void
display_disk(base)
int base;
{
X	int states[DISKSTATES], i;
X	long dk_time[DK_NDRIVE], dk_wds[DK_NDRIVE], dk_cp_time[CPUSTATES];
X	static long old_dk_time[DK_NDRIVE], old_dk_wds[DK_NDRIVE];
X	static double oldtime;
X	double newtime, elapsedtime;
X
X	/* compute elapsed time since last call */
X	kernel_get(nl[N_CP_TIME].n_value, (char *)dk_cp_time, 
X			sizeof(dk_cp_time), "dk_cp_time");
X	newtime=0.0;
X	for(i=0;i<CPUSTATES;i++) newtime += (double)dk_cp_time[i];
X	if(newtime<=0.0) newtime=1.0;
X	newtime /= (double)hz;
X	elapsedtime = newtime - oldtime;
X	oldtime = newtime;
X
X	kernel_get(nl[N_DK_WDS].n_value, (char *)dk_wds, sizeof(dk_wds), 
X			"dk_wds");
X	kernel_get(nl[N_DK_TIME].n_value, (char *)dk_time, sizeof(dk_time), 
X			"dk_time");
X
X	for(i=0; i<ndisk; i++){
X		int nstates=0;
X		double activetime, transfersize, diskrate, transfertime;
X		double seektime, idletime;
X
X		activetime = (double)(dk_time[i]-old_dk_time[i])/(double)hz;
X		diskrate = (double)dk_bps[i]*elapsedtime;
X		transfersize = (double)(DK_WDS_SIZE*(dk_wds[i]-old_dk_wds[i]));
X		if(diskrate > 0.0){
X			transfertime = transfersize/diskrate;
X			if(transfertime>1.0) transfertime=1.0;
X		} else {
X			transfertime = 0.0;
X		}
X		transfertime *= activetime;
X
X		seektime = activetime - transfertime;
X		if(seektime<0.0) seektime=0.0;
X
X		idletime = elapsedtime - (transfertime + seektime);
X		if(idletime<0.0) idletime=0.0;
X
X		states[nstates++] = (long)(hz*idletime*elapsedtime);
X		states[nstates++] = (long)(hz*seektime*elapsedtime);
X		states[nstates++] = (long)(hz*transfertime*elapsedtime);
X
X		draw_bar(i+base, states, nstates);
X
X		old_dk_wds[i]=dk_wds[i];
X		old_dk_time[i]=dk_time[i];
X	}
}
X
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
int nbars;
{
X	int n=0;
X	
X	if(cpuflag) {
X		display_cpu(n);
X		n+=ncpu;
X	}
#ifdef OMNI
X	if(omniflag) {
X		display_omni(n);
X		n+=nomni;
X	}
#endif /* OMNI */
X	if(diskflag) {
X		display_disk(n);
X		n+=ndisk;
X	}
}
SHAR_EOF
  $shar_touch -am 0710095097 's-sunos4.c' &&
  chmod 0644 's-sunos4.c' ||
  $echo 'restore of' 's-sunos4.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-sunos4.c:' 'MD5 check failed'
53a78296ffc2fca17d76722306be05d3  s-sunos4.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-sunos4.c'`"
    test 12704 -eq "$shar_count" ||
    $echo 's-sunos4.c:' 'original size' '12704,' 'current size' "$shar_count!"
  fi
fi
# ============= s-sunos5.c ==============
if test -f 's-sunos5.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-sunos5.c' '(file already exists)'
else
  $echo 'x -' extracting 's-sunos5.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-sunos5.c' &&
/* 
X * System dependent file for SunOS5.x machines, using the kstat library.
X * 
X * John DiMarco, CSLab, University of Toronto <jdd@cs.toronto.edu> 
X */
X
/* LINTLIBRARY */
X
#include <stdio.h>
#include <kstat.h>
#include <fcntl.h>
#include <sys/var.h>
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
X
#ifndef MAXHOSTNAMELEN
X  /* Some U*x deviants managed to not have this in sys/param.h */
# define MAXHOSTNAMELEN 64
#endif
X
static kstat_ctl_t *kctl;
X
static struct kstat_list {
X	kstat_t *k;
X	struct kstat_list *next;
} *disk=NULL, *cpu=NULL;
X
#ifndef kstime_t
#define kstime_t hrtime_t
#endif 
X
static ulong *cpu_old[CPU_STATES];
static kstime_t *old_update, *old_rtime, *old_wtime;
X
#define DISKSTATES 3 /* idle, wait, run */
#define NSTATES 4 /* idle, wait, user, kernel */
X
extern char *xmalloc(/* int nbytes */);
extern void shorten(/* char *hname */);
X
extern int read();
extern long lseek();
X
extern int diskflag;
extern int cpuflag;
extern int sep_wait;
X
int ncpu;       /* number of CPUs */
int ndisk;      /* number of disks */
X
int maxcpunum=0;	/* highest-numbered CPU */
X
int *cpupos;
X
#define BUFFSIZE 64
X
extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X	kstat_t *k;
X	struct kstat_list *diskcur,*cpucur;
X
X	/* Open the kstat interface */
X	if(NULL==(kctl=kstat_open())){
X		perror("kstat");
X		exit(1);
X	}
X
X	/* 
X	 * Follow the kstat chain, making note of each useful module we
X	 * come across. Usefulness = disk if diskflag, cpu if cpuflag.
X         */
X	for(k=kctl->kc_chain;k;k=k->ks_next){
X		if(cpuflag){
X			if(0==(strncmp(k->ks_name, "cpu_stat", 8))){
X				struct kstat_list *new;
X				int cpunum;
X
X				(void)sscanf(k->ks_name, "cpu_stat%d", &cpunum);
X				if(cpunum>maxcpunum) maxcpunum = cpunum;
X				new = (struct kstat_list *)xmalloc(
X					sizeof(struct kstat_list));
X				new->k=k;
X				new->next=NULL;
X				if(NULL==cpu){
X					cpu=new;
X					cpucur=new;
X				} else {
X					cpucur->next=new;
X					cpucur=new;
X				}
X				ncpu++;
X			}
X		}
X		if(diskflag){
X			if(0==(strcmp(k->ks_class, "disk"))
X			   && KSTAT_TYPE_IO==k->ks_type){
X				struct kstat_list *new;
X
X				new = (struct kstat_list *)xmalloc(
X						sizeof(struct kstat_list));
X				new->k=k;
X				new->next=NULL;
X				if(NULL==disk){
X					disk=new;
X					diskcur=new;
X				} else {
X					diskcur->next=new;
X					diskcur=new;
X				}
X
X				ndisk++;
X			}
X		}
X	}
X	if(maxcpunum<ncpu) maxcpunum=ncpu;
X	return(((cpuflag*ncpu)+(diskflag*ndisk)));
}
X
/* Called after num_bars to ask for the bar names */
char **
label_bars(nbars)
{
X        char **names;
X        int i, base, c;
X	struct kstat_list *k;
X        static char hname[MAXHOSTNAMELEN + 1];
X	char buf[MAXHOSTNAMELEN + 1 + BUFFSIZE];
X	char *cpname="";
X
X        hname[MAXHOSTNAMELEN] = '\0';
X        if (0 >gethostname(hname, MAXHOSTNAMELEN)) {
X                perror("gethostname");
X                *hname = '\0';
X        }
X        shorten(hname);
X        names = (char **) xmalloc(nbars * sizeof(char *));
X
X	base=0; 
X	if(cpuflag && cpu) {
X		/* do cpu names */
X
X		/* set up cpupos to map cpu numbers to cpu index */
X		cpupos=(int *)xmalloc((maxcpunum+1) * sizeof(int));
X		for(i=0;i<=maxcpunum;i++) cpupos[i]=-1;
X		for(k=cpu;k;k=k->next){
X			(void)sscanf(k->k->ks_name, "cpu_stat%d", &i);
X			cpupos[i]=1;
X		}
X		c=0;
X		for(i=0;i<=maxcpunum;i++) {
X			if(0<cpupos[i]) {
X				cpupos[i]=c;
X				(void) sprintf(buf, "%s%s%s%d", hname, 
X					hname[0]?" ":"", cpname, i);
X				names[c] = strcpy(xmalloc(strlen(buf)+1), buf);
X				c++;
X			}
X		}
X
X		base+=ncpu;
X	}
X	if(diskflag && disk) {
X		/* do disk names */
X		for(i=0,k=disk;k;i++,k=k->next){
X			(void) sprintf(buf, "%s%s%s", hname, hname[0]?" ":"", 
X					k->k->ks_name);
X			names[base+i] = strcpy(xmalloc(strlen(buf) + 1), buf);
X		}
X		base+=ndisk;
X        }
X
X        return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	if(cpuflag) {
X		int i;
X		for(i=0;i<CPU_STATES;i++){
X			cpu_old[i] = (ulong *)xmalloc(ncpu*sizeof(ulong));
X		}
X	}
X	if(diskflag){
X		old_update = (kstime_t *)xmalloc(ndisk*sizeof(kstime_t));
X		old_rtime = (kstime_t *)xmalloc(ndisk*sizeof(kstime_t));
X		old_wtime = (kstime_t *)xmalloc(ndisk*sizeof(kstime_t));
X	}
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i, n=0;
X
X    if(cpuflag){
X        for(i=0; i<ncpu; i++,n++){
X		if(sep_wait) {
X			items[n] = NSTATES;
X		} else {
X			items[n] = NSTATES-1;
X		}
X        }
X    }
X    if(diskflag){
X        for(i=0; i<ndisk; i++,n++){
X                items[n] = DISKSTATES;
X        }
X    }
}
X
static void
display_cpu(base)
int base;
{
X	int i,j,nstates;
X	int states[CPU_STATES];
X	cpu_stat_t cpustat;
X	struct kstat_list *k;
#define delta(cpustate) ((int)(cpustat.cpu_sysinfo.cpu[(cpustate)] - cpu_old[(cpustate)][i]))
X
X
X	for(k=cpu;k;k=k->next){	/* for each cpu... */
X		int cpunum;
X
X		(void)sscanf(k->k->ks_name, "cpu_stat%d", &cpunum);
X		i=cpupos[cpunum];
X
X		/* grab info */
X		if(-1==kstat_read(kctl, k->k, (void *)&cpustat)){
X			perror("kstat: cpustat");
X			exit(1);
X		}
X		
X		nstates=0;
X		if(sep_wait) {
X			states[nstates++] = delta(CPU_IDLE);
X			states[nstates++] = delta(CPU_WAIT);
X		} else {
X			states[nstates++] = delta(CPU_IDLE) + delta(CPU_WAIT);
X		}
X		states[nstates++] = delta(CPU_USER);
X		states[nstates++] = delta(CPU_KERNEL);
X
X		draw_bar(i+base, states, nstates);
X
X		/* save old values */
X		for(j=0;j<CPU_STATES;j++){
X			cpu_old[j][i]=cpustat.cpu_sysinfo.cpu[j];
X		}
X	}
}
X
static void
display_disk(base)
int base;
{
X	int i;
X	kstat_io_t dstat;
X	struct kstat_list *k;
X	int states[DISKSTATES], nstates;
X	
X	for(i=0,k=disk;k;k=k->next,i++){ /* for each disk... */
X		double elapsed, run, wait, idle;
X		/* grab info */
X		if(-1==kstat_read(kctl, k->k, (void *)&dstat)){
X			perror(	"kstat: diskstat");
X			exit(1);
X		}
X
X		/* 
X		 * The goofy *(double *)& stuff is to support both compilers
X		 * that know about long long and those that don't. 
X		 * <sys/types.h> defines long long as a union of long[2]
X		 * and double if it thinks the compiler doesn't know 
X		 * about long long. 
X		 */
X		elapsed = *(double *)&dstat.wlastupdate - 
X			  *(double *)&old_update[i];
X		if(elapsed <= 0.0) elapsed = (double) NANOSEC;
X
X		run = 100 * (*(double *)&dstat.rtime - 
X				*(double *)&old_rtime[i]) /elapsed; 
X		wait = 100 * (*(double *)&dstat.wtime - 
X				*(double *)&old_wtime[i]) /elapsed;
X		idle = 100 - (run + wait);
X		if(idle<0.0) idle=0.0;
X
X		nstates=0;
X		states[nstates++] = (int)idle;
X		states[nstates++] = (int)wait;
X		states[nstates++] = (int)run;
X
X		draw_bar(i+base, states, 3);
X
X		/* save old values */
X
X		*(double *)&old_update[i] = *(double *)&dstat.wlastupdate;
X		*(double *)&old_rtime[i] = *(double *)&dstat.rtime;
X		*(double *)&old_wtime[i] = *(double *)&dstat.wtime;
X
X	}
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
int nbars;
{
X	int n=0;
X	
X	if(cpuflag) {
X		display_cpu(n);
X		n+=ncpu;
X	}
X	if(diskflag) {
X		display_disk(n);
X		n+=ndisk;
X	}
}
SHAR_EOF
  $shar_touch -am 0522184997 's-sunos5.c' &&
  chmod 0644 's-sunos5.c' ||
  $echo 'restore of' 's-sunos5.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-sunos5.c:' 'MD5 check failed'
1aeb00716e40fd2c4f7eda257e351a73  s-sunos5.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-sunos5.c'`"
    test 7501 -eq "$shar_count" ||
    $echo 's-sunos5.c:' 'original size' '7501,' 'current size' "$shar_count!"
  fi
fi
# ============= s-ultrix.c ==============
if test -f 's-ultrix.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-ultrix.c' '(file already exists)'
else
  $echo 'x -' extracting 's-ultrix.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-ultrix.c' &&
/*
X * System dependent file for Ultrix 4.2A
X */
X
/* 
X * Ricardo E Gonzalez, Stanford University <recardog@chroma.stanford.edu>
X *      based on code by
X * Salvador P. Abreu, U.Nova de Lisboa, PORTUGAL <spa@fctunl.rccn.pt>
X *      based on code by
X * Chris Siebenmann, University of Toronto <cks@sys.toronto.edu>
X */
X
/* LINTLIBRARY */
#include <sys/param.h>
#include <sys/dk.h>
#include <machine/cpu.h>
#include <sys/cpudata.h>
#include <nlist.h>
#include <stdio.h>
#include <errno.h>
X
#define kmseek(N) if (lseek(kmem, (long) (N), 0) != (long) (N)) perror ("lseek kmem");
#define KMEM 	"/dev/kmem"
X
extern char *xmalloc(/* int nbytes */);
X
extern int open(), read();
extern long lseek();
X
extern char *kernelSymbols;
X
struct cpudata *cpu_data[MAXCPU];
long **cptime_old = NULL;
X
int	kmem;			/* file descriptor of /dev/kmem. */
struct nlist	nl[] = {
#define X_ACTIVECPU 0
X	{ "_cpu_avail" },	/* number of active CPUs */
#define X_CPUDATA 1
X	{ "_cpudata" },		/* cpudata[] array */
#define X_LOWCPU 2
X	{ "_lowcpu" },		/* lowest cpu number */
#define X_HIGHCPU 3
X	{ "_highcpu" },		/* highest cpu number */
X	{ 0 },
};
X
int activecpu;
int lowcpu = 0;
int highcpu = 0;
static unsigned long cpudata_offset = 0;
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X    if ((kmem = open("/dev/kmem", 0)) < 0) {
X	perror("/dev/kmem");
X	exit(1);
X    }
X    (void) nlist(kernelSymbols?kernelSymbols:"/vmunix", nl);
X
/*
X    printf("ACTIVE : %x\n", nl[X_ACTIVECPU].n_value);
X    printf("CPUDATA: %x\n", nl[X_CPUDATA].n_value);
X    fflush(stdout);
*/
X
X    (void) getkval(nl[X_LOWCPU].n_value, (int *)(&lowcpu), sizeof(lowcpu),
X	nl[X_LOWCPU].n_name);
X    (void) getkval(nl[X_HIGHCPU].n_value, (int *)(&highcpu), sizeof(highcpu),
X	nl[X_HIGHCPU].n_name);
X    activecpu = highcpu - lowcpu + 1;
X    cpudata_offset = nl[X_CPUDATA].n_value;
X
/*
X    printf("CPUS   : %d\n", activecpu);
X    fflush(stdout);
X    return (activecpu);
*/
X
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i;
X
X    for(i = 0; i < nbars; i++)
X        items[i] = CPUSTATES;
}
X
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    static char **names;
X    static char hname[MAXHOSTNAMELEN];
X    int i;
X
X    names = (char **) malloc (nbars * sizeof (char *));
X    for (i=0; i<nbars; i++) {
X	names[i] = (char *) malloc (strlen("cpuxxx")+1);
X	(void) sprintf (names[i], "cpu%d", i);
X    }
X    return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void init_bars(nbars)
X    int nbars;
{
X    int ncpu, i;
X    register struct cpudata cpu;
X
X    (void) getkval(cpudata_offset, cpu_data, sizeof(cpu_data), "_cpudata");
X	
X    cptime_old = (long **) malloc (nbars * sizeof (long *));
X    for (ncpu=lowcpu; ncpu<=highcpu; ++ncpu) {
X	if (cpu_data[ncpu] != NULL) {
X	    (void) getkval(cpu_data[ncpu], &cpu, sizeof(cpu), "???");
X	    cptime_old[ncpu] = (long *) malloc (CPUSTATES * sizeof (long));
X	    if (cpu.cpu_state & CPU_RUN) {
X		for (i = 0; i < CPUSTATES; i ++) {
X		    cptime_old[ncpu][i] = cpu.cpu_cptime[i];
X		}
X	    }
X	}
X    }
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
#define delta(ncpu, cpustate) \
X    ((int) (cpu.cpu_cptime[(cpustate)] - cptime_old[ncpu][(cpustate)]))
X
/* ARGSUSED */
void
display_bars(nbars)
{
X    int	states[CPUSTATES];
X    int	nstates;
X    int	i, ncpu;
X    int status;
X    register struct cpudata cpu;
X    extern void draw_bar(	/*int bar_num, int *states, int num_states*/);
X	
X
X    (void) getkval(cpudata_offset, cpu_data, sizeof(cpu_data), "_cpudata");
X    for (ncpu = lowcpu; ncpu <= highcpu; ++ncpu) {
X	if (cpu_data[ncpu] != NULL) {
X	    (void) getkval(cpu_data[ncpu], &cpu, sizeof(cpu), "???");
X	    if (cpu.cpu_state & CPU_RUN) {
X		nstates = 0;
X		states[nstates++] = delta(ncpu, CP_IDLE);
X		states[nstates++] = delta(ncpu, CP_USER);
X		states[nstates++] = delta(ncpu, CP_NICE);
X		states[nstates++] = delta(ncpu, CP_SYS);
X
X		draw_bar(ncpu, states, nstates);
X
X		for (i = 0; i < CPUSTATES; i ++) {
X		    cptime_old[ncpu][i] = cpu.cpu_cptime[i];
/*		    printf ("%d\t", cptime_old[ncpu][i]); */
X		}
/*		printf ("\n"); */
X	    }
X	}
X    }
}
X
X
/*
X *  getkval(offset, ptr, size, refstr) - get a value out of the kernel.
X *      "offset" is the byte offset into the kernel for the desired value,
X *      "ptr" points to a buffer into which the value is retrieved,
X *      "size" is the size of the buffer (and the object to retrieve),
X *      "refstr" is a reference string used when printing error meessages,
X *          if "refstr" starts with a '!', then a failure on read will not
X *          be fatal (this may seem like a silly way to do things, but I
X *          really didn't want the overhead of another argument).
X *  
X */
X
getkval(offset, ptr, size, refstr)
X
unsigned long offset;
int *ptr;
int size;
char *refstr;
X
{
X    if (lseek(kmem, (long)offset, SEEK_SET) == -1) {
X        if (*refstr == '!')
X            refstr++;
X        (void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM, 
X                       refstr, strerror(errno));
X        exit(23);
X    }
X    if (read(kmem, (char *) ptr, size) == -1) {
X        if (*refstr == '!') 
X            return(0);
X        else {
X            (void) fprintf(stderr, "%s: reading %s: %s\n", KMEM, 
X                           refstr, strerror(errno));
X            exit(23);
X        }
X    }
X    return(1);
}
SHAR_EOF
  $shar_touch -am 0326205397 's-ultrix.c' &&
  chmod 0644 's-ultrix.c' ||
  $echo 'restore of' 's-ultrix.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-ultrix.c:' 'MD5 check failed'
4ecf09ab8bf8b6fe151160163d385395  s-ultrix.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-ultrix.c'`"
    test 5822 -eq "$shar_count" ||
    $echo 's-ultrix.c:' 'original size' '5822,' 'current size' "$shar_count!"
  fi
fi
# ============= s-unicos.c ==============
if test -f 's-unicos.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-unicos.c' '(file already exists)'
else
  $echo 'x -' extracting 's-unicos.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-unicos.c' &&
/*
X * System dependent file for Cray Unicos >= 5.1 Systems
X * Walter D. Poxon, Cray Research, Inc., Eagan, MN  <wdp@cray.com>
X */
X
#include <nlist.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/unistd.h>
#include <sys/param.h>
#include <sys/pws.h>
#include <errno.h>
X
#define UNICOS "/unicos"
#define KMEM "/dev/kmem"
X
#define NSTATES 6
#define NCPUSTATES 3
X
int num_bars(void);
void bar_items(int nbars, int items[]);
char ** label_bars(int nbars);
void init_bars(int nbars);
void display_bars(int nbars);
X
static struct nlist nl[] = { {"cpuw"},{0} };
int kmem;
long bytes;
struct pw cpuw;
X
extern int sep_wait;
extern char *kernelSymbols;
X
extern char *xmalloc(/* int nbytes */);
X
union cpu_name {
X	word wval;
X	struct {
X		uint : 32,
X		c    : 8,
X		p    : 8,
X		u    : 8,
X		no   : 8;
X	} cval;
};
X
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars(void)
{
X	bzero(&cpuw,sizeof(cpuw));
X
X	if (nlist(kernelSymbols?kernelSymbols:UNICOS,nl) == -1) {
X		perror("nlist");
X		return 0;
X	}
X
X	bytes = nl[0].n_value;
X	
X	if ((kmem = open(KMEM, O_RDONLY)) <0) {
X		perror("open");
X		return 0;
X	}
X
X	if (lseek(kmem, bytes, SEEK_SET) != bytes) {
X		perror("lseek");
X		return 0;
X	}
X	
X
X	if (read(kmem, &cpuw, sizeof(cpuw)) != sizeof(cpuw)){
X		perror("read");
X		return 0;
X	}
X
X	return cpuw.pw_ccpu;       /* Number of CPU's configured in UNICOS */
}
X
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(int nbars, int items[])
{
X	int i;
X	
X	for (i = 0; i < nbars; i++)
X		items[i] = NCPUSTATES;
}
X
X
char **
label_bars(int nbars)          /* Called after num_bars to ask for bar names */
{
X	char **names;
X	int i;
X	extern char *strcpy(/* char *, const char * */);
X	union cpu_name c;
X
X	names = (char **) xmalloc(nbars * sizeof(char *));
X
X	for (i = 0; i < nbars; i++) {
X		char buf[8];
X		c.wval = cpuw.pws[i].pw_cpu;
X		sprintf(buf, "%c%c%c%c", c.cval.c, c.cval.p, c.cval.u,
X			c.cval.no);
X		names[i] = strcpy(xmalloc(strlen(buf)+1), buf);
X	}
X
X	return names;
}
X
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
void
init_bars(int nbars)
{
X	display_bars(nbars);
}
X
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
X
#define delta(cpustate) \
X  ((int) (si[i]->cpu[(cpustate)] - last_si[i]->cpu[(cpustate)]))
X
void
display_bars(int nbars)
{
X	int states[NSTATES];
X	int nstates;
X	int cpu;
X	extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X
X	if (lseek(kmem, bytes, SEEK_SET) != bytes) {
X		perror("lseek");
X		return;
X	}
X	
X    
X	if (read(kmem, &cpuw, sizeof(cpuw)) != sizeof(cpuw)) {
X		perror("read");
X		return;
X	}
X	
X
X	for (cpu=0; cpu < nbars; cpu++) {
X		nstates = 0;
X
X		if(sep_wait){
X			states[nstates++] = cpuw.pws[cpu].pw_idlee;
X			states[nstates++] = cpuw.pws[cpu].pw_syswe;
X		} else {	
X			states[nstates++] = cpuw.pws[cpu].pw_syswe
X				+ cpuw.pws[cpu].pw_idlee;
X		}
X		states[nstates++] = cpuw.pws[cpu].pw_usere;
X		states[nstates++] = cpuw.pws[cpu].pw_unixe;
X
X		draw_bar(cpu, states, nstates);
X	}
}
SHAR_EOF
  $shar_touch -am 0721162994 's-unicos.c' &&
  chmod 0644 's-unicos.c' ||
  $echo 'restore of' 's-unicos.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-unicos.c:' 'MD5 check failed'
b4b0dbe11f9e8c6b2309f0bf57d4f766  s-unicos.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-unicos.c'`"
    test 3332 -eq "$shar_count" ||
    $echo 's-unicos.c:' 'original size' '3332,' 'current size' "$shar_count!"
  fi
fi
# ============= s-ncr.c ==============
if test -f 's-ncr.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-ncr.c' '(file already exists)'
else
  $echo 'x -' extracting 's-ncr.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-ncr.c' &&
/* System dependent file for NCR System V Release 4 MP/RAS     */
X
/* $Id: s-ncr.c,v 1.2 1994/09/07 00:44:31 jdd Exp $ */
X
#include "s.h"
#include <stdio.h>
#include <nlist.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/unistd.h>
#include <sys/mman.h>
X
#include <sys/utsname.h>
#include <sys/pic.h>
#include <sys/sysinfo.h>
#include <sys/mp/percpu.h>
#include <sys/immu.h>
X
#include <sys/scsi/cs.h>
X
#include <errno.h>
X
extern int   diskflag, cpuflag;
extern char *kernelSymbols;
X
extern void draw_bar(int bar_num, int *states, int num_states);
extern void display_bars(int);
X
struct cpu_names
{
X  int   cpu_type;
X  char  cpu_type_name[8];
};
X
const struct cpu_names  cpu_model_names[] =
{
X  { CPU_386,     "i386" },
X  { CPU_486,     "i486" },
#ifdef CPU_586
X  { CPU_586,     "Pentium" },
#elif defined CPU_Pentium
X  { CPU_Pentium, "Pentium" },
#endif
};
X
X
/*  The following defines are used to index the variable kernel_nl[] */
#define KERNEL_UTSNAME   0
#define KERNEL_PERCPUP   1
#define KERNEL_CPU_INFOS 2
#define KERNEL_NCPU      3
#define KERNEL_SCSI_STAT 4
#define KERNEL_LBOLT     5
X
/* kernel_nl[]  --  list of symbol addresses needed.
*/
static struct nlist kernel_nl[] =
{
X  { "utsname",       0 },
X  { "percpup",       0 },
X  { "cpu_infos",     0 },
X  { "ncpu",          0 },
X  { "SCSI_Stat_Ptr", 0 },
X  { "lbolt",         0 },
X
X  { 0,               0 }
};
X
X
X
/* kernel_symbols[] -- list of places to look for the running kernel's symbols
*/
char *kernel_symbols[] = {
X  0,                   /* used by -kernel option  */
X  "/stand/unix.diag",
X  "/stand/unix",
X  "/stand/unix.old",
X
X  0
};
X  
X
X
enum stype
{
X  CPU_STATE,
X  DISK_STATE,
};
X
enum stype      state = CPU_STATE;
int             kmem;              /* file descriptor for /dev/kmem      */
char           *kernel_name;       /* name of kernel (/stand/unix)       */
struct utsname  nodename;          /* nodename.nodename                  */
int             kmem_is_mapped;
int             kmem_is_reading;
int             kmem_can_map    = 1;
X
X
/*  Fake kernel memory mapping information
*/
typedef struct kmem_map
{
X  struct kmem_map *km_next;
X  void            *km_addr;
X  size_t           km_size;
X  char             km_buf[4];
} kmem_map_t;
X
kmem_map_t *kmem_list;             /* linked list of fake memory mappings */
X
/*  CPU Information
*/
int             kncpu;             /* maximum number of cpu's on system  */
int             ncpus;             /* number of cpu's which exist        */
percpu_t      **kpercpup;          /* array of percpu_t pointers         */
percpu_t      **xpercpup;          /* percpu_t pointers when mmapped     */
percpu_t      **mypercpup    = 0;  /* Pointers to each cpu's percpu area */
time_t         *lastcpu;           /* last snapshot of each cpu's times  */
cpu_info_t     *kcpu_infos;        /* State of each cpu                  */
X
X
/* SCSI Disk Information
*/
int             ndisks;
long            kscsi_stat_ptr_addr;
long            kaddr;
X
typedef struct diskinfo
{
X  dev_t            di_dev;
X  SCSI_Device_t   *di_kscsi;
X  StatStructure_t  di_stats;
} diskinfo_t;
X
long           *lboltp;
long            last_lbolt, new_lbolt;
diskinfo_t     *kscsi_stat;
SCSI_Device_t  *lscsi_stat;
SCSI_Device_t   tscsi_stat;
X
X
X
/* The size of the array which holds the cpu
X   execution information.
*/
#if defined( CPU_Pentium )
#define  MPSYSINFO     c_sysinfo
#else
#define  MPSYSINFO     c_mpinfo
#endif
X
#define CPU_STATE_SZ   sizeof(mypercpup[0]->MPSYSINFO.cpu)
X
X
/* Computes the time spent in the specified state.
*/
X
#define delta(state) \
X   ((int) mypercpup[cpu]->MPSYSINFO.cpu[state] - cputime[state])
X
X
/* Save the state times for a specific cpu
*/
#define savecpuinfo(cpu) \
X   memcpy(cputime, mypercpup[cpu]->MPSYSINFO.cpu, CPU_STATE_SZ);
X
X
/* The size of the local state time array
*/
#define NSTATES   CPU_STATE_SZ
#define CPUSTATES (CPU_STATE_SZ / sizeof(mypercpup[0]->MPSYSINFO.cpu[0]))-1
X
/* Display an error message based upon errno and
X   return 0 to caller
*/
#define ERR_EXIT(msg) \
{               \
X   perror(msg); \
X   return 0;    \
}
X
X
/* Read a specified number of bytes of kernel memory
X   and report any error conditions which might arise.
*/
#define seekreadok(desc, seekpos, buf, sz, msg) \
X  if (-1 == lseek(desc, seekpos, SEEK_SET))  \
X    ERR_EXIT("lseeking " msg);               \
X \
X  if ((sz) != read(desc, buf, (sz)))         \
X    ERR_EXIT("reading " msg);
X
#define seekreaderr(desc, seekpos, buf, sz, msg) \
X   ( -1  == lseek(desc, seekpos, SEEK_SET) ||  \
X    (sz) != read(desc, buf, (sz)))
X
X
/* fakethis()  -- provide faked out memory mappings if unable to mmap kernel.
*/
void *
fakethis(void *loc, size_t sz)
{
X  kmem_map_t *mapping = (kmem_map_t *)malloc( sizeof(kmem_map_t) + sz );
X
X  if (!mapping)
X    return 0;
X
X  mapping->km_addr = loc;
X  mapping->km_size = sz;
X  mapping->km_next = kmem_list;
X
X  seekreadok(kmem, mapping->km_addr, mapping->km_buf, mapping->km_size,
X	     "faking mmap");
X
X  if (!kmem_list && kmem_can_map)
X    fprintf(stderr, "Unable to mmap kernel addresses, using lseek/read\n");
X
X  kmem_list = mapping;
X  kmem_is_reading++;
X
X  return (void *) mapping->km_buf;
}
X
/* refreshfakes()  --  Refresh fake mmap snapshots.
*/
int
refreshfakes(void)
{
X  kmem_map_t *mapping;
X  int         errs    = 0;
X
X  for (mapping = kmem_list; mapping; mapping = mapping->km_next)
X    if (seekreaderr(kmem, mapping->km_addr, mapping->km_buf, mapping->km_size,
X		    "refreshing fake mmap's"))
X      errs++;
X
X  return errs;
}
X
/*  Given an address (and size in bytes) in kernel virtual memory,
X    this function uses the mmap function to provide a mapping for
X    those addresses in the current process.  The result is either
X    a pointer to the data in this processes virtual space or
X    (void *)-1 if unable to provide the mapping.
*/
void *
mapthis(int desc, void *locp, unsigned long sz)
{
X  unsigned long pgoffs = (unsigned long) locp & POFFMASK;
X  unsigned long pgstrt = (unsigned long) locp & PG_ADDR;
X  unsigned long pgend  = ((unsigned long) locp + sz) & PG_ADDR;
X  unsigned long mapsz  = pgend - pgstrt + NBPP;
X  char         *map    = (char *)-1;
X
X  if (kmem_can_map)
X    map = mmap(0, mapsz, PROT_READ, MAP_SHARED, desc, pgstrt);
X
X  if ((char *)-1 == map)
X    {
X      if (kmem_is_mapped)
X	fprintf(stderr, "Mixing mapping and lseek/read kernel memory?\n");
X
X      map = fakethis(locp, sz);
X      return map ? map : (void *)-1;
X    }
X
X  kmem_is_mapped++;
X  return (void *) (map + pgoffs);
}
X
X
X
/* get_kernel_symbols  --  Find the file containing the symbol definitions
X                           for the currently running kernel.
X
X   The kernel must be running out of /stand (on an svr4 system) and the
X   symbol value for utsname must match the name returned by the uname()
X   system call.
X
X   This function is called given a list of possible files from /stand which
X   may be running and returns the name of the first file which appears
X   to be correct.
*/
X
char *
get_kernel_symbols(int kmemfd, char **knamelist)
{
X  char **cpp;
X  int    nf, errs;
X  int    nsz = strlen(nodename.nodename) + 1;
X  struct utsname nname;
X
X  if (1 >= nsz)
X    fprintf(stderr, "xcpustate: Empty node name\n");
X
X  if (kernelSymbols)
X    *knamelist = kernelSymbols;
X
X  if (!*knamelist) knamelist++;  /* skip over initial NULL pointer */
X
X  for (cpp = knamelist; *cpp; cpp++)
X    {
X      for (nf = 0; kernel_nl[nf].n_name; nf++)
X	kernel_nl[nf].n_value = 0;
X
X      nf = nlist(*cpp, kernel_nl);
X      if (-1 == nf || 0 == kernel_nl[KERNEL_UTSNAME].n_value)
X	continue;
X
X      if (!seekreaderr(kmemfd, kernel_nl[KERNEL_UTSNAME].n_value,
X		     &nname.nodename, nsz, "utsname") &&
X	  0 == strncmp(nodename.nodename, nname.nodename, nsz))
X	{
X	  for (errs = nf = 0; kernel_nl[nf].n_name; nf ++)
X	    if (0 == kernel_nl[nf].n_value)
X	      {
X		fprintf(stderr, "kernel symbol `%s' not found\n",
X			kernel_nl[nf].n_name);
X		errs++;
X	      }
X
X	  if (errs)
X	    return 0;
X
X	  return *cpp;
X	}
X    }
X
X  fprintf(stderr, "xcpustate: No kernel symbol file matches running kernel\n");
X  return 0;
}
X
X
X
/* init_cpu_init()  --  Initialize for CPU display
*/
int
init_cpu_info(void)
{
X  int nf;
X
X  seekreadok(kmem,
X	     kernel_nl[KERNEL_NCPU].n_value,
X	     &kncpu,
X	     sizeof(kncpu),
X	     "/dev/kmem [ncpu]");
X
X  if (kncpu > 64 || kncpu < 0)
X    {
X      fprintf(stderr, "Unlikely value for ncpu found.\n");
X      return 0;
X    }
X
X  kcpu_infos = mapthis(kmem,
X		       (void *)kernel_nl[KERNEL_CPU_INFOS].n_value,
X		       kncpu*sizeof(cpu_info_t));
X  if (-1 == (int)kcpu_infos)
X    ERR_EXIT("mapping cpu_infos[]");
X
X  kpercpup   = mapthis(kmem,
X		       (void *)kernel_nl[KERNEL_PERCPUP].n_value,
X		       kncpu * sizeof(percpu_t *));
X  if (-1 == (int)kpercpup)
X    ERR_EXIT("mapping percpup[]");
X
X  mypercpup = (percpu_t **) malloc( sizeof(percpu_t *) * kncpu );
X  if (!mypercpup)
X    ERR_EXIT("allocating memory");
X
X  xpercpup   = (percpu_t  **) malloc( kncpu * sizeof(percpu_t *));
X  if (!kpercpup)
X    ERR_EXIT("allocating memory");
X
X  memset(xpercpup, 0, kncpu * sizeof(percpu_t *));
X
X  for (ncpus = nf = 0;  nf < kncpu; nf++)
X    if (kcpu_infos[nf].cpu_flag & CPU_EXISTS)
X      {
X	if (kpercpup[nf])
X	  {
X	    xpercpup[ncpus] = kpercpup[nf];
X	    mypercpup[ncpus] = mapthis(kmem,
X				       xpercpup[ncpus],
X				       sizeof(*(kpercpup[nf])));
X	    if (-1 == mypercpup[ncpus])
X	      ERR_EXIT("mapping percpu area");
X	  }
X	ncpus++;
X      }
X
X  nf = ncpus * CPU_STATE_SZ;
X  lastcpu = (time_t *) malloc(nf);
X  memset(lastcpu, 0, nf);
X
X  return ncpus;
}
X
X
/* scsitype()  --  return string naming scsi device type.
*/
char *
scsitype(int t)
{
X  switch (t)
X    {
X    case SCSI_DAD_TYPE:     return "disk";
X    case SCSI_SAD_TYPE:     return "tape";
X    case SCSI_PRT_TYPE:     return "printer";
X    case SCSI_PROC_TYPE:    return "proc";
X    case SCSI_WORM_TYPE:    return "worm";
X    case SCSI_CD_ROM_TYPE:  return "cdrom";
X    case SCSI_SCAN_TYPE:    return "scanner";
X    case SCSI_OPTICAL_TYPE: return "optical";
X    case SCSI_CHANGER_TYPE: return "changer";
X    case SCSI_COMM_TYPE:    return "comm";
X    }
X
X  return "<unknown>";
}
X
X
/* diskname()   --  Return string naming disk device.
*/
char *
diskname(Partition_Identifier_t *s)
{
X  static char name[52];
X
X  if (0 == s->IO_Bus)
X    {
X      if (0 == s->SCSI_Controller)
X	sprintf(name, "c%xt%xd%xs%x",
X		s->SCSI_Bus,
X		s->PUN, s->LUN, s->Partition);
X      else
X	sprintf(name, "c%x%xt%xd%xs%x",
X		s->SCSI_Controller, s->SCSI_Bus,
X		s->PUN, s->LUN, s->Partition);
X    }
X  else
X    sprintf(name, "c%x%x%xt%xd%xs%x",
X	    s->IO_Bus, s->SCSI_Controller, s->SCSI_Bus,
X	    s->PUN,    s->LUN,             s->Partition);
X
X  return name;
}
X
int
init_disk_info(void)
{
X  long kaddr;
X  int  cdisk;
X  int head = 0, nprocs = 0, ncdroms = 0, ntapes = 0;
X  
X  seekreadok(kmem,
X	     kernel_nl[KERNEL_SCSI_STAT].n_value,
X	     &kscsi_stat_ptr_addr,
X	     sizeof(kscsi_stat_ptr_addr),
X	     "/dev/kmem [SCSI_Stat_Ptr]");
X
X  kaddr  = kscsi_stat_ptr_addr;
X  ndisks = 0;
X
X  do
X    {
X      seekreadok(kmem,kaddr,&tscsi_stat,sizeof(tscsi_stat),"/dev/kmem [SCSI]");
X      switch (tscsi_stat.inquiry_data.Periph_Device_Type)
X	{
X	case SCSI_DAD_TYPE:     ndisks++;   break;
X	case SCSI_SAD_TYPE:     ntapes++;   break;
X	case SCSI_CD_ROM_TYPE:  ncdroms++;  break;
X	case SCSI_PROC_TYPE:    nprocs++;   break;
X	}
X      kaddr = (long) tscsi_stat.Statistics.ForwardPointer;
X    }
X  while (kscsi_stat_ptr_addr != kaddr);
X
X  fprintf(stderr, "SCSI: %d disks, %d tapes, %d cdroms, %d controllers\n",
X	  ndisks, ntapes, ncdroms, nprocs);
X
X  kscsi_stat = (diskinfo_t *) malloc((1+ndisks) * sizeof(diskinfo_t));
X  if (!kscsi_stat)
X    ERR_EXIT("Allocate SCSI Disk memory");
#if 0
X  lscsi_stat = (SCSI_Device_t *) malloc((1+ndisks) * sizeof(SCSI_Device_t));
X  if (!lscsi_stat)
X    ERR_EXIT("Allocate SCSI Statistics array");
X  memset(lscsi_stat, 0, ndisks * sizeof(SCSI_Device_t));
#endif
X
X  kaddr  = kscsi_stat_ptr_addr;
X  cdisk = 0;
X
X  lboltp = (long *) mapthis(kmem, (void *)kernel_nl[KERNEL_LBOLT].n_value,
X			    sizeof(long));
X  if (-1 == (long) lboltp)
X    {
X      perror("Can't map lbolt");
X      return 0;
X    }
X  last_lbolt = *lboltp;
X
X  do
X    {
X      lscsi_stat = (SCSI_Device_t *) mapthis(kmem, (void *)kaddr,
X					     sizeof(tscsi_stat));
X      if (-1 == (long) lscsi_stat)
X	{
X	  perror("Can't map SCSI information");
X	  return 0;
X	}
X
X      kscsi_stat[cdisk].di_kscsi = (SCSI_Device_t *) lscsi_stat;
X      kscsi_stat[cdisk].di_dev   = lscsi_stat->dev;
X      memcpy(&kscsi_stat[cdisk].di_stats, &lscsi_stat->Statistics,
X	     sizeof(lscsi_stat->Statistics));
X
X      if (!head++)
X       fprintf(stderr,"  #  Bus  Ctrlr  SBus  PUN  LUN  Part  dev_num Name\n");
X
X      fprintf(stderr, "%3d  %3d  %5d  %4d  %3d  %3d  %4d %08x %s (%s)\n",
X	      cdisk,
X	      lscsi_stat->SCSI_device.IO_Bus,
X	      lscsi_stat->SCSI_device.SCSI_Controller,
X	      lscsi_stat->SCSI_device.SCSI_Bus,
X	      lscsi_stat->SCSI_device.PUN,
X	      lscsi_stat->SCSI_device.LUN,
X	      lscsi_stat->SCSI_device.Partition,
X	      lscsi_stat->dev,
X	      diskname(&lscsi_stat->SCSI_device),
X	      scsitype(lscsi_stat->inquiry_data.Periph_Device_Type));
X	      
X      kaddr = (long) lscsi_stat->Statistics.ForwardPointer;
X
X      if (SCSI_DAD_TYPE == lscsi_stat->inquiry_data.Periph_Device_Type)
X	cdisk++;
X    }
X  while (kscsi_stat_ptr_addr != kaddr);
X
X  if (cdisk != ndisks)
X    ERR_EXIT("Error counting disks");
X
X  return ndisks;
}
X
X
X
/* Called at the beginning to inquire how many bars are needed
*/
int
num_bars(void)
{
X  int         nf;
X  int         errs;
X  int         sz;
X  char       *pgs    = 0;
X
X  kmem   = open("/dev/kmem", O_RDONLY);
X  if (-1 == kmem)
X    ERR_EXIT("opening /dev/kmem");
X
X  if (-1 == uname(&nodename))
X    ERR_EXIT("uname");
X
X  kernel_name = get_kernel_symbols(kmem, kernel_symbols);
X  if (!kernel_name)
X    return 0;
X
X  if (diskflag)
X    {
X      if (cpuflag)
X	fprintf(stderr, "Only disk or cpu state can be monitored\n");
X      state  = DISK_STATE;
X      return init_disk_info();
X    }
X
X  return init_cpu_info();
}
X
X
X
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X  int i;
X  int nlevels = (DISK_STATE == state) ? 2 : CPUSTATES;
X
X  for (i = 0; i < nbars; )
X    items[i++] = nlevels;
}
X
X
/* Called after num_bars to ask for bar names */
char **
label_cpu_bars(nbars)
{
X  char **names;
X  int    hsz   = strlen(nodename.nodename);
/*****                  ' '   '#'   %d    ' '   'i486'   ' '  *****/
X  int    rowsz = hsz +   1 +   1 +   3 +   1 +      7 +   2;
X  int    sz    = nbars * rowsz;
X  int    cpu, i;
X  char  *cp;
X
X  shorten(nodename.nodename);
X
X  names  = (char **)malloc(sz + sizeof(char *) * nbars);
X
X  cp     = (char *)names + sizeof(char *) * nbars;
X
X  for (cpu = i = 0; i < kncpu; i++)
X    if (kcpu_infos[i].cpu_flag & CPU_EXISTS)
X      {
X	names[cpu++] = cp;
X
X	if (1 == ncpus)
X	  sprintf(cp, "%s", nodename.nodename);
X	else if (0 == i)
X	  sprintf(cp, "%s #%d", nodename.nodename, i);
X	else
X	  sprintf(cp, "%*s #%d", hsz, "", i);
X
X	cp += rowsz;
X      }
X
X  return names;
}
X
char **
label_disk_bars(nbars)
{
X  char **names;
X  char  *cp;
X  int    i;
X  int    hsz    = sizeof("cxxxtxdxsx");
X
X  names = (char **) malloc( hsz * nbars + nbars * sizeof(char *) );
X  cp    = (char *) names + sizeof(char *) * nbars;
X
X  for (i = 0; i < nbars; i++)
X    {
X      names[i]   = cp;
X      lscsi_stat = kscsi_stat[i].di_kscsi;
X      strcpy(cp, diskname(&lscsi_stat->SCSI_device));
X      cp += hsz;
X    }
X
X  return names;
}
X
X
char **
label_bars(nbars)
{
X  switch (state)
X    {
X    case CPU_STATE:  return label_cpu_bars(nbars);
X    case DISK_STATE: return label_disk_bars(nbars);
X    }
X
X  return NULL;
}
X
X
/*  Called after the bars are created to do machine dependent inits */
void
init_bars(nbars)
X  int nbars;
{
X  (void) display_bars(nbars);
}
X
X
X
X
/*
X   This function is called every interval to compute and display
X   the bars.  It should call draw_bar() with the bar number, the array of
X   integer values to display in the bar, and the number of values in the
X   array.
*/
void
display_cpu_bars(nbars)
{
X  int states[NSTATES];
X  int nstates;
X  int cpu, i;
X  time_t *cputime = lastcpu;
X
X  for (i = cpu = 0; i < kncpu && cpu < nbars; i++)
X    {
X      if (0 == (kcpu_infos[i].cpu_flag & CPU_EXISTS))
X	continue;
X
X      nstates = 0;
X
X      if (kcpu_infos[i].cpu_flag & CPU_RUNNING && kpercpup[i])
X	{
X	  if (kpercpup[cpu] != xpercpup[i])
X	    { /* mapping changed or became available */
X	      xpercpup[cpu] = kpercpup[i];
X	      mypercpup[ i] = mapthis(kmem, xpercpup[cpu],
X				      sizeof(*(xpercpup[cpu])));
X	    }
X	  states[nstates++] = delta(CPU_IDLE);
X	  states[nstates++] = delta(CPU_USER);
X	  states[nstates++] = delta(CPU_KERNEL);
X	  states[nstates++] = delta(CPU_WAIT) + delta(CPU_SXBRK);
#if 0
X	  states[nstates++] = delta(CPU_SXBRK);
#endif
X	}
X      else
X	{
X	  states[nstates++] = 100;  /* CPU_IDLE   */
X	  states[nstates++] =   0;  /* CPU_USER   */
X	  states[nstates++] =   0;  /* CPU_KERNEL */
X	  states[nstates++] =   0;  /* CPU_WAIT   */
#if 0
X	  states[nstates++] =   0;  /* CPU_SXBRK  */
#endif
X	}
X      savecpuinfo(cpu);
X      draw_bar(cpu, states, nstates);
X
X      cpu++;
X      cputime += CPU_STATE_SZ / sizeof(time_t);
X    }
}
X
X
void
display_disk_bars(nbars)
{
X  int    states[2];
X  int    i;
X  time_t t;
X  static time_t maxt = 0;
X  static int    npr  = 0;
X  time_t dlt;
X  struct iotime *new, *old;
X
X  new_lbolt  = *lboltp;
X  dlt        = new_lbolt - last_lbolt;
X  last_lbolt = new_lbolt;
X  
X  for (i = 0; i < ndisks; i++)
X    {
X      lscsi_stat = kscsi_stat[i].di_kscsi;
X
X      if (kscsi_stat[i].di_dev != lscsi_stat->dev)
X	{ /* device changed */
X	  states[0] = 100;  /* idle */
X	  states[1] = 0;    /* busy */
X	}
X      else
X	{
X	  new       = &lscsi_stat->Statistics.SCSI_Stats;
X	  old       = &kscsi_stat[i].di_stats.SCSI_Stats;
X	  t         = new->io_act - old->io_act;
X
X	  states[1] = t;
X	  if (states[1] > dlt)
X	    states[0] = 0;
X	  else
X	    states[0] = dlt - states[1];
X
X	  old->io_act  = new->io_act;
X	  old->io_resp = new->io_resp;
X	}
X      draw_bar(i, states, 2);
X    }
}
X
void
display_bars(nbars)
{
X  if (kmem_list)
X    refreshfakes();
X
X  switch (state)
X    {
X    case CPU_STATE:  display_cpu_bars(nbars);
X    case DISK_STATE: display_disk_bars(nbars);
X    }
X
X  return;
}
SHAR_EOF
  $shar_touch -am 0326205997 's-ncr.c' &&
  chmod 0640 's-ncr.c' ||
  $echo 'restore of' 's-ncr.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-ncr.c:' 'MD5 check failed'
14ca4d363af14e1d8012e85718ec8576  s-ncr.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-ncr.c'`"
    test 18420 -eq "$shar_count" ||
    $echo 's-ncr.c:' 'original size' '18420,' 'current size' "$shar_count!"
  fi
fi
# ============= s-svr4.c ==============
if test -f 's-svr4.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-svr4.c' '(file already exists)'
else
  $echo 'x -' extracting 's-svr4.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-svr4.c' &&
/* System dependent file for System V Release 4.0      */
/* Tested on Unixware 1.1 (SVR4.2)                     */
X
/* $Id: s-svr4.c,v 1.3 1996/01/04 20:12:08 jdd Exp $ */
X
#include "s.h"
X
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <nlist.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/immu.h>
X
#include <sys/utsname.h>
#include <sys/sysinfo.h>
X
#include <errno.h>
X
extern int   diskflag, cpuflag;
extern char *kernelSymbols;
X
extern void draw_bar(int bar_num, int *states, int num_states);
extern void display_bars(int);
X
X
X
/*  The following defines are used to index the variable kernel_nl[] */
#define KERNEL_UTSNAME   0
#define KERNEL_SYSINFO   1
#define KERNEL_LBOLT     2
X
/* kernel_nl[]  --  list of symbol addresses needed.
*/
static struct nlist kernel_nl[] =
{
X  { "utsname",       0 },
X  { "sysinfo",       0 },
X  { "lbolt",         0 },
X
X  { 0,               0 }
};
X
X
X
/* kernel_symbols[] -- list of places to look for the running kernel's symbols
*/
char *kernel_symbols[] = {
X  "/stand/unix.diag",
X  "/stand/unix",
X  "/stand/unix.old",
X  0,                   /* used by -kernel option  */
X
X  0
};
X
X
X
enum stype
{
X  CPU_STATE,
};
X
X
enum stype      state = CPU_STATE;
int             kmem;              /* file descriptor for /dev/kmem      */
char           *kernel_name;       /* name of kernel (/stand/unix)       */
struct utsname  nodename;          /* nodename.nodename                  */
int             kmem_is_mapped;
int             kmem_is_reading;
int             kmem_can_map    = 1;
X
X
/*  Fake kernel memory mapping information
*/
typedef struct kmem_map
{
X  struct kmem_map *km_next;
X  void            *km_addr;
X  size_t           km_size;
X  char             km_buf[4];
} kmem_map_t;
X
kmem_map_t *kmem_list;             /* linked list of fake memory mappings */
X
/*  CPU Information
*/
int             kncpu;             /* maximum number of cpu's on system  */
int             ncpus;             /* number of cpu's which exist        */
time_t         *lastcpu;           /* last snapshot of each cpu's times  */
struct sysinfo *cpuinfo;
X
X
X
#define CPU_STATE_SZ   sizeof(cpuinfo[0].cpu)
X
/* Computes the time spent in the specified state.
*/
X
#define delta(state) \
X   ((int) cpuinfo[cpu].cpu[state] - cputime[state])
X
X
/* Save the state times for a specific cpu
*/
#define savecpuinfo(cpu) \
X   memcpy(cputime, cpuinfo[cpu].cpu, CPU_STATE_SZ);
X
X
/* The size of the local state time array
*/
#define NSTATES   CPU_STATE_SZ
#define CPUSTATES (CPU_STATE_SZ / sizeof(cpuinfo[0].cpu[0]))
X
/* Display an error message based upon errno and
X   return 0 to caller
*/
#define ERR_EXIT(msg) \
{               \
X   perror(msg); \
X   return 0;    \
}
X
X
/* Read a specified number of bytes of kernel memory
X   and report any error conditions which might arise.
*/
#define seekreadok(desc, seekpos, buf, sz, msg) \
X  if (-1 == lseek(desc, (off_t)seekpos, SEEK_SET))  \
X    ERR_EXIT("lseeking " msg);               \
X \
X  if ((sz) != read(desc, buf, (sz)))         \
X    ERR_EXIT("reading " msg);
X
#define seekreaderr(desc, seekpos, buf, sz, msg) \
X   ( -1  == lseek(desc, (off_t)seekpos, SEEK_SET) ||  \
X    (sz) != read(desc, buf, (sz)))
X
X
/* fakethis()  -- provide faked out memory mappings if unable to mmap kernel.
*/
void *
fakethis(void *loc, size_t sz)
{
X  kmem_map_t *mapping = (kmem_map_t *)malloc( sizeof(kmem_map_t) + sz );
X
X  if (!mapping)
X    return 0;
X
X  mapping->km_addr = loc;
X  mapping->km_size = sz;
X  mapping->km_next = kmem_list;
X
X  seekreadok(kmem, mapping->km_addr, mapping->km_buf, mapping->km_size,
X	     "faking mmap");
X
X  if (!kmem_list && kmem_can_map)
X    fprintf(stderr, "Unable to mmap kernel addresses, using lseek/read\n");
X
X  kmem_list = mapping;
X  kmem_is_reading++;
X
X  return (void *) mapping->km_buf;
}
X
/* refreshfakes()  --  Refresh fake mmap snapshots.
*/
int
refreshfakes(void)
{
X  kmem_map_t *mapping;
X  int         errs    = 0;
X
X  for (mapping = kmem_list; mapping; mapping = mapping->km_next)
X    if (seekreaderr(kmem, mapping->km_addr, mapping->km_buf, mapping->km_size,
X		    "refreshing fake mmap's"))
X      errs++;
X
X  return errs;
}
X
/*  Given an address (and size in bytes) in kernel virtual memory,
X    this function uses the mmap function to provide a mapping for
X    those addresses in the current process.  The result is either
X    a pointer to the data in this processes virtual space or
X    (void *)-1 if unable to provide the mapping.
*/
void *
mapthis(int desc, void *locp, unsigned long sz)
{
X  unsigned long pgoffs = (unsigned long) locp & POFFMASK;
X  unsigned long pgstrt = (unsigned long) locp & PG_ADDR;
X  unsigned long pgend  = ((unsigned long) locp + sz) & PG_ADDR;
X  unsigned long mapsz  = pgend - pgstrt + NBPP;
X  char         *map    = (char *)-1;
X
X  if (kmem_can_map)
X    map = mmap(0, mapsz, PROT_READ, MAP_SHARED, desc, pgstrt);
X
X  if ((char *)-1 == map)
X    {
X      if (kmem_is_mapped)
X	fprintf(stderr, "Mixing mapping and lseek/read kernel memory?\n");
X
X      map = fakethis(locp, sz);
X      return map ? map : (void *)-1;
X    }
X
X  kmem_is_mapped++;
X  return (void *) (map + pgoffs);
}
X
X
X
/* get_kernel_symbols  --  Find the file containing the symbol definitions
X                           for the currently running kernel.
X
X   The kernel must be running out of /stand (on an svr4 system) and the
X   symbol value for utsname must match the name returned by the uname()
X   system call.
X
X   This function is called given a list of possible files from /stand which
X   may be running and returns the name of the first file which appears
X   to be correct.
*/
X
char *
get_kernel_symbols(int kmemfd, char **knamelist)
{
X  char **cpp;
X  int    nf, errs;
X  int    nsz = strlen(nodename.nodename) + 1;
X  struct utsname nname;
X
X  if (1 >= nsz)
X    fprintf(stderr, "xcpustate: Empty node name\n");
X
X  if (kernelSymbols)
X    *knamelist = kernelSymbols;
X
X  if (0 == *knamelist) knamelist++;  /* skip over initial NULL pointer */
X
X  for (cpp = knamelist; *cpp; cpp++)
X    {
X      for (nf = 0; kernel_nl[nf].n_name; nf++)
X	kernel_nl[nf].n_value = 0;
X
X      nf = nlist(*cpp, kernel_nl);
X      if (-1 == nf || 0 == kernel_nl[KERNEL_UTSNAME].n_value)
X	continue;
X
X      if (!seekreaderr(kmemfd, kernel_nl[KERNEL_UTSNAME].n_value,
X		     &nname, sizeof(struct utsname), "utsname") &&
X	  0 == strncmp(nodename.nodename, nname.nodename, nsz))
X	{
X	  for (errs = nf = 0; kernel_nl[nf].n_name; nf ++)
X	    if (0 == kernel_nl[nf].n_value)
X	      {
X		fprintf(stderr, "kernel symbol `%s' not found\n",
X			kernel_nl[nf].n_name);
X		errs++;
X	      }
X
X	  if (errs)
X	    return 0;
X
X	  return *cpp;
X	}
X    }
X
X  fprintf(stderr, "xcpustate: No kernel symbol file matches running kernel\n");
X  return 0;
}
X
X
X
/* init_cpu_init()  --  Initialize for CPU display
*/
int
init_cpu_info(void)
{
X  int nf;
X
X  cpuinfo    = mapthis(kmem, (void *)kernel_nl[KERNEL_SYSINFO].n_value,
X		       sizeof(struct sysinfo));
X  if (-1 == (int)cpuinfo)
X    ERR_EXIT("mapping sysinfo");
X
X  ncpus = kncpu = 1;
X
X  nf = kncpu * CPU_STATE_SZ;
X  lastcpu = (time_t *) malloc(nf);
X  memset(lastcpu, 0, nf);
X
X  return ncpus;
}
X
X
X
/* Called at the beginning to inquire how many bars are needed
*/
int
num_bars(void)
{
X  kmem   = open("/dev/kmem", O_RDONLY);
X  if (-1 == kmem)
X    ERR_EXIT("opening /dev/kmem");
X
X  if (-1 == uname(&nodename))
X    ERR_EXIT("uname");
X
X  kernel_name = get_kernel_symbols(kmem, kernel_symbols);
X  if (!kernel_name)
X    return 0;
X
X  if (diskflag)
X    {
X      fprintf(stderr, "Only cpu state information is supported\n");
X      return 0;
X    }
X
X  return init_cpu_info();
}
X
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    items[0] = CPUSTATES;
}
X
X
/* Called after num_bars to ask for bar names */
char **
label_cpu_bars(nbars)
X  int    nbars;
{
X  char **names;
X  int    hsz   = strlen(nodename.nodename);
X  int    rowsz = (hsz +   1 +   2 + 4) * kncpu;
X  int    sz    = nbars * rowsz;
X  int    cpu, i;
X  char  *cp;
X
X  shorten(nodename.nodename);
X
X  names  = (char **)malloc(sz + sizeof(char *) * nbars);
X
X  cp     = (char *)names + sizeof(char *) * nbars;
X
X  for (cpu = i = 0; i < kncpu; i++)
X    {
X      names[cpu++] = cp;
X
X      if (1 == kncpu)
X	sprintf(cp, "%s", nodename.nodename);
X      else if (0 == i)
X	sprintf(cp, "%s #%d", nodename.nodename, i);
X      else
X	sprintf(cp, "%*s #%d", hsz, "", i);
X
X      cp += rowsz;
X    }
X
X  return names;
}
X
X
X
char **
label_bars(nbars)
X  int    nbars;
{
X  switch (state)
X    {
X    case CPU_STATE:  return label_cpu_bars(nbars);
X    }
X
X  return NULL;
}
X
X
X
X
/*  Called after the bars are created to do machine dependent inits */
void
init_bars(nbars)
X  int nbars;
{
X  (void) display_bars(nbars);
}
X
X
X
X
/*
X   This function is called every interval to compute and display
X   the bars.  It should call draw_bar() with the bar number, the array of
X   integer values to display in the bar, and the number of values in the
X   array.
*/
void
display_cpu_bars(nbars)
X  int nbars;
{
X  int states[NSTATES];
X  int nstates;
X  int cpu, i;
X  time_t *cputime = lastcpu;
X
X  for (i = cpu = 0; i < kncpu && cpu < nbars; i++)
X    {
X      nstates = 0;
X
X      if (kncpu)
X	{
X	  states[nstates++] = delta(CPU_IDLE);
X	  states[nstates++] = delta(CPU_USER);
X	  states[nstates++] = delta(CPU_KERNEL);
X	  states[nstates++] = delta(CPU_WAIT) + delta(CPU_SXBRK);
#if 0
X	  states[nstates++] = delta(CPU_SXBRK);
#endif
X	}
X      else
X	{
X	  states[nstates++] = 100;  /* CPU_IDLE   */
X	  states[nstates++] =   0;  /* CPU_USER   */
X	  states[nstates++] =   0;  /* CPU_KERNEL */
X	  states[nstates++] =   0;  /* CPU_WAIT   */
#if 0
X	  states[nstates++] =   0;  /* CPU_SXBRK  */
#endif
X	}
X      savecpuinfo(cpu);
X      draw_bar(cpu, states, nstates);
X
X      cpu++;
X      cputime += CPU_STATE_SZ / sizeof(time_t);
X    }
}
X
X
X
void
display_bars(nbars)
X  int nbars;
{
X  if (kmem_list)
X    refreshfakes();
X
X  switch (state)
X    {
X    case CPU_STATE:  display_cpu_bars(nbars);
X    }
X
X  return;
}
SHAR_EOF
  $shar_touch -am 0326205997 's-svr4.c' &&
  chmod 0640 's-svr4.c' ||
  $echo 'restore of' 's-svr4.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-svr4.c:' 'MD5 check failed'
2c1e15787e4ab490a0551e71319bf9e8  s-svr4.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-svr4.c'`"
    test 10160 -eq "$shar_count" ||
    $echo 's-svr4.c:' 'original size' '10160,' 'current size' "$shar_count!"
  fi
fi
# ============= s-bsdi.c ==============
if test -f 's-bsdi.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-bsdi.c' '(file already exists)'
else
  $echo 'x -' extracting 's-bsdi.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-bsdi.c' &&
/*
X * System dependent file for BSDI and possibly BSD4.4
X */
/* Andy Beals, Telebit <asb@telebit.com> */
/* LINTLIBRARY */
#include <sys/param.h>
#include <sys/cpustats.h>
#include <sys/types.h>
#include <sys/kinfo.h>
#include <sys/kinfo_proc.h>
#include <sys/sysinfo.h>
#include <nlist.h>
X
#ifndef MAXHOSTNAMELEN
X  /* Some U*x deviants managed to not have this in sys/param.h */
# define MAXHOSTNAMELEN 64
#endif
X
extern char *xmalloc(/* int nbytes */);
X
extern int open(), read();
extern long lseek();
X
long	cp_time[CPUSTATES];
long	cp_old[CPUSTATES];
X
#define NPROCS 1
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X    return NPROCS;
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    static char *name[NPROCS];
X    static char hname[MAXHOSTNAMELEN];
X
X    name[0] = hname;
X    if (gethostname(name[0], MAXHOSTNAMELEN) < 0) {
X	perror("gethostname");
X	*name[0] = '\0';
X    }
X    return name;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	struct cpustats	s;
X	int t = sizeof s, j;
X
X	if(getkerninfo(KINFO_CPU, &s, &t, 0) == -1) {
X		perror("getkerninfo");
X		for(j=0;j<CPUSTATES;j++) cp_old[j] = 0;
X	} else {
X	    for(j=0;j<CPUSTATES;j++) cp_old[j] = s.cp_time[j];
X	}
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	states[CPUSTATES];
X	int	nstates;
X	int	i;
X	extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X	struct cpustats	s;
X	
X	i=sizeof s;
X	if(getkerninfo(KINFO_CPU, &s, &i, 0) == -1) {
X		perror("getkerninfo");
X	} else {
X	    for(i=0;i<CPUSTATES;i++) cp_time[i] = s.cp_time[i];
X	}
X	
#define delta(cpustate) ((int) (cp_time[(cpustate)] - cp_old[(cpustate)]))
X
X	nstates = 0;
X	states[nstates++] = delta(CP_IDLE);
X	states[nstates++] = delta(CP_USER);
X	states[nstates++] = delta(CP_NICE);
X	states[nstates++] = delta(CP_SYS);
X	draw_bar(0, states, nstates);
X	for (i = 0; i < CPUSTATES; i ++)
X		cp_old[i] = cp_time[i];
}
SHAR_EOF
  $shar_touch -am 1109160794 's-bsdi.c' &&
  chmod 0600 's-bsdi.c' ||
  $echo 'restore of' 's-bsdi.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-bsdi.c:' 'MD5 check failed'
429b26fb284d93a5e75b9280656520c3  s-bsdi.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-bsdi.c'`"
    test 2268 -eq "$shar_count" ||
    $echo 's-bsdi.c:' 'original size' '2268,' 'current size' "$shar_count!"
  fi
fi
# ============= s-aix.c ==============
if test -f 's-aix.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-aix.c' '(file already exists)'
else
  $echo 'x -' extracting 's-aix.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-aix.c' &&
/* 
X * AIX CPU support (including SMP for AIX 4.x) 
X * 
X * John DiMarco <jdd@cs.toronto.edu>, University of Toronto, CSLab
X */
X
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/sysinfo.h>
#include <nlist.h>
X
extern char *kernelSymbols;
extern int sep_wait, cpuflag;
X
#ifndef MAXCPU
#define MAXCPU 64
#endif /* MAXCPU */
X
#ifndef KMEM
#define KMEM "/dev/kmem"
#endif /* KMEM */
X
#ifndef KSYMS
#define KSYMS "/unix"
#endif /* KSYMS */
X
#ifdef SMP
#define NPROCS MAXCPU
#define CPUINFO "cpuinfo"
#else
#define cpuinfo sysinfo
#define CPUINFO "sysinfo"
#define NPROCS 1
#endif
X
#define BUFFSIZE 64
X
int	ncpus;
struct cpuinfo cpu[MAXCPU];
X
long	cp_time[NPROCS][CPU_NTIMES];
long	cp_old [NPROCS][CPU_NTIMES];
int	kmem;			/* file descriptor for /dev/kmem. */
struct nlist	nl[] = {
#define N_NCPU		0
X	{ "number_of_cpus" },
#define	N_CPUINFO	1
X	{ CPUINFO },
X	{ "" },
};
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X	if(!cpuflag) return 0;
X	if (0>(kmem = open(KMEM, O_RDONLY))){
X		perror(KMEM);
X		exit(1);
X	}
X	if (0>nlist(kernelSymbols?kernelSymbols:KSYMS, nl)){
X		perror(kernelSymbols?kernelSymbols:KSYMS);
X		exit(1);
X	}
#if 1==NPROCS
X	ncpus=1;
X	return NPROCS;
X	/* NOTREACHED */
#endif
X	if ((off_t)nl[N_NCPU].n_value != 
X	    lseek(kmem,(off_t)nl[N_NCPU].n_value, SEEK_SET)){
X		perror("lseek _number_of_cpus");
X		exit(1);
X	}
X	if (sizeof(ncpus) != read(kmem, (char *)&ncpus, sizeof(ncpus))){
X		perror("read _number_of_cpus");
X		exit(1);
X	}
X	return ncpus;
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X	int i;
X
X	for(i=0; i<nbars; i++){
X		items[i] = CPU_NTIMES;
X	}
}
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X        char **names;
X        int i;
X        static char hname[MAXHOSTNAMELEN + 1];
X	char buf[MAXHOSTNAMELEN + 1 + BUFFSIZE];
X	char *cpname="";
X
X        hname[MAXHOSTNAMELEN] = '\0';
X        if (0 >gethostname(hname, MAXHOSTNAMELEN)) {
X                perror("gethostname");
X                *hname = '\0';
X        }
X        shorten(hname);
X        names = (char **) xmalloc(nbars * sizeof(char *));
X
X	/* do cpu names */
X	for(i=0; i<ncpus; i++) {
X		(void) sprintf(buf, "%s%s%s%d", hname, 
X				hname[0]?" ":"", cpname, i);
X		names[i] = (char *)xmalloc(strlen(buf)+1);
X		(void) strcpy(names[i], buf);
X	}
X        return names;
}
X
/* 
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	int i,j;
X
X	if ((off_t)nl[N_CPUINFO].n_value != 
X	    lseek(kmem,(off_t)nl[N_CPUINFO].n_value, SEEK_SET)){
X		perror("lseek _cpuinfo");
X		exit(1);
X	}
X	if ((ncpus * sizeof(struct cpuinfo)) != 
X	    read(kmem, (char *)cpu, ncpus * sizeof(struct cpuinfo))){
X		perror("read _cpuinfo");
X		exit(1);
X	}
X	for (i=0;i<ncpus;i++) {
X		for(j=0;j<CPU_NTIMES;j++){
X			cp_old[i][j]=cpu[i].cpu[j];
X		}
X	}
}
X
/* 
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	states[CPU_NTIMES];
X	int	nstates;
X	int	i,j;
X
X	if ((off_t)nl[N_CPUINFO].n_value != 
X	    lseek(kmem,(off_t)nl[N_CPUINFO].n_value, SEEK_SET)){
X		perror("lseek _cpuinfo");
X		exit(1);
X	}
X	if ((ncpus * sizeof(struct cpuinfo)) != 
X	    read(kmem, (char *)cpu, ncpus * sizeof(struct cpuinfo))){
X		perror("read _cpuinfo");
X		exit(1);
X	}
X
#define delta(c) ((int) (cp_time[i][(c)] - cp_old[i][(c)]))
X
X	for (i=0; i<ncpus; i++) {
X		for(j=0;j<CPU_NTIMES;j++){
X			cp_time[i][j]=cpu[i].cpu[j];
X		}
X		nstates = 0;
X		if(sep_wait){
X			states[nstates++] = delta(CPU_IDLE);
X			states[nstates++] = delta(CPU_WAIT);
X		} else {
X			states[nstates++] = delta(CPU_IDLE) + delta(CPU_WAIT);
X		}
X		states[nstates++] = delta(CPU_USER);
X		states[nstates++] = delta(CPU_KERNEL);
X		draw_bar(i, states, nstates);
X	}
X	for (i=0; i<ncpus; i++){
X		for (j=0; j<CPU_NTIMES; j++){
X			cp_old[i][j] = cp_time[i][j];
X		}
X	}
}
SHAR_EOF
  $shar_touch -am 0326205197 's-aix.c' &&
  chmod 0644 's-aix.c' ||
  $echo 'restore of' 's-aix.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-aix.c:' 'MD5 check failed'
e9e2a623fdaaa8d3c84371f026a48aad  s-aix.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-aix.c'`"
    test 4313 -eq "$shar_count" ||
    $echo 's-aix.c:' 'original size' '4313,' 'current size' "$shar_count!"
  fi
fi
# ============= s-linux.c ==============
if test -f 's-linux.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's-linux.c' '(file already exists)'
else
  $echo 'x -' extracting 's-linux.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's-linux.c' &&
/*
X * System dependent file for Linux.   Includes SMP support.
X *
X * Kumsup Lee <klee@ima.umn.edu>
X * John DiMarco <jdd@cs.toronto.edu>,  University of Toronto, CSLab
X */
X
/* LINTLIBRARY */
#include <sys/param.h>
#include <sys/types.h>
X
#include <stdio.h>
X
#ifndef STATFILE
#define STATFILE "/proc/stat"
#endif /* STATFILE */
X
#define MAXHOSTNAMELEN 64
X
#define CPUSTATES 4 	/* idle, user, nice, system */
#ifndef NR_CPUS
#define NR_CPUS 8	
#endif /* NR_CPUS */
X
#define WHITESPACE "	 "
#define CPU "cpu"
X
extern char *xmalloc(/* int nbytes */);
X
extern int open(), read();
extern long lseek();
X
static long	cp_time[NR_CPUS+1][CPUSTATES];
static long	cp_old[NR_CPUS+1][CPUSTATES];
X
static char line[1024];
X
int numcpus=0;
X
/* Called at the beginning to inquire how many bars are needed. */
int
num_bars()
{
X	/* 
X	 * Assume any line in /proc/stat beginning with cpuN, where N is a
X	 * number, corresponds to a specific CPU.  If there are no such lines,
X	 * this must be a uniprocessor -- look for the line beginning with 
X	 * "cpu ".  If there isn't one of those, there's no recognizable 
X	 * evidence of any cpu in /proc/stat, which means something is wrong.
X	 */
X
X	FILE *proc_stat;
X	long junk;
X	int foundcpu=0;  /* we found a line beginning with "cpu " */
X
X
X	/* count the number of CPUs mentioned in the stat file */
X	if(0>(proc_stat=fopen(STATFILE, "r"))) {
X		perror(STATFILE);
X		return 0;
X	}
X	while(NULL!=fgets(line, sizeof(line)-1, proc_stat)){
X		if(0==strncmp(line, CPU, strlen(CPU))){
X			if(' '==line[strlen(CPU)]){
X				/* line looks like "cpu ..." */
X				foundcpu=1;
X			} else if(isdigit(line[strlen(CPU)])){
X				/* line looks like "cpuN ..." */
X				numcpus++;
X			}
X		}
X	}
X	(void)fclose(proc_stat);
X
X	/* 
X	 * If there is no line beginning with "cpuN" (eg. cpu0), then 
X	 * this is a uniprocessor system.
X	 */
X	if(0==numcpus) {
X		numcpus=foundcpu; 
X	} 
#ifdef SHOWAVG
X	  else {
X		numcpus++;
X	}
#endif /* SHOWAVG */
X	if(numcpus>(NR_CPUS+1)) numcpus=NR_CPUS+1;
X	return(numcpus);
}
X
/*
X * Indicates how many levels each bar has.  For most machines, each bar will
X * have the same stuff.  But one can, for instance, display memory use on one
X * bar, processor levels on others, etc.
X */
void
bar_items(nbars, items)
int nbars;
int items[];    /* nbars items in this */
{
X    int i;
X
X    for(i = 0; i < nbars; i++)
X        items[i] = CPUSTATES;
}
X
X
/* Called after num_bars to ask for the bar names */
/* ARGSUSED */
char **
label_bars(nbars)
{
X    static char **names;
X    int i;
X    static char hname[MAXHOSTNAMELEN+1];
X
X    hname[MAXHOSTNAMELEN] = '\0';
X    if (gethostname(hname, MAXHOSTNAMELEN) < 0) {
X	perror("gethostname");
X	*hname = '\0';
X    }
X    shorten(hname);
X    names=(char **) xmalloc(nbars * sizeof(char *));
X    for(i=0; i < nbars; i++) {
#define CPUNAME "%s %d"
X	char buf[MAXHOSTNAMELEN + 1 + 32];
X
#ifdef SHOWAVG
X	if ( i == 0 )
X		(void) sprintf(buf, "CPU");
X	else
X		(void) sprintf(buf, CPUNAME, hname, i-1);
#else  /* !SHOWAVG */
X	(void) sprintf(buf, CPUNAME, hname, i);
#endif /* !SHOWAVG */
X	
X    	names[i] = xmalloc(strlen(buf) + 1);
X	(void) strcpy(names[i], buf);
X    }
X    return names;
}
X
/*
X *  Called after the bars are created to perform any machine dependent
X *  initializations.
X */
/* ARGSUSED */
void
init_bars(nbars)
int nbars;
{
X	FILE *proc_stat;
X	char dummy[256];
X	int i, j;
X
X	if((proc_stat=fopen(STATFILE,"r")) == NULL ) {
X		perror(STATFILE);
X  		for( i=0; i < nbars; i++)
X		    for(j=0;j<CPUSTATES;j++) cp_old[i][j] = 0;
X	} else {
#ifndef SHOWAVG
X	    if(nbars>1){
X		/* skip the first ("cpu") line */
X		   fscanf(proc_stat, "%s %ld %ld %ld %ld",
X                       dummy, &cp_time[0][0], &cp_time[0][1], &cp_time[0][2],
X                       &cp_time[0][3]);
X	    }
#endif /* SHOWAVG */
X            for (i=0; i < nbars; i++)
X                fscanf(proc_stat, "%s %ld %ld %ld %ld \n",
X		       dummy, &cp_old[i][0], &cp_old[i][1], &cp_old[i][2],
X		       &cp_old[i][3]);
X	}
X	(void)fclose(proc_stat);
}
X
/*
X *  This procedure gets called every interval to compute and display the
X *  bars. It should call draw_bar() with the bar number, the array of
X *  integer values to display in the bar, and the number of values in
X *  the array.
X */
/* ARGSUSED */
void
display_bars(nbars)
{
X	int	states[CPUSTATES];
X	int	nstates;
X	int	i, j;
X	FILE *proc_stat;
X	char dummy[256];
X	extern void draw_bar(/*int bar_num, int *states, int num_states*/);
X
X        if((proc_stat=fopen(STATFILE,"r")) == NULL ) {
X                perror(STATFILE);
X        } else {
#ifndef SHOWAVG
X	    if(nbars>1){
X		/* skip the first ("cpu") line */
X		   fscanf(proc_stat, "%s %ld %ld %ld %ld",
X                       dummy, &cp_time[0][0], &cp_time[0][1], &cp_time[0][2],
X                       &cp_time[0][3]);
X	    }
#endif /* SHOWAVG */
X            for (i=0; i < nbars; i++)
X                fscanf(proc_stat, "%s %ld %ld %ld %ld",
X                       dummy, &cp_time[i][0], &cp_time[i][1], &cp_time[i][2],
X                       &cp_time[i][3]);
X        }
X	(void)fclose(proc_stat);
X
X	for (i=0; i < nbars; i++) {
#define delta(cpustate) ((int) (cp_time[i][(cpustate)] - cp_old[i][(cpustate)]))
X
X		nstates = 0;
X		states[nstates++] = delta(3); /* IDLE */
X		states[nstates++] = delta(0); /* USER */
X		states[nstates++] = delta(1); /* NICE */
X		states[nstates++] = delta(2); /* SYS  */
X		draw_bar(i, states, nstates);
X			cp_old[i][0] = cp_time[i][0];
X			cp_old[i][1] = cp_time[i][1];
X			cp_old[i][2] = cp_time[i][2];
X			cp_old[i][3] = cp_time[i][3];
X	}
}
SHAR_EOF
  $shar_touch -am 0728173799 's-linux.c' &&
  chmod 0600 's-linux.c' ||
  $echo 'restore of' 's-linux.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's-linux.c:' 'MD5 check failed'
28e5157a9cd7113191511b8d1da34afc  s-linux.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's-linux.c'`"
    test 5461 -eq "$shar_count" ||
    $echo 's-linux.c:' 'original size' '5461,' 'current size' "$shar_count!"
  fi
fi
# ============= s.c ==============
if test -f 's.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's.c' '(file already exists)'
else
  $echo 'x -' extracting 's.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's.c' &&
/*
X * for each type of machine, stick the appropriate ifdef's in here and define
X * s_included.  
X */
#ifdef sgi
# ifdef mips
#  include "s-irix.c"
#  define s_included
# endif
#endif
X
#ifdef CRAY1
# include "s-unicos.c"
# define s_included
#endif
X
#if defined(MACH)
# include "s-mach.c"
# define s_included
#endif
X
#ifdef kap
# include "s-solbourne.c"
# define s_included
#endif
X
#ifdef ultrix
# include "s-ultrix.c"
# define s_included
#endif
X
#ifdef GOULD_NP1
# include "s-gould-np1.c"
# define s_included
#endif
X
#ifdef SUNOS4
# include "s-sunos4.c"
# define s_included
#endif
X
#ifdef SUNOS5
# include "s-sunos5.c"
# define s_included
#endif
X
#ifdef NCR
# include "s-ncr.c"
# define  s_included
#endif
X
#ifdef __bsdi__
# include "s-bsdi.c"
# define  s_included
#endif
X
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include "s-bsd44.c"
# define  s_included
#endif
X
#if defined( SVR4 ) && !defined( SUNOS5 ) && !defined( IRIX )
# include "s-svr4.c"
# define  s_included
#endif
X
#ifdef _AIX
# include "s-aix.c"
# define  s_included
#endif
X
#if !defined(s_included) && defined(BSD)
# include "s-bsd.c"
#endif
X
#ifdef linux
# include "s-linux.c"
# define  s_included
#endif
X
#ifndef s_included
X  /* "nothing" mode: stub functions */
X  int num_bars(){ return 0; }
X  void bar_items(){}
X  char **label_bars(){}
X  void init_bars(){}
X  void display_bars(){}
#endif
/* Do not add anything after this line */
SHAR_EOF
  $shar_touch -am 0315170597 's.c' &&
  chmod 0644 's.c' ||
  $echo 'restore of' 's.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's.c:' 'MD5 check failed'
beff2d302322084d2b695698f5cd836a  s.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's.c'`"
    test 1429 -eq "$shar_count" ||
    $echo 's.c:' 'original size' '1429,' 'current size' "$shar_count!"
  fi
fi
# ============= s.h ==============
if test -f 's.h' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 's.h' '(file already exists)'
else
  $echo 'x -' extracting 's.h' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 's.h' &&
/*
X *  Any system dependent file must implement these routines. See s-bsd.c
X *  and s-sunos5.c for examples.
X */
extern int num_bars();
extern void bar_items(/* int nbars, int items[] */);
extern char **label_bars(/* int nbars */);
extern void init_bars(/* int nbars */);
extern void display_bars(/* int nbars */);
SHAR_EOF
  $shar_touch -am 0408190394 's.h' &&
  chmod 0640 's.h' ||
  $echo 'restore of' 's.h' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 's.h:' 'MD5 check failed'
0bc5a4bad116c5a18364954d67d02de3  s.h
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 's.h'`"
    test 315 -eq "$shar_count" ||
    $echo 's.h:' 'original size' '315,' 'current size' "$shar_count!"
  fi
fi
# ============= xcpustate.c ==============
if test -f 'xcpustate.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'xcpustate.c' '(file already exists)'
else
  $echo 'x -' extracting 'xcpustate.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'xcpustate.c' &&
/*
*  Displays CPU state distribution
*/
#ifndef lint
static char rcsid[] = "$Id: xcpustate.c,v 1.31 1999/07/28 19:49:36 jdd Exp $";
#endif /*lint*/
X
#include <stdio.h>
X
#include <X11/Xos.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xmu/Xmu.h>
#include "array.h"
#include "Bar.h"
#include "s.h"
#include "levels.h"
#include "patchlevel.h"
X
#define MAXSTR 1024
#define MAXAVG 1024
#define MAXBARS 256
#ifndef INTERVAL_MIN
#define INTERVAL_MIN 0.000
#endif /* INTERVAL_MIN */
#ifndef DEF_INTERVAL
#define DEF_INTERVAL    1.000
#endif /* DEF_INTERVAL */
#ifndef DEF_FONT
#define DEF_FONT        XtDefaultFont
#endif /* DEF_FONT */
X
#define NOTSET minusTwo
X
char *progname;
X
typedef enum {
X	grayscale,	
X	color,
X	tile,
X	stipple,
X	autodetect
} FillType; 
X
static float defaultInterval = (1.0*DEF_INTERVAL);
static int one = 1;
static int minusOne = -1;
static int minusTwo = -2;
static Boolean def_true = True, def_false= False;
static Colormap colormap;
static Pixel colors[MAXLEVELS];
static FillType filltype;
int cpuflag, diskflag, sep_wait;
char *kernelSymbols;
int kmem_can_map;
int avg;
#ifdef OMNI
int omniflag;
#endif /* OMNI */
#ifdef RSTAT
char *rstathost;
#endif /* RSTAT */
X
static struct _resource {
X	XFontStruct *font;
X	char *colorspec;
X	int count;
X	float interval;
X	int shortenTo;
X	Pixel fg, bg;
X	Boolean rv;
X	char *filltypestr;
X	int cpuflag, diskflag, sep_wait, version;
X	char *kernelSymbols;
X	int   kmem_can_map;
X	int avg;
#ifdef OMNI
X	int omniflag;
#endif /* OMNI */
#ifdef RSTAT
X	char *rstathost;
#endif /* RSTAT */
} resource;
X
#define offset(field)   XtOffsetOf(struct _resource, field)
X
extern char *strtok();
X
static int allocstyles(), parsecolors();
X
static void setup_WMPROTOCOL(), close_window();
X
#ifdef RSTAT
extern int rstat_num_bars();
extern char **rstat_label_bars();
extern void rstat_init_bars();
extern void rstat_display_bars();
X
#define numBars() ((NULL==rstathost)?num_bars():rstat_num_bars())
#define labelBars(n) ((NULL==rstathost)?label_bars(n):rstat_label_bars(n))
#define initBars(n) if(NULL==rstathost)init_bars(n);else rstat_init_bars(n)
#define displayBars(n) if(NULL==rstathost)display_bars(n);else rstat_display_bars(n)
#define barItems(n,ni) if(NULL==rstathost)bar_items(n,ni);else rstat_bar_items(n,ni)
X
#else /* RSTAT */
X
#define numBars() num_bars()
#define labelBars(n) label_bars(n)
#define initBars(n) init_bars(n)
#define displayBars(n) display_bars(n)
#define barItems(n,ni) bar_items(n,ni) 
X
#endif /* RSTAT */
X
/* Application Resources - no particular widget */
static XtResource application_resources[] = {
X    {"interval", "Interval", XtRFloat, sizeof(float),
X            offset(interval), XtRFloat, (caddr_t) &defaultInterval},
X    {"count", "Count", XtRInt, sizeof(int),
X            offset(count), XtRInt, (caddr_t) &minusOne},
X    {"shorten", "Shorten", XtRInt, sizeof(int),
X            offset(shortenTo), XtRInt, (caddr_t) &NOTSET},
X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X            offset(fg), XtRString, XtDefaultForeground},
X    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
X            offset(bg), XtRString, XtDefaultBackground},
X    {XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof(Boolean),
X            offset(rv), XtRBoolean, (caddr_t) &def_false},
X    {"font", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X            offset(font), XtRString, DEF_FONT},
X    {"colors", "Colors", XtRString, sizeof(char *),
X            offset(colorspec), XtRString, (caddr_t)NULL},
X    {"filltype", "Filltype", XtRString, sizeof(char *),
X            offset(filltypestr), XtRString, (caddr_t)"auto"},
X    {"cpu", "Cpu", XtRBoolean, sizeof(Boolean),
X            offset(cpuflag), XtRImmediate, (XtPointer)True},
X    {"disk", "Disk", XtRBoolean, sizeof(Boolean),
X            offset(diskflag), XtRImmediate, (XtPointer)False},
X    {"wait", "Wait", XtRBoolean, sizeof(Boolean),
X            offset(sep_wait), XtRImmediate, (XtPointer)False},
X    {"version", "Version", XtRBoolean, sizeof(Boolean),
X            offset(version), XtRImmediate, (XtPointer)False},
X    {"kernel", "Kernel", XtRString,  sizeof(char *),
X            offset(kernelSymbols), XtRString, (caddr_t) NULL},
X    {"mmap", "Mmap", XtRBoolean, sizeof(Boolean),
X            offset(kmem_can_map), XtRInt, (caddr_t)&def_true},
X    {"avg", "Avg", XtRInt, sizeof(int),
X            offset(avg), XtRInt, (caddr_t)&one},
#ifdef OMNI
X    {"omni", "Omni", XtRBoolean, sizeof(Boolean),
X            offset(omniflag), XtRImmediate, (XtPointer)False},
#endif /* OMNI */
#ifdef RSTAT
X    {"host", "Host", XtRString, sizeof(char *),
X            offset(rstathost), XtRString, (caddr_t)NULL},
#endif /* RSTAT */
};
X
/*
*  Command line options table. The command line is parsed for these,
*  and it sets/overrides the appropriate values in the resource
*  database
*/
static XrmOptionDescRec optionDescList[] = {
X    {"-interval",   ".interval",    XrmoptionSepArg,    (caddr_t) NULL},
X    {"-count",      ".count",       XrmoptionSepArg,    (caddr_t) NULL},
X    {"-shorten",    ".shorten",     XrmoptionSepArg,    (caddr_t) NULL},
X    {"-cpu",        ".cpu",         XrmoptionNoArg,     (caddr_t) "True"},
X    {"-nocpu",      ".cpu",         XrmoptionNoArg,     (caddr_t) "False"},
X    {"-disk",       ".disk",        XrmoptionNoArg,     (caddr_t) "True"},
X    {"-nodisk",     ".disk",        XrmoptionNoArg,     (caddr_t) "False"},
X    {"-wait",       ".wait",        XrmoptionNoArg,     (caddr_t) "True"},
X    {"-nowait",     ".wait",        XrmoptionNoArg,     (caddr_t) "False"},
X    {"-host",       ".host",        XrmoptionSepArg,    (caddr_t) NULL},
X    {"-colors",     ".colors",      XrmoptionSepArg,    (caddr_t) NULL},
X    {"-filltype",   ".filltype",    XrmoptionSepArg,    (caddr_t) NULL},
X    {"-kernel",     ".kernel",      XrmoptionSepArg,    (caddr_t) NULL},
X    {"-mmap",       ".mmap",        XrmoptionNoArg,     (caddr_t) "True"},
X    {"-nommap",     ".mmap",        XrmoptionNoArg,     (caddr_t) "False"},
X    {"-version",    ".version",     XrmoptionNoArg,     (caddr_t) "True"},
X    {"-avg",        ".avg",         XrmoptionSepArg,    (caddr_t) NULL},
#ifdef OMNI
X    {"-omni",       ".omni",        XrmoptionNoArg,     (caddr_t) "True"},
X    {"-noomni",     ".omni",        XrmoptionNoArg,     (caddr_t) "False"},
#endif /* OMNI */
};
X
/*
*  DON'T CHANGE THE ORDER OF THE ARGS IN THE VARIOUS ARG STRUCTS. IF
*  YOU WANT TO ADD STUFF, ADD IT AT THE END OF THE STRUCT, BECAUSE WE
*  REFER TO SOME OF THE ELEMENTS BY POSITION IN THE CODE.
*/
/* No spacing between the widgets on the Form */
static Arg form_args[] = {
X    {XtNdefaultDistance, (XtArgVal) 0},
};
X
static Arg subform_args[] = {
X    {XtNfromVert, (XtArgVal) 0},
X    {XtNdefaultDistance, (XtArgVal) 0},
X    {XtNborderWidth, (XtArgVal) 0},
X    {XtNtop, (XtArgVal) XtRubber},
X    {XtNbottom, (XtArgVal) XtRubber}, /* ChainBottom causes strange resize */
X    {XtNright, (XtArgVal) XtChainRight},
X    {XtNleft, (XtArgVal) XtChainLeft},
};
X
static Arg bar_args[] = {
X    {XtNfromHoriz, (XtArgVal) 0},
X    {XtNpixmaps, (XtArgVal) 0},
X    {XtNfillStyle, (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) XtChainBottom},
X    {XtNright, (XtArgVal) XtChainRight},
X    {XtNleft, (XtArgVal) XtChainLeft},
X    {XtNvertDistance, (XtArgVal) 0},
X    {XtNhorizDistance, (XtArgVal) 0},
X    {XtNresizable, (XtArgVal) TRUE},
};
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    {XtNwidth, (XtArgVal) 1},
X    {XtNfont, (XtArgVal) 0},
};
X
void
usage()
{
X        /* Ugly! */
X    (void) fprintf(stderr, 
"\
Usage: %s [Xt options] [-count iterations]\n\
\t[-interval delay_seconds][-shorten components][-cpu]\n\
\t[-nocpu] [-disk] [-nodisk] [-wait] [-nowait] %s%s\n\
\t[-filltype auto|grayscale|color|tile|stipple ]\n\
\t[-colors colorname[,colorname[,...]]]\n\
\t[-avg numintervals]\n\
\t[-kernel kernelname ] [-mmap] [-nommap]\n",
progname,
#ifdef OMNI
" [-omni] [-noomni]",
#else  /* OMNI */
"",
#endif /* OMNI */
#ifdef RSTAT
" [-host hostname]"
#else  /* RSTAT */
""
#endif /* RSTAT */
);
X    exit(-1);
}
X
char *
xmalloc(n)
unsigned int n;
{
X    return XtMalloc(n);
}
X
static int nbars;
static Widget *bar;
static char **barnames;
X    
/* ARGSUSED */
static void
update_display(closure, id)
XXtPointer closure;
XXtIntervalId *id;
{
X    unsigned long timeout;
X    displayBars(nbars);
X    
X    if (resource.count > 0) {
X        if (--resource.count == 0)
X            return;
X    }
X    timeout=(unsigned long)(resource.interval * 1000.0);
X    (void) XtAddTimeOut(timeout, update_display, (XtPointer) NULL);
}
X
main(argc, argv)
int argc;
char **argv;
{
X    int i, maxlabellen=0, *nbaritems, fstyle;
X    Widget topLevel, form, label, subform = NULL;
X    Array *arrp;
X    Display *dpy;
X    int scr;
X
#ifndef index
X    extern char *index(/* const char *, char */);
#endif
X
X    if ((progname = index(argv[0], '/')) == NULL)
X        progname = argv[0];
X    else
X        progname++;
X
X    topLevel = XtInitialize(progname, "CPUStateMonitor",
X                            optionDescList, XtNumber(optionDescList),
X                            &argc, argv);
X    dpy=XtDisplay(topLevel);
X    scr=DefaultScreen(dpy);
X
X    XtGetApplicationResources(topLevel, (XtPointer) &resource,
X			      application_resources,
X                              XtNumber(application_resources), 
X                              (ArgList)NULL, (Cardinal)0 );
X
X    cpuflag = resource.cpuflag;
X    diskflag = resource.diskflag;
X    sep_wait = resource.sep_wait;
X    kernelSymbols = resource.kernelSymbols;
X    kmem_can_map = resource.kmem_can_map;
X    avg = resource.avg; if(avg<1) avg=1; if(avg>MAXAVG) avg=MAXAVG;
#ifdef OMNI
X    omniflag = resource.omniflag;
#endif /* OMNI */
#ifdef RSTAT
X    rstathost = resource.rstathost;
#endif /* RSTAT */
X
X    if(resource.version) { 
X	printf("%s\n", patchlevel);
X        exit(0);
X    }
X    if(argc>1) usage();
X
X    if(0==strcmp(resource.filltypestr, "auto")){
X	if(DefaultDepth(dpy, scr)>1){
X	    VisualID vid;
X	    XVisualInfo vinfo, *vinfo_p;
X	    int count;
X
X	    vid=XVisualIDFromVisual(DefaultVisual(dpy, scr));
X	    vinfo.visualid = vid;
X	    vinfo_p = XGetVisualInfo(dpy, VisualIDMask, &vinfo, &count);
X	    if(1!=count){
X	        (void) fprintf(stderr, 
X				"VisualID doesn't map to one visual???\n"); 
X		filltype=grayscale; /* lowest common denominator */
X	    } else {
X		if((GrayScale==vinfo_p->class || StaticGray==vinfo_p->class)){
X		    filltype=grayscale;
X		} else {
X		    filltype=color;
X		}
X	    }
X	} else {
X	    filltype=tile;
X	}
X    } else if(0==strcmp(resource.filltypestr, "grayscale")){
X	filltype=grayscale;
X    } else if (0==strcmp(resource.filltypestr, "color")){
X	filltype=color;
X    } else if (0==strcmp(resource.filltypestr, "stipple")){
X	filltype=stipple;
X    } else if (0==strcmp(resource.filltypestr, "tile")){
X	filltype=tile;
X    } else {
X	if(NULL!=resource.filltypestr) {
X		fprintf(stderr, 
X			"%s: Unknown filltype %s, using \"tile\".\n", progname,
X			resource.filltypestr);
X	}
X	filltype=tile;
X    }
X
X    if(color==filltype || grayscale==filltype){
X        colormap = DefaultColormap(XtDisplay(topLevel), 
X                        DefaultScreen(XtDisplay(topLevel)));
X        if(color==filltype) {
X            (void)parsecolors(topLevel,colormap,colornames,resource.colorspec,colors);
X        } else if(grayscale==filltype){ 
X            (void)parsecolors(topLevel,colormap,graycolornames,NULL,colors);
X        }
X    }
X
X    if(cpuflag) cpuflag=1;
X    if(diskflag) diskflag=1;
X    if(sep_wait) sep_wait=1;
X    if(kmem_can_map) kmem_can_map=1;
#ifdef OMNI
X    if(omniflag) omniflag=1;
#endif /* OMNI */
X
X    if(NULL==resource.font) {
X        (void) fprintf(stderr, "Can't find font '%s'\n", DEF_FONT);
X        exit(-1);
X    }
X
X    /* Make sure the default interval isn't less than the minimum. */
X    if(defaultInterval<INTERVAL_MIN){
X	if(resource.interval==defaultInterval){
X		resource.interval=INTERVAL_MIN;
X	}
X	defaultInterval=INTERVAL_MIN;
X    }
X    if(resource.interval < INTERVAL_MIN){
X	(void) fprintf(stderr, 
"The minimum interval is '%.4f'; '%.4f' is too small.  Using '%.4f'\n", 
X		(1.0*INTERVAL_MIN), resource.interval, defaultInterval);
X	resource.interval=defaultInterval;
X    }
X
X    nbars = numBars();
X    if (0==nbars) {
X        (void) fprintf(stderr, "Nothing to do. Exiting.\n");
X        exit(-1);
X    }
X
X    bar = (Widget *) xmalloc(nbars * sizeof(Widget));
X    barnames = labelBars(nbars);
X    nbaritems = (int *) xmalloc(nbars * sizeof(int));
X    barItems(nbars, nbaritems);
X    arrp = (Array *) xmalloc(nbars * sizeof(Array));
X    fstyle = allocstyles(topLevel, nbars, nbaritems, arrp);
X
X    /* find width of biggest label */
X    for(i=0;i<nbars;i++){
X        int labellen;
X        labellen=XTextWidth(resource.font, barnames[i], strlen(barnames[i]));
X        if(labellen>maxlabellen) maxlabellen=labellen;
X    }
X
X    form = XtCreateManagedWidget("form", formWidgetClass, topLevel,
X                                 form_args, XtNumber(form_args));
X    
X    for(i = 0; i < nbars; i++) {
#define FORMNAMEFMT     "form%d"
X        char formname[sizeof(FORMNAMEFMT) + 32];
#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	if (resource.shortenTo >= 0 || resource.shortenTo == NOTSET) {
X		label_args[10].value = (XtArgVal) (6+maxlabellen);
X	} else {
X		label_args[10].value = (XtArgVal) 1;
X	}
X        label_args[11].value = (XtArgVal) resource.font;
X	label = XtCreateManagedWidget(barnames[i], labelWidgetClass,
X			 subform, label_args, XtNumber(label_args));
X        (void) sprintf(barname, BARNAMEFMT, i);
X        bar_args[0].value = (XtArgVal) label;
X        bar_args[1].value = (XtArgVal) (arrp + i);
X        bar_args[2].value = (XtArgVal) fstyle;
X        bar[i] = XtCreateManagedWidget(barname, barWidgetClass, subform,
X                                    bar_args, XtNumber(bar_args));
X    }
X    XtRealizeWidget(topLevel);
X    setup_WMPROTOCOL(topLevel, "");
X
X    initBars(nbars);
X    
X
X    displayBars(nbars);  /* First display is always rubbish */
X
X    /* let's look at rubbish for only 0.01 second, regardless of interval */
X    (void) XtAddTimeOut((unsigned long) (10), update_display, 
X			(XtPointer)NULL);
X
X    XtMainLoop();
}
X
void
draw_bar(i, states, nstates)
int i;
int states[];
int nstates;
{
X	static int sa[MAXBARS][MAXAVG][MAXLEVELS];
X	static int avged[MAXLEVELS];
X	static int pos=0, notfirsttime[MAXBARS];
X	int j, k, sum=0;
X	
X	pos++; if(pos>=avg) pos=0;
X
X	for(j=0;j<nstates;j++) {
X		if(notfirsttime[i]) {
X			/* 
X			 * If this is the first time for this bar, the numbers
X			 * are likely to be total nonsense, so don't keep them
X			 * around for later.  Otherwise the bars may be
X			 * totally wrong for avg number of intervals.
X			 */
X			sa[i][pos][j]=states[j];
X		}
X		avged[j]=0;
X		for(k=0;k<avg;k++){
X			avged[j] += sa[i][k][j];
X		}
X		/* avged[j] = avged[j]/avg; */
X	}
X    	SetBarValues((Widget) bar[i], avged, nstates); 
X	notfirsttime[i]=1;
}
X
void
shorten(hname)
char *hname;
{
X    if (resource.shortenTo >= 0) {
X        int i;
X        char *cp = hname;
X        
X        for(i = 0; i < resource.shortenTo; i++) {
X            cp = index(++cp, '.');
X            if (cp == NULL)
X                break;
X        }
X        if (cp)
X            *cp = '\0';
X    }
}
X
static void
allocbarstyle(w, arrp, n)
Widget w;
Array *arrp;
int n;
{
#define newpixmap     XCreatePixmapFromBitmapData
X      Display *dpy = XtDisplay(w);
X      Window root = DefaultRootWindow(dpy);
X      Pixmap *pp;
X      int i, igray;
X
X      pp = (Pixmap *) xmalloc(n * sizeof(Pixmap));
X
X      arrp->nitems = n;
X      arrp->itemtype = sizeof(Pixmap);
X      arrp->items = (caddr_t) pp;
X
X      for(igray = level_mapping[n-1][0], i=0; 
X                        i<n; 
X                        i++, igray=level_mapping[n-1][i]) {
X              if (tile==filltype) {
X                      unsigned depth = DefaultDepthOfScreen(XtScreen(w));
X
X                      pp[i] = newpixmap(dpy, root, (char *)gray_bits[igray],
X                       (unsigned) 3, (unsigned) 3, resource.fg, resource.bg, depth);
X              } else {
X                      Pixel black = 1;
X                      Pixel white = 0;
X                      unsigned depth = 1;
X
X                      pp[i] = newpixmap(dpy, root, (char *)gray_bits[igray],
X                       (unsigned) 3, (unsigned) 3, black, white, depth);
X              }
X      }
}
X
static void
allocbarcolor(w, arrp, n)
Widget w;
Array *arrp;
int n;
{
X        arrp->nitems = n;
X        arrp->itemtype = sizeof(Pixel);
X        if(grayscale == filltype) {
X                int i, igray;
X                Pixel *px;
X                
X                px = (Pixel *) xmalloc(n * sizeof(Pixel));
X                for(igray = level_mapping[n-1][0], i=0;
X                                i<n;
X                                i++, igray=level_mapping[n-1][i]) {
X                        px[i] = colors[igray];
X                }
X                arrp->items= (caddr_t) px;
X        } else {
X                arrp->items = (caddr_t) colors;
X        } 
}
X
static int
allocstyles(w, nbars, nbaritems, arrp)
Widget w;
int nbars;
int nbaritems[];
Array arrp[]; /* nbars elements */
{
X        int i;
X
X        if(grayscale==filltype || color==filltype){
X                /* Fillsolid */
X                for(i = 0; i < nbars; i++)
X                        allocbarcolor(w, &arrp[i], nbaritems[i]);
X                return (FillSolid);
X        } else {
X                /* Tiled or stippled */
X                for(i = 0; i < nbars; i++)
X                      allocbarstyle(w, &arrp[i], nbaritems[i]);
X                return ((tile==filltype) ?  FillTiled : FillOpaqueStippled);
X        }
}
X
static int
parsecolors(w, cmap, names, newnames, parr)
Widget w;
Colormap cmap;
char *names;     /* List of color names separated by commas */
char *newnames;  /* As names, "." is a placeholder. Used to override names */
Pixel *parr;     /* Points to MAXLEVELS array of pixels */
{
X        char nm[MAXSTR], nnm[MAXSTR], *cnames[MAXLEVELS], *cp;
X        int i, retval=0;
X
X        (void)strncpy(nm, names, MAXSTR-1);
X        if(NULL!=newnames) (void)strncpy(nnm, newnames, MAXSTR-1);
X
X        /* parse names */
X        for(cp=strtok(nm,","),i=0; NULL!=cp; cp=strtok(NULL,","),i++){
X                if(i>=MAXLEVELS) break;
X                cnames[i]=cp;
X        }
X
X        /* override names with newnames */
X        if(NULL!=newnames){
X                for(cp=strtok(nnm,","),i=0; NULL!=cp; cp=strtok(NULL,","),i++){
X                        if(i>=MAXLEVELS) break;
X                        if('.'!=*cp) cnames[i]=cp;
X                }
X        }
X
X        /* allocate colors */
X        for(i=0;i<MAXLEVELS;i++){
X                XColor scolor, ecolor;
X                if(XAllocNamedColor(XtDisplay(w), cmap,
X                        cnames[i], &scolor, &ecolor)) {
X                                parr[i]=scolor.pixel;
X                } else {
X                        fprintf(stderr,
X                          "Can't find color %s, using foreground color.\n",
X                          cnames[i]);
X                        parr[i]=resource.fg;
X                        retval++;
X                }
X        }
X        return(retval);
}
X
X
X
static Atom protocol[1];
static XtActionsRec actionTable[] =
{ /* action for window manager close window protocol message */
X  { "WMclose_window",		close_window },
};
X
#define WMPROTOCOL_TRANSLATIONS  "<Message>WM_PROTOCOLS: WMclose_window()\n"
X
static void
close_window(w, ev, params, nparams)
X  Widget   *w;
X  XEvent   *ev;
X  String   *params;
X  Cardinal *nparams;
{
X  exit(0);
}
X
X
static void
setup_WMPROTOCOL(w, acttype)
X  Widget  w;
X  char   *acttype;
{
X  static int init = 0;
X
X  if (!init++)
X    {
X      XtAppAddActions(XtWidgetToApplicationContext(w),
X		      actionTable, XtNumber(actionTable));
X    }
X
X  protocol[0] = XInternAtom ( XtDisplay(w) , "WM_DELETE_WINDOW" , False ) ;
X  XSetWMProtocols ( XtDisplay(w) , XtWindow(w) , protocol , 1 ) ;
X
X  XtOverrideTranslations(w, XtParseTranslationTable(WMPROTOCOL_TRANSLATIONS));
}
SHAR_EOF
  $shar_touch -am 0728154999 'xcpustate.c' &&
  chmod 0644 'xcpustate.c' ||
  $echo 'restore of' 'xcpustate.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'xcpustate.c:' 'MD5 check failed'
f2668c1e8db86c3880173e830a051c69  xcpustate.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'xcpustate.c'`"
    test 20882 -eq "$shar_count" ||
    $echo 'xcpustate.c:' 'original size' '20882,' 'current size' "$shar_count!"
  fi
fi
# ============= xcpustate.man ==============
if test -f 'xcpustate.man' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'xcpustate.man' '(file already exists)'
else
  $echo 'x -' extracting 'xcpustate.man' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'xcpustate.man' &&
X.TH XCPUSTATE 1 "Mar 29, 1996" 
X.SH NAME
xcpustate - display CPU states (idle, nice, system, kernel) statistics
X.SH SYNTAX
\fBxcpustate\fP [\fI -toolkitoption\fP ...] [\fI -count\fP iterations] 
[\fI -interval\fP seconds] [\fI -shorten\fP components]
[\fI -cpu\fP] [\fI -nocpu\fP] [\fI -disk\fP] [\fI -nodisk\fP] [\fI -omni\fP] 
[\fI -noomni\fP] [\fI -wait\fP] [\fI -nowait\fP] 
[\fI -filltype\fP auto|grayscale|color|tile|stipple] 
[\fI -host\fP hostname] [\fI -version\fP]
[\fI -colors\fP colorname[,colorname[,...]]] 
[\fI -avg\fP iterations][\fI -kernel pathname] [\fI -mmap] [\fI -nommap]
X.SH DESCRIPTION
X.I Xcpustate
displays bars showing the percentage of time the CPU spends in
different states. On some systems, it optionally indicates disk states in
the same manner. It can also query remote systems that offer RSTAT RPC services.
X.PP
When using the RSTAT protocol, or when running locally on machines running 
Linux, or Berkeley Unix or a derivative (eg. suns with SunOS<=4.1.1, 
microVaxen with Ultrix), the bar indicates the proportions of idle, user, 
nice, and system time with increasing levels of grayscale or color (from 
left to right).  When running locally on supported multiprocessors 
(Solbourne OS/MP systems, Ultrix multiprocessors, Linux/SMP, and the 
Gould NP1), there will be one bar for each CPU. 
X.PP
On an SGI system running IRIX, there will be one bar for each CPU, indicating 
the proportions of idle + wait, user, kernel, sxbrk and interrupt time for 
that CPU. If  the ``wait'' option is set, the bars indicate idle, wait, user, 
kernel, sxbrk, and interrupt time, from left to right.
X.PP
On a Sun multiprocessor under SunOS 4.1.2 or 4.1.3, bars indicate the
proportions of idle + diskwait, user, nice, system, spinlock, and crosscall
service time for each CPU.
X.PP
On a Sun or other system (eg. Solbourne, Cray Superserver-6400) running 
Solaris 2.x, and on an IBM system running AIX, bars indicate the proportions 
of idle + wait, user, and kernel time for each CPU.  If the ``wait'' option 
is set, the bars indicate idle, wait, user, and system/kernel time, 
from left to right.
X.PP
On a Cray X/MP or Y/MP running Unicos 5.1 or greater, bars indicate
the proportions of idle + wait, user and system/kernel time for each CPU. 
X.PP
On systems running the Mach operating system, bars indicates the
proportions of user, system, and idle time for each CPU.
X.PP
On supported SVR4 systems (at least DELL Unix 2.2), a single bar is 
displayed showing idle, user, system and wait times.
X.PP
On NCR SVR4 MP/RAS systems,
one bar for each CPU (or disk drive) is displayed.
Each bar indicates the relative proportions of idle, user, system and
wait times for that CPU.  Disk drive times show device idle and busy.
X.SH OPTIONS
X.I Xcpustate
accepts all of the standard X Toolkit command line options, plus:
X.TP 8
X.IR -count " iterations"
The number of times it should update the display. Default is forever.
X.TP 8
X.IR -avg " iterations"
The number of iterations the bar values should be averaged over. Default is one.
X.TP 8
X.IR -interval " seconds"
the interval in seconds (fractions permitted) between updates.  Default is 
1 second.
X.TP 8
X.IR -shorten " components"
On some systems, 
X.I xcpustate 
will display the hostname in the bar labels.  Since some fully
qualified domain names can be very long, this option allows them
to be shortened to a specific number of components.  eg.
if your hostname is 
X.I foo.wherever.edu,
you can shorten it to
X.I foo
by specifying
X.I "-shorten 1"
or to
X.I foo.wherever
by specifying
X.I "-shorten 2".
Specifying
X.I "-shorten 0"
will omit the hostname completely; a negative number will cause
X.I xcpustate
to draw unlabeled bars.
Some systems may not support this option.
X.TP 8
X.I -cpu
Display CPU statistics (default).
X.TP 8
X.I -nocpu
Do not display CPU statistics. 
X.TP 8
X.I -disk
Display Disk statistics. This is supported only on Suns running SunOS 4.x or
5.x, or when using RSTAT. One bar is displayed for each disk. Disk bars appear
below the CPU bars, if any. When using RSTAT, exactly four bars appear 
regardless of the number of disks on the remote host (this is a limitation
of the current version of the RSTAT protocol). For Suns running SunOS 4.x,
the bars report idle, seek, and transfer time. For Suns running SunOS 5.x, 
the bars report idle, wait, and run time. When RSTAT is being used, the 
bars report idle and transfer time.
X.TP 8
X.I -nodisk
Do not display disk statistics (default).
X.TP 8
X.I -omni
Display Omni Network Coprocessor Statistics. This is supported only on
Suns running SunOS 4.x. One bar is displayed for each Network Coprocessor,
and placed immediately below the bars for the regular CPU(s). Each bar
indicates idle and system time.
X.TP 8
X.I -noomni
Do not display omni statistics (default).
X.TP 8
X.I -wait
Display CPU disk/system wait time as a separate statistic on applicable 
systems (Eg. SunOS 5.x, SGI IRIX, IBM AIX). 
X.TP 8
X.I -nowait
Include CPU disk/system wait time as part of idle (default).
X.TP 8
X.I -version
Print out version information and exit.
X.TP 8
X.I -filltype
Specify the method 
X.B xcpustate 
should use to fill the bars. Available options include grayscale,
color, tile, stipple, or auto. Auto automatically chooses between tiling,
grayscale, and colour, depending on your display type. Auto is the default.
X.TP 8
X.I -colors
Specify the colors used to draw the bars. Colors are specified in 
left-to-right order, separated by commas. A single dot can be used to
specify the default color at that position. Up to ten colors may be specified.
Defaults are used for the leftmost colors if less than ten are specified. 
X.TP 8
X.IR -kernel " pathname"
Specify the path that
X.B xcpustate
will use to find kernel symbol file information on some systems. This option
is ignored on IRIX, Mach, and SunOS 5.x.
X.TP 8
X.I -mmap
Request that
X.B xcpustate
use mmap to directly map kernel memory into the current process address
space on some systems (SVR4 and NCR). This is the default.
X.TP 8
X.I -nommap
Inverse of mmap option. 
X.SH X DEFAULTS
For
X.I xcpustate
the available class identifiers are:
X.sp
X.nf
CPUStateMonitor - the application
Form - enclosing the entire application, and sub-Forms enclosing 
Label/Bar pairs.
X.fi
X.PP
For
X.I xcpustate,
the available name identifiers are:
X.sp
X.nf
xcpustate - application name
The outer Form is "form".
The Forms enclosing the Label/Bar pairs are "formN", where N is the
index number, starting with the top pair as zero.
Each Label name is the same as the label string.
Each Bar name is "barN".
X.fi
X.sp
X.LP
For
X.I xcpustate,
the available resources are:
X.IP "name interval, class Interval"
corresponds to the -interval option. Takes a float value.
X.IP "name count, class Count"
corresponds to the -count argument. Takes an integer value.
X.IP "name avg, class Avg"
corresponds to the -avg argument. Takes an integer value.
X.IP "name shorten, class Shorten"
corresponds to the -shorten argument. Takes an integer value.
X.IP "name cpu, class Cpu"
corresponds to the -cpu and -nocpu arguments. Takes a boolean value.
X.IP "name disk, class Disk"
corresponds to the -disk and -nodisk arguments. Takes a boolean value.
X.IP "name omni, class Omni"
corresponds to the -omni and -noomni arguments. Takes a boolean value.
Not available on systems other than Suns running SunOS 4.x.
X.IP "name wait, class Wait"
corresponds to the -wait and -nowait arguments. Takes a boolean value.
X.IP "name filltype, class Filltype"
corresponds to the -filltype argument. Takes a string.
X.IP "name host, class Host"
corresponds to the -host argument. Takes a hostname.
X.IP "name colors, class Colors"
corresponds to the -colors argument. Takes a comma-separated list of color
names. 
X.IP "name mmap, class Mmap"
corresponds to the -mmap and -nommap argument. Takes a boolean value.
X.IP "name kernel, class Kernel"
corresponds to the -kernel argument. Takes a pathname.
X.SH NOTES
X.I Xcpustate 
is meant to be easy to port, and extend to monitor a wide variety of statistics.
X.SH SEE ALSO
xperfmon, xload, xmeter
X.SH AUTHORS
Mark Moraes at D. E. Shaw wrote the original X code and the SGI IRIX
code. He also enhanced the code for the Bar widget to support color. 
John DiMarco at the University of Toronto is the current maintainer. He 
contributed to the color support, fixed some minor problems, added support for
SunOS 4.x multiprocessors, SunOS 5.x, disks, Omni network coprocessors, AIX
(SMP on AIX 4.x) and RSTAT. Thanks to David O'Brien of the University of
California, Davis for the Free/Net/OpenBSD code, Chris Siebenmann of the
University of Toronto for the code for 4.3BSD systems; Walter D. Poxon from
Cray Research for the code for Cray machines running Unicos; Melinda Shore at
mt Xinu for the code for Mach systems; Bill Kucharski at Solbourne for the
code for Solbourne systems; Salvador Pinto Abreu at Universidade Nova de
Lisboa, Portugal, for the code for Ultrix multiprocessors; Hugues Leroy at
Irisa, Rennes, France for the code for Gould NP1 bi-processors, Bruce
Frost at NCR for the code for (Dell) SVR4 and NCR systems, and Kumsup Lee
at the University of Minnesota for the Linux code. Thanks also to
Robert Montjoy from the University of Cincinatti for contributing and testing
some of the SunOS 5.x code, to Dave Cahlander from Cray for cleaning up the X
resource code, and to Ron Wigmore from Ryerson Polytechnic University for his
assistance with the AIX port.
X.SH BUGS
The RSTAT RPC protocol supports only one processor and four disks on the 
remote system. On a multiprocessor, the CPU data reported by RSTAT will
be an average of all the active CPUs on the machine.
X.PP
X.I Xcpustate
may initially display nonsensical data, before being updated the first time.
X.PP
The use of very small (significantly less than one second) intervals may
result in xcpustate using significant resources, particularly when running
over the network.  A minimum interval may be specified as a compile-time
option, and intervals less than this will not be permitted.
SHAR_EOF
  $shar_touch -am 0305182398 'xcpustate.man' &&
  chmod 0644 'xcpustate.man' ||
  $echo 'restore of' 'xcpustate.man' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'xcpustate.man:' 'MD5 check failed'
bed7b15874c65b0f2dff192efdec7b4c  xcpustate.man
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'xcpustate.man'`"
    test 9995 -eq "$shar_count" ||
    $echo 'xcpustate.man:' 'original size' '9995,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh06559
exit 0
