Annotation of 43BSD/contrib/X/xload/xload.c, revision 1.1.1.1

1.1       root        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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.