1
/* $Id: plugin_proc_stat.c 1079 2010-01-15 21:44:04Z volker $
2
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_proc_stat.c $
4
* plugin for /proc/stat parsing
6
* Copyright (C) 2003 Michael Reinelt <michael@reinelt.co.at>
7
* Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
9
* This file is part of LCD4Linux.
11
* LCD4Linux is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2, or (at your option)
16
* LCD4Linux is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30
* int plugin_init_proc_stat (void)
31
* adds functions to access /proc/stat
44
#ifdef __MAC_OS_X_VERSION_10_3
45
#include <mach/mach_host.h>
46
#include <mach/host_info.h>
56
static FILE *stream = NULL;
59
static void hash_put1(const char *key1, const char *val)
61
hash_put_delta(&Stat, key1, val);
65
static void hash_put2(const char *key1, const char *key2, const char *val)
69
qprintf(key, sizeof(key), "%s.%s", key1, key2);
74
static void hash_put3(const char *key1, const char *key2, const char *key3, const char *val)
78
qprintf(key, sizeof(key), "%s.%s.%s", key1, key2, key3);
83
static int parse_proc_stat(void)
87
/* reread every 10 msec only */
88
age = hash_age(&Stat, NULL);
89
if (age > 0 && age <= 10)
92
#ifndef __MAC_OS_X_VERSION_10_3
94
/* Linux Kernel, /proc-filesystem */
97
stream = fopen("/proc/stat", "r");
99
error("fopen(/proc/stat) failed: %s", strerror(errno));
105
while (!feof(stream)) {
107
if (fgets(buffer, sizeof(buffer), stream) == NULL)
110
if (strncmp(buffer, "cpu", 3) == 0) {
111
char *key[] = { "user", "nice", "system", "idle", "iow", "irq", "sirq" };
112
char delim[] = " \t\n";
113
char *cpu, *beg, *end;
118
/* skip "cpu" or "cpu0" block */
119
if ((end = strpbrk(buffer, delim)) != NULL)
121
beg = end ? end + 1 : NULL;
123
for (i = 0; i < 7 && beg != NULL; i++) {
124
while (strchr(delim, *beg))
126
if ((end = strpbrk(beg, delim)))
128
hash_put2(cpu, key[i], beg);
129
beg = end ? end + 1 : NULL;
133
else if (strncmp(buffer, "page ", 5) == 0) {
134
char *key[] = { "in", "out" };
135
char delim[] = " \t\n";
139
for (i = 0, beg = buffer + 5; i < 2 && beg != NULL; i++) {
140
while (strchr(delim, *beg))
142
if ((end = strpbrk(beg, delim)))
144
hash_put2("page", key[i], beg);
145
beg = end ? end + 1 : NULL;
149
else if (strncmp(buffer, "swap ", 5) == 0) {
150
char *key[] = { "in", "out" };
151
char delim[] = " \t\n";
155
for (i = 0, beg = buffer + 5; i < 2 && beg != NULL; i++) {
156
while (strchr(delim, *beg))
158
if ((end = strpbrk(beg, delim)))
160
hash_put2("swap", key[i], beg);
161
beg = end ? end + 1 : NULL;
165
else if (strncmp(buffer, "intr ", 5) == 0) {
166
char delim[] = " \t\n";
167
char *beg, *end, num[4];
170
for (i = 0, beg = buffer + 5; i < 17 && beg != NULL; i++) {
171
while (strchr(delim, *beg))
173
if ((end = strpbrk(beg, delim)))
178
qprintf(num, sizeof(num), "%d", i - 1);
179
hash_put2("intr", num, beg);
180
beg = end ? end + 1 : NULL;
184
else if (strncmp(buffer, "disk_io:", 8) == 0) {
185
char *key[] = { "io", "rio", "rblk", "wio", "wblk" };
186
char delim[] = " ():,\t\n";
187
char *dev, *beg, *end, *p;
191
while (dev != NULL) {
192
while (strchr(delim, *dev))
194
if ((end = strchr(dev, ')')))
196
while ((p = strchr(dev, ',')) != NULL)
198
beg = end ? end + 1 : NULL;
199
for (i = 0; i < 5 && beg != NULL; i++) {
200
while (strchr(delim, *beg))
202
if ((end = strpbrk(beg, delim)))
204
hash_put3("disk_io", dev, key[i], beg);
205
beg = end ? end + 1 : NULL;
212
char delim[] = " \t\n";
216
if ((end = strpbrk(beg, delim)))
218
beg = end ? end + 1 : NULL;
219
if ((end = strpbrk(beg, delim)))
221
while (strchr(delim, *beg))
223
hash_put1(buffer, beg);
229
/* MACH Kernel, MacOS X */
232
mach_msg_type_number_t count;
234
host_cpu_load_info_data_t cpu_load;
238
count = HOST_CPU_LOAD_INFO_COUNT;
239
err = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, r_load, &count);
240
if (KERN_SUCCESS != err) {
241
error("Error getting cpu load");
244
snprintf(s_val, sizeof(s_val), "%d", cpu_load.cpu_ticks[CPU_STATE_USER]);
245
hash_put2("cpu", "user", s_val);
246
snprintf(s_val, sizeof(s_val), "%d", cpu_load.cpu_ticks[CPU_STATE_NICE]);
247
hash_put2("cpu", "nice", s_val);
248
snprintf(s_val, sizeof(s_val), "%d", cpu_load.cpu_ticks[CPU_STATE_SYSTEM]);
249
hash_put2("cpu", "system", s_val);
250
snprintf(s_val, sizeof(s_val), "%d", cpu_load.cpu_ticks[CPU_STATE_IDLE]);
251
hash_put2("cpu", "idle", s_val);
259
static void my_proc_stat(RESULT * result, const int argc, RESULT * argv[])
264
if (parse_proc_stat() < 0) {
265
SetResult(&result, R_STRING, "");
271
string = hash_get(&Stat, R2S(argv[0]), NULL);
274
SetResult(&result, R_STRING, string);
277
number = hash_get_delta(&Stat, R2S(argv[0]), NULL, R2N(argv[1]));
278
SetResult(&result, R_NUMBER, &number);
281
error("proc_stat(): wrong number of parameters");
282
SetResult(&result, R_STRING, "");
287
static void my_cpu(RESULT * result, RESULT * arg1, RESULT * arg2)
292
double cpu_user, cpu_nice, cpu_system, cpu_idle, cpu_total;
293
double cpu_iow, cpu_irq, cpu_sirq;
295
if (parse_proc_stat() < 0) {
296
SetResult(&result, R_STRING, "");
303
cpu_user = hash_get_delta(&Stat, "cpu.user", NULL, delay);
304
cpu_nice = hash_get_delta(&Stat, "cpu.nice", NULL, delay);
305
cpu_system = hash_get_delta(&Stat, "cpu.system", NULL, delay);
306
cpu_idle = hash_get_delta(&Stat, "cpu.idle", NULL, delay);
308
/* new fields for kernel 2.6 */
309
/* even if we dont have this param (ie kernel 2.4) */
310
/* the return is 0.0 and not change the results */
311
cpu_iow = hash_get_delta(&Stat, "cpu.iow", NULL, delay);
312
cpu_irq = hash_get_delta(&Stat, "cpu.irq", NULL, delay);
313
cpu_sirq = hash_get_delta(&Stat, "cpu.sirq", NULL, delay);
315
cpu_total = cpu_user + cpu_nice + cpu_system + cpu_idle + cpu_iow + cpu_irq + cpu_sirq;
317
if (strcasecmp(key, "user") == 0)
319
else if (strcasecmp(key, "nice") == 0)
321
else if (strcasecmp(key, "system") == 0)
323
else if (strcasecmp(key, "idle") == 0)
325
else if (strcasecmp(key, "iowait") == 0)
327
else if (strcasecmp(key, "irq") == 0)
329
else if (strcasecmp(key, "softirq") == 0)
331
else if (strcasecmp(key, "busy") == 0)
332
value = cpu_total - cpu_idle;
335
value = 100 * value / cpu_total;
339
SetResult(&result, R_NUMBER, &value);
343
static void my_disk(RESULT * result, RESULT * arg1, RESULT * arg2, RESULT * arg3)
345
char *dev, *key, buffer[32];
349
if (parse_proc_stat() < 0) {
350
SetResult(&result, R_STRING, "");
358
qprintf(buffer, sizeof(buffer), "disk_io\\.%s\\.%s", dev, key);
359
value = hash_get_regex(&Stat, buffer, NULL, delay);
361
SetResult(&result, R_NUMBER, &value);
365
int plugin_init_proc_stat(void)
368
AddFunction("proc_stat", -1, my_proc_stat);
369
AddFunction("proc_stat::cpu", 2, my_cpu);
370
AddFunction("proc_stat::disk", 3, my_disk);
374
void plugin_exit_proc_stat(void)
376
if (stream != NULL) {