/*
* Displays CPU state distribution
*/
#ifndef lint
static char rcsid[] = "$Id: xcpustate.c,v 1.32 2004/05/30 01:41:03 jdd Exp $";
#endif /*lint*/
#include <stdio.h>
#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"
#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 */
#define NOTSET minusTwo
char *progname;
typedef enum {
grayscale,
color,
tile,
stipple,
autodetect
} FillType;
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 */
static struct _resource {
XFontStruct *font;
char *colorspec;
int count;
float interval;
int shortenTo;
Pixel fg, bg;
Boolean rv;
char *filltypestr;
int cpuflag, diskflag, sep_wait, version;
char *kernelSymbols;
int kmem_can_map;
int avg;
#ifdef OMNI
int omniflag;
#endif /* OMNI */
#ifdef RSTAT
char *rstathost;
#endif /* RSTAT */
} resource;
#define offset(field) XtOffsetOf(struct _resource, field)
extern char *strtok();
static int allocstyles(), parsecolors();
static void setup_WMPROTOCOL(), close_window();
#ifdef RSTAT
extern int rstat_num_bars();
extern char **rstat_label_bars();
extern void rstat_init_bars();
extern void rstat_display_bars();
#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)
#else /* RSTAT */
#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)
#endif /* RSTAT */
/* Application Resources - no particular widget */
static XtResource application_resources[] = {
{"interval", "Interval", XtRFloat, sizeof(float),
offset(interval), XtRFloat, (caddr_t) &defaultInterval},
{"count", "Count", XtRInt, sizeof(int),
offset(count), XtRInt, (caddr_t) &minusOne},
{"shorten", "Shorten", XtRInt, sizeof(int),
offset(shortenTo), XtRInt, (caddr_t) &NOTSET},
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(fg), XtRString, XtDefaultForeground},
{XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
offset(bg), XtRString, XtDefaultBackground},
{XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof(Boolean),
offset(rv), XtRBoolean, (caddr_t) &def_false},
{"font", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
offset(font), XtRString, DEF_FONT},
{"colors", "Colors", XtRString, sizeof(char *),
offset(colorspec), XtRString, (caddr_t)NULL},
{"filltype", "Filltype", XtRString, sizeof(char *),
offset(filltypestr), XtRString, (caddr_t)"auto"},
{"cpu", "Cpu", XtRBoolean, sizeof(Boolean),
offset(cpuflag), XtRImmediate, (XtPointer)True},
{"disk", "Disk", XtRBoolean, sizeof(Boolean),
offset(diskflag), XtRImmediate, (XtPointer)False},
{"wait", "Wait", XtRBoolean, sizeof(Boolean),
offset(sep_wait), XtRImmediate, (XtPointer)False},
{"version", "Version", XtRBoolean, sizeof(Boolean),
offset(version), XtRImmediate, (XtPointer)False},
{"kernel", "Kernel", XtRString, sizeof(char *),
offset(kernelSymbols), XtRString, (caddr_t) NULL},
{"mmap", "Mmap", XtRBoolean, sizeof(Boolean),
offset(kmem_can_map), XtRInt, (caddr_t)&def_true},
{"avg", "Avg", XtRInt, sizeof(int),
offset(avg), XtRInt, (caddr_t)&one},
#ifdef OMNI
{"omni", "Omni", XtRBoolean, sizeof(Boolean),
offset(omniflag), XtRImmediate, (XtPointer)False},
#endif /* OMNI */
#ifdef RSTAT
{"host", "Host", XtRString, sizeof(char *),
offset(rstathost), XtRString, (caddr_t)NULL},
#endif /* RSTAT */
};
/*
* 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[] = {
{"-interval", ".interval", XrmoptionSepArg, (caddr_t) NULL},
{"-count", ".count", XrmoptionSepArg, (caddr_t) NULL},
{"-shorten", ".shorten", XrmoptionSepArg, (caddr_t) NULL},
{"-cpu", ".cpu", XrmoptionNoArg, (caddr_t) "True"},
{"-nocpu", ".cpu", XrmoptionNoArg, (caddr_t) "False"},
{"-disk", ".disk", XrmoptionNoArg, (caddr_t) "True"},
{"-nodisk", ".disk", XrmoptionNoArg, (caddr_t) "False"},
{"-wait", ".wait", XrmoptionNoArg, (caddr_t) "True"},
{"-nowait", ".wait", XrmoptionNoArg, (caddr_t) "False"},
{"-host", ".host", XrmoptionSepArg, (caddr_t) NULL},
{"-colors", ".colors", XrmoptionSepArg, (caddr_t) NULL},
{"-filltype", ".filltype", XrmoptionSepArg, (caddr_t) NULL},
{"-kernel", ".kernel", XrmoptionSepArg, (caddr_t) NULL},
{"-mmap", ".mmap", XrmoptionNoArg, (caddr_t) "True"},
{"-nommap", ".mmap", XrmoptionNoArg, (caddr_t) "False"},
{"-version", ".version", XrmoptionNoArg, (caddr_t) "True"},
{"-avg", ".avg", XrmoptionSepArg, (caddr_t) NULL},
#ifdef OMNI
{"-omni", ".omni", XrmoptionNoArg, (caddr_t) "True"},
{"-noomni", ".omni", XrmoptionNoArg, (caddr_t) "False"},
#endif /* OMNI */
};
/*
* 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[] = {
{XtNdefaultDistance, (XtArgVal) 0},
};
static Arg subform_args[] = {
{XtNfromVert, (XtArgVal) 0},
{XtNdefaultDistance, (XtArgVal) 0},
{XtNborderWidth, (XtArgVal) 0},
{XtNtop, (XtArgVal) XtRubber},
{XtNbottom, (XtArgVal) XtRubber}, /* ChainBottom causes strange resize */
{XtNright, (XtArgVal) XtChainRight},
{XtNleft, (XtArgVal) XtChainLeft},
};
static Arg bar_args[] = {
{XtNfromHoriz, (XtArgVal) 0},
{XtNpixmaps, (XtArgVal) 0},
{XtNfillStyle, (XtArgVal) 0},
{XtNorientation, (XtArgVal) XtorientHorizontal},
{XtNborderWidth, (XtArgVal) 1},
{XtNlength, (XtArgVal) ((Dimension) 200)},
{XtNthickness, (XtArgVal) ((Dimension) 20)},
{XtNtop, (XtArgVal) XtChainTop},
{XtNbottom, (XtArgVal) XtChainBottom},
{XtNright, (XtArgVal) XtChainRight},
{XtNleft, (XtArgVal) XtChainLeft},
{XtNvertDistance, (XtArgVal) 0},
{XtNhorizDistance, (XtArgVal) 0},
{XtNresizable, (XtArgVal) TRUE},
};
static Arg label_args[] = {
{XtNlabel, (XtArgVal) 0},
{XtNjustify, (XtArgVal) XtJustifyLeft},
{XtNborderWidth, (XtArgVal) 0},
{XtNtop, (XtArgVal) XtChainTop},
{XtNbottom, (XtArgVal) XtChainTop},
{XtNright, (XtArgVal) XtChainLeft},
{XtNleft, (XtArgVal) XtChainLeft},
{XtNvertDistance, (XtArgVal) 0},
{XtNhorizDistance, (XtArgVal) 0},
{XtNresizable, (XtArgVal) FALSE},
{XtNwidth, (XtArgVal) 1},
{XtNfont, (XtArgVal) 0},
};
void
usage()
{
/* Ugly! */
(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 */
);
exit(-1);
}
char *
xmalloc(n)
unsigned int n;
{
return XtMalloc(n);
}
static int nbars;
static Widget *bar;
static char **barnames;
/* ARGSUSED */
static void
update_display(closure, id)
XtPointer closure;
XtIntervalId *id;
{
unsigned long timeout;
displayBars(nbars);
if (resource.count > 0) {
if (--resource.count == 0)
return;
}
timeout=(unsigned long)(resource.interval * 1000.0);
(void) XtAddTimeOut(timeout, update_display, (XtPointer) NULL);
}
main(argc, argv)
int argc;
char **argv;
{
int i, maxlabellen=0, *nbaritems, fstyle;
Widget topLevel, form, label, subform = NULL;
Array *arrp;
Display *dpy;
int scr;
#ifndef index
extern char *index(/* const char *, char */);
#endif
if ((progname = index(argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;
topLevel = XtInitialize(progname, "CPUStateMonitor",
optionDescList, XtNumber(optionDescList),
&argc, argv);
dpy=XtDisplay(topLevel);
scr=DefaultScreen(dpy);
XtGetApplicationResources(topLevel, (XtPointer) &resource,
application_resources,
XtNumber(application_resources),
(ArgList)NULL, (Cardinal)0 );
cpuflag = resource.cpuflag;
diskflag = resource.diskflag;
sep_wait = resource.sep_wait;
kernelSymbols = resource.kernelSymbols;
kmem_can_map = resource.kmem_can_map;
avg = resource.avg; if(avg<1) avg=1; if(avg>MAXAVG) avg=MAXAVG;
#ifdef OMNI
omniflag = resource.omniflag;
#endif /* OMNI */
#ifdef RSTAT
rstathost = resource.rstathost;
#endif /* RSTAT */
if(resource.version) {
printf("%s\n", patchlevel);
version();
#ifdef RSTAT
rstat_version();
#endif /* RSTAT */
exit(0);
}
if(argc>1) usage();
if(0==strcmp(resource.filltypestr, "auto")){
if(DefaultDepth(dpy, scr)>1){
VisualID vid;
XVisualInfo vinfo, *vinfo_p;
int count;
vid=XVisualIDFromVisual(DefaultVisual(dpy, scr));
vinfo.visualid = vid;
vinfo_p = XGetVisualInfo(dpy, VisualIDMask, &vinfo, &count);
if(1!=count){
(void) fprintf(stderr,
"VisualID doesn't map to one visual???\n");
filltype=grayscale; /* lowest common denominator */
} else {
if((GrayScale==vinfo_p->class || StaticGray==vinfo_p->class)){
filltype=grayscale;
} else {
filltype=color;
}
}
} else {
filltype=tile;
}
} else if(0==strcmp(resource.filltypestr, "grayscale")){
filltype=grayscale;
} else if (0==strcmp(resource.filltypestr, "color")){
filltype=color;
} else if (0==strcmp(resource.filltypestr, "stipple")){
filltype=stipple;
} else if (0==strcmp(resource.filltypestr, "tile")){
filltype=tile;
} else {
if(NULL!=resource.filltypestr) {
fprintf(stderr,
"%s: Unknown filltype %s, using \"tile\".\n", progname,
resource.filltypestr);
}
filltype=tile;
}
if(color==filltype || grayscale==filltype){
colormap = DefaultColormap(XtDisplay(topLevel),
DefaultScreen(XtDisplay(topLevel)));
if(color==filltype) {
(void)parsecolors(topLevel,colormap,colornames,resource.colorspec,colors);
} else if(grayscale==filltype){
(void)parsecolors(topLevel,colormap,graycolornames,NULL,colors);
}
}
if(cpuflag) cpuflag=1;
if(diskflag) diskflag=1;
if(sep_wait) sep_wait=1;
if(kmem_can_map) kmem_can_map=1;
#ifdef OMNI
if(omniflag) omniflag=1;
#endif /* OMNI */
if(NULL==resource.font) {
(void) fprintf(stderr, "Can't find font '%s'\n", DEF_FONT);
exit(-1);
}
/* Make sure the default interval isn't less than the minimum. */
if(defaultInterval<INTERVAL_MIN){
if(resource.interval==defaultInterval){
resource.interval=INTERVAL_MIN;
}
defaultInterval=INTERVAL_MIN;
}
if(resource.interval < INTERVAL_MIN){
(void) fprintf(stderr,
"The minimum interval is '%.4f'; '%.4f' is too small. Using '%.4f'\n",
(1.0*INTERVAL_MIN), resource.interval, defaultInterval);
resource.interval=defaultInterval;
}
nbars = numBars();
if (0==nbars) {
(void) fprintf(stderr, "Nothing to do. Exiting.\n");
exit(-1);
}
bar = (Widget *) xmalloc(nbars * sizeof(Widget));
barnames = labelBars(nbars);
nbaritems = (int *) xmalloc(nbars * sizeof(int));
barItems(nbars, nbaritems);
arrp = (Array *) xmalloc(nbars * sizeof(Array));
fstyle = allocstyles(topLevel, nbars, nbaritems, arrp);
/* find width of biggest label */
for(i=0;i<nbars;i++){
int labellen;
labellen=XTextWidth(resource.font, barnames[i], strlen(barnames[i]));
if(labellen>maxlabellen) maxlabellen=labellen;
}
form = XtCreateManagedWidget("form", formWidgetClass, topLevel,
form_args, XtNumber(form_args));
for(i = 0; i < nbars; i++) {
#define FORMNAMEFMT "form%d"
char formname[sizeof(FORMNAMEFMT) + 32];
#define BARNAMEFMT "bar%d"
char barname[sizeof(BARNAMEFMT) + 32];
if (i > 0)
subform_args[0].value = (XtArgVal) subform;
(void) sprintf(formname, FORMNAMEFMT, i);
subform = XtCreateManagedWidget(formname, formWidgetClass, form,
subform_args, XtNumber(subform_args));
label_args[0].value = (XtArgVal) barnames[i];
if (resource.shortenTo >= 0 || resource.shortenTo == NOTSET) {
label_args[10].value = (XtArgVal) (6+maxlabellen);
} else {
label_args[10].value = (XtArgVal) 1;
}
label_args[11].value = (XtArgVal) resource.font;
label = XtCreateManagedWidget(barnames[i], labelWidgetClass,
subform, label_args, XtNumber(label_args));
(void) sprintf(barname, BARNAMEFMT, i);
bar_args[0].value = (XtArgVal) label;
bar_args[1].value = (XtArgVal) (arrp + i);
bar_args[2].value = (XtArgVal) fstyle;
bar[i] = XtCreateManagedWidget(barname, barWidgetClass, subform,
bar_args, XtNumber(bar_args));
}
XtRealizeWidget(topLevel);
setup_WMPROTOCOL(topLevel, "");
initBars(nbars);
displayBars(nbars); /* First display is always rubbish */
/* let's look at rubbish for only 0.01 second, regardless of interval */
(void) XtAddTimeOut((unsigned long) (10), update_display,
(XtPointer)NULL);
XtMainLoop();
}
void
draw_bar(i, states, nstates)
int i;
int states[];
int nstates;
{
static int sa[MAXBARS][MAXAVG][MAXLEVELS];
static int avged[MAXLEVELS];
static int pos=0, notfirsttime[MAXBARS];
int j, k, sum=0;
pos++; if(pos>=avg) pos=0;
for(j=0;j<nstates;j++) {
if(notfirsttime[i]) {
/*
* If this is the first time for this bar, the numbers
* are likely to be total nonsense, so don't keep them
* around for later. Otherwise the bars may be
* totally wrong for avg number of intervals.
*/
sa[i][pos][j]=states[j];
}
avged[j]=0;
for(k=0;k<avg;k++){
avged[j] += sa[i][k][j];
}
/* avged[j] = avged[j]/avg; */
}
SetBarValues((Widget) bar[i], avged, nstates);
notfirsttime[i]=1;
}
void
shorten(hname)
char *hname;
{
if (resource.shortenTo >= 0) {
int i;
char *cp = hname;
for(i = 0; i < resource.shortenTo; i++) {
cp = index(++cp, '.');
if (cp == NULL)
break;
}
if (cp)
*cp = '\0';
}
}
static void
allocbarstyle(w, arrp, n)
Widget w;
Array *arrp;
int n;
{
#define newpixmap XCreatePixmapFromBitmapData
Display *dpy = XtDisplay(w);
Window root = DefaultRootWindow(dpy);
Pixmap *pp;
int i, igray;
pp = (Pixmap *) xmalloc(n * sizeof(Pixmap));
arrp->nitems = n;
arrp->itemtype = sizeof(Pixmap);
arrp->items = (caddr_t) pp;
for(igray = level_mapping[n-1][0], i=0;
i<n;
i++, igray=level_mapping[n-1][i]) {
if (tile==filltype) {
unsigned depth = DefaultDepthOfScreen(XtScreen(w));
pp[i] = newpixmap(dpy, root, (char *)gray_bits[igray],
(unsigned) 3, (unsigned) 3, resource.fg, resource.bg, depth);
} else {
Pixel black = 1;
Pixel white = 0;
unsigned depth = 1;
pp[i] = newpixmap(dpy, root, (char *)gray_bits[igray],
(unsigned) 3, (unsigned) 3, black, white, depth);
}
}
}
static void
allocbarcolor(w, arrp, n)
Widget w;
Array *arrp;
int n;
{
arrp->nitems = n;
arrp->itemtype = sizeof(Pixel);
if(grayscale == filltype) {
int i, igray;
Pixel *px;
px = (Pixel *) xmalloc(n * sizeof(Pixel));
for(igray = level_mapping[n-1][0], i=0;
i<n;
i++, igray=level_mapping[n-1][i]) {
px[i] = colors[igray];
}
arrp->items= (caddr_t) px;
} else {
arrp->items = (caddr_t) colors;
}
}
static int
allocstyles(w, nbars, nbaritems, arrp)
Widget w;
int nbars;
int nbaritems[];
Array arrp[]; /* nbars elements */
{
int i;
if(grayscale==filltype || color==filltype){
/* Fillsolid */
for(i = 0; i < nbars; i++)
allocbarcolor(w, &arrp[i], nbaritems[i]);
return (FillSolid);
} else {
/* Tiled or stippled */
for(i = 0; i < nbars; i++)
allocbarstyle(w, &arrp[i], nbaritems[i]);
return ((tile==filltype) ? FillTiled : FillOpaqueStippled);
}
}
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 */
{
char nm[MAXSTR], nnm[MAXSTR], *cnames[MAXLEVELS], *cp;
int i, retval=0;
(void)strncpy(nm, names, MAXSTR-1);
if(NULL!=newnames) (void)strncpy(nnm, newnames, MAXSTR-1);
/* parse names */
for(cp=strtok(nm,","),i=0; NULL!=cp; cp=strtok(NULL,","),i++){
if(i>=MAXLEVELS) break;
cnames[i]=cp;
}
/* override names with newnames */
if(NULL!=newnames){
for(cp=strtok(nnm,","),i=0; NULL!=cp; cp=strtok(NULL,","),i++){
if(i>=MAXLEVELS) break;
if('.'!=*cp) cnames[i]=cp;
}
}
/* allocate colors */
for(i=0;i<MAXLEVELS;i++){
XColor scolor, ecolor;
if(XAllocNamedColor(XtDisplay(w), cmap,
cnames[i], &scolor, &ecolor)) {
parr[i]=scolor.pixel;
} else {
fprintf(stderr,
"Can't find color %s, using foreground color.\n",
cnames[i]);
parr[i]=resource.fg;
retval++;
}
}
return(retval);
}
static Atom protocol[1];
static XtActionsRec actionTable[] =
{ /* action for window manager close window protocol message */
{ "WMclose_window", close_window },
};
#define WMPROTOCOL_TRANSLATIONS "<Message>WM_PROTOCOLS: WMclose_window()\n"
static void
close_window(w, ev, params, nparams)
Widget *w;
XEvent *ev;
String *params;
Cardinal *nparams;
{
exit(0);
}
static void
setup_WMPROTOCOL(w, acttype)
Widget w;
char *acttype;
{
static int init = 0;
if (!init++)
{
XtAppAddActions(XtWidgetToApplicationContext(w),
actionTable, XtNumber(actionTable));
}
protocol[0] = XInternAtom ( XtDisplay(w) , "WM_DELETE_WINDOW" , False ) ;
XSetWMProtocols ( XtDisplay(w) , XtWindow(w) , protocol , 1 ) ;
XtOverrideTranslations(w, XtParseTranslationTable(WMPROTOCOL_TRANSLATIONS));
}
syntax highlighted by Code2HTML, v. 0.9.1