1: #include <X/mit-copyright.h>
   2: 
   3: /* Copyright 1985, by the Massachusetts Institute of Technology */
   4: /* xload -- graph load average on X window system display.
   5:  * K. Shane Hartman and Stuart A. Malone with ripoffs from xclock.
   6:  * Host name feature added by Jim Gettys.
   7:  * Scale feature added by Bob Scheifler.
   8:  * Rescale feature added by Stuart A. Malone.
   9:  */
  10: #ifndef lint
  11: static char *rcsid_xload_c = "$Header: xload.c,v 10.9 86/02/01 16:00:54 tony Rel $";
  12: #endif  lint
  13: 
  14: #include <stdio.h>
  15: #include <strings.h>
  16: #include <nlist.h>
  17: #include <sys/time.h>
  18: #include <sys/file.h>
  19: #include <sys/param.h>
  20: #include <X/Xlib.h>
  21: 
  22: typedef enum _bool {FALSE, TRUE} Bool;
  23: 
  24: #define KMEM_FILE "/dev/kmem"
  25: #define KMEM_ERROR "cannot open /dev/kmem"
  26: 
  27: #define DEFAULT_BORDER_WIDTH 3
  28: #define DEFAULT_UPDATE 5            /* Any smaller leads to lossage */
  29: #define DEFAULT_FONT "6x10"
  30: #define DEFAULT_POSITION "=360x120-0+0"     /* upper right hand corner */
  31: #define DEFAULT_SCALE 1
  32: 
  33: struct nlist namelist[] = {         /* namelist for vmunix grubbing */
  34: #define LOADAV 0
  35:     {"_avenrun"},
  36:     {0}
  37: };
  38: 
  39: extern char *getenv();
  40: 
  41: /* GLOBAL */
  42: 
  43: Window win;                 /* load average window */
  44: double data[2048];              /* accumulated load average data */
  45: int background;                     /* color of background */
  46: int foreground;                     /* color of graph */
  47: int highlight;                  /* color of text, scale */
  48: Font font;                  /* font for printing hostname */
  49: char *fn = DEFAULT_FONT;            /* font for hostname */
  50: FontInfo font_info;
  51: char host[256];                             /* the host name */
  52: double scale = DEFAULT_SCALE;           /* n divisions for graph */
  53: double min_scale = DEFAULT_SCALE;       /* minimum value for scale */
  54: double max_loadavg = 0.0;           /* maximum loadavg on the graph */
  55: int mapped = 1;                 /* should really display? */
  56: 
  57: short gray_bits[16] = {
  58:     0xaaaa, 0x5555, 0xaaaa, 0x5555,
  59:     0xaaaa, 0x5555, 0xaaaa, 0x5555,
  60:     0xaaaa, 0x5555, 0xaaaa, 0x5555,
  61:     0xaaaa, 0x5555, 0xaaaa, 0x5555};
  62: 
  63: /* Diagnostic printer - Print message and exit */
  64: 
  65: void xload_error(message)
  66:     char *message;
  67: {
  68:     fprintf(stderr, "xload: %s\n", message);
  69:     perror("xload");
  70:     exit(1);
  71: }
  72: 
  73: /* Blts data according to current size, then redraws the load average window.
  74:  * Next represents the number of valid points in data.  Returns the (possibly)
  75:  * adjusted value of next.  If next is 0, this routine draws an empty window
  76:  * (scale - 1 lines for graph).  If next is less than the current window width,
  77:  * the returned value is identical to the initial value of next and data is
  78:  * unchanged.  Otherwise keeps half a window's worth of data.  If data is
  79:  * changed, then max_loadavg is updated to reflect the largest data point.
  80:  */
  81: 
  82: int repaint_window(width, height, next)
  83:     register int width, height, next;
  84: {
  85:     register int i, j;
  86: 
  87:     if (mapped)
  88:     XClear(win);
  89:     if (next >= width) {
  90:     j = width >> 1;
  91:     bcopy((char *)(data + next - j),(char *)data, j * sizeof(double));
  92:     next = j;
  93:     /* Since we just lost some data, recompute the max_loadavg. */
  94:     max_loadavg = 0.0;
  95:     for (i = 0; i < next; i++) {
  96:         if (data[i] > max_loadavg) max_loadavg = data[i];
  97:     }
  98:     }
  99: 
 100:     /* Compute the minimum scale required to graph the data, but don't go
 101:        lower than min_scale. */
 102:     if (max_loadavg > min_scale) scale = ((int)max_loadavg) + 1;
 103:     else scale = min_scale;
 104: 
 105:     if (!mapped) return(next);
 106: 
 107:     /* Print hostname */
 108:     XTextMask(win, 2, 2, host, strlen(host), font, highlight);
 109: 
 110:     /* Draw graph reference lines */
 111:     for (i = 1; i < scale; i++) {
 112:     j = (i * height) / scale;
 113:     XLine(win, 0, j, width, j, 1, 1, highlight, GXcopy, AllPlanes);
 114:     }
 115: 
 116:     /* Draw data point lines. */
 117:     for (i = 0; i < next; i++)
 118:         XLine(win, i, height, i, (int)(height - (data[i] * height) / scale),
 119:         1, 1, foreground, GXcopy, AllPlanes);
 120:     return(next);
 121: }
 122: 
 123: /* Exit with message describing command line format */
 124: 
 125: void usage()
 126: {
 127:     fprintf(stderr,
 128: "usage: xload [-fn {font}] [-update {seconds}] [-scale {integer}] [-rv]\n"
 129: );
 130:     fprintf(stderr,
 131: "             [=[{width}][x{height}][{+-}{xoff}[{+-}{yoff}]]] [[{host}]:[{vs}]]\n"
 132: );
 133:     fprintf(stderr,
 134: "             [-fg {color}] [-bg {color}] [-hl {color}] [-bd {color}] [-bw {pixels}]\n");
 135:     exit(1);
 136: }
 137: 
 138: /* Returns pointer to first char in search which is also in what, else NULL. */
 139: 
 140: char *strscan(search, what)
 141:     register char *search;
 142:     register char *what;
 143: {
 144:     register int i;
 145:     register len = strlen(what);
 146:     register char c;
 147:     while (c = *(search++))
 148:     for (i = 0; i < len; i++)
 149:         if (c == what[i]) return (--search);
 150:     return (NULL);
 151: }
 152: 
 153: 
 154: void main(argc, argv)
 155:     int argc;
 156:     char **argv;
 157: {
 158:     char *arg;
 159: 
 160:     register int i;
 161: 
 162:     register int kmem;                      /* kmem pointer */
 163:     register double loadavg;                /* load average value */
 164:     long loadavg_seek;                      /* offset to load average in kmem */
 165: 
 166:     char display[256];                      /* will contain vs host */
 167:     int vsnum;                              /* will contain vs number */
 168: 
 169:     int reverse = 0;
 170:     char *border_color;
 171:     char *fore_color;
 172:     char *back_color;
 173:     char *high_color;
 174:     int border_pixmap;
 175:     int border_width = DEFAULT_BORDER_WIDTH;
 176:     int update = DEFAULT_UPDATE;
 177:     Color cdef;
 178:     OpaqueFrame window;             /* frame for the window */
 179:     char *geometry = NULL;
 180:     char *def = DEFAULT_POSITION;       /* default position */
 181:     char *option;
 182: 
 183:     XEvent event;
 184: 
 185:     int maxfds;                             /* for select call */
 186:     int readfds;
 187:     int fdmask;
 188:     struct timeval timeout;                 /* will contain update interval */
 189: 
 190:     /* Get name list. Then open kmem so we can seek for load average. */
 191: 
 192:     nlist("/vmunix", namelist);
 193:     if (namelist[LOADAV].n_type == 0) xload_error("cannot get name list");
 194:     loadavg_seek = namelist[LOADAV].n_value;
 195:     kmem = open(KMEM_FILE, O_RDONLY);
 196:     if (kmem < 0) xload_error(KMEM_ERROR);
 197: 
 198:     gethostname(host, sizeof(host));        /* Who are we? */
 199:     display[0] = '\0';
 200: 
 201:     if ((option = XGetDefault(argv[0],"ReverseVideo")) != NULL )
 202:             if (strcmp (option, "on") == 0)
 203:             reverse = 1;
 204:     if ((option = XGetDefault(argv[0],"BorderWidth")) != NULL)
 205:         border_width = atoi(option);
 206:     if ((option = XGetDefault(argv[0],"BodyFont")) != NULL)
 207:     fn = option;
 208:     if ((border_color = XGetDefault(argv[0],"Border")) == NULL)
 209:     border_color = XGetDefault(argv[0],"BorderColor");
 210:     back_color = XGetDefault(argv[0],"Background");
 211:     fore_color = XGetDefault(argv[0],"Foreground");
 212:     high_color = XGetDefault(argv[0],"Highlight");
 213:     if ((option = XGetDefault(argv[0],"Update")) != NULL)
 214:     update = atoi(option);
 215:     if ((option = XGetDefault(argv[0],"Scale")) != NULL)
 216:     min_scale = atoi(option);
 217: 
 218:     for (i = 1; i < argc; i++) {                    /* Parse line */
 219:     if (argv[i][0] == '=') {
 220:         geometry = argv[i];
 221:         continue;
 222:     }
 223:     if (index(argv[i], ':') != NULL) {          /* host:display */
 224:         strncpy(display, argv[i], sizeof(display));
 225:         continue;
 226:     }
 227:     if (strcmp(argv[i], "-rv") == 0 ||
 228:         strcmp(argv[i], "-reverse") == 0) {     /* black on white */
 229:         reverse = 1;
 230:         continue;
 231:     }
 232:     if (strcmp(argv[i], "-fw") == 0 ||
 233:         strcmp(argv[i], "-forward") == 0) {     /* white on black */
 234:         reverse = 0;
 235:         continue;
 236:     }
 237:     if (strcmp(argv[i], "-bw") == 0 ||
 238:         strcmp(argv[i], "-border") == 0) {      /* border width */
 239:         if (++i >= argc) usage();
 240:         border_width = atoi(argv[i]);
 241:         continue;
 242:     }
 243:     if (strcmp(argv[i], "-fn") == 0 ||
 244:         strcmp(argv[i], "-font") == 0) {            /* host name font */
 245:         if (++i >= argc) usage();
 246:         fn = argv[i];
 247:         continue;
 248:     }
 249:     if (strcmp(argv[i], "-bd") == 0 ||
 250:         strcmp(argv[i], "-color") == 0) {          /* border color */
 251:        if (++i >= argc) usage();
 252:        border_color = argv[i];
 253:        continue;
 254:     }
 255:     if (strcmp(argv[i], "-fg") == 0 ||
 256:         strcmp(argv[i], "-foreground") == 0) {     /* foreground color */
 257:        if (++i >= argc) usage();
 258:        fore_color = argv[i];
 259:        continue;
 260:     }
 261:     if (strcmp(argv[i], "-bg") == 0 ||
 262:         strcmp(argv[i], "-background") == 0) {     /* background color */
 263:        if (++i >= argc) usage();
 264:        back_color = argv[i];
 265:        continue;
 266:     }
 267:     if (strcmp(argv[i], "-hl") == 0 ||
 268:         strcmp(argv[i], "-highlight") == 0) {     /* highlight color */
 269:        if (++i >= argc) usage();
 270:        high_color = argv[i];
 271:        continue;
 272:     }
 273:     if (strcmp(argv[i], "-u") == 0 ||
 274:         strcmp(argv[i], "-update") == 0) {      /* update interval */
 275:         if (++i >= argc) usage();
 276:         update = atoi(argv[i]);
 277:         continue;
 278:     }
 279:     if (strcmp(argv[i], "-s") == 0 ||
 280:         strcmp(argv[i], "-scale") == 0) {       /* load scale */
 281:         if (++i >= argc) usage();
 282:         min_scale = atoi(argv[i]);
 283:         continue;
 284:     }
 285:     usage();
 286:     }
 287: 
 288:     if (border_width < 0) border_width = DEFAULT_BORDER_WIDTH;
 289:     if (update < DEFAULT_UPDATE) update = DEFAULT_UPDATE;
 290:     if (min_scale <= 0) min_scale = DEFAULT_SCALE;
 291:     scale = min_scale;
 292: 
 293:     /* Open display  */
 294:     if (!XOpenDisplay(display))
 295:     xload_error("cannot open display");
 296: 
 297:     /* Need a font to print hostname in */
 298:     font = XGetFont(fn);
 299:     if (!font)
 300:     xload_error("cannot open font");
 301:     XQueryFont(font, &font_info);
 302: 
 303:     if (border_color && DisplayCells() > 2 &&
 304:     XParseColor(border_color, &cdef) && XGetHardwareColor(&cdef))
 305:     border_pixmap = XMakeTile(cdef.pixel);
 306:     else if (border_color && strcmp(border_color, "black") == 0)
 307:     border_pixmap = BlackPixmap;
 308:     else if (border_color && strcmp(border_color, "white") == 0)
 309:     border_pixmap = WhitePixmap;
 310:     else
 311:     border_pixmap = XMakePixmap ((Bitmap) XStoreBitmap (16, 16, gray_bits),
 312:                     BlackPixel, WhitePixel);
 313: 
 314:     if (back_color && DisplayCells() > 2 &&
 315:     XParseColor(back_color, &cdef) && XGetHardwareColor(&cdef)) {
 316:     background = cdef.pixel;
 317:     } else if (back_color && strcmp(back_color, "white") == 0) {
 318:     background = WhitePixel;
 319:     reverse = 0;
 320:     } else if (back_color && strcmp(back_color, "black") == 0) {
 321:     background = BlackPixel;
 322:     reverse = 0;
 323:     } else
 324:     background = BlackPixel;
 325: 
 326:     if (fore_color && DisplayCells() > 2 &&
 327:     XParseColor(fore_color, &cdef) && XGetHardwareColor(&cdef)) {
 328:     foreground = cdef.pixel;
 329:     } else if (fore_color && strcmp(fore_color, "black") == 0) {
 330:     foreground = BlackPixel;
 331:     reverse = 0;
 332:     } else if (fore_color && strcmp(fore_color, "white") == 0) {
 333:     foreground = WhitePixel;
 334:     reverse = 0;
 335:     } else
 336:     foreground = WhitePixel;
 337: 
 338:     if (high_color && DisplayCells() > 2 &&
 339:     XParseColor(high_color, &cdef) && XGetHardwareColor(&cdef))
 340:     highlight = cdef.pixel;
 341:     else if (reverse)
 342:     highlight = background;
 343:     else
 344:     highlight = foreground;
 345: 
 346:     if (reverse) {
 347:     background = foreground;
 348:     foreground = highlight;
 349:     }
 350: 
 351:     window.bdrwidth = border_width;
 352:     window.border = border_pixmap;
 353:     window.background = XMakeTile(background);
 354:     win = XCreate ("Load Average", argv[0], geometry, def, &window,
 355:            font_info.width * strlen(host) + 4, font_info.height + 4);
 356:     XSelectInput(win, ExposeWindow|UnmapWindow);
 357:     XMapWindow(win);                /* Map window to screen */
 358:     timeout.tv_sec = update;            /* Set up timeout for select */
 359:     timeout.tv_usec = 0;
 360:     maxfds = dpyno() + 1;           /* Set up select arguments */
 361:     fdmask = 1 << dpyno();
 362:     i = 0;                  /* Window is initially empty */
 363: 
 364:     while (1) {                 /* Main loop */
 365:     if (XPending()) {
 366:         XNextEvent(&event);
 367:         switch (event.type) {
 368:         case ExposeWindow:
 369:         mapped = 1;
 370:         window.width = ((XExposeEvent *) &event)->width;
 371:         window.height = ((XExposeEvent *) &event)->height;
 372:         i = repaint_window(window.width, window.height, i);
 373:         break;
 374:         case UnmapWindow:
 375:         mapped = 0;
 376:         break;
 377:         default:
 378:         xload_error("unexpected X event");
 379:         }
 380:     }
 381:     else if (i >= window.width) i = repaint_window(window.width, window.height, i);
 382:     /* Get the load average, stash the point and draw corresponding line. */
 383:     lseek(kmem, loadavg_seek, 0);
 384: #ifdef  sun
 385:     {
 386:         long temp;
 387:         read(kmem, (char *)&temp, sizeof(long));
 388:         loadavg = (double)temp/FSCALE;
 389:     }
 390: #else
 391:     read(kmem, (char *)&loadavg, sizeof(double));
 392: #endif
 393: 
 394:     /* Keep max_loadavg up to date, and if this data point is off the
 395: 	   graph, change the scale to make it fit. */
 396:     if (loadavg > max_loadavg) {
 397:         max_loadavg = loadavg;
 398:         if (max_loadavg > scale) {
 399:         scale = ((int)max_loadavg) + 1;
 400:         i = repaint_window(window.width, window.height, i);
 401:         }
 402:     }
 403: 
 404:     data[i] = loadavg;
 405:     if (mapped) {
 406:         XLine(win, i, window.height, i,
 407:             (int)(window.height - (window.height * loadavg) / scale),
 408:             1, 1, foreground, GXcopy, AllPlanes);
 409:         XFlush();               /* Flush output buffers */
 410:     }
 411:     i++;                    /* Next point */
 412:     readfds = fdmask;           /* Initialize select mask */
 413:                         /* and select on display fd */
 414:     if (select(maxfds, &readfds, NULL, NULL, &timeout) == -1)
 415:         xload_error("select error on display file descriptor");
 416:     } /* while */
 417: } /* main */

