|
|
1.1 ! root 1: /* $Header: Load.c,v 1.2 87/09/12 12:43:16 swick Exp $ */ ! 2: #ifndef lint ! 3: static char *sccsid = "@(#)Load.c 1.15 2/25/87"; ! 4: #endif lint ! 5: ! 6: /* ! 7: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 8: * ! 9: * All Rights Reserved ! 10: * ! 11: * Permission to use, copy, modify, and distribute this software and its ! 12: * documentation for any purpose and without fee is hereby granted, ! 13: * provided that the above copyright notice appear in all copies and that ! 14: * both that copyright notice and this permission notice appear in ! 15: * supporting documentation, and that the name of Digital Equipment ! 16: * Corporation not be used in advertising or publicity pertaining to ! 17: * distribution of the software without specific, written prior permission. ! 18: * ! 19: * ! 20: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 21: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 22: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 23: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 24: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 25: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 26: * SOFTWARE. ! 27: */ ! 28: ! 29: ! 30: #include <stdio.h> ! 31: #include <strings.h> ! 32: #include "Xlib.h" ! 33: #include "Xutil.h" ! 34: #include "Intrinsic.h" ! 35: #include "Load.h" ! 36: #include "Atoms.h" ! 37: #include <nlist.h> ! 38: #include <sys/time.h> ! 39: #include <sys/file.h> ! 40: #include <sys/param.h> ! 41: ! 42: extern long lseek(); ! 43: ! 44: /* Private Definitions */ ! 45: ! 46: typedef struct WidgetDataRec { ! 47: Display *dpy; /* widget display connection */ ! 48: Window window; /* widget window */ ! 49: Dimension brwidth; /* border width in pixels */ ! 50: Dimension width, height; /* width/height in pixels */ ! 51: Position x, y; ! 52: Pixel fgpixel; /* color index for text */ ! 53: Pixel bgpixel; /* color index for background */ ! 54: Pixel brpixel; /* pixel for border */ ! 55: XFontStruct *fontstruct; /* font for text */ ! 56: GC myGC; /* pointer to GraphicsContext */ ! 57: /* start of graph stuff */ ! 58: int update; /* update frequence */ ! 59: int scale; /* scale factor */ ! 60: int min_scale; /* smallest scale factor */ ! 61: int interval; /* data point interval */ ! 62: char *text; /* label */ ! 63: double max_value; /* Max Value in window */ ! 64: int mapped; /* is exposed */ ! 65: double valuedata[2048];/* record of data points */ ! 66: /* start of xload stuff ! 67: char *vmunix; /* path of namelist */ ! 68: caddr_t cookie; ! 69: } WidgetDataRec, *WidgetData; ! 70: ! 71: ! 72: /* Private Data */ ! 73: ! 74: static WidgetDataRec globaldata; ! 75: ! 76: static int initDone = 0; /* initialization flag */ ! 77: static XContext widgetContext; ! 78: static int def_border = 1; ! 79: static int def_width = 120; ! 80: static int def_height = 120; ! 81: static int def_update = 5; ! 82: static int def_x = 0; ! 83: static int def_y = 0; ! 84: static int def_scale = 1; ! 85: ! 86: static Resource resourcelist[] = { ! 87: {XtNwindow, XtCWindow, XrmRWindow, ! 88: sizeof(Window), (caddr_t)&globaldata.window, (caddr_t)NULL}, ! 89: {XtNborderWidth, XtCBorderWidth, XrmRInt, ! 90: sizeof(int), (caddr_t)&globaldata.brwidth, (caddr_t) &def_border}, ! 91: {XtNwidth, XtCWidth, XrmRInt, ! 92: sizeof(int), (caddr_t)&globaldata.width, (caddr_t) &def_width}, ! 93: {XtNheight, XtCHeight, XrmRInt, ! 94: sizeof(int), (caddr_t)&globaldata.height, (caddr_t) &def_height }, ! 95: {XtNx, XtCX, XrmRInt, ! 96: sizeof(int), (caddr_t)&globaldata.x, (caddr_t) &def_x }, ! 97: {XtNy, XtCX, XrmRInt, ! 98: sizeof(int), (caddr_t)&globaldata.y, (caddr_t) &def_y }, ! 99: {XtNupdate, XtCInterval, XrmRInt, ! 100: sizeof(int), (caddr_t)&globaldata.update, (caddr_t) &def_update }, ! 101: {XtNscale, XtCScale, XrmRInt, ! 102: sizeof(int), (caddr_t)&globaldata.scale, (caddr_t) &def_scale }, ! 103: {XtNminScale, XtCScale, XrmRInt, ! 104: sizeof(int), (caddr_t)&globaldata.min_scale, (caddr_t) &def_scale }, ! 105: {XtNlabel, XtCLabel, XrmRString, ! 106: sizeof(char *), (caddr_t)&globaldata.text, (caddr_t) "Amnesia" }, ! 107: {XtNforeground, XtCColor, XrmRPixel, ! 108: sizeof(int), (caddr_t)&globaldata.fgpixel, (caddr_t)&XtDefaultFGPixel}, ! 109: {XtNbackground, XtCColor, XrmRPixel, ! 110: sizeof(int), (caddr_t)&globaldata.bgpixel, (caddr_t)&XtDefaultBGPixel}, ! 111: {XtNborder, XtCColor, XrmRPixel, ! 112: sizeof(int),(caddr_t)&globaldata.brpixel, (caddr_t)&XtDefaultFGPixel}, ! 113: {XtNfont, XtCFont, XrmRFontStruct, ! 114: sizeof(XFontStruct *), (caddr_t)&globaldata.fontstruct, (caddr_t)NULL} ! 115: }; ! 116: ! 117: ! 118: /**************************************************************** ! 119: * ! 120: * Private Procedures ! 121: * ! 122: ****************************************************************/ ! 123: ! 124: static void LoadInitialize (dpy) ! 125: Display *dpy; ! 126: { ! 127: if(!initDone) ! 128: globaldata.fontstruct = XLoadQueryFont(dpy,"fixed"); ! 129: widgetContext = XUniqueContext(); ! 130: ! 131: initDone = 1; ! 132: } ! 133: ! 134: ! 135: /* ! 136: * Given a display and window, get the widget data. ! 137: */ ! 138: ! 139: static WidgetData DataFromWindow(dpy, window) ! 140: Display *dpy; ! 141: Window window; ! 142: { ! 143: WidgetData result; ! 144: if (XFindContext(dpy, window, widgetContext, (caddr_t *)&result)) ! 145: return NULL; ! 146: return result; ! 147: } ! 148: ! 149: static void Destroy(); ! 150: ! 151: /* ! 152: * ! 153: * Generic widget event handler ! 154: * ! 155: */ ! 156: ! 157: ! 158: static XtEventReturnCode EventHandler(event, eventdata) ! 159: XEvent *event; ! 160: caddr_t eventdata; ! 161: { ! 162: WidgetData data = (WidgetData ) eventdata; ! 163: ! 164: switch (event->type) { ! 165: case ConfigureNotify: ! 166: data->height = event->xconfigure.height; ! 167: data->width = event->xconfigure.width; ! 168: break; ! 169: ! 170: case DestroyNotify: ! 171: Destroy(data); ! 172: break; ! 173: ! 174: case ClientMessage: ! 175: if (((XClientMessageEvent *)event)->message_type == ! 176: (unsigned) XtTimerExpired) ! 177: draw_it(data); ! 178: break; ! 179: ! 180: case Expose: ! 181: data->mapped = 1; ! 182: if( ((XExposeEvent *)event)->count == 0) ! 183: data->interval = repaint_window(data); ! 184: break; ! 185: ! 186: case NoExpose: ! 187: data->mapped = 0; ! 188: break; ! 189: } ! 190: ! 191: return (XteventHandled); ! 192: } ! 193: ! 194: /* ! 195: * ! 196: * Destroy the widget ! 197: * ! 198: */ ! 199: ! 200: static void Destroy(data) ! 201: WidgetData data; ! 202: { ! 203: ! 204: XtClearEventHandlers(data->dpy, data->window); ! 205: (void) XtClearTimeOut(data->window, data->cookie); ! 206: XtFree ((char *) data); ! 207: } ! 208: ! 209: ! 210: ! 211: /**************************************************************** ! 212: * ! 213: * Public Procedures ! 214: * ! 215: ****************************************************************/ ! 216: ! 217: Window XtLoadCreate(dpy, pw, arglist, argCount) ! 218: Display *dpy; ! 219: Window pw; /* parent window */ ! 220: ArgList arglist; ! 221: int argCount; ! 222: { ! 223: WidgetData data; ! 224: int eventmask; ! 225: GCMask valuemask; ! 226: XrmNameList names; ! 227: XrmClassList classes; ! 228: XGCValues myXGCV; ! 229: if (!initDone)LoadInitialize (dpy); ! 230: ! 231: data = (WidgetData ) XtMalloc (sizeof (WidgetDataRec)); ! 232: ! 233: /* Set Default Values */ ! 234: globaldata.dpy = dpy; ! 235: XtGetResources(dpy, resourcelist, XtNumber(resourcelist), arglist, argCount, pw, ! 236: "load", "Load", &names, &classes); ! 237: *data = globaldata; ! 238: valuemask = GCForeground | GCFont | GCBackground; ! 239: myXGCV.foreground = (*data).fgpixel; ! 240: myXGCV.font = (*data).fontstruct->fid; ! 241: myXGCV.background = data->bgpixel; ! 242: (*data).myGC = XtGetGC(data->dpy, widgetContext, pw, valuemask, &myXGCV); ! 243: ! 244: if (data->window != NULL) { ! 245: XWindowAttributes wi; ! 246: /* set global data from window parameters */ ! 247: if (! XGetWindowAttributes(data->dpy,data->window, &wi)) { ! 248: data->window = NULL; ! 249: } else { ! 250: data->brwidth = wi.border_width; ! 251: data->width = wi.width; ! 252: data->height = wi.height; ! 253: } ! 254: } ! 255: if (data->window == NULL) { ! 256: /* create the Load window */ ! 257: if(data->width >= 2048) data->width = 2047; ! 258: data->window = XCreateSimpleWindow(data->dpy, pw, data->x, data->y, ! 259: data->width, data->height, ! 260: data->brwidth, data->brpixel, data->bgpixel); ! 261: } ! 262: ! 263: XtSetNameAndClass(data->dpy, data->window, names, classes); ! 264: XrmFreeNameList(names); ! 265: XrmFreeClassList(classes); ! 266: ! 267: (void)XSaveContext(data->dpy, data->window, widgetContext, (caddr_t)data); ! 268: ! 269: /* set handler for expose, resize, and message events */ ! 270: ! 271: eventmask = ExposureMask+StructureNotifyMask; ! 272: XtSetEventHandler ( ! 273: data->dpy, data->window, (XtEventHandler)EventHandler, ! 274: (unsigned long) eventmask, (caddr_t)data); ! 275: ! 276: XtSetTimeOut(data->window, XtNLoad,data->update*1000); ! 277: ! 278: return (data->window); ! 279: } ! 280: ! 281: /* ! 282: * Get Attributes ! 283: */ ! 284: ! 285: void XtLoadGetValues (dpy, window, arglist, argCount) ! 286: Display *dpy; ! 287: Window window; ! 288: ArgList arglist; ! 289: int argCount; ! 290: { ! 291: WidgetData data; ! 292: data = DataFromWindow(dpy, window); ! 293: if (data) { ! 294: globaldata = *data; ! 295: XtGetValues(resourcelist, XtNumber(resourcelist), arglist, argCount); ! 296: } ! 297: } ! 298: ! 299: /* ! 300: * Set Attributes ! 301: */ ! 302: ! 303: void XtLoadSetValues (dpy, window, arglist, argCount) ! 304: Display *dpy; ! 305: Window window; ! 306: ArgList arglist; ! 307: int argCount; ! 308: { ! 309: WidgetData data; ! 310: data = DataFromWindow(dpy, window); ! 311: globaldata = *data; ! 312: if (data == NULL) return; ! 313: ! 314: XtSetValues(resourcelist, XtNumber(resourcelist), arglist, argCount); ! 315: ! 316: if (globaldata.update != data->update) { ! 317: (void) XtClearTimeOut(data->window, data->cookie); ! 318: XtSetTimeOut(data->window, data->cookie, globaldata.update*1000); ! 319: data->update = globaldata.update; ! 320: } ! 321: if (globaldata.brpixel != data->brpixel) { ! 322: data->brpixel = globaldata.brpixel; ! 323: if (data->brwidth != 0) ! 324: XSetWindowBorder(data->dpy, data->window, data->brpixel); ! 325: } ! 326: if(!strcmp(globaldata.text, data->text)) { ! 327: data->interval = repaint_window(data); ! 328: } ! 329: if(data->width >= 2048) data->width = 2047; ! 330: ! 331: *data = globaldata; ! 332: } ! 333: ! 334: ! 335: static draw_it(data) ! 336: WidgetDataRec *data; ! 337: { ! 338: double value, GetLoadPoint(); ! 339: ! 340: if (data->interval >= data->width) ! 341: data->interval = ! 342: repaint_window(data); ! 343: /* Get the value, stash the point and draw corresponding line. */ ! 344: ! 345: value = GetLoadPoint(); ! 346: /* Keep data->max_value up to date, and if this data point is off the ! 347: graph, change the scale to make it fit. */ ! 348: if (value > data->max_value) { ! 349: data->max_value = value; ! 350: if (data->max_value > data->scale) { ! 351: data->scale = ((int)data->max_value) + 1; ! 352: data->interval = ! 353: repaint_window(data); ! 354: } ! 355: } ! 356: ! 357: data->valuedata[data->interval] = value; ! 358: if (data->mapped) { ! 359: ! 360: XDrawLine(data->dpy, data->window, data->myGC, ! 361: data->interval, (int)data->height, data->interval, ! 362: (int)(data->height - (data->height * value) /data->scale)); ! 363: XFlush(data->dpy); /* Flush output buffers */ ! 364: } ! 365: data->interval++; /* Next point */ ! 366: } /* draw_it */ ! 367: ! 368: /* Blts data according to current size, then redraws the load average window. ! 369: * Next represents the number of valid points in data. Returns the (possibly) ! 370: * adjusted value of next. If next is 0, this routine draws an empty window ! 371: * (scale - 1 lines for graph). If next is less than the current window width, ! 372: * the returned value is identical to the initial value of next and data is ! 373: * unchanged. Otherwise keeps half a window's worth of data. If data is ! 374: * changed, then data->max_value is updated to reflect the largest data point. ! 375: */ ! 376: ! 377: static int repaint_window(data) ! 378: WidgetDataRec *data; ! 379: { ! 380: register int i, j; ! 381: register int next = data->interval; ! 382: extern void bcopy(), exit(); ! 383: ! 384: if (data->mapped) ! 385: XClearWindow(data->dpy, data->window); ! 386: if (next >= data->width) { ! 387: j = data->width >> 1; ! 388: bcopy((char *)(data->valuedata + next - j), ! 389: (char *)(data->valuedata), j * sizeof(double)); ! 390: next = j; ! 391: /* Since we just lost some data, recompute the data->max_value. */ ! 392: data->max_value = 0.0; ! 393: for (i = 0; i < next; i++) { ! 394: if (data->valuedata[i] > data->max_value) ! 395: data->max_value = data->valuedata[i]; ! 396: } ! 397: } ! 398: ! 399: /* Compute the minimum scale required to graph the data, but don't go ! 400: lower than min_scale. */ ! 401: if (data->max_value > data->min_scale) ! 402: data->scale = ((int)data->max_value) + 1; ! 403: else ! 404: data->scale = data->min_scale; ! 405: ! 406: if (!data->mapped) return(next); ! 407: ! 408: /* Print hostname */ ! 409: XDrawString(data->dpy, data->window, data->myGC, 2, ! 410: 2 + data->fontstruct->ascent, data->text, strlen(data->text)); ! 411: ! 412: /* Draw graph reference lines */ ! 413: for (i = 1; i < data->scale; i++) { ! 414: j = (i * data->height) / data->scale; ! 415: XDrawLine(data->dpy, data->window, data->myGC, 0, j, ! 416: (int)data->width, j); ! 417: } ! 418: ! 419: /* Draw data point lines. */ ! 420: for (i = 0; i < next; i++) ! 421: XDrawLine(data->dpy, data->window, data->myGC , i, (int)data->height, ! 422: i, (int)(data->height-(data->valuedata[i] * data->height) ! 423: /data->scale)); ! 424: return(next); ! 425: } ! 426: ! 427: #define KMEM_FILE "/dev/kmem" ! 428: #define KMEM_ERROR "cannot open /dev/kmem" ! 429: ! 430: static struct nlist namelist[] = { /* namelist for vmunix grubbing */ ! 431: #define LOADAV 0 ! 432: {"_avenrun"}, ! 433: {0} ! 434: }; ! 435: ! 436: static double GetLoadPoint() ! 437: { ! 438: double loadavg; ! 439: static int init = 0; ! 440: static kmem; ! 441: static long loadavg_seek; ! 442: extern void nlist(); ! 443: ! 444: if(!init) { ! 445: nlist( "/vmunix", namelist); ! 446: if (namelist[LOADAV].n_type == 0){ ! 447: xload_error("xload: cannot get name list"); ! 448: exit(-1); ! 449: } ! 450: loadavg_seek = namelist[LOADAV].n_value; ! 451: kmem = open(KMEM_FILE, O_RDONLY); ! 452: if (kmem < 0) xload_error(KMEM_ERROR); ! 453: init = 1; ! 454: } ! 455: ! 456: ! 457: (void) lseek(kmem, loadavg_seek, 0); ! 458: #ifdef sun ! 459: { ! 460: long temp; ! 461: (void) read(kmem, (char *)&temp, sizeof(long)); ! 462: loadavg = (double)temp/FSCALE; ! 463: } ! 464: #else ! 465: (void) read(kmem, (char *)&loadavg, sizeof(double)); ! 466: #endif ! 467: return(loadavg); ! 468: } ! 469: ! 470: static xload_error(str) ! 471: char *str; ! 472: { ! 473: extern void exit(); ! 474: ! 475: (void) fprintf(stderr,"xload: %s\n",str); ! 476: exit(-1); ! 477: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.