3 * Cputnik - a simple cpu and memory monitor
5 * Copyright (C) 2002-2005 pasp and sill
7 * This program 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 * This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 FILE *fp_stat
, *fp_loadavg
, *fp_memory
;
27 int cmd_lmb
, cmd_rmb
, update_period
;
28 int show_memory
, free_memory
;
29 char command_lmb
[PATH_MAX
], command_rmb
[PATH_MAX
], *ProgName
;
32 /*----------------------------------------------------------------------*/
34 void get_mem_statistics(int *free
)
36 long long int m_total
, m_free
, m_cached
;
37 char temp
[BUFFER_SIZE
];
39 fp_memory
= freopen("/proc/meminfo", "r", fp_memory
);
41 while(fscanf(fp_memory
, "%s", temp
)!=EOF
) {
43 if(!strncmp(temp
,"MemTotal:", 9))
44 fscanf(fp_memory
, "%Ld", &m_total
);
46 if(!strncmp(temp
,"MemFree:", 8))
47 fscanf(fp_memory
, "%Ld", &m_free
);
49 if(!strncmp(temp
,"Cached:", 7))
50 fscanf(fp_memory
, "%Ld", &m_cached
);
53 *free
= (int)(((float)(m_total
- m_free
- m_cached
) / m_total
) * 100.0);
56 /*----------------------------------------------------------------------*/
58 void draw_memory_meter(void)
60 free_memory
= free_memory
* (METER_WIDTH
/ 100.0);
61 if (free_memory
> METER_WIDTH
) free_memory
= METER_WIDTH
;
62 dcl_copy_xpm_area(0, 64, METER_WIDTH
, 5, 26, 12);
63 dcl_copy_xpm_area(32, 64, free_memory
, 5, 26, 12);
66 /*----------------------------------------------------------------------*/
68 void get_cpu_statistics(char *devname
, long *is
, long *ds
, long *idle
)
70 char temp
[BUFFER_SIZE
], *p
, *tokens
= " \t\n";
74 *is
= *ds
= *idle
= 0;
76 if (!strncmp(devname
, "cpu", 3)) {
78 fseek(fp_stat
, 0, SEEK_SET
);
80 while (fgets(temp
, 128, fp_stat
)) {
82 if (strstr(temp
, "cpu")) {
83 p
= strtok(temp
, tokens
);
84 /* 1..3, 4 == idle, we don't want idle! */
86 p
= strtok(NULL
, tokens
);
90 p
= strtok(NULL
, tokens
);
96 fp_loadavg
= freopen("/proc/loadavg", "r", fp_loadavg
);
97 fscanf(fp_loadavg
, "%f", &f
);
98 *is
= (long) (100 * f
);
103 /*----------------------------------------------------------------------*/
105 void draw_stats(int *his
, int num
, int size
, int x_left
, int y_bottom
)
107 int pixels_per_byte
, j
, k
, *p
, d
;
109 pixels_per_byte
= 100;
112 for (j
=0; j
<num
; j
++) {
113 if (p
[0] > pixels_per_byte
)
114 pixels_per_byte
+= 100;
120 for (k
=0; k
<num
; k
++) {
121 d
= (1.0 * p
[0] / pixels_per_byte
) * size
;
123 for (j
=0; j
<size
; j
++) {
126 dcl_copy_xpm_area(0, 71, 1, 1, k
+x_left
, y_bottom
-j
);
128 dcl_copy_xpm_area(1, 71, 1, 1, k
+x_left
, y_bottom
-j
);
130 dcl_copy_xpm_area(2, 71, 1, 1, k
+x_left
, y_bottom
-j
);
135 /* horizontal line */
136 for (j
= pixels_per_byte
-100; j
> 0; j
-=100) {
137 for (k
=0; k
<num
; k
++) {
138 d
= (40.0 / pixels_per_byte
) * j
;
139 dcl_copy_xpm_area(3, 71, 1, 1, k
+x_left
, y_bottom
-d
);
145 /*----------------------------------------------------------------------*/
147 void update_stat_cpu(stat_dev
*st
)
151 get_cpu_statistics(st
->name
, &k
, &istat
, &idle
);
153 st
->rt_idle
= idle
- st
->idlelast
;
156 st
->rt_stat
= istat
- st
->statlast
;
157 st
->statlast
= istat
;
159 st
->his
[V_WIDTH
] += k
;
163 /*----------------------------------------------------------------------*/
165 void cputnik_routine(int argc
, char **argv
)
168 int but_stat
= -1, xfd
= 0;
169 long start_time
, current_time
, next_time
, istat
, idle
, k
;
172 struct timeval timeout
;
174 fp_memory
= fopen("/proc/meminfo", "r");
175 fp_loadavg
= fopen("/proc/loadavg", "r");
176 fp_stat
= fopen("/proc/stat", "r");
178 for (j
=0; j
<V_WIDTH
+1; j
++)
179 cpu_device
.his
[j
] = 0;
181 cpu_device
.hisaddcnt
= 0;
182 dcl_strcpy(cpu_device
.name
, CPU_NAME
, CPU_NAME_LEN
);
185 timeout
.tv_usec
= 250000;
187 dcl_open_x_window(argc
, argv
, cputnik_master_xpm
, cputnik_mask_bits
, MASK_WIDTH
, MASK_HEIGHT
);
189 /* add mouse region */
190 dcl_add_mouse_region(0, 4, 4, 59, 59);
192 start_time
= time(0);
193 next_time
= start_time
+ update_period
;
195 get_cpu_statistics(cpu_device
.name
, &k
, &istat
, &idle
);
196 cpu_device
.statlast
= istat
;
197 cpu_device
.idlelast
= idle
;
201 dcl_draw_string(6, 5, "cpu", FONT_NORMAL
, 3);
202 dcl_draw_string(6, 12, "mem", FONT_NORMAL
, 3);
203 dcl_copy_xpm_area(5, 57, 54, 1, 5, 18);
204 get_mem_statistics(&free_memory
);
206 draw_stats(cpu_device
.his
, V_WIDTH
, V_HEIGHT_MEM
, 5, 55);
210 dcl_draw_string(6, 5, "cpu", FONT_LARGE
, 3);
211 dcl_copy_xpm_area(5, 57, 54, 1, 5, 13);
212 draw_stats(cpu_device
.his
, V_WIDTH
, V_HEIGHT
, 5, 55);
218 current_time
= time(0);
220 waitpid(0, NULL
, WNOHANG
);
222 update_stat_cpu(&cpu_device
);
225 dcl_copy_xpm_area(0, 64, 32, 7-(show_memory
*2), 26, 5);
227 j
= (cpu_device
.rt_stat
+ cpu_device
.rt_idle
);
228 if (j
!= 0) j
= (cpu_device
.rt_stat
* 100) / j
;
229 j
= j
* (METER_WIDTH
/ 100.0);
230 if (j
> METER_WIDTH
) j
= METER_WIDTH
;
232 dcl_copy_xpm_area(32, 64, j
, 7-(show_memory
*2), 26, 5);
234 if (current_time
>= next_time
) {
235 next_time
+= update_period
;
237 if (cpu_device
.his
[V_WIDTH
])
238 cpu_device
.his
[V_WIDTH
] /= cpu_device
.hisaddcnt
;
240 for (j
=1; j
<V_WIDTH
+1; j
++)
241 cpu_device
.his
[j
-1] = cpu_device
.his
[j
];
245 get_mem_statistics(&free_memory
);
247 draw_stats(cpu_device
.his
, V_WIDTH
, V_HEIGHT_MEM
, 5, 55);
250 draw_stats(cpu_device
.his
, V_WIDTH
, V_HEIGHT
, 5, 55);
252 cpu_device
.his
[V_WIDTH
] = 0;
253 cpu_device
.hisaddcnt
= 0;
257 xfd
= ConnectionNumber(display
);
260 FD_SET(xfd
, &inputs
);
262 switch(select(FD_SETSIZE
, &inputs
, NULL
, NULL
, &timeout
)) {
266 timeout
.tv_usec
= 250000;
277 while(FD_ISSET(xfd
, &inputs
) && XPending(display
)) {
278 XNextEvent(display
, &Event
);
279 switch (Event
.type
) {
284 XCloseDisplay(display
);
288 but_stat
= dcl_check_mouse_region(Event
.xbutton
.x
, Event
.xbutton
.y
);
291 i
= dcl_check_mouse_region(Event
.xbutton
.x
, Event
.xbutton
.y
);
293 if(!i
&& Event
.xbutton
.button
== LMB
&& cmd_lmb
)
294 dcl_execute_command(command_lmb
, 0);
295 else if(!i
&& Event
.xbutton
.button
== RMB
&& cmd_rmb
)
296 dcl_execute_command(command_rmb
, 0);
304 /*----------------------------------------------------------------------*/
306 void cputnik_write_prefs(void)
309 if (dcl_prefs_openfile (dcl_getfilename_config (".clay", "cputnik.rc"), P_WRITE
)) {
311 dcl_prefs_put_int ("update_period", update_period
);
312 dcl_prefs_put_int ("show_memory", show_memory
);
313 dcl_prefs_put_string ("command_lmb", command_lmb
);
314 dcl_prefs_put_string ("command_rmb", command_rmb
);
318 dcl_prefs_closefile ();
321 /*----------------------------------------------------------------------*/
323 void cputnik_read_prefs(void)
326 if (dcl_prefs_openfile (dcl_getfilename_config(".clay", "cputnik.rc"), P_READ
)) {
328 update_period
= dcl_prefs_get_int("update_period");
329 show_memory
= dcl_prefs_get_int("show_memory") % 2;
330 dcl_strcpy(command_lmb
, dcl_prefs_get_string("command_lmb"), BUFFER_SIZE
);
331 dcl_strcpy(command_rmb
, dcl_prefs_get_string("command_rmb"), BUFFER_SIZE
);
333 cmd_lmb
= cmd_rmb
= 0;
335 if(strlen(command_lmb
)) cmd_lmb
= 1;
336 if(strlen(command_rmb
)) cmd_rmb
= 1;
338 dcl_prefs_closefile ();
344 strcpy(command_lmb
, "gnome-system-monitor");
345 strcpy(command_rmb
, "xkill");
347 cputnik_write_prefs ();
352 /*----------------------------------------------------------------------*/
354 int main(int argc
, char **argv
)
356 cputnik_read_prefs();
357 cputnik_routine(argc
, argv
);