2
wmsysmon -- system monitoring dockapp
4
Copyright (C) 1998-1999 Dave Clark - clarkd@skynet.ca
5
Copyright (C) 2000 Vito Caputo - swivel@gnugeneration.com
7
wmsysmon is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
wmsysmon is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33
#include <sys/param.h>
34
#include <sys/types.h>
35
#include <sys/ioctl.h>
39
#include <X11/extensions/shape.h>
42
#include "wmgeneral.h"
45
#include "wmsysmon-master-alpha.xpm"
47
#include "wmsysmon-master-i386.xpm"
50
#define WMSYSMON_VERSION "0.7.7"
56
#define BCHAR_HEIGHT 9
72
/* meter definitions */
77
#define INT_METERS (2)
79
char wmsysmon_mask_bits[64*64];
80
int wmsysmon_mask_width = 64;
81
int wmsysmon_mask_height = 64;
84
long start_uptime = 0;
86
int Mem_l; /* line in /proc/meminfo "Mem:" is on */
87
int Swap_l; /* line in /proc/meminfo "Swap:" is on */
88
int intr_l; /* line in /proc/stat "intr" is on */
89
int rio_l; /* line in /proc/stat "disk_rio" is on */
90
int wio_l; /* line in /proc/stat "disk_wio" is on */
91
int page_l; /* line in /proc/stat "page" is on */
92
int swap_l; /* line in /proc/stat "swap" is on */
110
long int_mode = INT_METERS;
113
long last_pageouts=0;
116
long last_swapouts=0;
122
int update_rate = 50;
131
void printversion(void);
132
void BlitString(char *name, int x, int y);
133
void BlitNum(int num, int x, int y);
134
void wmsysmon_routine(int, char **);
135
void DrawBar(int sx, int sy, int w, int h, float percent, int dx, int dy);
136
void DrawLite(int state, int dx, int dy);
137
void DrawUptime(void);
138
void DrawStuff( void );
139
void DrawMem( void );
140
void DrawMeter(unsigned int, unsigned int, int, int);
142
int main(int argc, char *argv[]) {
145
/* set meter x,y pairs */
155
last_ints = _last_ints;
158
/* Parse Command Line */
161
if (strlen(ProgName) >= 5)
162
ProgName += (strlen(ProgName) - 5);
164
for (i = 1; i < argc; i++) {
170
if (strcmp(arg + 1, "display")) {
176
if (strcmp(arg+1, "geometry")) {
186
if (argc > (i + 1)) {
187
update_rate = (atoi(argv[i + 1]));
192
int_mode = INT_LITES;
203
wmsysmon_routine(argc, argv);
210
void wmsysmon_routine(int argc, char **argv)
219
createXBMfromXPM(wmsysmon_mask_bits, wmsysmon_master_xpm, wmsysmon_mask_width, wmsysmon_mask_height);
221
xfd = openXwindow(argc, argv, wmsysmon_master_xpm, wmsysmon_mask_bits, wmsysmon_mask_width, wmsysmon_mask_height);
225
pfd.events = (POLLIN);
228
bzero(&_last_ints, sizeof(_last_ints));
229
bzero(&_ints, sizeof(_ints));
230
bzero(&int_peaks, sizeof(int_peaks));
234
fp = fopen("/proc/uptime", "r");
236
fscanf(fp, "%ld", &start_time);
238
start_uptime = time(NULL);
241
statfp = fopen("/proc/stat", "r");
242
memfp = fopen("/proc/meminfo", "r");
244
/* here we find tags in /proc/stat & /proc/meminfo and note their
245
* lines, for faster lookup throughout execution.
248
for(i = 0; fgets(buf, 1024, memfp); i++) {
249
if(strstr(buf, "Mem:")) Mem_l = i;
250
else if(strstr(buf, "Swap:")) Swap_l = i;
254
for(i = 0; fgets(buf, 1024, statfp); i++) {
255
if(strstr(buf, "disk_wio")) wio_l = i;
256
else if(strstr(buf, "disk_rio")) rio_l = i;
257
else if(strstr(buf, "page")) page_l = i;
258
else if(strstr(buf, "swap")) swap_l = i;
259
else if(strstr(buf, "intr")) intr_l = i;
272
poll(&pfd, 1, update_rate);
273
while (XPending(display)) {
274
XNextEvent(display, &Event);
275
switch (Event.type) {
277
DirtyWindow(Event.xexpose.x,
280
Event.xexpose.height);
283
XCloseDisplay(display);
289
printf("got: %i\n", Event.type);
294
/* usleep(update_rate); */
299
void DrawMeter(unsigned int level, unsigned int peak, int dx, int dy)
301
static unsigned int a;
303
/* meters are on a per interruptscale, dictated by the peak, maintain
304
* this peak outside of here, you can use a fixed peak for all ints but
305
* since we're using only 4 lines for our level, the timer interrupt
306
* usually kills the peak for the others so they never move. */
309
a = level * 3 / peak;
313
printf("level: %u peak: %u selection: %u\n", level, peak, a);
319
copyXPMArea(meter[a][0],
329
void DrawBar(int sx, int sy, int w, int h, float percent, int dx, int dy)
333
tx = (float)((float)w * ((float)percent / (float)100.0));
335
copyXPMArea(sx, sy, tx, h, dx, dy);
337
copyXPMArea(sx, sy + h + 1, w - tx, h, dx + tx, dy);
342
void DrawLite(int state, int dx, int dy)
347
copyXPMArea(BREDX, BREDY, LITEW, LITEH, dx, dy);
350
copyXPMArea(BGREENX, BGREENY, LITEW, LITEH, dx, dy);
354
copyXPMArea(BOFFX, BOFFY, LITEW, LITEH, dx, dy);
361
void DrawUptime(void)
363
static int first = 1;
364
static int old_days = 0, old_hours = 0, old_minutes = 0;
369
uptime = curtime - start_uptime + start_time;
375
if(old_minutes != i || first) {
377
sprintf(buf, "%02i", i);
379
BlitString(buf, 45, 29);
381
BlitString(buf, 45, 37);
389
if(old_hours != i || first) {
391
sprintf(buf, "%02i", i);
393
BlitString(buf, 29, 29);
395
BlitString(buf, 29, 37);
403
if(old_days != i || first) {
405
sprintf(buf, "%03i", i);
407
BlitString(buf, 6, 29);
409
BlitString(buf, 6, 37);
417
void DrawStuff( void )
419
static int io_last = 0, first = 1;
421
static int int_lites[24] =
422
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
423
/* to keep track of on/off status */
425
static int int_lites[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
427
static int pagein_lite = 0, pageout_lite = 0, swapin_lite = 0, swapout_lite = 0;
429
static char seps[] = {" "};
434
static int iopercent;
437
static long pageouts;
439
static long swapouts;
444
stage = io = iodiff = iopercent = pageins = pageouts = swapins = swapouts = 0;
446
statfp = freopen("/proc/stat", "r", statfp);
449
for(i = 0, ents = 0; ents < 5 && fgets(buf, 1024, statfp); i++) {
451
tok = strtok(buf, seps);
454
tok = strtok(NULL, seps);
457
tok = strtok(NULL, seps);
460
tok = strtok(NULL, seps);
463
tok = strtok(NULL, seps);
465
} else if(i == wio_l) {
466
tok = strtok(buf, seps);
469
tok = strtok(NULL, seps);
472
tok = strtok(NULL, seps);
475
tok = strtok(NULL, seps);
478
tok = strtok(NULL, seps);
480
} else if(i == page_l) {
481
sscanf(buf, "%*s %ld %ld", &pageins, &pageouts);
483
} else if(i == swap_l) {
484
sscanf(buf, "%*s %ld %ld",
485
&swapins, &swapouts);
487
} else if(i == intr_l) {
490
"%*s %*d %ld %ld %ld %ld %ld"
491
"%ld %ld %ld %ld %ld %ld %ld"
492
"%ld %ld %ld %ld %ld %ld %ld"
493
"%ld %ld %ld %ld %ld",
494
&ints[0], &ints[1], &ints[2],
495
&ints[3], &ints[4], &ints[5],
496
&ints[6], &ints[7], &ints[8],
497
&ints[9], &ints[10], &ints[11],
498
&ints[12], &ints[13], &ints[14],
499
&ints[15], &ints[16], &ints[17],
500
&ints[18], &ints[19], &ints[20],
501
&ints[21], &ints[22], &ints[23]);
503
"%*s %*d %ld %ld %ld %ld %ld"
504
"%ld %ld %ld %ld %ld %ld %ld"
506
&ints[0], &ints[1], &ints[2],
507
&ints[3], &ints[4], &ints[5],
508
&ints[6], &ints[7], &ints[8],
509
&ints[9], &ints[10], &ints[11],
510
&ints[12], &ints[13], &ints[14],
518
/* ------------------ IO bar ------------------ */
519
if(io_max == 0) io_max = io;
521
if(io > io_max) iodiff = abs(io_max - io);
527
if(io_max_diff !=0) iopercent = ((float) iodiff / (float) io_max_diff) * 100.0;
530
if(iodiff > io_max_diff) io_max_diff = iodiff;
532
if (iopercent > 100) iopercent = 100;
535
if(iopercent != io_last || first) {
538
DrawBar(67, 36, 58, 4, iopercent, 3, 20);
540
DrawBar(67, 36, 58, 6, iopercent, 3, 26);
545
if(int_mode == INT_LITES) {
547
for (i = 0; i < 8; i++) {
548
if ( ints[i] > last_ints[i] && !int_lites[i]) {
551
DrawLite(B_GREEN, 4 + (i * LITEW) + i, 43);
553
DrawLite(B_GREEN, 4 + (i * LITEW) + i, 51);
555
} else if(ints[i] == last_ints[i] && int_lites[i]) {
558
DrawLite(B_OFF, 4 + (i * LITEW) + i, 43);
560
DrawLite(B_OFF, 4 + (i * LITEW) + i, 51);
564
/* middle/bottom 8 */
565
for (i = 8; i < 16; i++) {
566
if ( ints[i] > last_ints[i] && !int_lites[i]) {
569
DrawLite(B_GREEN, 4 + ((i - 8) *LITEW) + (i - 8), 48);
571
DrawLite(B_GREEN, 4 + ((i - 8) *LITEW) + (i - 8), 56);
573
} else if(ints[i] == last_ints[i] && int_lites[i]) {
576
DrawLite(B_OFF, 4 + ((i - 8) * LITEW) + (i - 8), 48);
578
DrawLite(B_OFF, 4 + ((i - 8) * LITEW) + (i - 8), 56);
584
/* bottom 8 on alpha/smp x86 */
585
for (i = 16; i < 24; i++) {
586
if (ints[i] > last_ints[i] && !int_lites[i] ) {
588
DrawLite(B_GREEN, 4 + ((i - 16) * LITEW) + (i - 16), 53);
589
} else if(ints[i] == last_ints[i] && int_lites[i]) {
591
DrawLite(B_OFF, 4 + ((i -16) * LITEW) + (i - 16), 53);
595
} else if(int_mode == INT_METERS) {
596
for (i = 0; i < 8; i++) {
598
intdiff = ints[i] - last_ints[i];
599
int_peaks[i] = (int_peaks[i] + intdiff) >> 1;
603
VBAR_H + (i * VBAR_W) + i,
608
VBAR_H + (i * VBAR_W) + i,
614
for (i = 8; i < 16; i++) {
616
intdiff = ints[i] - last_ints[i];
617
int_peaks[i] = (int_peaks[i] + intdiff) >> 1;
621
VBAR_H + ((i - 8) * VBAR_W) + (i - 8),
626
VBAR_H + ((i - 8) * VBAR_W) + (i - 8),
633
for (i = 16; i < 24; i++) {
635
intdiff = ints[i] - last_ints[i];
636
int_peaks[i] = (int_peaks[i] + intdiff) >> 1;
640
VBAR_H + ((i - 16) * VBAR_W) + (i - 16),
653
if (pageins > last_pageins && !pagein_lite) {
656
DrawLite(B_RED, 51, 43);
658
DrawLite(B_RED, 51, 51);
660
} else if(pagein_lite) {
663
DrawLite(B_OFF, 51, 43);
665
DrawLite(B_OFF, 51, 51);
669
if (pageouts > last_pageouts && !pageout_lite) {
672
DrawLite(B_RED, 56, 43);
674
DrawLite(B_RED, 56, 51);
676
} else if(pageout_lite) {
679
DrawLite(B_OFF, 56, 43);
681
DrawLite(B_OFF, 56, 51);
685
last_pageins = pageins;
686
last_pageouts = pageouts;
690
if(swapins > last_swapins && !swapin_lite) {
693
DrawLite(B_RED, 51, 48);
695
DrawLite(B_RED, 51, 56);
697
} else if(swapin_lite) {
700
DrawLite(B_OFF, 51, 48);
702
DrawLite(B_OFF, 51, 56);
706
if (swapouts > last_swapouts && !swapout_lite) {
709
DrawLite(B_RED, 56, 48);
711
DrawLite(B_RED, 56, 56);
713
} else if(swapout_lite) {
716
DrawLite(B_OFF, 56, 48);
718
DrawLite(B_OFF, 56, 56);
722
last_swapins = swapins;
723
last_swapouts = swapouts;
732
static int last_mem = 0, last_swap = 0, first = 1;
733
static long mem_total = 0;
734
static long mem_used = 0;
735
static long mem_buffers = 0;
736
static long mem_cache = 0;
737
static long swap_total = 0;
738
static long swap_used = 0;
739
static long swap_free = 0;
741
static int mempercent = 0;
742
static int swappercent = 0;
748
if(counter >= 0) return; /* polling /proc/meminfo is EXPENSIVE */
749
counter = 3000000 / update_rate;
751
memfp = freopen("/proc/meminfo", "r", memfp);
753
for(i = 0, ents = 0; ents < 2 && fgets(buf, 1024, memfp); i++) {
755
sscanf(buf, "%*s %ld %ld %*d %*d %ld %ld",
761
} else if(i == Swap_l) {
762
sscanf(buf, "%*s %ld %ld %ld",
770
/* could speed this up but we'd lose precision, look more into it to see
771
* if precision change would be noticable, and if speed diff is significant
773
mempercent = ((float)(mem_used - mem_buffers - mem_cache)
775
(float)mem_total) * 100;
777
swappercent = ((float)(swap_used)
779
(float)swap_total) * 100;
781
if(mempercent != last_mem || first) {
782
last_mem = mempercent;
784
DrawBar(67, 36, 58,4 , mempercent, 3, 4);
786
DrawBar(67, 36, 58, 6, mempercent, 3, 4);
790
if(swappercent != last_swap || first) {
791
last_swap = swappercent;
793
DrawBar(67, 36, 58, 4, swappercent, 3, 12);
795
DrawBar(67, 36, 58, 6, swappercent, 3, 15);
804
/* Blits a string at given co-ordinates */
805
void BlitString(char *name, int x, int y)
810
for (i=0; name[i]; i++) {
812
c = toupper(name[i]);
813
if (c >= 'A' && c <= 'Z') {
815
copyXPMArea(c * 6, 74, 6, 8, k, y);
819
copyXPMArea(c * 6, 64, 6, 8, k, y);
827
void BlitNum(int num, int x, int y)
834
sprintf(buf, "%03i", num);
836
BlitString(buf, newx, y);
843
fprintf(stderr, "\nwmsysmon - http://www.gnugeneration.com\n");
844
fprintf(stderr, "\n-------------------\n"
845
"|[---------------]| <--- Memory Use %%\n"
846
"|[---------------]| <--- Swap Use %%\n"
847
"|[---------------]| <--- I/O %%\n"
849
"| 000:00:00 | <--- Uptime days:hours:minutes\n"
852
"| 01234567 UV | <--- 0-N are hardware interrupts 0-23\n"
853
"| 89ABCDEF WX | <--- U,V are Page IN/OUT, W,X are Swap IN/OUT\n"
856
"| 01234567 WX | <--- 0-F are hardware interrupts 0-15\n"
857
"| 89ABCDEF YZ | <--- W,X are Page IN/OUT, W,X are Swap IN/OUT\n"
859
"-------------------\n");
861
fprintf(stderr, "usage:\n");
862
fprintf(stderr, "\t-display <display name>\n");
863
fprintf(stderr, "\t-geometry +XPOS+YPOS\tinitial window position\n");
864
fprintf(stderr, "\t-r\t\t\tupdate rate in milliseconds (default:300)\n");
865
fprintf(stderr, "\t-l\t\t\tblinky lights for interrupts vs. meters(default)\n");
866
fprintf(stderr, "\t-h\t\t\tthis help screen\n");
867
fprintf(stderr, "\t-v\t\t\tprint the version number\n");
868
fprintf(stderr, "\n");
872
void printversion(void)
874
fprintf(stderr, "wmsysmon v%s\n", WMSYSMON_VERSION);