Defined functions

main defined in line 154; never used
repaint_window defined in line 82; used 3 times
strscan defined in line 140; never used
usage defined in line 125; used 9 times
xload_error defined in line 65; used 6 times

Defined variables

background defined in line 45; used 8 times
data defined in line 44; used 6 times
fn defined in line 49; used 3 times
font defined in line 48; used 4 times
font_info defined in line 50; used 3 times
foreground defined in line 46; used 9 times
gray_bits defined in line 57; used 1 times
highlight defined in line 47; used 6 times
host defined in line 51; used 5 times
mapped defined in line 55; used 5 times
max_loadavg defined in line 54; used 9 times
min_scale defined in line 53; used 7 times
namelist defined in line 33; used 3 times
rcsid_xload_c defined in line 11; never used
scale defined in line 52; used 9 times
win defined in line 43; used 8 times

Defined enum's

_bool defined in line 22; never used

Defined typedef's

Bool defined in line 22; never used

Defined macros

DEFAULT_BORDER_WIDTH defined in line 27; used 2 times
DEFAULT_FONT defined in line 29; used 1 times
  • in line 49
DEFAULT_POSITION defined in line 30; used 1 times
DEFAULT_SCALE defined in line 31; used 3 times
DEFAULT_UPDATE defined in line 28; used 3 times
KMEM_ERROR defined in line 25; used 1 times
KMEM_FILE defined in line 24; used 1 times
LOADAV defined in line 34; used 2 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1650
Valid CSS Valid XHTML 1.0 Strict