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