--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+
+#include "parser.h"
+
+static int str_to_dec(char *src, char **dst)
+{
+ int ret;
+
+ while(((*src < '0') || (*src > '9')) && *src)
+ src++;
+
+ ret = atoi(src);
+
+ if (dst) {
+ while(((*src >= '0') && (*src <= '9')) && *src)
+ src++;
+ *dst = src;
+ }
+
+ return ret;
+}
+
+static int get_word(char *src, char **dst, char *word)
+{
+ int ret = 0;
+ while(((*src == ' ') || (*src == '\t')) && *src)
+ src++;
+
+ while(((*src != ' ') && (*src != '\t')) && *src) {
+ *word = *src;
+ word++;
+ src++;
+ ret++;
+ }
+ *word = 0;
+
+ if (dst)
+ *dst = src;
+
+ return ret;
+}
+
+#define STATFILE "/proc/stat"
+
+int cpu_parser(char *data)
+{
+ char buf[1024];
+ char *str = buf;
+ FILE *file = fopen(STATFILE, "r");
+ int user, nice, sys, idle, wait, irq, softirq;
+
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open file %s\n", STATFILE);
+ return -1;
+ }
+
+ if (!fgets(buf, 1024, file)) {
+ fprintf(stderr, "Failed to read file %s\n", STATFILE);
+ fclose(file);
+ return -1;
+ }
+
+ user = str_to_dec(str, &str);
+ nice = str_to_dec(str, &str);
+ sys = str_to_dec(str, &str);
+ idle = str_to_dec(str, &str);
+ wait = str_to_dec(str, &str);
+ irq = str_to_dec(str, &str);
+ softirq = str_to_dec(str, &str);
+
+ sprintf(data, "%d:%d:%d:%d:%d:%d:%d",
+ user, nice, sys, idle, wait, irq, softirq);
+
+ fclose(file);
+ return 0;
+}
+
+#define MEMFILE "/proc/meminfo"
+
+int mem_parser(char *data)
+{
+ char buf[1024], word[1024];
+ int free = 0, buffered = 0, cache = 0, active = 0, inactive = 0,
+ swapfree = 0, anon = 0, slab = 0, tables = 0;
+ FILE *file = fopen(MEMFILE, "r");
+
+ if (file == NULL) {
+ fprintf(stderr, "Failed to open file %s\n", MEMFILE);
+ return -1;
+ }
+
+ while (fgets(buf, 1024, file)) {
+ get_word(buf, 0, word);
+
+ if (!strcmp(word, "MemFree:")) {
+ free = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "Buffers:")) {
+ buffered = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "Cached:")) {
+ cache = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "Active:")) {
+ active = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "Inactive:")) {
+ inactive = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "SwapFree:")) {
+ swapfree = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "AnonPages:")) {
+ anon = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "Slab:")) {
+ slab = str_to_dec(buf, 0);
+ } else if (!strcmp(word, "PageTables:")) {
+ tables = str_to_dec(buf, 0);
+ }
+ }
+ fclose(file);
+
+ sprintf(data, "%f:%f:%f:%f:%f:%f:%f:%f:%f",
+ free / 1024.0,
+ buffered / 1024.0,
+ cache / 1024.0,
+ active / 1024.0,
+ inactive / 1024.0,
+ swapfree / 1024.0,
+ anon / 1024.0,
+ slab / 1024.0,
+ tables / 1024.0);
+
+ return 0;
+}
+
+int cpu_mem_parser(char *data)
+{
+ char cpu[1024], mem[1024];
+
+ cpu_parser(cpu);
+ mem_parser(mem);
+ sprintf(data, "%s:%s", cpu, mem);
+
+ return 0;
+}
--- /dev/null
+#ifndef _TESTDATA_H
+#define _TESTDATA_H
+
+#include "draw_graphs.h"
+#include "scheduler.h"
+#include "parser.h"
+
+const char blank[] = "COMMENT: ";
+#define numfmt " % 8.2lf "
+
+const char *cputext[] = {
+ "DEF:us=/home/kaapeli/sysinfo/sysinfo.rrd:User:AVERAGE",
+ "DEF:ni=/home/kaapeli/sysinfo/sysinfo.rrd:Nice:AVERAGE",
+ "DEF:sy=/home/kaapeli/sysinfo/sysinfo.rrd:Sys:AVERAGE",
+ "DEF:id=/home/kaapeli/sysinfo/sysinfo.rrd:Idle:AVERAGE",
+ "DEF:wa=/home/kaapeli/sysinfo/sysinfo.rrd:Wait:AVERAGE",
+ "DEF:in=/home/kaapeli/sysinfo/sysinfo.rrd:IRQ:AVERAGE",
+ "DEF:so=/home/kaapeli/sysinfo/sysinfo.rrd:SoftIRQ:AVERAGE",
+ "COMMENT:\\n",
+ blank,
+ "COMMENT: "
+ "MIN MAX AVG Last\\n",
+ blank,
+ "AREA:sy#ff0000:System ",
+ "GPRINT:sy:MIN:" numfmt,
+ "GPRINT:sy:MAX:" numfmt,
+ "GPRINT:sy:AVERAGE:" numfmt,
+ "GPRINT:sy:LAST:" numfmt "\\n",
+ blank,
+ "STACK:us#0000ff:User ",
+ "GPRINT:us:MIN:" numfmt,
+ "GPRINT:us:MAX:" numfmt,
+ "GPRINT:us:AVERAGE:" numfmt,
+ "GPRINT:us:LAST:" numfmt "\\n",
+ blank,
+ "STACK:ni#00ff00:Nice ",
+ "GPRINT:ni:MIN:" numfmt,
+ "GPRINT:ni:MAX:" numfmt,
+ "GPRINT:ni:AVERAGE:" numfmt,
+ "GPRINT:ni:LAST:" numfmt "\\n",
+ blank,
+ "STACK:id#ffffff:Idle ",
+ "GPRINT:id:MIN:" numfmt,
+ "GPRINT:id:MAX:" numfmt,
+ "GPRINT:id:AVERAGE:" numfmt,
+ "GPRINT:id:LAST:" numfmt "\\n",
+ blank,
+ "STACK:wa#0000ff:IO wait ",
+ "GPRINT:wa:MIN:" numfmt,
+ "GPRINT:wa:MAX:" numfmt,
+ "GPRINT:wa:AVERAGE:" numfmt,
+ "GPRINT:wa:LAST:" numfmt "\\n",
+ blank,
+ "STACK:in#ffff00:IRQ ",
+ "GPRINT:in:MIN:" numfmt,
+ "GPRINT:in:MAX:" numfmt,
+ "GPRINT:in:AVERAGE:" numfmt,
+ "GPRINT:in:LAST:" numfmt "\\n",
+ blank,
+ "STACK:so#00ffff:Soft IRQ ",
+ "GPRINT:so:MIN:" numfmt,
+ "GPRINT:so:MAX:" numfmt,
+ "GPRINT:so:AVERAGE:" numfmt,
+ "GPRINT:so:LAST:" numfmt "\\n",
+ "COMMENT: \\n",
+ 0
+};
+
+const char *memtext[] = {
+ "DEF:fr=/home/kaapeli/sysinfo/sysinfo.rrd:Free:AVERAGE",
+ "DEF:bu=/home/kaapeli/sysinfo/sysinfo.rrd:Buffers:AVERAGE",
+ "DEF:ca=/home/kaapeli/sysinfo/sysinfo.rrd:Cached:AVERAGE",
+ "DEF:an=/home/kaapeli/sysinfo/sysinfo.rrd:Anon:AVERAGE",
+ "DEF:sl=/home/kaapeli/sysinfo/sysinfo.rrd:Slab:AVERAGE",
+ "DEF:ta=/home/kaapeli/sysinfo/sysinfo.rrd:Tables:AVERAGE",
+ "COMMENT:\\n",
+ blank,
+ "COMMENT: "
+ "MIN MAX AVG Last\\n",
+ blank,
+ "AREA:bu#ff0000:Buffers ",
+ "GPRINT:bu:MIN:" numfmt,
+ "GPRINT:bu:MAX:" numfmt,
+ "GPRINT:bu:AVERAGE:" numfmt,
+ "GPRINT:bu:LAST:" numfmt "\\n",
+ blank,
+ "STACK:an#000000:AnonPages ",
+ "GPRINT:an:MIN:" numfmt,
+ "GPRINT:an:MAX:" numfmt,
+ "GPRINT:an:AVERAGE:" numfmt,
+ "GPRINT:an:LAST:" numfmt "\\n",
+ blank,
+ "STACK:ca#00ff00:Cached ",
+ "GPRINT:ca:MIN:" numfmt,
+ "GPRINT:ca:MAX:" numfmt,
+ "GPRINT:ca:AVERAGE:" numfmt,
+ "GPRINT:ca:LAST:" numfmt "\\n",
+ blank,
+ "STACK:fr#ffffff:Free ",
+ "GPRINT:fr:MIN:" numfmt,
+ "GPRINT:fr:MAX:" numfmt,
+ "GPRINT:fr:AVERAGE:" numfmt,
+ "GPRINT:fr:LAST:" numfmt "\\n",
+ blank,
+ "STACK:sl#00ffff:Slab ",
+ "GPRINT:sl:MIN:" numfmt,
+ "GPRINT:sl:MAX:" numfmt,
+ "GPRINT:sl:AVERAGE:" numfmt,
+ "GPRINT:sl:LAST:" numfmt "\\n",
+ blank,
+ "STACK:ta#0000ff:PageTables ",
+ "GPRINT:ta:MIN:" numfmt,
+ "GPRINT:ta:MAX:" numfmt,
+ "GPRINT:ta:AVERAGE:" numfmt,
+ "GPRINT:ta:LAST:" numfmt "\\n",
+ "COMMENT: \\n",
+ 0
+};
+
+const char *systemptext[] = {
+ "DEF:sda_c=/root/systemp/systemp.rrd:sda:AVERAGE",
+ "DEF:SYS_c=/root/systemp/systemp.rrd:SYS:AVERAGE",
+ "DEF:CPU_c=/root/systemp/systemp.rrd:CPU:AVERAGE",
+ "COMMENT:\\n",
+ blank,
+ "COMMENT: "
+ "MIN MAX AVG Last\\n",
+ blank,
+ "LINE1:sda_c#0000FF:SAMSUNG HD501LJ ",
+ "GPRINT:sda_c:MIN: %5.2lf °C",
+ "GPRINT:sda_c:MAX: %5.2lf °C",
+ "GPRINT:sda_c:AVERAGE: %5.2lf °C",
+ "GPRINT:sda_c:LAST: %5.2lf °C\\n",
+ blank,
+ "LINE1:SYS_c#00FF00:Sys Temp ",
+ "GPRINT:SYS_c:MIN: %5.2lf °C",
+ "GPRINT:SYS_c:MAX: %5.2lf °C",
+ "GPRINT:SYS_c:AVERAGE: %5.2lf °C",
+ "GPRINT:SYS_c:LAST: %5.2lf °C\\n",
+ blank,
+ "LINE1:CPU_c#FF0000:Intel Core2 Quad ",
+ "GPRINT:CPU_c:MIN: %5.2lf °C",
+ "GPRINT:CPU_c:MAX: %5.2lf °C",
+ "GPRINT:CPU_c:AVERAGE: %5.2lf °C",
+ "GPRINT:CPU_c:LAST: %5.2lf °C\\n",
+ "COMMENT: \\n",
+ 0
+};
+
+const char *cpuoptions[] = {
+ "--alt-autoscale-max",
+ "--vertical-label",
+ "CPU Tics",
+ 0
+};
+
+const char *memoptions[] = {
+ "--alt-autoscale-max",
+ "--vertical-label",
+ "Mem usage (MB)",
+ "--units-exponent", "0",
+ 0
+};
+
+const char *systempoptions[] = {
+ "--alt-autoscale",
+ "--vertical-label", "Temp °C",
+ 0
+};
+
+static struct rrd_image cpudaily = {
+ .image_filename = "/home/kaapeli/sysinfo/images/cpu_daily.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1d",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&cpuoptions,
+ .text = (char **)&cputext
+};
+
+static struct rrd_image cpuweekly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/cpu_weekly.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1w",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&cpuoptions,
+ .text = (char **)&cputext
+};
+
+static struct rrd_image cpumonthly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/cpu_monthly.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1m",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&cpuoptions,
+ .text = (char **)&cputext
+};
+
+static struct rrd_image cpuyearly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/cpu_yearly.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1y",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&cpuoptions,
+ .text = (char **)&cputext
+};
+
+static struct rrd_image memdaily = {
+ .image_filename = "/home/kaapeli/sysinfo/images/mem_daily.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1d",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&memoptions,
+ .text = (char **)&memtext
+};
+
+static struct rrd_image memweekly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/mem_weekly.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1w",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&memoptions,
+ .text = (char **)&memtext
+};
+static struct rrd_image memmonthly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/mem_monthly.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1m",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&memoptions,
+ .text = (char **)&memtext
+};
+static struct rrd_image memyearly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/mem_yearly.png",
+ .width = 720,
+ .height = 480,
+ .timestart = "end-1y",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&memoptions,
+ .text = (char **)&memtext
+};
+
+static struct rrd_image systempdaily = {
+ .image_filename = "/home/kaapeli/sysinfo/images/systemp_daily.png",
+ .width = 600,
+ .height = 200,
+ .timestart = "end-1d",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&systempoptions,
+ .text = (char **)&systemptext
+};
+
+static struct rrd_image systempweekly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/systemp_weekly.png",
+ .width = 600,
+ .height = 200,
+ .timestart = "end-1w",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&systempoptions,
+ .text = (char **)&systemptext
+};
+
+static struct rrd_image systempmonthly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/systemp_monthly.png",
+ .width = 600,
+ .height = 200,
+ .timestart = "end-1m",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&systempoptions,
+ .text = (char **)&systemptext
+};
+
+static struct rrd_image systempyearly = {
+ .image_filename = "/home/kaapeli/sysinfo/images/systemp_yearly.png",
+ .width = 600,
+ .height = 200,
+ .timestart = "end-1y",
+ .timeend = "now",
+ .imageformat = "PNG",
+ .options = (char **)&systempoptions,
+ .text = (char **)&systemptext
+};
+
+static struct rrd_image *cpu_mem_images[] = {
+ &cpudaily,
+ &cpuweekly,
+ &cpumonthly,
+ &cpuyearly,
+ &memdaily,
+ &memweekly,
+ &memmonthly,
+ &memyearly,
+ 0
+};
+
+static struct rrd_image *systemp_images[] = {
+ &systempdaily,
+ &systempweekly,
+ &systempmonthly,
+ &systempyearly,
+ 0
+};
+
+static struct rrd_database cpumem_rrd = {
+ .filename = "/home/kaapeli/sysinfo/sysinfo.rrd",
+ .interval = 60,
+ .parse = cpu_mem_parser,
+ .images = (struct rrd_image **)&cpu_mem_images,
+ .name = "cpumem"
+};
+
+static struct rrd_database systemp_rrd = {
+ .interval = 300,
+ .parse = NULL,
+ .images = (struct rrd_image **)&systemp_images,
+ .name = "systemp"
+};
+
+static struct rrd_database *all_rrds[] = {
+ &cpumem_rrd,
+ &systemp_rrd,
+ 0
+};
+
+#endif