summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--common.c14
-rw-r--r--common.h7
-rw-r--r--cpu.c157
-rw-r--r--entropy.c35
-rw-r--r--forks.c44
-rw-r--r--fw_packets.c60
-rw-r--r--interrupts.c47
-rw-r--r--load.c47
-rw-r--r--main.c64
-rw-r--r--open_files.c52
-rw-r--r--open_inodes.c42
-rw-r--r--processes.c42
-rw-r--r--swap.c78
-rw-r--r--uptime.c32
15 files changed, 737 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..56a56f6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+CFLAGS=-W -Wall -pedantic -Wextra -g -O2
+OBJS=main.o common.o cpu.o entropy.o forks.o fw_packets.o interrupts.o load.o \
+ open_files.o open_inodes.o processes.o swap.o uptime.o
+LINKS=cpu entropy forks fw_packets interrupts load open_files open_inodes \
+ processes swap uptime
+
+%.o:%.c
+ ${CC} ${CFLAGS} -c $< -o $@
+all:main
+ for l in ${LINKS}; do test -f $$l || ln -s main $$l; done
+main:${OBJS}
+ ${CC} ${CFLAGS} $^ -o $@
+clean:
+ rm -f main ${OBJS} ${LINKS}
+.PHONY:all clean
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..3d78e51
--- /dev/null
+++ b/common.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+int writeyes(void) {
+ puts("yes");
+ return 0;
+}
+
+int writeno(const char *s) {
+ if(s)
+ printf("no (%s)\n", s);
+ else
+ puts("no");
+ return 1;
+}
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..67a5beb
--- /dev/null
+++ b/common.h
@@ -0,0 +1,7 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+int writeyes(void);
+int writeno(const char *);
+
+#endif
diff --git a/cpu.c b/cpu.c
new file mode 100644
index 0000000..120293d
--- /dev/null
+++ b/cpu.c
@@ -0,0 +1,157 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "common.h"
+
+#define SYSWARNING 30
+#define SYSCRITICAL 50
+#define USRWARNING 80
+
+int cpu(int argc, char **argv) {
+ FILE *f;
+ char buff[256], *s;
+ int ncpu=0, extinfo=0, scaleto100=0;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ s = getenv("scaleto100");
+ if(s && !strcmp(s, "yes"))
+ scaleto100=1;
+
+ if(!(f=fopen("/proc/stat", "r"))) {
+ fputs("cannot open /proc/stat\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 256, f)) {
+ if(!strncmp(buff, "cpu", 3)) {
+ if(isdigit(buff[3]))
+ ncpu++;
+ if(buff[3] == ' ') {
+ s = strtok(buff+4, " \t");
+ for(extinfo=0;strtok(NULL, " \t");extinfo++)
+ ;
+ }
+ }
+ }
+ fclose(f);
+
+ if(ncpu < 1 || extinfo < 4) {
+ fputs("cannot parse /proc/stat\n", stderr);
+ return 1;
+ }
+
+ puts("graph_title CPU usage");
+ if(extinfo == 7)
+ puts("graph_order system user nice idle iowait irq softirq");
+ else
+ puts("graph_order system user nice idle");
+ if(scaleto100)
+ puts("graph_args --base 1000 -r --lower-limit 0 --upper-limit 100");
+ else
+ printf("graph_args --base 1000 -r --lower-limit 0 --upper-limit %d\n", 100 * ncpu);
+ puts("graph_vlabel %\n"
+ "graph_scale no\n"
+ "graph_info This graph shows how CPU time is spent.\n"
+ "graph_category system\n"
+ "graph_period second\n"
+ "system.label system\n"
+ "system.draw AREA");
+ printf("system.max %d\n", 100 * ncpu);
+ puts("system.min 0\n"
+ "system.type DERIVE");
+ printf("system.warning %d\n", SYSWARNING * ncpu);
+ printf("system.critical %d\n", SYSCRITICAL * ncpu);
+ puts("system.info CPU time spent by the kernel in system activities\n"
+ "user.label user\n"
+ "user.draw STACK\n"
+ "user.min 0");
+ printf("user.max %d\n", 100 * ncpu);
+ printf("user.warning %d\n", USRWARNING * ncpu);
+ puts("user.type DERIVE\n"
+ "user.info CPU time spent by normal programs and daemons\n"
+ "nice.label nice\n"
+ "nice.draw STACK\n"
+ "nice.min 0");
+ printf("nice.max %d\n", 100 * ncpu);
+ puts("nice.type DERIVE\n"
+ "nice.info CPU time spent by nice(1)d programs\n"
+ "idle.label idle\n"
+ "idle.draw STACK\n"
+ "idle.min 0");
+ printf("idle.max %d\n", 100 * ncpu);
+ puts("idle.type DERIVE\n"
+ "idle.info Idle CPU time");
+ if(scaleto100)
+ printf("system.cdef system,%d,/\n"
+ "user.cdef user,%d,/\n"
+ "nice.cdef nice,%d,/\n"
+ "idle.cdef idle,%d,/\n", ncpu, ncpu, ncpu, ncpu);
+ if(extinfo == 7) {
+ puts("iowait.label iowait\n"
+ "iowait.draw STACK\n"
+ "iowait.min 0");
+ printf("iowait.max %d\n", 100 * ncpu);
+ puts("iowait.type DERIVE\n"
+ "iowait.info CPU time spent waiting for I/O operations to finish\n"
+ "irq.label irq\n"
+ "irq.draw STACK\n"
+ "irq.min 0");
+ printf("irq.max %d\n", 100 * ncpu);
+ puts("irq.type DERIVE\n"
+ "irq.info CPU time spent handling interrupts\n"
+ "softirq.label softirq\n"
+ "softirq.draw STACK\n"
+ "softirq.min 0");
+ printf("softirq.max %d\n", 100 * ncpu);
+ puts("softirq.type DERIVE\n"
+ "softirq.info CPU time spent handling \"batched\" interrupts");
+ if(scaleto100)
+ printf("iowait.cdef iowait,%d,/\n"
+ "irq.cdef irq,%d,/\n"
+ "softirq.cdef softirq,%d,/\n", ncpu, ncpu, ncpu);
+ }
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/stat", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/stat not readable");
+ }
+ }
+ if(!(f=fopen("/proc/stat", "r"))) {
+ fputs("cannot open /proc/stat\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 256, f)) {
+ if(!strncmp(buff, "cpu ", 4)) {
+ fclose(f);
+ if(!(s = strtok(buff+4, " \t")))
+ break;
+ printf("user.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ printf("nice.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ printf("system.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ printf("idle.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ return 0;
+ printf("iowait.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ return 0;
+ printf("irq.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ return 0;
+ printf("softirq.value %s\n", s);
+ return 0;
+ }
+ }
+ fclose(f);
+ fputs("no cpu line found in /proc/stat\n", stderr);
+ return 1;
+}
diff --git a/entropy.c b/entropy.c
new file mode 100644
index 0000000..4a5d846
--- /dev/null
+++ b/entropy.c
@@ -0,0 +1,35 @@
+#include <string.h>
+#include <stdio.h>
+#include "common.h"
+
+int entropy(int argc, char **argv) {
+ FILE *f;
+ int entropy;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Available entropy\n"
+ "graph_args --base 1000 -l 0\n"
+ "graph_vlabel entropy (bytes)\n"
+ "graph_scale no\n"
+ "graph_category system\n"
+ "graph_info This graph shows the amount of entropy available in the system.\n"
+ "entropy.label entropy\n"
+ "entropy.info The number of random bytes available. This is typically used by cryptographic applications.");
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf"))
+ return writeyes();
+ }
+ if(!(f=fopen("/proc/sys/kernel/random/entropy_avail", "r"))) {
+ fputs("cannot open /proc/sys/kernel/random/entropy_avail\n", stderr);
+ return 1;
+ }
+ if(1 != fscanf(f, "%d", &entropy)) {
+ fputs("cannot read from /proc/sys/kernel/random/entropy_avail\n", stderr);
+ fclose(f);
+ return 1;
+ }
+ fclose(f);
+ printf("entropy.value %d\n", entropy);
+ return 0;
+}
diff --git a/forks.c b/forks.c
new file mode 100644
index 0000000..fa4dadb
--- /dev/null
+++ b/forks.c
@@ -0,0 +1,44 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "common.h"
+
+int forks(int argc, char **argv) {
+ FILE *f;
+ char buff[256];
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Fork rate\n"
+ "graph_args --base 1000 -l 0 \n"
+ "graph_vlabel forks / ${graph_period}\n"
+ "graph_category processes\n"
+ "graph_info This graph shows the forking rate (new processes started).\n"
+ "forks.label forks\n"
+ "forks.type DERIVE\n"
+ "forks.min 0\n"
+ "forks.max 100000\n"
+ "forks.info The number of forks per second.");
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/stat", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/stat not readable");
+ }
+ }
+ if(!(f=fopen("/proc/stat", "r"))) {
+ fputs("cannot open /proc/stat\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 256, f)) {
+ if(!strncmp(buff, "processes ", 10)) {
+ fclose(f);
+ printf("forks.value %s", buff+10);
+ return 0;
+ }
+ }
+ fclose(f);
+ fputs("no processes line found in /proc/stat\n", stderr);
+ return 1;
+}
diff --git a/fw_packets.c b/fw_packets.c
new file mode 100644
index 0000000..06367dd
--- /dev/null
+++ b/fw_packets.c
@@ -0,0 +1,60 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "common.h"
+
+int fw_packets(int argc, char **argv) {
+ FILE *f;
+ char buff[1024], *s;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Firewall Throughput\n"
+ "graph_args --base 1000 -l 0\n"
+ "graph_vlabel Packets/${graph_period}\n"
+ "graph_category network\n"
+ "received.label Received\n"
+ "received.draw AREA\n"
+ "received.type DERIVE\n"
+ "received.min 0\n"
+ "forwarded.label Forwarded\n"
+ "forwarded.draw LINE2\n"
+ "forwarded.type DERIVE\n"
+ "forwarded.min 0");
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/net/snmp", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/net/snmp not readable");
+ }
+ }
+ if(!(f=fopen("/proc/net/snmp", "r"))) {
+ fputs("cannot open /proc/net/snmp\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 1024, f)) {
+ if(!strncmp(buff, "Ip: ", 4) && isdigit(buff[4])) {
+ fclose(f);
+ if(!(s = strtok(buff+4, " \t")))
+ break;
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ printf("received.value %s\n", s);
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ if(!(s = strtok(NULL, " \t")))
+ break;
+ printf("forwarded.value %s\n", s);
+ return 0;
+ }
+ }
+ fclose(f);
+ fputs("no ip line found in /proc/net/snmp\n", stderr);
+ return 1;
+}
diff --git a/interrupts.c b/interrupts.c
new file mode 100644
index 0000000..2755ccf
--- /dev/null
+++ b/interrupts.c
@@ -0,0 +1,47 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "common.h"
+
+int interrupts(int argc, char **argv) {
+ FILE *f;
+ char buff[256];
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Interrupts & context switches\n"
+ "graph_args --base 1000 -l 0\n"
+ "graph_vlabel interrupts & ctx switches / ${graph_period}\n"
+ "graph_category system\n"
+ "graph_info This graph shows the number of interrupts and context switches on the system. These are typically high on a busy system.\n"
+ "intr.info Interrupts are events that alter sequence of instructions executed by a processor. They can come from either hardware (exceptions, NMI, IRQ) or software.");
+ puts("ctx.info A context switch occurs when a multitasking operatings system suspends the currently running process, and starts executing another.\n"
+ "intr.label interrupts\n"
+ "ctx.label context switches\n"
+ "intr.type DERIVE\n"
+ "ctx.type DERIVE\n"
+ "intr.max 100000\n"
+ "ctx.max 100000\n"
+ "intr.min 0\n"
+ "ctx.min 0");
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/stat", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/stat not readable");
+ }
+ }
+ if(!(f=fopen("/proc/stat", "r"))) {
+ fputs("cannot open /proc/stat\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 256, f)) {
+ if(!strncmp(buff, "intr ", 5))
+ printf("intr.value %s", buff+5);
+ else if(!strncmp(buff, "ctxt ", 5))
+ printf("ctx.value %s", buff+5);
+ }
+ fclose(f);
+ return 0;
+}
diff --git a/load.c b/load.c
new file mode 100644
index 0000000..c894f5e
--- /dev/null
+++ b/load.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "common.h"
+
+int load(int argc, char **argv) {
+ FILE *f;
+ int warn, crit;
+ float val;
+ char *s;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ s = getenv("load_warn");
+ if(s)
+ warn = atoi(s);
+ else
+ warn = 10;
+ s = getenv("load_crit");
+ if(s)
+ crit = atoi(s);
+ else
+ crit = 120;
+ puts("graph_title Load average\n"
+ "graph_args --base 1000 -l 0\n"
+ "graph_vlabel load\n"
+ "graph_scale no\n"
+ "graph_category system\n"
+ "load.label load");
+ printf("load.warning %d\nload.critical %d\n", warn, crit);
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf"))
+ return writeyes();
+ }
+ if(!(f=fopen("/proc/loadavg", "r"))) {
+ fputs("cannot open /proc/loadavg\n", stderr);
+ return 1;
+ }
+ if(1 != fscanf(f, "%*f %f", &val)) {
+ fputs("cannot read from /proc/loadavg\n", stderr);
+ fclose(f);
+ return 1;
+ }
+ fclose(f);
+ printf("load.value %.2f\n", val);
+ return 0;
+}
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..348b4f6
--- /dev/null
+++ b/main.c
@@ -0,0 +1,64 @@
+#include <libgen.h>
+#include <string.h>
+#include <stdio.h>
+
+int cpu(int argc, char **argv);
+int entropy(int argc, char **argv);
+int forks(int argc, char **argv);
+int fw_packets(int argc, char **argv);
+int interrupts(int argc, char **argv);
+int load(int argc, char **argv);
+int open_files(int argc, char **argv);
+int open_inodes(int argc, char **argv);
+int processes(int argc, char **argv);
+int swap(int argc, char **argv);
+int uptime(int argc, char **argv);
+
+int main(int argc, char **argv) {
+ char *progname;
+ progname = basename(argv[0]);
+ switch(*progname) {
+ case 'c':
+ if(!strcmp(progname+1, "pu"))
+ return cpu(argc, argv);
+ break;
+ case 'e':
+ if(!strcmp(progname+1, "ntropy"))
+ return entropy(argc, argv);
+ break;
+ case 'f':
+ if(!strcmp(progname+1, "orks"))
+ return forks(argc, argv);
+ if(!strcmp(progname+1, "w_packets"))
+ return fw_packets(argc, argv);
+ break;
+ case 'i':
+ if(!strcmp(progname+1, "nterrupts"))
+ return interrupts(argc, argv);
+ break;
+ case 'l':
+ if(!strcmp(progname+1, "oad"))
+ return load(argc, argv);
+ break;
+ case 'o':
+ if(!strcmp(progname+1, "pen_files"))
+ return open_files(argc, argv);
+ if(!strcmp(progname+1, "pen_inodes"))
+ return open_inodes(argc, argv);
+ break;
+ case 'p':
+ if(!strcmp(progname+1, "rocesses"))
+ return processes(argc, argv);
+ break;
+ case 's':
+ if(!strcmp(progname+1, "wap"))
+ return swap(argc, argv);
+ break;
+ case 'u':
+ if(!strcmp(progname+1, "ptime"))
+ return uptime(argc, argv);
+ break;
+ }
+ fprintf(stderr, "function not specified\n");
+ return 1;
+}
diff --git a/open_files.c b/open_files.c
new file mode 100644
index 0000000..3f82c8b
--- /dev/null
+++ b/open_files.c
@@ -0,0 +1,52 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "common.h"
+
+int open_files(int argc, char **argv) {
+ FILE *f;
+ int alloc, freeh, avail;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ if(!(f=fopen("/proc/sys/fs/file-nr", "r"))) {
+ fprintf(stderr, "cannot open /proc/sys/fs/file-nr\n");
+ return 1;
+ }
+ if(1 != fscanf(f, "%*d %*d %d", &avail)) {
+ fclose(f);
+ fprintf(stderr, "cannot read from /proc/sys/fs/file-nr\n");
+ return 1;
+ }
+ fclose(f);
+ puts("graph_title File table usage\n"
+ "graph_args --base 1000 -l 0\n"
+ "graph_vlabel number of open files\n"
+ "graph_category system\n"
+ "graph_info This graph monitors the Linux open files table.\n"
+ "used.label open files\n"
+ "used.info The number of currently open files.\n"
+ "max.label max open files\n"
+ "max.info The maximum supported number of open files. Tune by modifying /proc/sys/fs/file-max.");
+ printf("used.warning %d\nused.critical %d\n", (int)(avail*0.92), (int)(avail*0.98));
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/sys/fs/file-nr", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/sys/fs/file-nr not readable");
+ }
+ }
+ if(!(f=fopen("/proc/sys/fs/file-nr", "r"))) {
+ fputs("cannot open /proc/sys/fs/file-nr\n", stderr);
+ return 1;
+ }
+ if(3 != fscanf(f, "%d %d %d", &alloc, &freeh, &avail)) {
+ fclose(f);
+ fputs("cannot read from /proc/sys/fs/file-nr\n", stderr);
+ return 1;
+ }
+ fclose(f);
+ printf("used.value %d\nmax.value %d\n", alloc-freeh, avail);
+ return 0;
+}
diff --git a/open_inodes.c b/open_inodes.c
new file mode 100644
index 0000000..bc20cc6
--- /dev/null
+++ b/open_inodes.c
@@ -0,0 +1,42 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "common.h"
+
+int open_inodes(int argc, char **argv) {
+ FILE *f;
+ int nr, freen;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Inode table usage\n"
+ "graph_args --base 1000 -l 0\n"
+ "graph_vlabel number of open inodes\n"
+ "graph_category system\n"
+ "graph_info This graph monitors the Linux open inode table.\n"
+ "used.label open inodes\n"
+ "used.info The number of currently open inodes.\n"
+ "max.label inode table size\n"
+ "max.info The size of the system inode table. This is dynamically adjusted by the kernel.");
+
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/sys/fs/inode-nr", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/sys/fs/inode-nr not readable");
+ }
+ }
+ if(!(f=fopen("/proc/sys/fs/inode-nr", "r"))) {
+ fputs("cannot open /proc/sys/fs/inode-nr\n", stderr);
+ return 1;
+ }
+ if(2 != fscanf(f, "%d %d", &nr, &freen)) {
+ fclose(f);
+ fputs("cannot read from /proc/sys/fs/inode-nr\n", stderr);
+ return 1;
+ }
+ fclose(f);
+ printf("used.value %d\nmax.value %d\n", nr-freen, nr);
+ return 0;
+}
diff --git a/processes.c b/processes.c
new file mode 100644
index 0000000..b522768
--- /dev/null
+++ b/processes.c
@@ -0,0 +1,42 @@
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <ctype.h>
+#include "common.h"
+
+int processes(int argc, char **argv) {
+ DIR *d;
+ struct dirent *e;
+ char *s;
+ int n=0;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Number of Processes\n"
+ "graph_args --base 1000 -l 0 \n"
+ "graph_vlabel number of processes\n"
+ "graph_category processes\n"
+ "graph_info This graph shows the number of processes in the system.\n"
+ "processes.label processes\n"
+ "processes.draw LINE2\n"
+ "processes.info The current number of processes.");
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf"))
+ return writeyes();
+ }
+ if(!(d = opendir("/proc"))) {
+ fputs("cannot open /proc\n", stderr);
+ return 1;
+ }
+ while((e = readdir(d))) {
+ for(s=e->d_name;*s;++s)
+ if(!isdigit(*s))
+ break;
+ if(!*s)
+ ++n;
+ }
+ closedir(d);
+ printf("processes.value %d\n", n);
+ return 0;
+}
diff --git a/swap.c b/swap.c
new file mode 100644
index 0000000..fef6cc3
--- /dev/null
+++ b/swap.c
@@ -0,0 +1,78 @@
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "common.h"
+
+int swap(int argc, char **argv) {
+ FILE *f;
+ char buff[256];
+ int in, out;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Swap in/out\n"
+ "graph_args -l 0 --base 1000\n"
+ "graph_vlabel pages per ${graph_period} in (-) / out (+)\n"
+ "graph_category system\n"
+ "swap_in.label swap\n"
+ "swap_in.type DERIVE\n"
+ "swap_in.max 100000\n"
+ "swap_in.min 0\n"
+ "swap_in.graph no\n"
+ "swap_out.label swap\n"
+ "swap_out.type DERIVE\n"
+ "swap_out.max 100000\n"
+ "swap_out.min 0\n"
+ "swap_out.negative swap_in");
+
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf")) {
+ if(0 == access("/proc/stat", R_OK))
+ return writeyes();
+ else
+ return writeno("/proc/stat not readable");
+ }
+ }
+ if(!access("/proc/vmstat", F_OK)) {
+ in=out=0;
+ if(!(f=fopen("/proc/vmstat", "r"))) {
+ fputs("cannot open /proc/vmstat\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 256, f)) {
+ if(!in && !strncmp(buff, "pswpin ", 7)) {
+ ++in;
+ printf("swap_in.value %s", buff+7);
+ }
+ else if(!out && !strncmp(buff, "pswpout ", 8)) {
+ ++out;
+ printf("swap_out.value %s", buff+8);
+ }
+ }
+ fclose(f);
+ if(!in*out) {
+ fputs("no usable data on /proc/vmstat\n", stderr);
+ return 1;
+ }
+ return 0;
+ } else {
+ if(!(f=fopen("/proc/stat", "r"))) {
+ fputs("cannot open /proc/stat\n", stderr);
+ return 1;
+ }
+ while(fgets(buff, 256, f)) {
+ if(!strncmp(buff, "swap ", 5)) {
+ fclose(f);
+ if(2 != sscanf(buff+5, "%d %d", &in, &out)) {
+ fputs("bad data on /proc/stat\n", stderr);
+ return 1;
+ }
+ printf("swap_in.value %d\nswap_out.value %d\n", in, out);
+ return 0;
+ }
+ }
+ fclose(f);
+ fputs("no swap line found in /proc/stat\n", stderr);
+ return 1;
+ }
+}
diff --git a/uptime.c b/uptime.c
new file mode 100644
index 0000000..ce6093f
--- /dev/null
+++ b/uptime.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+
+int uptime(int argc, char **argv) {
+ FILE *f;
+ float uptime;
+ if(argc > 1) {
+ if(!strcmp(argv[1], "config")) {
+ puts("graph_title Uptime\n"
+ "graph_args --base 1000 -l 0 \n"
+ "graph_vlabel uptime in days\n"
+ "uptime.label uptime\n"
+ "uptime.draw AREA");
+ return 0;
+ }
+ if(!strcmp(argv[1], "autoconf"))
+ return writeyes();
+ }
+ if(!(f=fopen("/proc/uptime", "r"))) {
+ fputs("cannot open /proc/uptime\n", stderr);
+ return 1;
+ }
+ if(1 != fscanf(f, "%f", &uptime)) {
+ fputs("cannot read from /proc/uptime\n", stderr);
+ fclose(f);
+ return 1;
+ }
+ fclose(f);
+ printf("uptime.value %.2f\n", uptime/86400);
+ return 0;
+}