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/03/2014 (Pedro Gimeno Fortea)
32 * Fix jiffy counter overflowing long on 32-bit systems.
33 17/06/2012 (Rodolfo García Peñas (kix), <kix@kix.es>)
35 13/3/2012 (Barry Kelly (wbk), <coydog@devio.us>)
36 * Fixed get_statistics() I/O features to work with newer
37 /proc/diskstats instead of the old /proc/stat.
38 * Fixes to graph/meter scaling for I/O. Original code let
39 the scaling grow out of control due to inappropriate static
41 * Eliminated rounding down relatively low stats in getWidth()
42 and DrawStats_io() by using double and float types instead
43 of ints. We now round up tiny values to prevent the system
44 appearing idle when it's not.
45 * Style/readbility edits.
46 * TODO: Merge in Gentoo and possibly BSD local patches. This
47 should aid in fixing I/O monitoring on non-Linux systems.
48 * TODO: Color swapping. User supplies color values in .rc, and
49 app modifies pixmap in memory on startup. Should be simple.
50 * TODO: address compiler warnings (GCC has gotten pickier over
52 17/10/2009 (Romuald Delavergne, romuald.delavergne@free.fr)
53 * Support SMP processors in realtime CPU stress meter
54 15/05/2004 (Simon Law, sfllaw@debian.org)
55 * Support disabling of mode-cycling
56 23/10/2003 (Simon Law, sfllaw@debian.org)
57 * Eliminated exploitable static buffers
58 * Added -geometry support.
59 * /proc/meminfo support for Linux 2.6
60 18/05/1998 (Antoine Nulle, warp@xs4all.nl)
61 * MEM/SWAP/UPTIME only updated when visible
62 * Using global file descriptors to reduce file
63 system overhead, both updates are based on a diff
64 supplied by Dave Harden (dharden@wisewire.com)
65 15/05/1998 (Antoine Nulle, warp@xs4all.nl)
66 * Fixed memory overflow in the MEM gaugebar
67 * MEM gauge displays now real used mem
68 (buffered + cached mem removed)
69 14/05/1998 (Antoine Nulle, warp@xs4all.nl)
70 * Added -i & -s kludge for selecting startupmode,
71 tijno, don't hate me for this :)
72 12/05/1998 (Antoine Nulle, warp@xs4all.nl)
73 * Finetuned master-xpm, tijno don't worry, no
74 reprogramming needed this time ;-)
75 07/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
77 03/05/1998 (Antoine Nulle, warp@xs4all.nl)
78 * Added new master-xpm which contains the gfx
79 for the upcoming SysInfo part :P
80 02/05/1998 (Martijn Pieterse, pieterse@xs4all.nl)
81 * Removed a lot of code, that was put in wmgeneral
82 23/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
83 * Added zombie destroying code (aka wait :) )
84 18/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
85 * Added CPU-on-screen.
86 * Added -display command line
87 15/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
88 * Fixed a bug in the stats routine
89 (Top 3 bright pixels were not shown when 100% loaded)
90 * Changed xpm to a no-title one.
91 This included the reprogramming of all positions.
92 warpstah, i hate you! ;)
93 05/04/1998 (Martijn Pieterse, pieterse@xs4all.nl)
94 * First Working Version
105 #include <sys/wait.h>
108 #include <X11/Xlib.h>
110 #include <libdockapp/wmgeneral.h>
111 #include <libdockapp/misc.h>
114 #include "wmmon-master.xpm"
115 #include "wmmon-mask.xbm"
120 #define HISTORY_ENTRIES 55
121 #define MAX_CPU (10) /* depends on graph height */
122 #define MAX_STAT_DEVICES (4)
124 /********************/
125 /* Global Variables */
126 /********************/
127 int stat_current
= 0; /* now global */
128 int mode_cycling
= 1; /* Allow mode-cycling */
129 int cpu_avg_max
= 0; /* CPU stress meter with average and max for SMP */
130 int show_buffers
= 0; /* wbk adding per Gentoo -b enhancement. */
135 FILE *fp_diskstats
; /* wbk new io stats API */
139 void printversion(void);
140 void DrawStats(int *, int, int, int, int);
141 void DrawStats_io(int *, int, int, int, int);
142 void wmmon_routine(int, char **);
144 int main(int argc
, char *argv
[])
147 char *name
= argv
[0];
149 /* Parse Command Line */
150 for (i
= 1; i
< argc
; i
++) {
156 if (strcmp(arg
+1, "display")) {
162 if (strcmp(arg
+1, "geometry")) {
190 wmmon_routine(argc
, argv
);
194 /*******************************************************************************\
196 \*******************************************************************************/
199 char name
[5]; /* "cpu0..cpuz", eventually.. :) */
200 int his
[HISTORY_ENTRIES
];
206 /* Processors stats */
213 stat_dev stat_device
[MAX_STAT_DEVICES
];
215 char *left_action
, *right_action
, *middle_action
;
219 unsigned long getWidth(long, long);
220 int checksysdevs(void);
221 void get_statistics(char *, long *, ullong
*, ullong
*, ullong
*, ullong
*);
222 void DrawActive(char *);
224 void update_stat_cpu(stat_dev
*, ullong
*, ullong
*);
225 void update_stat_io(stat_dev
*);
226 void update_stat_mem(stat_dev
*st
, stat_dev
*st2
);
227 void update_stat_swp(stat_dev
*);
229 void wmmon_routine(int argc
, char **argv
)
231 rckeys wmmon_keys
[] = {
232 { "left", &left_action
},
233 { "right", &right_action
},
234 { "middle", &middle_action
},
245 long starttime
, curtime
, nexttime
;
246 ullong istat
, idle
, *istat2
, *idle2
;
249 char *conffile
= NULL
;
251 int xpm_X
= 0, xpm_Y
= 0;
253 long online_time
= 0;
258 fp
= fopen("/proc/uptime", "r");
259 fp_meminfo
= fopen("/proc/meminfo", "r");
260 fp_loadavg
= fopen("/proc/loadavg", "r");
261 fp_stat
= fopen("/proc/stat", "r");
262 fp_diskstats
= fopen("/proc/diskstats", "r");
265 if (fscanf(fp
, "%ld", &online_time
) == EOF
)
266 perror("Error! fscanf() of /proc/uptime failed!\n");
271 for (i
= 0; i
< MAX_STAT_DEVICES
; i
++) {
272 for (j
= 0; j
< HISTORY_ENTRIES
; j
++)
273 stat_device
[i
].his
[j
] = 0;
275 stat_device
[i
].hisaddcnt
= 0;
278 /* wbk - I don't fully understand this. Probably just a means of providing
279 * test cases. ifdef'ing to clear compiler warnings. TODO: remove. */
282 left_action
= strdup(LEFT_ACTION
);
286 right_action
= strdup(RIGHT_ACTION
);
290 middle_action
= strdup(MIDDLE_ACTION
);
293 /* Scan through the .rc files */
294 if (asprintf(&conffile
, "/etc/wmmonrc") >= 0) {
295 parse_rcfile(conffile
, wmmon_keys
);
299 if (asprintf(&conffile
, "%s/.wmmonrc", getenv("HOME")) >= 0) {
300 parse_rcfile(conffile
, wmmon_keys
);
304 if (asprintf(&conffile
, "/etc/wmmonrc.fixed") >= 0) {
305 parse_rcfile(conffile
, wmmon_keys
);
309 stat_online
= checksysdevs();
312 stat_device
[0].cpu_stat
= calloc(nb_cpu
, sizeof(long));
313 stat_device
[0].cpu_last
= calloc(nb_cpu
, sizeof(ullong
));
314 stat_device
[0].idle_stat
= calloc(nb_cpu
, sizeof(long));
315 stat_device
[0].idle_last
= calloc(nb_cpu
, sizeof(ullong
));
316 if (!stat_device
[0].cpu_stat
||
317 !stat_device
[0].cpu_last
||
318 !stat_device
[0].idle_stat
||
319 !stat_device
[0].idle_last
) {
320 fprintf(stderr
, "%s: Unable to alloc memory !\n", argv
[0]);
324 istat2
= calloc(nb_cpu
, sizeof(ullong
));
325 idle2
= calloc(nb_cpu
, sizeof(ullong
));
326 if (!istat2
|| !idle2
) {
327 fprintf(stderr
, "%s: Unable to alloc memory !!\n", argv
[0]);
331 openXwindow(argc
, argv
, wmmon_master_xpm
, (char *)wmmon_mask_bits
,
332 wmmon_mask_width
, wmmon_mask_height
);
334 /* add mouse region */
335 AddMouseRegion(0, 12, 13, 58, 57);
336 AddMouseRegion(1, 5, 5, 24, 14);
339 nexttime
= starttime
+ 10;
341 /* Collect information on each panel */
342 for (i
= 0; i
< stat_online
; i
++) {
343 get_statistics(stat_device
[i
].name
, &k
, &istat
, &idle
, istat2
, idle2
);
344 stat_device
[i
].statlast
= istat
;
345 stat_device
[i
].idlelast
= idle
;
346 if (i
== 0 && nb_cpu
> 1) {
348 for (cpu
= 0; cpu
< nb_cpu
; cpu
++) {
349 stat_device
[i
].cpu_last
[cpu
] = istat2
[cpu
];
350 stat_device
[i
].idle_last
[cpu
] = idle2
[cpu
];
355 /* Set the mask for the current window */
356 switch (stat_current
) {
369 /* Draw statistics */
370 if (stat_current
== 0) {
371 DrawStats(stat_device
[stat_current
].his
,
372 HISTORY_ENTRIES
-1, 40, 5, 58);
373 } else if (stat_current
== 1) {
374 DrawStats_io(stat_device
[stat_current
].his
,
375 HISTORY_ENTRIES
, 40, 5, 58);
378 DrawActive(stat_device
[stat_current
].name
);
381 curtime
= time(NULL
);
383 waitpid(0, NULL
, WNOHANG
);
386 update_stat_cpu(&stat_device
[0], istat2
, idle2
);
387 update_stat_io(&stat_device
[1]);
389 if(stat_current
== 2)
390 update_stat_mem(&stat_device
[2], &stat_device
[3]);
392 if (stat_current
< 2) {
395 /* Load ding is 45 pixels hoog */
396 copyXPMArea(0, 64, 32, 12, 28, 4);
398 if (i
== 0 && nb_cpu
> 1) {
399 if (nb_cpu
> MAX_CPU
|| cpu_avg_max
) {
400 /* show average CPU */
401 j
= getWidth(stat_device
[i
].rt_stat
, stat_device
[i
].rt_idle
);
402 copyXPMArea(32, 64, j
, 6, 28, 4);
404 j
= getWidth(stat_device
[i
].cpu_stat
[cpu_max
],
405 stat_device
[i
].idle_stat
[cpu_max
]);
406 copyXPMArea(32, 70, j
, 6, 28, 10);
409 for (cpu
= 0; cpu
< nb_cpu
; cpu
++) {
410 j
= getWidth(stat_device
[i
].cpu_stat
[cpu
],
411 stat_device
[i
].idle_stat
[cpu
]);
412 copyXPMArea(32, 65, j
,
413 MAX_CPU
/ nb_cpu
, 28,
414 5 + (MAX_CPU
/ nb_cpu
) * cpu
);
418 j
= getWidth(stat_device
[i
].rt_stat
, stat_device
[i
].rt_idle
);
419 copyXPMArea(32, 64, j
, 12, 28, 4);
422 /* Nu zal ie wel 3 zijn. */
424 copyXPMArea(0, 64, 32, 12, 28+64, 4);
425 copyXPMArea(0, 64, 32, 12, 28+64, 18);
427 j
= stat_device
[2].rt_idle
;
429 j
= (stat_device
[2].rt_stat
* 100) / j
;
433 copyXPMArea(32, 64, j
, 12, 28+64, 4);
435 /*--------------------- swap? ------------------*/
436 j
= stat_device
[3].rt_idle
;
438 j
= (stat_device
[3].rt_stat
* 100) / j
;
442 copyXPMArea(32, 64, j
, 12, 28+64, 18);
444 /*----------- online tijd neerzetten! ----------*/
445 cnt_time
= time(0) - ref_time
+ online_time
;
447 /* cnt_time = uptime in seconden */
452 digits = 40,78, 6breed, 9hoog
456 copyXPMArea(40 + (i
% 10)*7, 78, 6, 9, 115, 47);
457 copyXPMArea(40 + (i
/ 10)*7, 78, 6, 9, 108, 47);
461 copyXPMArea(40 + (i
% 10)*7, 78, 6, 9, 96, 47);
462 copyXPMArea(40 + (i
/ 10)*7, 78, 6, 9, 89, 47);
466 copyXPMArea(40 + (i
% 10)*7, 78, 6, 9, 77, 47);
467 copyXPMArea(40 + (i
/ 10)*7, 78, 6, 9, 70, 47);
469 /* De rest is dagen! 5x7*/
471 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 88, 35);
473 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 82, 35);
475 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 76, 35);
477 copyXPMArea(66 + (i
% 10)*6, 66, 5, 7, 70, 35);
480 if (curtime
>= nexttime
) {
483 if (curtime
> nexttime
) /* dont let APM suspends make this crazy */
486 for (i
=0; i
<stat_online
; i
++) {
487 stat_dev
*sd
= stat_device
+ i
;
489 if (sd
->his
[HISTORY_ENTRIES
-1])
490 sd
->his
[HISTORY_ENTRIES
-1] /= sd
->hisaddcnt
;
492 for (j
= 1; j
< HISTORY_ENTRIES
; j
++)
493 sd
->his
[j
-1] = sd
->his
[j
];
495 if (i
== stat_current
) {
497 DrawStats(sd
->his
, HISTORY_ENTRIES
- 1, 40, 5, 58);
499 DrawStats_io(sd
->his
, HISTORY_ENTRIES
- 1, 40, 5, 58);
501 sd
->his
[HISTORY_ENTRIES
-1] = 0;
506 RedrawWindowXY(xpm_X
, xpm_Y
);
508 while (XPending(display
)) {
509 XNextEvent(display
, &Event
);
510 switch (Event
.type
) {
512 RedrawWindowXY(xpm_X
, xpm_Y
);
515 XCloseDisplay(display
);
519 but_stat
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
522 i
= CheckMouseRegion(Event
.xbutton
.x
, Event
.xbutton
.y
);
523 if (but_stat
== i
&& but_stat
>= 0) {
526 switch (Event
.xbutton
.button
) {
529 execCommand(left_action
);
533 execCommand(middle_action
);
537 execCommand(right_action
);
544 if (stat_current
== stat_online
)
547 DrawActive(stat_device
[stat_current
].name
);
548 if (stat_current
== 0)
549 DrawStats(stat_device
[stat_current
].his
,
550 HISTORY_ENTRIES
-1, 40, 5, 58);
552 if (stat_current
== 1)
553 DrawStats_io(stat_device
[stat_current
].his
,
554 HISTORY_ENTRIES
-1, 40, 5, 58);
556 if (stat_current
== 2) {
563 RedrawWindowXY(xpm_X
, xpm_Y
);
576 void update_stat_cpu(stat_dev
*st
, ullong
*istat2
, ullong
*idle2
)
581 get_statistics(st
->name
, &k
, &istat
, &idle
, istat2
, idle2
);
583 st
->rt_idle
= ullsub(&idle
, &st
->idlelast
);
586 st
->rt_stat
= ullsub(&istat
, &st
->statlast
);
587 st
->statlast
= istat
;
591 unsigned long max
, j
;
592 cpu_max
= 0; max
= 0;
593 for (cpu
= 0; cpu
< nb_cpu
; cpu
++) {
594 st
->idle_stat
[cpu
] = ullsub(&idle2
[cpu
], &st
->idle_last
[cpu
]);
595 st
->idle_last
[cpu
] = idle2
[cpu
];
597 st
->cpu_stat
[cpu
] = ullsub(&istat2
[cpu
], &st
->cpu_last
[cpu
]);
598 st
->cpu_last
[cpu
] = istat2
[cpu
];
600 j
= st
->cpu_stat
[cpu
] + st
->idle_stat
[cpu
];
603 j
= (st
->cpu_stat
[cpu
] << 7) / j
;
612 st
->his
[HISTORY_ENTRIES
-1] += k
;
617 void update_stat_io(stat_dev
*st
)
622 /* Periodically re-sample. Sometimes we get anomalously high readings;
623 * this discards them. */
624 static int stalemax
= 300;
625 static long maxdiskio
= 0;
626 if (--stalemax
<= 0) {
631 get_statistics(st
->name
, &k
, &istat
, &idle
, NULL
, NULL
);
633 st
->rt_idle
= ullsub(&idle
, &st
->idlelast
);
636 st
->rt_stat
= ullsub(&istat
, &st
->statlast
);
637 st
->statlast
= istat
;
639 /* remember peak for scaling of upper-right meter. */
644 /* Calculate scaling factor for upper-right meter. "/ 5" will clip
645 * the highest peaks, but makes moderate values more visible. We are
646 * compensating for wild fluctuations which are probably caused by
647 * kernel I/O buffering.
649 st
->rt_idle
= (maxdiskio
- j
) / 5;
650 if (j
> 0 && st
->rt_idle
< 1)
651 st
->rt_idle
= 1; /* scale up tiny values so they are visible */
653 st
->his
[HISTORY_ENTRIES
-1] += st
->rt_stat
;
658 void update_stat_mem(stat_dev
*st
, stat_dev
*st2
)
660 static char *line
= NULL
;
661 static size_t line_size
= 0;
663 unsigned long swapfree
;
664 unsigned long free
, shared
, buffers
, cached
;
666 if (freopen("/proc/meminfo", "r", fp_meminfo
) == NULL
)
667 perror("freopen() of /proc/meminfo failed!)\n");
669 while ((getline(&line
, &line_size
, fp_meminfo
)) > 0) {
670 /* The original format for the first two lines of /proc/meminfo was
671 * Mem: total used free shared buffers cached
672 * Swap: total used free
674 * As of at least 2.5.47 these two lines were removed, so that the
675 * required information has to come from the rest of the lines.
676 * On top of that, used is no longer recorded - you have to work
677 * this out yourself, from total - free.
679 * So, these changes below should work. They should also work with
680 * older kernels, too, since the new format has been available for
683 if (strstr(line
, "MemTotal:"))
684 sscanf(line
, "MemTotal: %ld", &st
->rt_idle
);
685 else if (strstr(line
, "MemFree:"))
686 sscanf(line
, "MemFree: %lu", &free
);
687 else if (strstr(line
, "MemShared:"))
688 sscanf(line
, "MemShared: %lu", &shared
);
689 else if (strstr(line
, "Buffers:"))
690 sscanf(line
, "Buffers: %lu", &buffers
);
691 else if (strstr(line
, "Cached:"))
692 sscanf(line
, "Cached: %lu", &cached
);
693 else if (strstr(line
, "SwapTotal:"))
694 sscanf(line
, "SwapTotal: %ld", &st2
->rt_idle
);
695 else if (strstr(line
, "SwapFree:"))
696 sscanf(line
, "SwapFree: %lu", &swapfree
);
699 /* memory use - rt_stat is the amount used, it seems, and this isn't
700 * recorded in current version of /proc/meminfo (as of 2.5.47), so we
701 * calculate it from MemTotal - MemFree
703 st
->rt_stat
= st
->rt_idle
- free
;
705 /* wbk -b flag (from Gentoo patchkit) */
707 st
->rt_stat
-= buffers
+cached
;
708 /* As with the amount of memory used, it's not recorded any more, so
709 * we have to calculate it ourselves.
711 st2
->rt_stat
= st2
->rt_idle
- swapfree
;
714 void update_stat_swp(stat_dev
*st
)
716 static char *line
= NULL
;
717 static size_t line_size
= 0;
718 unsigned long swapfree
;
720 fseek(fp_meminfo
, 0, SEEK_SET
);
721 while ((getline(&line
, &line_size
, fp_meminfo
)) > 0) {
722 /* As with update_stat_mem(), the format change to /proc/meminfo has
723 * forced some changes here. */
724 if (strstr(line
, "SwapTotal:"))
725 sscanf(line
, "SwapTotal: %ld", &st
->rt_idle
);
726 else if (strstr(line
, "SwapFree:"))
727 sscanf(line
, "SwapFree: %lu", &swapfree
);
729 st
->rt_stat
= st
->rt_idle
- swapfree
;
732 /*******************************************************************************\
734 \*******************************************************************************/
735 void get_statistics(char *devname
, long *is
, ullong
*ds
, ullong
*idle
, ullong
*ds2
, ullong
*idle2
)
738 static char *line
= NULL
;
739 static size_t line_size
= 0;
741 char *tokens
= " \t\n";
749 if (!strncmp(devname
, "cpu", 3)) {
750 fseek(fp_stat
, 0, SEEK_SET
);
751 while ((getline(&line
, &line_size
, fp_stat
)) > 0) {
752 if (strstr(line
, "cpu")) {
753 int cpu
= -1; /* by default, cumul stats => average */
754 if (!strstr(line
, "cpu ")) {
755 sscanf(line
, "cpu%d", &cpu
);
757 ullreset(&idle2
[cpu
]);
759 p
= strtok(line
, tokens
);
760 /* 1..3, 4 == idle, we don't want idle! */
761 for (i
=0; i
<3; i
++) {
762 p
= strtok(NULL
, tokens
);
763 ullparse(&ulltmp
, p
);
767 ulladd(&ds2
[cpu
], &ulltmp
);
769 p
= strtok(NULL
, tokens
);
773 ullparse(&idle2
[cpu
], p
);
776 if ((fp_loadavg
= freopen("/proc/loadavg", "r", fp_loadavg
)) == NULL
)
777 perror("ger_statistics(): freopen(proc/loadavg) failed!\n");
779 if (fscanf(fp_loadavg
, "%f", &f
) == EOF
)
780 perror("fscanf() failed to read f\n");
781 *is
= (long) (100 * f
);
784 if (!strncmp(devname
, "i/o", 3)) {
785 if (fseek(fp_diskstats
, 0, SEEK_SET
) == -1)
786 perror("get_statistics() seek failed\n");
788 /* wbk 20120308 These are no longer in /proc/stat. /proc/diskstats
789 * seems to be the closest replacement. Under modern BSD's, /proc is
790 * now deprecated, so iostat() might be the answer.
791 * http://www.gossamer-threads.com/lists/linux/kernel/314618
792 * has good info on this being removed from kernel. Also see
793 * kernel sources Documentation/iostats.txt
795 * TODO: We will end up with doubled values. We are adding the
796 * aggregate to the individual partition, due to device selection
797 * logic. Either grab devices' stats with numbers, or without (sda
798 * OR sda[1..10]. Could use strstr() return plus offset, but would
799 * have to be careful with bounds checking since we're in a
800 * limited buffer. Or just divide by 2 (inefficient). Shouldn't
801 * matter for graphing (we care about proportions, not numbers). */
802 while ((getline(&line
, &line_size
, fp_diskstats
)) > 0) {
803 if (strstr(line
, "sd") || strstr(line
, "sr")) {
804 p
= strtok(line
, tokens
);
805 /* skip 3 tokens, then use fields from
806 `* linux/Documentation/iostats.txt */
807 for (i
= 1; i
<= 6; i
++)
808 p
= strtok(NULL
, tokens
);
810 ullparse(&ulltmp
, p
);
812 for (i
= 7; i
<= 10; i
++)
813 p
= strtok(NULL
, tokens
);
815 ullparse(&ulltmp
, p
);
823 /*******************************************************************************\
825 \*******************************************************************************/
826 unsigned long getWidth(long actif
, long idle
)
828 /* wbk - work with a decimal value so we don't round < 1 down to zero. */
834 j
= (actif
* 100) / j
;
838 /* round up very low positive values so they are visible. */
839 if (actif
> 0 && j
< 2)
845 r
= (unsigned long) j
;
850 /*******************************************************************************\
852 \*******************************************************************************/
855 static char *line
= NULL
;
856 static size_t line_size
= 0;
859 fseek(fp_stat
, 0, SEEK_SET
);
860 while ((getline(&line
, &line_size
, fp_stat
)) > 0) {
861 if (strstr(line
, "cpu") && !strstr(line
, "cpu "))
862 sscanf(line
, "cpu%d", &cpu
);
869 /*******************************************************************************\
871 \*******************************************************************************/
872 int checksysdevs(void) {
873 strcpy(stat_device
[0].name
, "cpu0");
874 strcpy(stat_device
[1].name
, "i/o");
875 strcpy(stat_device
[2].name
, "sys");
881 /*******************************************************************************\
882 |* void DrawActive(char *) *|
883 \*******************************************************************************/
884 void DrawActive(char *name
)
896 copyXPMArea(0, 77, 19, 10, 5, 5);
897 else if (name
[0] == 'i')
898 copyXPMArea(19, 77, 19, 10, 5, 5);
902 /*******************************************************************************\
904 \*******************************************************************************/
905 void DrawStats(int *his
, int num
, int size
, int x_left
, int y_bottom
)
907 int pixels_per_byte
, j
, k
, *p
, d
, hint_height
, hint_color
;
909 pixels_per_byte
= 100;
912 for (j
=0; j
<num
; j
++) {
913 while (p
[0] > pixels_per_byte
)
914 pixels_per_byte
+= 100;
920 for (k
=0; k
<num
; k
++) {
921 d
= (1.0 * p
[0] / pixels_per_byte
) * size
;
923 for (j
=0; j
<size
; j
++) {
925 copyXPMArea(2, 88, 1, 1, k
+x_left
, y_bottom
-j
);
927 copyXPMArea(2, 89, 1, 1, k
+x_left
, y_bottom
-j
);
929 copyXPMArea(2, 90, 1, 1, k
+x_left
, y_bottom
-j
);
934 /* Nu horizontaal op 100/200/300 etc lijntje trekken! */
935 if (pixels_per_byte
> 10000) {
937 hint_color
= 93; /* red */
938 } else if (pixels_per_byte
> 1000) {
940 hint_color
= 92; /* yellow */
943 hint_color
= 91; /* green */
946 for (j
= hint_height
; j
< pixels_per_byte
; j
+= hint_height
) {
947 d
= (40.0 / pixels_per_byte
) * j
- 1;
948 for (k
=0; k
<num
; k
++) {
949 copyXPMArea(2, hint_color
, 1, 1, k
+x_left
, y_bottom
-d
);
955 /*******************************************************************************\
957 \*******************************************************************************/
958 void DrawStats_io(int *his
, int num
, int size
, int x_left
, int y_bottom
)
960 float pixels_per_byte
;
962 /* wbk - Use a double to avoid rounding values of d < 1 to zero. */
966 /* wbk - this should not be static. No need to track the scale, since
967 * we always calculate it on the fly anyway. This static variable did
968 * not get re-initialized when we entered this function, so the scale
969 * would always grow and never shrink.
971 /*static int global_io_scale = 1;*/
975 for (j
=0; j
<num
; j
++)
976 if (p
[j
] > io_scale
) io_scale
= p
[j
];
978 pixels_per_byte
= 1.0 * io_scale
/ size
;
979 if (pixels_per_byte
== 0)
982 for (k
=0; k
<num
; k
++) {
983 d
= (1.0 * p
[0] / pixels_per_byte
);
985 /* graph values too low for graph resolution */
986 if (d
> 0 && d
< 1) {
993 for (j
=0; j
<size
; j
++) {
995 copyXPMArea(2, 88, 1, 1, k
+x_left
, y_bottom
-j
);
997 copyXPMArea(2, 89, 1, 1, k
+x_left
, y_bottom
-j
);
999 copyXPMArea(2, 90, 1, 1, k
+x_left
, y_bottom
-j
);
1001 p
+= 1; /* beware... */
1006 /*******************************************************************************\
1008 \*******************************************************************************/
1009 void usage(char *name
)
1011 printf("Usage: %s [OPTION]...\n", name
);
1012 printf("WindowMaker dockapp that displays system information.\n");
1014 printf(" -display DISPLAY contact the DISPLAY X server\n");
1015 printf(" -geometry GEOMETRY position the clock at GEOMETRY\n");
1016 printf(" -l locked view - cannot cycle modes\n");
1017 printf(" -c show average and max CPU for SMP machine.\n");
1018 printf(" default if there is more than %d processors\n", MAX_CPU
);
1019 printf(" -i start in Disk I/O mode\n");
1020 printf(" -s start in System Info mode\n");
1021 printf(" -b include buffers and cache in memory usage\n");
1022 printf(" -h display this help and exit\n");
1023 printf(" -v output version information and exit\n");
1027 /*******************************************************************************\
1029 \*******************************************************************************/
1030 void printversion(void)
1032 printf("WMMon version %s\n", PACKAGE_VERSION
);
1034 /* vim: sw=4 ts=4 columns=82