|
|
1.1 ! root 1: #ifndef lint ! 2: static char rcsid[] = "$Header: Load.c,v 1.12 87/09/13 22:50:22 newman Exp $"; ! 3: #endif lint ! 4: ! 5: /* ! 6: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 7: * ! 8: * All Rights Reserved ! 9: * ! 10: * Permission to use, copy, modify, and distribute this software and its ! 11: * documentation for any purpose and without fee is hereby granted, ! 12: * provided that the above copyright notice appear in all copies and that ! 13: * both that copyright notice and this permission notice appear in ! 14: * supporting documentation, and that the name of Digital Equipment ! 15: * Corporation not be used in advertising or publicity pertaining to ! 16: * distribution of the software without specific, written prior permission. ! 17: * ! 18: * ! 19: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 20: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 21: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 22: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 23: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 24: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 25: * SOFTWARE. ! 26: */ ! 27: #ifndef lint ! 28: static char *sccsid = "@(#)Load.c 1.15 2/25/87"; ! 29: #endif lint ! 30: ! 31: #include <stdio.h> ! 32: #include <string.h> ! 33: #include "Xlib.h" ! 34: #include "Xutil.h" ! 35: #include "Intrinsic.h" ! 36: #include "Load.h" ! 37: #include "LoadP.h" ! 38: #include "Atoms.h" ! 39: #include <nlist.h> ! 40: #include <sys/time.h> ! 41: #include <sys/file.h> ! 42: #include <sys/param.h> ! 43: ! 44: extern long lseek(); ! 45: extern void exit(); ! 46: ! 47: /* Private Data */ ! 48: ! 49: #define offset(field) XtOffset(LoadWidget,load.field) ! 50: #define goffset(field) XtOffset(Widget,core.field) ! 51: ! 52: static XtResource resources[] = { ! 53: {XtNwidth, XtCWidth, XrmRInt, sizeof(int), ! 54: goffset(width), XrmRString, "120"}, ! 55: {XtNheight, XtCHeight, XrmRInt, sizeof(int), ! 56: goffset(height), XrmRString, "120"}, ! 57: {XtNupdate, XtCInterval, XrmRInt, sizeof(int), ! 58: offset(update), XrmRString, "5"}, ! 59: {XtNscale, XtCScale, XrmRInt, sizeof(int), ! 60: offset(scale), XrmRString, "1"}, ! 61: {XtNminScale, XtCScale, XrmRInt, sizeof(int), ! 62: offset(min_scale), XrmRString, "1"}, ! 63: {XtNlabel, XtCLabel, XrmRString, sizeof(char *), ! 64: offset(text), XrmRString, "Amnesia"}, ! 65: {XtNforeground, XtCForeground, XrmRPixel, sizeof(Pixel), ! 66: offset(fgpixel), XrmRString, "Black"}, ! 67: {XtNfont, XtCFont, XrmRFontStruct, sizeof(XFontStruct *), ! 68: offset(font), XrmRString, "fixed"}, ! 69: }; ! 70: ! 71: #undef offset ! 72: #undef goffset ! 73: ! 74: static void Initialize(), Realize(), Destroy(), Redisplay(); ! 75: static Boolean SetValues(); ! 76: static int repaint_window(); ! 77: ! 78: LoadClassRec loadClassRec = { ! 79: { /* core fields */ ! 80: /* superclass */ &widgetClassRec, ! 81: /* class_name */ "Load", ! 82: /* size */ sizeof(LoadRec), ! 83: /* class_initialize */ NULL, ! 84: /* class_inited */ FALSE, ! 85: /* initialize */ Initialize, ! 86: /* realize */ Realize, ! 87: /* actions */ NULL, ! 88: /* num_actions */ 0, ! 89: /* resources */ resources, ! 90: /* resource_count*/ XtNumber(resources), ! 91: /* xrm_class */ NULL, ! 92: /* compress_motion */ TRUE, ! 93: /* compress_exposure*/ TRUE, ! 94: /* visible_interest */ FALSE, ! 95: /* destroy */ Destroy, ! 96: /* resize */ NULL, ! 97: /* expose */ Redisplay, ! 98: /* set_values */ SetValues, ! 99: /* accept_focus */ NULL, ! 100: } ! 101: }; ! 102: ! 103: WidgetClass loadWidgetClass = (WidgetClass) &loadClassRec; ! 104: ! 105: /**************************************************************** ! 106: * ! 107: * Private Procedures ! 108: * ! 109: ****************************************************************/ ! 110: ! 111: static void draw_it(); ! 112: ! 113: static void EventHandler(gw, closure, event) ! 114: Widget gw; ! 115: char *closure; ! 116: XEvent *event; ! 117: { ! 118: if (event->type == ClientMessage && event->xclient.message_type == XtTimerExpired) ! 119: draw_it ((LoadWidget)gw); ! 120: } ! 121: ! 122: static void Initialize (greq, gnew) ! 123: Widget greq, gnew; ! 124: { ! 125: LoadWidget w = (LoadWidget)gnew; ! 126: XtGCMask valuemask; ! 127: XGCValues myXGCV; ! 128: ! 129: valuemask = GCForeground | GCFont | GCBackground; ! 130: myXGCV.foreground = w->load.fgpixel; ! 131: myXGCV.font = w->load.font->fid; ! 132: myXGCV.background = w->core.background_pixel; ! 133: w->load.myGC = XtGetGC(w, valuemask, &myXGCV); ! 134: ! 135: XtAddEventHandler (gnew, 0, TRUE, EventHandler, NULL); ! 136: ! 137: w->load.interval_id = XtAddTimeOut(gnew, w->load.update*1000); ! 138: w->load.interval = 0; ! 139: w->load.max_value = 0.0; ! 140: } ! 141: ! 142: static void Realize (gw, valueMask, attrs) ! 143: Widget gw; ! 144: XtValueMask valueMask; ! 145: XSetWindowAttributes *attrs; ! 146: { ! 147: gw->core.window = XCreateWindow (XtDisplay(gw), gw->core.parent->core.window, ! 148: gw->core.x, gw->core.y, gw->core.width, gw->core.height, gw->core.border_width, ! 149: gw->core.depth, InputOutput, /* visualID */ CopyFromParent, valueMask, attrs); ! 150: } ! 151: ! 152: static void Destroy (gw) ! 153: Widget gw; ! 154: { ! 155: LoadWidget w = (LoadWidget)gw; ! 156: XtRemoveTimeOut (w->load.interval_id); ! 157: XtDestroyGC (w->load.myGC); ! 158: } ! 159: ! 160: static void Redisplay(gw) ! 161: Widget gw; ! 162: { ! 163: (void) repaint_window ((LoadWidget)gw); ! 164: } ! 165: ! 166: static void draw_it(w) ! 167: LoadWidget w; ! 168: { ! 169: double value, GetLoadPoint(); ! 170: ! 171: if (w->load.interval >= w->core.width) ! 172: w->load.interval = ! 173: repaint_window(w); ! 174: /* Get the value, stash the point and draw corresponding line. */ ! 175: ! 176: value = GetLoadPoint(); ! 177: /* Keep w->load.max_value up to date, and if this data point is off the ! 178: graph, change the scale to make it fit. */ ! 179: if (value > w->load.max_value) { ! 180: w->load.max_value = value; ! 181: if (w->load.max_value > w->load.scale) { ! 182: w->load.scale = ((int)w->load.max_value) + 1; ! 183: w->load.interval = ! 184: repaint_window(w); ! 185: } ! 186: } ! 187: ! 188: w->load.valuedata[w->load.interval] = value; ! 189: if (XtIsRealized(w)) { ! 190: XDrawLine(XtDisplay(w), XtWindow(w), w->load.myGC, ! 191: w->load.interval, w->core.height, w->load.interval, ! 192: (int)(w->core.height - (w->core.height * value) /w->load.scale)); ! 193: XFlush(XtDisplay(w)); /* Flush output buffers */ ! 194: } ! 195: w->load.interval++; /* Next point */ ! 196: } /* draw_it */ ! 197: ! 198: /* Blts data according to current size, then redraws the load average window. ! 199: * Next represents the number of valid points in data. Returns the (possibly) ! 200: * adjusted value of next. If next is 0, this routine draws an empty window ! 201: * (scale - 1 lines for graph). If next is less than the current window width, ! 202: * the returned value is identical to the initial value of next and data is ! 203: * unchanged. Otherwise keeps half a window's worth of data. If data is ! 204: * changed, then w->load.max_value is updated to reflect the largest data point. ! 205: */ ! 206: ! 207: static int repaint_window(w) ! 208: LoadWidget w; ! 209: { ! 210: register int i, j; ! 211: register int next = w->load.interval; ! 212: extern void bcopy(); ! 213: ! 214: if (next >= w->core.width) { ! 215: j = w->core.width >> 1; ! 216: bcopy((char *)(w->load.valuedata + next - j), ! 217: (char *)(w->load.valuedata), j * sizeof(double)); ! 218: next = j; ! 219: /* Since we just lost some data, recompute the w->load.max_value. */ ! 220: w->load.max_value = 0.0; ! 221: for (i = 0; i < next; i++) { ! 222: if (w->load.valuedata[i] > w->load.max_value) ! 223: w->load.max_value = w->load.valuedata[i]; ! 224: } ! 225: } ! 226: ! 227: /* Compute the minimum scale required to graph the data, but don't go ! 228: lower than min_scale. */ ! 229: if (w->load.max_value > w->load.min_scale) ! 230: w->load.scale = ((int)w->load.max_value) + 1; ! 231: else ! 232: w->load.scale = w->load.min_scale; ! 233: ! 234: if (XtIsRealized(w)) { ! 235: Display *dpy = XtDisplay(w); ! 236: Window win = XtWindow(w); ! 237: ! 238: XClearWindow(dpy, win); ! 239: ! 240: /* Print hostname */ ! 241: XDrawString(dpy, win, w->load.myGC, 2, ! 242: 2 + w->load.font->ascent, w->load.text, strlen(w->load.text)); ! 243: ! 244: /* Draw graph reference lines */ ! 245: for (i = 1; i < w->load.scale; i++) { ! 246: j = (i * w->core.height) / w->load.scale; ! 247: XDrawLine(dpy, win, w->load.myGC, 0, j, ! 248: (int)w->core.width, j); ! 249: } ! 250: ! 251: /* Draw data point lines. */ ! 252: for (i = 0; i < next; i++) ! 253: XDrawLine(dpy, win, w->load.myGC, i, w->core.height, ! 254: i, (int)(w->core.height-(w->load.valuedata[i] * w->core.height) ! 255: /w->load.scale)); ! 256: } ! 257: ! 258: return(next); ! 259: } ! 260: ! 261: #define KMEM_FILE "/dev/kmem" ! 262: #define KMEM_ERROR "cannot open /dev/kmem" ! 263: ! 264: static struct nlist namelist[] = { /* namelist for vmunix grubbing */ ! 265: #define LOADAV 0 ! 266: {"_avenrun"}, ! 267: {0} ! 268: }; ! 269: ! 270: static double GetLoadPoint() ! 271: { ! 272: double loadavg; ! 273: static int init = 0; ! 274: static kmem; ! 275: static long loadavg_seek; ! 276: extern void nlist(); ! 277: ! 278: if(!init) { ! 279: nlist( "/vmunix", namelist); ! 280: if (namelist[LOADAV].n_type == 0){ ! 281: xload_error("xload: cannot get name list"); ! 282: exit(-1); ! 283: } ! 284: loadavg_seek = namelist[LOADAV].n_value; ! 285: kmem = open(KMEM_FILE, O_RDONLY); ! 286: if (kmem < 0) xload_error(KMEM_ERROR); ! 287: init = 1; ! 288: } ! 289: ! 290: ! 291: (void) lseek(kmem, loadavg_seek, 0); ! 292: #ifdef sun ! 293: { ! 294: long temp; ! 295: (void) read(kmem, (char *)&temp, sizeof(long)); ! 296: loadavg = (double)temp/FSCALE; ! 297: } ! 298: #else ! 299: (void) read(kmem, (char *)&loadavg, sizeof(double)); ! 300: #endif ! 301: return(loadavg); ! 302: } ! 303: ! 304: static xload_error(str) ! 305: char *str; ! 306: { ! 307: (void) fprintf(stderr,"xload: %s\n",str); ! 308: exit(-1); ! 309: } ! 310: ! 311: static Boolean SetValues (w, newvals) ! 312: Widget w, newvals; ! 313: { ! 314: return (FALSE); ! 315: } ! 316: ! 317: #ifdef notdef ! 318: void XtLoadSetValues (dpy, window, arglist, argCount) ! 319: Display *dpy; ! 320: Window window; ! 321: ArgList arglist; ! 322: int argCount; ! 323: { ! 324: WidgetData data; ! 325: data = DataFromWindow(dpy, window); ! 326: globaldata = *data; ! 327: if (data == NULL) return; ! 328: ! 329: XtSetValues(resourcelist, XtNumber(resourcelist), arglist, argCount); ! 330: ! 331: if (globaldata.update != data->update) { ! 332: (void) XtClearTimeOut(data->window, data->cookie); ! 333: XtSetTimeOut(data->window, data->cookie, globaldata.update*1000); ! 334: data->update = globaldata.update; ! 335: } ! 336: if (globaldata.brpixel != data->brpixel) { ! 337: data->brpixel = globaldata.brpixel; ! 338: if (data->brwidth != 0) ! 339: XSetWindowBorder(data->dpy, data->window, data->brpixel); ! 340: } ! 341: if(!strcmp(globaldata.text, data->text)) { ! 342: data->interval = repaint_window(data); ! 343: } ! 344: if(w->core.width >= 2048) w->core.width = 2047; ! 345: ! 346: *data = globaldata; ! 347: } ! 348: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.