2 Code based on wmppp/wmifs
6 This code was mainly put together by looking at the
10 A neat piece of equip, used to display the date
11 and time on the screen.
12 Comes with every AfterStep installation.
15 How do I create a not so solid window?
16 How do I open a window?
19 ------------------------------------------------------------
21 Authors: Martijn Pieterse (pieterse@xs4all.nl)
22 Antoine Nulle (warp@xs4all.nl)
24 This program is distributed under the GPL license.
25 (as were asclock and pppstats)
31 17/06/2012 (Rodolfo García Peñas (kix), <kix@kix.es>)
33 13/3/2012 (Barry Kelly (wbk), <coydog@devio.us>)
34 * Fixed get_statistics() I/O features to work with newer
35 /proc/diskstats instead of the old /proc/stat.
36 * Fixes to graph/meter scaling for I/O. Original code let
37 the scaling grow out of control due to inappropriate static
39 * Eliminated rounding down relatively low stats in getWidth()
40 and DrawStats_io() by using double and float types instead
41 of ints. We now round up tiny values to prevent the system
42 appearing idle when it's not.
43 * Style/readbility edits.
44 * TODO: Merge in Gentoo and possibly BSD local patches. This
45 should aid in fixing I/O monitoring on non-Linux systems.
46 * TODO: Color swapping. User supplies color values in .rc, and
47 app modifies pixmap in memory on startup. Should be simple.
48 * TODO: address compiler warnings (GCC has gotten pickier over
50 17/10/2009 (Romuald Delavergne, romuald.delavergne@free.fr)
51 * Support SMP processors in realtime CPU stress meter
52 15/05/2004 (Simon Law, sfllaw@debian.org)
53 * Support disabling of mode-cycling
54 23/10/2003 (Simon Law, sfllaw@debian.org)
55 * Eliminated exploitable static buffers
56 * Added -geometry support.
57 * /proc/meminfo support for Linux 2.6
58 18/05/1998 (Antoine Nulle, warp@xs4all.nl)
59 * MEM/SWAP/UPTIME only updated when visible
60 * Using global file descriptors to reduce file
61 system overhead, both updates are based on a diff
62 supplied by Dave Harden (dharden@wisewire.com)
63 15/05/1998 (Antoine Nulle, warp@xs4all.nl)
64 * Fixed memory overflow in the MEM gaugebar
65 * MEM gauge displays now real used mem
66 (buffered + cached mem removed)
67 14/05/1998 (Antoine Nulle, warp@xs4all.nl)
68 * Added -i & -s kludge for selecting startupmode,
69 tijno, don't hate me for this :)
70 12/05/1998 (Antoine Nulle, warp@xs4all.nl)
71 * Finetuned master-xpm, tijno don't worry, no
72 reprogramming needed this time ;-)
73 07/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
75 03/05/1998 (Antoine Nulle, warp@xs4all.nl)
76 * Added new master-xpm which contains the gfx
77 for the upcoming SysInfo part :P
78 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
79 * Removed a lot of code, that was put in wmgeneral
80 23/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
81 * Added zombie destroying code (aka wait :) )
82 18/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
83 * Added CPU-on-screen.
84 * Added -display command line
85 15/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
86 * Fixed a bug in the stats routine
87 (Top 3 bright pixels were not shown when 100% loaded)
88 * Changed xpm to a no-title one.
89 This included the reprogramming of all positions.
90 warpstah, i hate you! ;)
91 05/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
92 * First Working Version
103 #include <sys/wait.h>
106 #include <X11/Xlib.h>
108 #include <libdockapp/wmgeneral.h>
109 #include <libdockapp/misc.h>
111 #include "wmmon-master.xpm"
112 #include "wmmon-mask.xbm"
117 #define HISTORY_ENTRIES 55
118 #define HISTORY_ENTRIES 55
119 #define MAX_CPU (10) /* depends on graph height */
120 #define MAX_STAT_DEVICES (4)
122 /********************/
123 /* Global Variables */
124 /********************/
125 int stat_current
= 0; /* now global */
126 int mode_cycling
= 1; /* Allow mode-cycling */
127 int cpu_avg_max
= 0; /* CPU stress meter with average and max for SMP */
128 int show_buffers
= 0; /* wbk adding per Gentoo -b enhancement. */
133 FILE *fp_diskstats
; /* wbk new io stats API */
137 void printversion(void);
138 void DrawStats(int *, int, int, int, int);
139 void DrawStats_io(int *, int, int, int, int);
140 void wmmon_routine(int, char **);
142 int main(int argc
, char *argv
[])
145 char *name
= argv
[0];
147 /* Parse Command Line */
148 for (i
= 1; i
< argc
; i
++) {
154 if (strcmp(arg
+1, "display")) {
160 if (strcmp(arg
+1, "geometry")) {
188 wmmon_routine(argc
, argv
);
192 /*******************************************************************************\
194 \*******************************************************************************/
197 char name
[5]; /* "cpu0..cpuz", eventually.. :) */
198 int his
[HISTORY_ENTRIES
];
204 /* Processors stats */
211 stat_dev stat_device
[MAX_STAT_DEVICES
];
213 char *left_action
, *right_action
, *middle_action
;
217 unsigned long getWidth(long, long);
218 int checksysdevs(void);
219 void get_statistics(char *, long *, long *, long *, long *, long *);
220 void DrawActive(char *);
222 void update_stat_cpu(stat_dev
*, long *, long *);
223 void update_stat_io(stat_dev
*);
224 void update_stat_mem(stat_dev
*st
, stat_dev
*st2
);
225 void update_stat_swp(stat_dev
*);
227 void wmmon_routine(int argc
, char **argv
)
229 rckeys wmmon_keys
[] = {
230 { "left", &left_action
},
231 { "right", &right_action
},
232 { "middle", &middle_action
},
243 long starttime
, curtime
, nexttime
;
244 long istat
, idle
, *istat2
, *idle2
;
247 char *conffile
= NULL
;
249 int xpm_X
= 0, xpm_Y
= 0;
251 long online_time
= 0;
256 fp
= fopen("/proc/uptime", "r");
257 fp_meminfo
= fopen("/proc/meminfo", "r");
258 fp_loadavg
= fopen("/proc/loadavg", "r");
259 fp_stat
= fopen("/proc/stat", "r");
260 fp_diskstats
= fopen("/proc/diskstats", "r");
263 if (fscanf(fp
, "%ld", &online_time
) == EOF
)
264 perror("Error! fscanf() of /proc/uptime failed!\n");
269 for (i
= 0; i
< MAX_STAT_DEVICES
; i
++) {
270 for (j
= 0; j
< HISTORY_ENTRIES
; j
++)
271 stat_device
[i
].his
[j
] = 0;
273 stat_device
[i
].hisaddcnt
= 0;
276 /* wbk - I don't fully understand this. Probably just a means of providing
277 * test cases. ifdef'ing to clear compiler warnings. TODO: remove. */
280 left_action
= strdup(LEFT_ACTION
);
284 right_action
= strdup(RIGHT_ACTION
);
288 middle_action
= strdup(MIDDLE_ACTION
);
291 /* Scan through the .rc files */
292 if (asprintf(&conffile
, "/etc/wmmonrc") >= 0) {
293 parse_rcfile(conffile
, wmmon_keys
);
297 if (asprintf(&conffile
, "%s/.wmmonrc", getenv("HOME")) >= 0) {
298 parse_rcfile(conffile
, wmmon_keys
);
302 if (asprintf(&conffile
, "/etc/wmmonrc.fixed") >= 0) {
303 parse_rcfile(conffile
, wmmon_keys
);
307 stat_online
= checksysdevs();
310 stat_device
[0].cpu_stat
= calloc(nb_cpu
, sizeof(long));
311 stat_device
[0].cpu_last
= calloc(nb_cpu
, sizeof(long));
312 stat_device
[0].idle_stat
= calloc(nb_cpu
, sizeof(long));
313 stat_device
[0].idle_last
= calloc(nb_cpu
, sizeof(long));
314 if (!stat_device
[0].cpu_stat
||
315 !stat_device
[0].cpu_last
||
316 !stat_device
[0].idle_stat
||
317 !stat_device
[0].idle_last
) {
318 fprintf(stderr
, "%s: Unable to alloc memory !\n", argv
[0]);
322 istat2
= calloc(nb_cpu
, sizeof(long));
323 idle2
= calloc(nb_cpu
, sizeof(long));
324 if (!istat2
|| !idle2
) {
325 fprintf(stderr
, "%s: Unable to alloc memory !!\n", argv
[0]);
329 openXwindow(argc
, argv
, wmmon_master_xpm
, wmmon_mask_bits
,
330 wmmon_mask_width
, wmmon_mask_height
);
332 /* add mouse region */
333 AddMouseRegion(0, 12, 13, 58, 57);
334 AddMouseRegion(1, 5, 5, 24, 14);
337 nexttime
= starttime
+ 10;
339 /* Collect information on each panel */
340 for (i
= 0; i
< stat_online
; i
++) {
341 get_statistics(stat_device
[i
].name
, &k
, &istat
, &idle
, istat2
, idle2
);
342 stat_device
[i
].statlast
= istat
;
343 stat_device
[i
].idlelast
= idle
;
344 if (i
== 0 && nb_cpu
> 1) {
346 for (cpu
= 0; cpu
< nb_cpu
; cpu
++) {
347 stat_device
[i
].cpu_last
[cpu
] = istat2
[cpu
];
348 stat_device
[i
].idle_last
[cpu
] = idle2
[cpu
];
353 /* Set the mask for the current window */
354 switch (stat_current
) {
367 /* Draw statistics */
368 if (stat_current
== 0) {
369 DrawStats(stat_device
[stat_current
].his
,
370 HISTORY_ENTRIES
-1, 40, 5, 58);
371 } else if (stat_current
== 1) {
372 DrawStats_io(stat_device
[stat_current
].his
,
373 HISTORY_ENTRIES
, 40, 5, 58);
376 DrawActive(stat_device
[stat_current
].name
);
379 curtime
= time(NULL
);
381 waitpid(0, NULL
, WNOHANG
);
384 update_stat_cpu(&stat_device
[0], istat2
, idle2
);
385 update_stat_io(&stat_device
[1]);
387 if(stat_current
== 2)
388 update_stat_mem(&stat_device
[2], &stat_device
[3]);
390 if (stat_current
< 2) {
393 /* Load ding is 45 pixels hoog */
394 copyXPMArea(0, 64, 32, 12, 28, 4);
396 if (i
== 0 && nb_cpu
> 1) {
397 if (nb_cpu
> MAX_CPU
|| cpu_avg_max
) {
398 /* show average CPU */
399 j
= getWidth(stat_device
[i
].rt_stat
, stat_device
[i
].rt_idle
);
400 copyXPMArea(32, 64, j
, 6, 28, 4);
402 j
= getWidth(stat_device
[i
].cpu_stat
[cpu_max
],
403 stat_device
[i
].idle_stat
[cpu_max
]);
404 copyXPMArea(32, 70, j
, 6, 28, 10);
407 for (cpu
= 0; cpu
< nb_cpu
; cpu
++) {
408 j
= getWidth(stat_device
[i
].cpu_stat
[cpu
],
409 stat_device
[i
].idle_stat
[cpu
]);
410 copyXPMArea(32, 65, j
,
411 MAX_CPU
/ nb_cpu
, 28,
412 5 + (MAX_CPU
/ nb_cpu
) * cpu
);
416 j
= getWidth(stat_device
[i
].rt_stat
, stat_device
[i
].rt_idle
);
417 copyXPMArea(32, 64, j
, 12, 28, 4);
420 /* Nu zal ie wel 3 zijn. */
422 copyXPMArea(0, 64, 32, 12, 28+64, 4);
423 copyXPMArea(0, 64, 32, 12, 28+64, 18);
425 j
= stat_device
[2].rt_idle
;
427 j
= (stat_device
[2].rt_stat
* 100) / j
;
431 copyXPMArea(32, 64, j
, 12, 28+64, 4);
433 /*--------------------- swap? ------------------*/
434 j
= stat_device
[3].rt_idle
;
436 j
= (stat_device
[3].rt_stat
* 100) / j
;
440 copyXPMArea(32, 64, j
, 12, 28+64, 18);
442 /*----------- online tijd neerzetten! ----------*/
443 cnt_time
= time(0) - ref_time
+ online_time
;
445 /* cnt_time = uptime in seconden */
450 digits = 40,78, 6breed, 9hoog
454 copyXPMArea(40 + (i
% 10)*7, 78, 6, 9, 115, 47);
455 copyXPMArea(40 + (i
/ 10)*7, 78, 6, 9, 108, 47);
459 copyXPMArea(40 + (i
% 10)*7, 78, 6, 9, 96, 47);
460 copyXPMArea(40 + (i
/ 10)*7, 78, 6, 9, 89, 47);
464 copyXPMArea(40 + (i
% 10)*7, 78, 6, 9, 77, 47);
465 copyXPMArea(40 + (i
/ 10)*7, 78, 6, 9, 70, 47);
467 /* De rest is dagen! 5x7*/
469 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 88, 35);
471 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 82, 35);
473 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 76, 35);
475 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 70, 35);
478 if (curtime
>= nexttime
) {
481 if (curtime
> nexttime
) /* dont let APM suspends make this crazy */
484 for (i
=0; i
<stat_online
; i
++) {
485 stat_dev
*sd
= stat_device
+ i
;
487 if (sd
->his
[HISTORY_ENTRIES
-1])
488 sd
->his
[HISTORY_ENTRIES
-1] /= sd
->hisaddcnt
;
490 for (j
= 1; j
< HISTORY_ENTRIES
; j
++)
491 sd
->his
[j
-1] = sd
->his
[j
];
493 if (i
== stat_current
) {
495 DrawStats(sd
->his
, HISTORY_ENTRIES
- 1, 40, 5, 58);
497 DrawStats_io(sd
->his
, HISTORY_ENTRIES
- 1, 40, 5, 58);
499 sd
->his
[HISTORY_ENTRIES
-1] = 0;
504 RedrawWindowXY(xpm_X
, xpm_Y
);
506 while (XPending(display
)) {
507 XNextEvent(display
, &Event
);
508 switch (Event
.type
) {
510 RedrawWindowXY(xpm_X
, xpm_Y
);
513 XCloseDisplay(display
);
517 but_stat
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
520 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
521 if (but_stat
== i
&& but_stat
>= 0) {
524 switch (Event
.xbutton
.button
) {
527 execCommand(left_action
);
531 execCommand(middle_action
);
535 execCommand(right_action
);
542 if (stat_current
== stat_online
)
545 DrawActive(stat_device
[stat_current
].name
);
546 if (stat_current
== 0)
547 DrawStats(stat_device
[stat_current
].his
,
548 HISTORY_ENTRIES
-1, 40, 5, 58);
550 if (stat_current
== 1)
551 DrawStats_io(stat_device
[stat_current
].his
,
552 HISTORY_ENTRIES
-1, 40, 5, 58);
554 if (stat_current
== 2) {
561 RedrawWindowXY(xpm_X
, xpm_Y
);
574 void update_stat_cpu(stat_dev
*st
, long *istat2
, long *idle2
)
578 get_statistics(st
->name
, &k
, &istat
, &idle
, istat2
, idle2
);
580 st
->rt_idle
= idle
- st
->idlelast
;
583 st
->rt_stat
= istat
- st
->statlast
;
584 st
->statlast
= istat
;
588 unsigned long max
, j
;
589 cpu_max
= 0; max
= 0;
590 for (cpu
= 0; cpu
< nb_cpu
; cpu
++) {
591 st
->idle_stat
[cpu
] = idle2
[cpu
] - st
->idle_last
[cpu
];
592 st
->idle_last
[cpu
] = idle2
[cpu
];
594 st
->cpu_stat
[cpu
] = istat2
[cpu
] - st
->cpu_last
[cpu
];
595 st
->cpu_last
[cpu
] = istat2
[cpu
];
597 j
= st
->cpu_stat
[cpu
] + st
->idle_stat
[cpu
];
600 j
= (st
->cpu_stat
[cpu
] << 7) / j
;
609 st
->his
[HISTORY_ENTRIES
-1] += k
;
614 void update_stat_io(stat_dev
*st
)
616 long j
, k
, istat
, idle
;
618 /* Periodically re-sample. Sometimes we get anomalously high readings;
619 * this discards them. */
620 static int stalemax
= 300;
621 static long maxdiskio
= 0;
622 if (--stalemax
<= 0) {
627 get_statistics(st
->name
, &k
, &istat
, &idle
, NULL
, NULL
);
629 st
->rt_idle
= idle
- st
->idlelast
;
632 st
->rt_stat
= istat
- st
->statlast
;
633 st
->statlast
= istat
;
635 /* remember peak for scaling of upper-right meter. */
640 /* Calculate scaling factor for upper-right meter. "/ 5" will clip
641 * the highest peaks, but makes moderate values more visible. We are
642 * compensating for wild fluctuations which are probably caused by
643 * kernel I/O buffering.
645 st
->rt_idle
= (maxdiskio
- j
) / 5;
646 if (j
> 0 && st
->rt_idle
< 1)
647 st
->rt_idle
= 1; /* scale up tiny values so they are visible */
649 st
->his
[HISTORY_ENTRIES
-1] += st
->rt_stat
;
654 void update_stat_mem(stat_dev
*st
, stat_dev
*st2
)
656 static char *line
= NULL
;
657 static size_t line_size
= 0;
659 unsigned long swapfree
;
660 unsigned long free
, shared
, buffers
, cached
;
662 if (freopen("/proc/meminfo", "r", fp_meminfo
) == NULL
)
663 perror("freopen() of /proc/meminfo failed!)\n");
665 while ((getline(&line
, &line_size
, fp_meminfo
)) > 0) {
666 /* The original format for the first two lines of /proc/meminfo was
667 * Mem: total used free shared buffers cached
668 * Swap: total used free
670 * As of at least 2.5.47 these two lines were removed, so that the
671 * required information has to come from the rest of the lines.
672 * On top of that, used is no longer recorded - you have to work
673 * this out yourself, from total - free.
675 * So, these changes below should work. They should also work with
676 * older kernels, too, since the new format has been available for
679 if (strstr(line
, "MemTotal:"))
680 sscanf(line
, "MemTotal: %ld", &st
->rt_idle
);
681 else if (strstr(line
, "MemFree:"))
682 sscanf(line
, "MemFree: %ld", &free
);
683 else if (strstr(line
, "MemShared:"))
684 sscanf(line
, "MemShared: %ld", &shared
);
685 else if (strstr(line
, "Buffers:"))
686 sscanf(line
, "Buffers: %ld", &buffers
);
687 else if (strstr(line
, "Cached:"))
688 sscanf(line
, "Cached: %ld", &cached
);
689 else if (strstr(line
, "SwapTotal:"))
690 sscanf(line
, "SwapTotal: %ld", &st2
->rt_idle
);
691 else if (strstr(line
, "SwapFree:"))
692 sscanf(line
, "SwapFree: %ld", &swapfree
);
695 /* memory use - rt_stat is the amount used, it seems, and this isn't
696 * recorded in current version of /proc/meminfo (as of 2.5.47), so we
697 * calculate it from MemTotal - MemFree
699 st
->rt_stat
= st
->rt_idle
- free
;
701 /* wbk -b flag (from Gentoo patchkit) */
703 st
->rt_stat
-= buffers
+cached
;
704 /* As with the amount of memory used, it's not recorded any more, so
705 * we have to calculate it ourselves.
707 st2
->rt_stat
= st2
->rt_idle
- swapfree
;
710 void update_stat_swp(stat_dev
*st
)
712 static char *line
= NULL
;
713 static size_t line_size
= 0;
714 unsigned long swapfree
;
716 fseek(fp_meminfo
, 0, SEEK_SET
);
717 while ((getline(&line
, &line_size
, fp_meminfo
)) > 0) {
718 /* As with update_stat_mem(), the format change to /proc/meminfo has
719 * forced some changes here. */
720 if (strstr(line
, "SwapTotal:"))
721 sscanf(line
, "SwapTotal: %ld", &st
->rt_idle
);
722 else if (strstr(line
, "SwapFree:"))
723 sscanf(line
, "SwapFree: %ld", &swapfree
);
725 st
->rt_stat
= st
->rt_idle
- swapfree
;
728 /*******************************************************************************\
730 \*******************************************************************************/
731 void get_statistics(char *devname
, long *is
, long *ds
, long *idle
, long *ds2
, long *idle2
)
734 static char *line
= NULL
;
735 static size_t line_size
= 0;
737 char *tokens
= " \t\n";
744 if (!strncmp(devname
, "cpu", 3)) {
745 fseek(fp_stat
, 0, SEEK_SET
);
746 while ((getline(&line
, &line_size
, fp_stat
)) > 0) {
747 if (strstr(line
, "cpu")) {
748 int cpu
= -1; /* by default, cumul stats => average */
749 if (!strstr(line
, "cpu ")) {
750 sscanf(line
, "cpu%d", &cpu
);
754 p
= strtok(line
, tokens
);
755 /* 1..3, 4 == idle, we don't want idle! */
756 for (i
=0; i
<3; i
++) {
757 p
= strtok(NULL
, tokens
);
763 p
= strtok(NULL
, tokens
);
767 idle2
[cpu
] = atol(p
);
770 if ((fp_loadavg
= freopen("/proc/loadavg", "r", fp_loadavg
)) == NULL
)
771 perror("ger_statistics(): freopen(proc/loadavg) failed!\n");
773 if (fscanf(fp_loadavg
, "%f", &f
) == EOF
)
774 perror("fscanf() failed to read f\n");
775 *is
= (long) (100 * f
);
778 if (!strncmp(devname
, "i/o", 3)) {
779 if (fseek(fp_diskstats
, 0, SEEK_SET
) == -1)
780 perror("get_statistics() seek failed\n");
782 /* wbk 20120308 These are no longer in /proc/stat. /proc/diskstats
783 * seems to be the closest replacement. Under modern BSD's, /proc is
784 * now deprecated, so iostat() might be the answer.
785 * http://www.gossamer-threads.com/lists/linux/kernel/314618
786 * has good info on this being removed from kernel. Also see
787 * kernel sources Documentation/iostats.txt
789 * TODO: We will end up with doubled values. We are adding the
790 * aggregate to the individual partition, due to device selection
791 * logic. Either grab devices' stats with numbers, or without (sda
792 * OR sda[1..10]. Could use strstr() return plus offset, but would
793 * have to be careful with bounds checking since we're in a
794 * limited buffer. Or just divide by 2 (inefficient). Shouldn't
795 * matter for graphing (we care about proportions, not numbers). */
796 while ((getline(&line
, &line_size
, fp_diskstats
)) > 0) {
797 if (strstr(line
, "sd") || strstr(line
, "sr")) {
798 p
= strtok(line
, tokens
);
799 /* skip 3 tokens, then use fields from
800 `* linux/Documentation/iostats.txt */
801 for (i
= 1; i
<= 6; i
++)
802 p
= strtok(NULL
, tokens
);
805 for (i
= 7; i
<= 10; i
++)
806 p
= strtok(NULL
, tokens
);
815 /*******************************************************************************\
817 \*******************************************************************************/
818 unsigned long getWidth(long actif
, long idle
)
820 /* wbk - work with a decimal value so we don't round < 1 down to zero. */
826 j
= (actif
* 100) / j
;
830 /* round up very low positive values so they are visible. */
831 if (actif
> 0 && j
< 2)
837 r
= (unsigned long) j
;
842 /*******************************************************************************\
844 \*******************************************************************************/
847 static char *line
= NULL
;
848 static size_t line_size
= 0;
851 fseek(fp_stat
, 0, SEEK_SET
);
852 while ((getline(&line
, &line_size
, fp_stat
)) > 0) {
853 if (strstr(line
, "cpu") && !strstr(line
, "cpu "))
854 sscanf(line
, "cpu%d", &cpu
);
861 /*******************************************************************************\
863 \*******************************************************************************/
864 int checksysdevs(void) {
865 strcpy(stat_device
[0].name
, "cpu0");
866 strcpy(stat_device
[1].name
, "i/o");
867 strcpy(stat_device
[2].name
, "sys");
873 /*******************************************************************************\
874 |* void DrawActive(char *) *|
875 \*******************************************************************************/
876 void DrawActive(char *name
)
888 copyXPMArea(0, 77, 19, 10, 5, 5);
889 else if (name
[0] == 'i')
890 copyXPMArea(19, 77, 19, 10, 5, 5);
894 /*******************************************************************************\
896 \*******************************************************************************/
897 void DrawStats(int *his
, int num
, int size
, int x_left
, int y_bottom
)
899 int pixels_per_byte
, j
, k
, *p
, d
;
901 pixels_per_byte
= 100;
904 for (j
=0; j
<num
; j
++) {
905 if (p
[0] > pixels_per_byte
)
906 pixels_per_byte
+= 100;
912 for (k
=0; k
<num
; k
++) {
913 d
= (1.0 * p
[0] / pixels_per_byte
) * size
;
915 for (j
=0; j
<size
; j
++) {
917 copyXPMArea(2, 88, 1, 1, k
+x_left
, y_bottom
-j
);
919 copyXPMArea(2, 89, 1, 1, k
+x_left
, y_bottom
-j
);
921 copyXPMArea(2, 90, 1, 1, k
+x_left
, y_bottom
-j
);
926 /* Nu horizontaal op 100/200/300 etc lijntje trekken! */
927 for (j
= pixels_per_byte
-100; j
> 0; j
-=100) {
928 for (k
=0; k
<num
; k
++) {
929 d
= (40.0 / pixels_per_byte
) * j
;
931 copyXPMArea(2, 91, 1, 1, k
+x_left
, y_bottom
-d
);
937 /*******************************************************************************\
939 \*******************************************************************************/
940 void DrawStats_io(int *his
, int num
, int size
, int x_left
, int y_bottom
)
942 float pixels_per_byte
;
944 /* wbk - Use a double to avoid rounding values of d < 1 to zero. */
948 /* wbk - this should not be static. No need to track the scale, since
949 * we always calculate it on the fly anyway. This static variable did
950 * not get re-initialized when we entered this function, so the scale
951 * would always grow and never shrink.
953 /*static int global_io_scale = 1;*/
957 for (j
=0; j
<num
; j
++)
958 if (p
[j
] > io_scale
) io_scale
= p
[j
];
960 pixels_per_byte
= 1.0 * io_scale
/ size
;
961 if (pixels_per_byte
== 0)
964 for (k
=0; k
<num
; k
++) {
965 d
= (1.0 * p
[0] / pixels_per_byte
);
967 /* graph values too low for graph resolution */
968 if (d
> 0 && d
< 1) {
975 for (j
=0; j
<size
; j
++) {
977 copyXPMArea(2, 88, 1, 1, k
+x_left
, y_bottom
-j
);
979 copyXPMArea(2, 89, 1, 1, k
+x_left
, y_bottom
-j
);
981 copyXPMArea(2, 90, 1, 1, k
+x_left
, y_bottom
-j
);
983 p
+= 1; /* beware... */
988 /*******************************************************************************\
990 \*******************************************************************************/
991 void usage(char *name
)
993 printf("Usage: %s [OPTION]...\n", name
);
994 printf("WindowMaker dockapp that displays system information.\n");
996 printf(" -display DISPLAY contact the DISPLAY X server\n");
997 printf(" -geometry GEOMETRY position the clock at GEOMETRY\n");
998 printf(" -l locked view - cannot cycle modes\n");
999 printf(" -c show average and max CPU for SMP machine.\n");
1000 printf(" default if there is more than %d processors\n", MAX_CPU
);
1001 printf(" -i start in Disk I/O mode\n");
1002 printf(" -s start in System Info mode\n");
1003 printf(" -b include buffers and cache in memory usage\n");
1004 printf(" -h display this help and exit\n");
1005 printf(" -v output version information and exit\n");
1009 /*******************************************************************************\
1011 \*******************************************************************************/
1012 void printversion(void)
1014 printf("WMMon version %s\n", PACKAGE_VERSION
);
1016 /* vim: sw=4 ts=4 columns=82