|
|
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.