Commit Diff


commit - d72054aa270d6f3d539e830ef9892138a255872a
commit + f0f4401f0cfc654646bdf21849627ebcbd5d82b5
blob - /dev/null
blob + da6c2a220e676a679c56e776a44d7afd3dda74c8 (mode 644)
--- /dev/null
+++ src/cmd/auxstats/Darwin.c
@@ -0,0 +1,250 @@
+/*
+ * No idea whether this will work.  It does compile.
+ */
+
+#include <u.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <sys/types.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/dkstat.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void xloadavg(int);
+void xcpu(int);
+void xswap(int);
+void xsysctl(int);
+void xnet(int);
+void xkvm(int);
+
+void (*statfn[])(int) =
+{
+	xkvm,
+	xloadavg,
+	xswap,
+	xcpu,
+	xsysctl,
+	xnet,
+	0
+};
+
+static kvm_t *kvm;
+
+static struct nlist nl[] = {
+	{ "_ifnet" },
+	{ "_cp_time" },
+	{ "" },
+};
+
+void
+kvminit(void)
+{
+	char buf[_POSIX2_LINE_MAX];
+
+	if(kvm)
+		return;
+	kvm = kvm_openfiles(nil, nil, nil, OREAD, buf);
+	if(kvm == nil)
+		return;
+	if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){
+		kvm = nil;
+		return;
+	}
+}
+
+void
+xkvm(int first)
+{
+	if(first)
+		kvminit();
+}
+
+int
+kread(ulong addr, char *buf, int size)
+{
+	if(kvm_read(kvm, addr, buf, size) != size){
+		memset(buf, 0, size);
+		return -1;
+	}
+	return size;
+}
+
+void
+xnet(int first)
+{
+	ulong out, in, outb, inb, err;
+	static ulong ifnetaddr;
+	ulong addr;
+	struct ifnet ifnet;
+	struct ifnethead ifnethead;
+	char name[16];
+
+	if(first)
+		return;
+
+	if(ifnetaddr == 0){
+		ifnetaddr = nl[0].n_value;
+		if(ifnetaddr == 0)
+			return;
+	}
+
+	if(kread(ifnetaddr, (char*)&ifnethead, sizeof ifnethead) < 0)
+		return;
+
+	out = in = outb = inb = err = 0;
+	addr = (ulong)TAILQ_FIRST(&ifnethead);
+	while(addr){
+		if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
+		|| kread((ulong)ifnet.if_name, name, 16) < 0)
+			return;
+		name[15] = 0;
+		addr = (ulong)TAILQ_NEXT(&ifnet, if_link);
+		out += ifnet.if_opackets;
+		in += ifnet.if_ipackets;
+		outb += ifnet.if_obytes;
+		inb += ifnet.if_ibytes;
+		err += ifnet.if_oerrors+ifnet.if_ierrors;
+	}
+	Bprint(&bout, "etherin %lud\n", in);
+	Bprint(&bout, "etherout %lud\n", out);
+	Bprint(&bout, "etherinb %lud\n", inb);
+	Bprint(&bout, "etheroutb %lud\n", outb);
+	Bprint(&bout, "ethererr %lud\n", err);
+	Bprint(&bout, "ether %lud\n", in+out);
+	Bprint(&bout, "etherb %lud\n", inb+outb);
+}
+
+
+int
+rsys(char *name, char *buf, int len)
+{
+	size_t l;
+
+	l = len;
+	if(sysctlbyname(name, buf, &l, nil, 0) < 0)
+		return -1;
+	buf[l] = 0;
+	return l;
+}
+
+vlong
+isys(char *name)
+{
+	ulong u;
+	size_t l;
+
+	l = sizeof u;
+	if(sysctlbyname(name, &u, &l, nil, 0) < 0)
+		return 0;
+	return u;
+}
+
+void
+xsysctl(int first)
+{
+	static int pgsize;
+	vlong t;
+
+	if(first){
+		pgsize = isys("vm.stats.vm.v_page_size");
+		if(pgsize == 0)
+			pgsize = 4096;
+	}
+	if((t = isys("vm.stats.vm.v_page_count")) != 0)
+		Bprint(&bout, "mem %lld %lld\n", 
+			isys("vm.stats.vm.v_active_count")*pgsize, 
+			t*pgsize);
+	Bprint(&bout, "context %lld 1000\n", isys("vm.stats.sys.v_swtch"));
+	Bprint(&bout, "syscall %lld 1000\n", isys("vm.stats.sys.v_syscall"));
+	Bprint(&bout, "intr %lld 1000\n", isys("vm.stats.sys.v_intr")+isys("vm.stats.sys.v_trap"));
+	Bprint(&bout, "fault %lld 1000\n", isys("vm.stats.vm.v_vm_faults"));
+	Bprint(&bout, "fork %lld 1000\n", isys("vm.stats.vm.v_forks")
+		+isys("vm.stats.vm.v_rforks")
+		+isys("vm.stats.vm.v_vforks"));
+}
+
+void
+xcpu(int first)
+{
+#if 0
+	static int stathz;
+	ulong x[20];
+	struct clockinfo *ci;
+	int n;
+
+	if(first){
+		if(rsys("kern.clockrate", (char*)&x, sizeof x) < sizeof ci)
+			stathz = 128;
+		else{
+			ci = (struct clockinfo*)x;
+			stathz = ci->stathz;
+		}
+		return;
+	}
+
+	if((n=rsys("kern.cp_time", (char*)x, sizeof x)) < 5*sizeof(ulong))
+		return;
+
+	Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz);
+	Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz);
+	Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz);
+	Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz);
+#endif
+}
+
+void
+xloadavg(int first)
+{
+	double l[3];
+
+	if(first)
+		return;
+
+	if(getloadavg(l, 3) < 0)
+		return;
+	Bprint(&bout, "load %d 1000\n", (int)(l[0]*1000.0));
+}
+
+void
+xswap(int first)
+{
+#if 0
+	static struct kvm_swap s;
+	static ulong pgin, pgout;
+	int i, o;
+	static int pgsize;
+
+	if(first){
+		pgsize = getpagesize();
+		if(pgsize == 0)
+			pgsize = 4096;
+		return;
+	}
+
+	if(kvm == nil)
+		return;
+
+	i = isys("vm.stats.vm.v_swappgsin");
+	o = isys("vm.stats.vm.v_swappgsout");
+	if(i != pgin || o != pgout){
+		pgin = i;
+		pgout = o;
+		kvm_getswapinfo(kvm, &s, 1, 0);
+	}
+
+
+	Bprint(&bout, "swap %lld %lld\n", s.ksw_used*(vlong)pgsize, s.ksw_total*(vlong)pgsize);
+#endif
+}
+
blob - /dev/null
blob + b0379f88e86113f904d501f72eca621628c26a1a (mode 644)
--- /dev/null
+++ src/cmd/auxstats/FreeBSD.c
@@ -0,0 +1,262 @@
+#include <u.h>
+#include <kvm.h>
+#include <nlist.h>
+#include <sys/types.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/dkstat.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <machine/apm_bios.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void xapm(int);
+void xloadavg(int);
+void xcpu(int);
+void xswap(int);
+void xsysctl(int);
+void xnet(int);
+void xkvm(int);
+
+void (*statfn[])(int) =
+{
+	xkvm,
+	xapm,
+	xloadavg,
+	xswap,
+	xcpu,
+	xsysctl,
+	xnet,
+	0
+};
+
+static kvm_t *kvm;
+
+static struct nlist nl[] = {
+	{ "_ifnet" },
+	{ "_cp_time" },
+	{ "" },
+};
+
+void
+kvminit(void)
+{
+	char buf[_POSIX2_LINE_MAX];
+
+	if(kvm)
+		return;
+	kvm = kvm_openfiles(nil, nil, nil, OREAD, buf);
+	if(kvm == nil)
+		return;
+	if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){
+		kvm = nil;
+		return;
+	}
+}
+
+void
+xkvm(int first)
+{
+	if(first)
+		kvminit();
+}
+
+int
+kread(ulong addr, char *buf, int size)
+{
+	if(kvm_read(kvm, addr, buf, size) != size){
+		memset(buf, 0, size);
+		return -1;
+	}
+	return size;
+}
+
+void
+xnet(int first)
+{
+	ulong out, in, outb, inb, err;
+	static ulong ifnetaddr;
+	ulong addr;
+	struct ifnet ifnet;
+	struct ifnethead ifnethead;
+	char name[16];
+	int n;
+
+	if(first)
+		return;
+
+	if(ifnetaddr == 0){
+		ifnetaddr = nl[0].n_value;
+		if(ifnetaddr == 0)
+			return;
+	}
+
+	if(kread(ifnetaddr, (char*)&ifnethead, sizeof ifnethead) < 0)
+		return;
+
+	out = in = outb = inb = err = 0;
+	addr = (ulong)TAILQ_FIRST(&ifnethead);
+	while(addr){
+		if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
+		|| kread((ulong)ifnet.if_name, name, 16) < 0)
+			return;
+		name[15] = 0;
+		addr = (ulong)TAILQ_NEXT(&ifnet, if_link);
+		out += ifnet.if_opackets;
+		in += ifnet.if_ipackets;
+		outb += ifnet.if_obytes;
+		inb += ifnet.if_ibytes;
+		err += ifnet.if_oerrors+ifnet.if_ierrors;
+	}
+	Bprint(&bout, "etherin %lud 1000\n", in);
+	Bprint(&bout, "etherout %lud 1000\n", out);
+	Bprint(&bout, "etherinb %lud 1000000\n", inb);
+	Bprint(&bout, "etheroutb %lud 1000000\n", outb);
+	Bprint(&bout, "ethererr %lud 1000\n", err);
+	Bprint(&bout, "ether %lud 1000\n", in+out);
+	Bprint(&bout, "etherb %lud 1000000\n", inb+outb);
+}
+
+void
+xapm(int first)
+{
+	static int fd;
+	struct apm_info ai;
+
+	if(first){
+		fd = open("/dev/apm", OREAD);
+		return;
+	}
+
+	if(ioctl(fd, APMIO_GETINFO, &ai) < 0)
+		return;
+
+	if(ai.ai_batt_life <= 100)
+		Bprint(&bout, "battery =%d 100\n", ai.ai_batt_life);
+}
+
+int
+rsys(char *name, char *buf, int len)
+{
+	size_t l;
+
+	l = len;
+	if(sysctlbyname(name, buf, &l, nil, 0) < 0)
+		return -1;
+	buf[l] = 0;
+	return l;
+}
+
+vlong
+isys(char *name)
+{
+	ulong u;
+	size_t l;
+
+	l = sizeof u;
+	if(sysctlbyname(name, &u, &l, nil, 0) < 0)
+		return -1;
+	return u;
+}
+
+void
+xsysctl(int first)
+{
+	static int pgsize;
+
+	if(first){
+		pgsize = isys("vm.stats.vm.v_page_size");
+		if(pgsize == 0)
+			pgsize = 4096;
+	}
+
+	Bprint(&bout, "mem =%lld %lld\n", 
+		isys("vm.stats.vm.v_active_count")*pgsize, 
+		isys("vm.stats.vm.v_page_count")*pgsize);
+	Bprint(&bout, "context %lld 1000\n", isys("vm.stats.sys.v_swtch"));
+	Bprint(&bout, "syscall %lld 1000\n", isys("vm.stats.sys.v_syscall"));
+	Bprint(&bout, "intr %lld 1000\n", isys("vm.stats.sys.v_intr")+isys("vm.stats.sys.v_trap"));
+	Bprint(&bout, "fault %lld 1000\n", isys("vm.stats.vm.v_vm_faults"));
+	Bprint(&bout, "fork %lld 1000\n", isys("vm.stats.vm.v_forks")
+		+isys("vm.stats.vm.v_rforks")
+		+isys("vm.stats.vm.v_vforks"));
+}
+
+void
+xcpu(int first)
+{
+	static int stathz;
+	ulong x[20];
+	struct clockinfo *ci;
+	int n;
+
+	if(first){
+		if(rsys("kern.clockrate", (char*)&x, sizeof x) < sizeof ci)
+			stathz = 128;
+		else{
+			ci = (struct clockinfo*)x;
+			stathz = ci->stathz;
+		}
+		return;
+	}
+
+	if((n=rsys("kern.cp_time", (char*)x, sizeof x)) < 5*sizeof(ulong))
+		return;
+
+	Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz);
+	Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz);
+	Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz);
+	Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz);
+}
+
+void
+xloadavg(int first)
+{
+	double l[3];
+
+	if(first)
+		return;
+
+	if(getloadavg(l, 3) < 0)
+		return;
+	Bprint(&bout, "load =%d 1000\n", (int)(l[0]*1000.0));
+}
+
+void
+xswap(int first)
+{
+	static struct kvm_swap s;
+	static ulong pgin, pgout;
+	int i, o;
+	static int pgsize;
+
+	if(first){
+		pgsize = getpagesize();
+		if(pgsize == 0)
+			pgsize = 4096;
+		return;
+	}
+
+	if(kvm == nil)
+		return;
+
+	i = isys("vm.stats.vm.v_swappgsin");
+	o = isys("vm.stats.vm.v_swappgsout");
+	if(i != pgin || o != pgout){
+		pgin = i;
+		pgout = o;
+		kvm_getswapinfo(kvm, &s, 1, 0);
+	}
+
+
+	Bprint(&bout, "swap =%lld %lld\n", s.ksw_used*(vlong)pgsize, s.ksw_total*(vlong)pgsize);
+}
+
blob - /dev/null
blob + 06e9d422d4195a0422158e7a2e744a72c8a787d7 (mode 644)
--- /dev/null
+++ src/cmd/auxstats/Linux.c
@@ -0,0 +1,177 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void xapm(int);
+void xloadavg(int);
+void xmeminfo(int);
+void xnet(int);
+void xstat(int);
+
+void (*statfn[])(int) =
+{
+	xapm,
+	xloadavg,
+	xmeminfo,
+	xnet,
+	xstat,
+	0
+};
+
+void
+xapm(int first)
+{
+	static int fd = -1;
+
+	if(first){
+		fd = open("/proc/apm", OREAD);
+		return;
+	}
+	readfile(fd);
+	tokens(0);
+	if(ntok >= 7 && atoi(tok[6]) != -1)
+		Bprint(&bout, "battery =%d 100\n", atoi(tok[6]));
+}
+	
+void
+xloadavg(int first)
+{
+	static int fd = -1;
+
+	if(first){
+		fd = open("/proc/loadavg", OREAD);
+		return;
+	}
+
+	readfile(fd);
+	tokens(0);
+	if(ntok >= 1)
+		Bprint(&bout, "load =%d 1000\n", (int)(atof(tok[0])*1000));
+}
+
+void
+xmeminfo(int first)
+{
+	int i;
+	vlong tot, used;
+	static int fd = -1;
+
+	if(first){
+		fd = open("/proc/meminfo", OREAD);
+		return;
+	}
+
+	readfile(fd);
+	for(i=0; i<nline; i++){
+		tokens(i);
+		if(ntok < 4)
+			continue;
+		tot = atoll(tok[1]);
+		used = atoll(tok[2]);
+		if(strcmp(tok[0], "Mem:") == 0)
+			Bprint(&bout, "mem =%lld %lld\n", used/1024, tot/1024);
+		else if(strcmp(tok[0], "Swap:") == 0)
+			Bprint(&bout, "swap =%lld %lld\n", used/1024, tot/1024);
+	}
+}
+
+void
+xnet(int first)
+{
+	int i, n;
+	vlong totb, totp, tote, totin, totou, totinb, totoub, b, p, e, in, ou, inb, oub;
+	char *q;
+	static int fd = -1;
+
+	if(first){
+		fd = open("/proc/net/dev", OREAD);
+		return;
+	}
+
+	readfile(fd);
+	n = 0;
+	totb = 0;
+	tote = 0;
+	totp = 0;
+	totin = 0;
+	totou = 0;
+	totinb = 0;
+	totoub = 0;
+	for(i=0; i<nline; i++){
+		tokens(i);
+		if(ntok < 8+8)
+			continue;
+		if(strncmp(tok[0], "eth", 3) != 0)
+			continue;
+		q = strchr(tok[0], ':');
+		*q++ = 0;
+		tok[0] = q;
+		inb = atoll(tok[0]);
+		oub = atoll(tok[8]);
+		in = atoll(tok[1]);
+		ou = atoll(tok[9]);
+		b = inb+oub;
+		p = in+ou;
+		e = atoll(tok[2])+atoll(tok[10]);
+		totb += b;
+		totp += p;
+		tote += e;
+		totin += in;
+		totou += ou;
+		totinb += inb;
+		totoub += oub;
+		n++;
+	}
+	Bprint(&bout, "etherb %lld %d\n", totb, n*1000000);
+	Bprint(&bout, "ether %lld %d\n", totp, n*1000);
+	Bprint(&bout, "ethererr %lld %d\n", tote, n*1000);
+	Bprint(&bout, "etherin %lld %d\n", totin, n*1000);
+	Bprint(&bout, "etherout %lld %d\n", totou, n*1000);
+	Bprint(&bout, "etherinb %lld %d\n", totinb, n*1000);
+	Bprint(&bout, "etheroutb %lld %d\n", totoub, n*1000);
+}
+
+void
+xstat(int first)
+{
+	static int fd = -1;
+	int i;
+
+	if(first){
+		fd = open("/proc/stat", OREAD);
+		return;
+	}
+
+	readfile(fd);
+	for(i=0; i<nline; i++){
+		tokens(i);
+		if(ntok < 2)
+			continue;
+		if(strcmp(tok[0], "cpu") == 0 && ntok >= 5){
+			Bprint(&bout, "user %lld 100\n", atoll(tok[1]));
+			Bprint(&bout, "sys %lld 100\n", atoll(tok[3]));
+			Bprint(&bout, "cpu %lld 100\n", atoll(tok[1])+atoll(tok[3]));
+			Bprint(&bout, "idle %lld\n", atoll(tok[4]));
+		}
+	/*
+		if(strcmp(tok[0], "page") == 0 && ntok >= 3){
+			Bprint(&bout, "pagein %lld 500\n", atoll(tok[1]));
+			Bprint(&bout, "pageout %lld 500\n", atoll(tok[2]));
+			Bprint(&bout, "page %lld 1000\n", atoll(tok[1])+atoll(tok[2]));
+		}
+		if(strcmp(tok[0], "swap") == 0 && ntok >= 3){
+			Bprint(&bout, "swapin %lld 500\n", atoll(tok[1]));
+			Bprint(&bout, "swapout %lld 500\n", atoll(tok[2]));
+			Bprint(&bout, "swap %lld 1000\n", atoll(tok[1])+atoll(tok[2]));
+		}
+	*/
+		if(strcmp(tok[0], "intr") == 0)
+			Bprint(&bout, "interrupt %lld 1000\n", atoll(tok[1]));
+		if(strcmp(tok[0], "ctxt") == 0)
+			Bprint(&bout, "context %lld 1000\n", atoll(tok[1]));
+		if(strcmp(tok[0], "processes") == 0)
+			Bprint(&bout, "fork %lld 1000\n", atoll(tok[1]));
+	}
+}
+
blob - /dev/null
blob + ec9310447017e5215754d96967872b6d5a70f59b (mode 644)
--- /dev/null
+++ src/cmd/auxstats/NetBSD.c
@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void (*statfn[])(int) = 
+{
+	0
+};
+
blob - /dev/null
blob + ec9310447017e5215754d96967872b6d5a70f59b (mode 644)
--- /dev/null
+++ src/cmd/auxstats/OpenBSD.c
@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void (*statfn[])(int) = 
+{
+	0
+};
+
blob - /dev/null
blob + ec9310447017e5215754d96967872b6d5a70f59b (mode 644)
--- /dev/null
+++ src/cmd/auxstats/SunOS.c
@@ -0,0 +1,10 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+void (*statfn[])(int) = 
+{
+	0
+};
+
blob - /dev/null
blob + f8fc24176efab053795c2367c8b68d6e9d6298e4 (mode 644)
Binary files /dev/null and src/cmd/auxstats/core differ
blob - /dev/null
blob + 17e5c615c64ac3891f59d6763d5def0a21106a8c (mode 644)
--- /dev/null
+++ src/cmd/auxstats/dat.h
@@ -0,0 +1,9 @@
+extern Biobuf bout;
+extern void (*statfn[])(int);
+extern char buf[];
+extern char *line[];
+extern char *tok[];
+extern int nline, ntok;
+
+void readfile(int);
+void tokens(int);
blob - /dev/null
blob + a3624824c2dabaf37ec10072112af4f7db2a54fe (mode 644)
--- /dev/null
+++ src/cmd/auxstats/main.c
@@ -0,0 +1,123 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "dat.h"
+
+Biobuf bout;
+
+void
+usage(void)
+{
+	fprint(2, "usage: auxstats [system [executable]]\n");
+	exits("usage");
+}
+
+int pid;
+
+void
+notifyf(void *v, char *msg)
+{
+	USED(v);
+
+	if(strcmp(msg, "child") == 0)
+		noted(NCONT);
+	postnote(PNPROC, pid, msg);
+	exits(nil);
+}
+
+void
+main(int argc, char **argv)
+{
+	char *sys, *exe;
+	int i;
+	Waitmsg *w;
+
+	ARGBEGIN{
+	default:
+		usage();
+	}ARGEND
+
+	notify(notifyf);
+
+	sys = nil;
+	exe = nil;
+	if(argc > 0)
+		sys = argv[0];
+	if(argc > 1)
+		exe = argv[1];
+	if(argc > 2)
+		usage();
+
+	if(sys){
+		if(exe == nil)
+			exe = "auxstats";
+		for(;;){
+			switch(pid = fork()){
+			case -1:
+				sysfatal("fork: %r");
+			case 0:
+				rfork(RFNOTEG);
+				execlp("ssh", "ssh", "-C", sys, exe, nil);
+				_exit(12);
+			default:
+				if((w = wait()) == nil)
+					sysfatal("wait: %r");
+				if(w->pid != pid)
+					sysfatal("wait got wrong pid");
+				if(atoi(w->msg) == 12)
+					sysfatal("exec ssh failed");
+				free(w);
+				fprint(2, "stats: %s hung up; sleeping 60\n", sys);
+				sleep(60*1000);
+				fprint(2, "stats: redialing %s\n", sys);
+				break;
+			}
+		}
+	}
+
+	for(i=0; statfn[i]; i++)
+		statfn[i](1);
+
+	Binit(&bout, 1, OWRITE);
+	for(;;){
+		Bflush(&bout);
+		sleep(900);
+		for(i=0; statfn[i]; i++)
+			statfn[i](0);
+	}
+}
+
+char buf[16384];
+char *line[100];
+char *tok[100];
+int nline, ntok;
+
+void
+readfile(int fd)
+{
+	int n;
+
+	if(fd == -1){
+		nline = 0;
+		return;
+	}
+
+	seek(fd, 0, 0);
+	n = read(fd, buf, sizeof buf-1);
+	if(n < 0)
+		n = 0;
+	buf[n] = 0;
+
+	nline = getfields(buf, line, nelem(line), 0, "\n");
+}
+
+void
+tokens(int i)
+{
+	if(i >= nline){
+		ntok = 0;
+		return;
+	}
+	ntok = tokenize(line[i], tok, nelem(tok));
+}
+
blob - /dev/null
blob + 5652c60c5a9a7b487e04d3cf0c8b3e61ac905b37 (mode 644)
--- /dev/null
+++ src/cmd/auxstats/mkfile
@@ -0,0 +1,15 @@
+<$PLAN9/src/mkhdr
+
+TARG=auxstats
+
+OFILES=\
+	$SYSNAME.$O\
+	main.$O\
+
+HFILES=\
+	dat.h\
+
+SHORTLIB=bio 9
+
+<$PLAN9/src/mkone
+