xref: /plan9/sys/src/cmd/stats.c (revision fee9fd16fbcb514a4f462b56ff20c7199c0fc677)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ctype.h>
47dd7cddfSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include <fcall.h>
67dd7cddfSDavid du Colombier #include <draw.h>
77dd7cddfSDavid du Colombier #include <event.h>
83e12c5d1SDavid du Colombier 
9f86ef3ceSDavid du Colombier #define	MAXNUM	10	/* maximum number of numbers on data line */
103e12c5d1SDavid du Colombier 
117dd7cddfSDavid du Colombier typedef struct Graph	Graph;
127dd7cddfSDavid du Colombier typedef struct Machine	Machine;
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier struct Graph
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier 	int		colindex;
177dd7cddfSDavid du Colombier 	Rectangle	r;
18853458f3SDavid du Colombier 	uvlong		*data;
197dd7cddfSDavid du Colombier 	int		ndata;
207dd7cddfSDavid du Colombier 	char		*label;
21b2495906SDavid du Colombier 	void		(*newvalue)(Machine*, uvlong*, uvlong*, int);
22b2495906SDavid du Colombier 	void		(*update)(Graph*, uvlong, uvlong);
237dd7cddfSDavid du Colombier 	Machine		*mach;
247dd7cddfSDavid du Colombier 	int		overflow;
257dd7cddfSDavid du Colombier 	Image		*overtmp;
267dd7cddfSDavid du Colombier };
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier enum
293e12c5d1SDavid du Colombier {
302e7ae8b5SDavid du Colombier 	/* old /dev/swap */
317dd7cddfSDavid du Colombier 	Mem		= 0,
327dd7cddfSDavid du Colombier 	Maxmem,
333e12c5d1SDavid du Colombier 	Swap,
347dd7cddfSDavid du Colombier 	Maxswap,
352e7ae8b5SDavid du Colombier 
367dd7cddfSDavid du Colombier 	/* /dev/sysstats */
377dd7cddfSDavid du Colombier 	Procno	= 0,
387dd7cddfSDavid du Colombier 	Context,
397dd7cddfSDavid du Colombier 	Interrupt,
403e12c5d1SDavid du Colombier 	Syscall,
413e12c5d1SDavid du Colombier 	Fault,
427dd7cddfSDavid du Colombier 	TLBfault,
437dd7cddfSDavid du Colombier 	TLBpurge,
443e12c5d1SDavid du Colombier 	Load,
45dc5a79c1SDavid du Colombier 	Idle,
46f86ef3ceSDavid du Colombier 	InIntr,
473432ceaeSDavid du Colombier 	/* /net/ether0/stats */
487dd7cddfSDavid du Colombier 	In		= 0,
497def40e1SDavid du Colombier 	Link,
507dd7cddfSDavid du Colombier 	Out,
517dd7cddfSDavid du Colombier 	Err0,
523e12c5d1SDavid du Colombier };
533e12c5d1SDavid du Colombier 
547dd7cddfSDavid du Colombier struct Machine
553e12c5d1SDavid du Colombier {
567dd7cddfSDavid du Colombier 	char		*name;
57eebedd9aSDavid du Colombier 	char		*shortname;
587dd7cddfSDavid du Colombier 	int		remote;
597dd7cddfSDavid du Colombier 	int		statsfd;
607dd7cddfSDavid du Colombier 	int		swapfd;
617dd7cddfSDavid du Colombier 	int		etherfd;
629a747e4fSDavid du Colombier 	int		ifstatsfd;
6380ee5cbfSDavid du Colombier 	int		batteryfd;
649a747e4fSDavid du Colombier 	int		bitsybatfd;
65b2495906SDavid du Colombier 	int		tempfd;
667dd7cddfSDavid du Colombier 	int		disable;
673e12c5d1SDavid du Colombier 
68b2495906SDavid du Colombier 	uvlong		devswap[4];
69b2495906SDavid du Colombier 	uvlong		devsysstat[10];
70b2495906SDavid du Colombier 	uvlong		prevsysstat[10];
717dd7cddfSDavid du Colombier 	int		nproc;
72eebedd9aSDavid du Colombier 	int		lgproc;
73b2495906SDavid du Colombier 	uvlong		netetherstats[8];
74b2495906SDavid du Colombier 	uvlong		prevetherstats[8];
75b2495906SDavid du Colombier 	uvlong		batterystats[2];
76b2495906SDavid du Colombier 	uvlong		netetherifstats[2];
77b2495906SDavid du Colombier 	uvlong		temp[10];
783e12c5d1SDavid du Colombier 
79b4aa05a1SDavid du Colombier 	/* big enough to hold /dev/sysstat even with many processors */
80b4aa05a1SDavid du Colombier 	char		buf[8*1024];
817dd7cddfSDavid du Colombier 	char		*bufp;
827dd7cddfSDavid du Colombier 	char		*ebufp;
833e12c5d1SDavid du Colombier };
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier enum
867dd7cddfSDavid du Colombier {
877dd7cddfSDavid du Colombier 	Mainproc,
887dd7cddfSDavid du Colombier 	Mouseproc,
897dd7cddfSDavid du Colombier 	NPROC,
907dd7cddfSDavid du Colombier };
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier enum
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier 	Ncolor		= 6,
957dd7cddfSDavid du Colombier 	Ysqueeze	= 2,	/* vertical squeezing of label text */
967dd7cddfSDavid du Colombier 	Labspace	= 2,	/* room around label */
977dd7cddfSDavid du Colombier 	Dot		= 2,	/* height of dot */
987dd7cddfSDavid du Colombier 	Opwid		= 5,	/* strlen("add  ") or strlen("drop ") */
9980ee5cbfSDavid du Colombier 	Nlab		= 3,	/* max number of labels on y axis */
10080ee5cbfSDavid du Colombier 	Lablen		= 16,	/* max length of label */
10180ee5cbfSDavid du Colombier 	Lx		= 4,	/* label tick length */
1027dd7cddfSDavid du Colombier };
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier enum Menu2
1057dd7cddfSDavid du Colombier {
106f86ef3ceSDavid du Colombier 	Mbattery,
1077dd7cddfSDavid du Colombier 	Mcontext,
1087dd7cddfSDavid du Colombier 	Mether,
1097dd7cddfSDavid du Colombier 	Methererr,
1107dd7cddfSDavid du Colombier 	Metherin,
1117dd7cddfSDavid du Colombier 	Metherout,
1127dd7cddfSDavid du Colombier 	Mfault,
113f86ef3ceSDavid du Colombier 	Midle,
114f86ef3ceSDavid du Colombier 	Minintr,
1157dd7cddfSDavid du Colombier 	Mintr,
1167dd7cddfSDavid du Colombier 	Mload,
1177dd7cddfSDavid du Colombier 	Mmem,
1187dd7cddfSDavid du Colombier 	Mswap,
1197dd7cddfSDavid du Colombier 	Msyscall,
1207dd7cddfSDavid du Colombier 	Mtlbmiss,
1217dd7cddfSDavid du Colombier 	Mtlbpurge,
1229a747e4fSDavid du Colombier 	Msignal,
123b2495906SDavid du Colombier 	Mtemp,
1247dd7cddfSDavid du Colombier 	Nmenu2,
1257dd7cddfSDavid du Colombier };
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier char	*menu2str[Nmenu2+1] = {
128f86ef3ceSDavid du Colombier 	"add  battery ",
1297dd7cddfSDavid du Colombier 	"add  context ",
1307dd7cddfSDavid du Colombier 	"add  ether   ",
1317dd7cddfSDavid du Colombier 	"add  ethererr",
1327dd7cddfSDavid du Colombier 	"add  etherin ",
1337dd7cddfSDavid du Colombier 	"add  etherout",
1347dd7cddfSDavid du Colombier 	"add  fault   ",
135f86ef3ceSDavid du Colombier 	"add  idle    ",
136f86ef3ceSDavid du Colombier 	"add  inintr  ",
1377dd7cddfSDavid du Colombier 	"add  intr    ",
1387dd7cddfSDavid du Colombier 	"add  load    ",
1397dd7cddfSDavid du Colombier 	"add  mem     ",
1407dd7cddfSDavid du Colombier 	"add  swap    ",
1417dd7cddfSDavid du Colombier 	"add  syscall ",
1427dd7cddfSDavid du Colombier 	"add  tlbmiss ",
1437dd7cddfSDavid du Colombier 	"add  tlbpurge",
1449a747e4fSDavid du Colombier 	"add  802.11b ",
145b2495906SDavid du Colombier 	"add  temp    ",
1467dd7cddfSDavid du Colombier 	nil,
1477dd7cddfSDavid du Colombier };
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 
150b2495906SDavid du Colombier void	contextval(Machine*, uvlong*, uvlong*, int),
151b2495906SDavid du Colombier 	etherval(Machine*, uvlong*, uvlong*, int),
152b2495906SDavid du Colombier 	ethererrval(Machine*, uvlong*, uvlong*, int),
153b2495906SDavid du Colombier 	etherinval(Machine*, uvlong*, uvlong*, int),
154b2495906SDavid du Colombier 	etheroutval(Machine*, uvlong*, uvlong*, int),
155b2495906SDavid du Colombier 	faultval(Machine*, uvlong*, uvlong*, int),
156b2495906SDavid du Colombier 	intrval(Machine*, uvlong*, uvlong*, int),
157b2495906SDavid du Colombier 	inintrval(Machine*, uvlong*, uvlong*, int),
158b2495906SDavid du Colombier 	loadval(Machine*, uvlong*, uvlong*, int),
159b2495906SDavid du Colombier 	idleval(Machine*, uvlong*, uvlong*, int),
160b2495906SDavid du Colombier 	memval(Machine*, uvlong*, uvlong*, int),
161b2495906SDavid du Colombier 	swapval(Machine*, uvlong*, uvlong*, int),
162b2495906SDavid du Colombier 	syscallval(Machine*, uvlong*, uvlong*, int),
163b2495906SDavid du Colombier 	tlbmissval(Machine*, uvlong*, uvlong*, int),
164b2495906SDavid du Colombier 	tlbpurgeval(Machine*, uvlong*, uvlong*, int),
165b2495906SDavid du Colombier 	batteryval(Machine*, uvlong*, uvlong*, int),
166b2495906SDavid du Colombier 	signalval(Machine*, uvlong*, uvlong*, int),
167b2495906SDavid du Colombier 	tempval(Machine*, uvlong*, uvlong*, int);
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier Menu	menu2 = {menu2str, nil};
1707dd7cddfSDavid du Colombier int	present[Nmenu2];
171b2495906SDavid du Colombier void	(*newvaluefn[Nmenu2])(Machine*, uvlong*, uvlong*, int init) = {
172f86ef3ceSDavid du Colombier 	batteryval,
1737dd7cddfSDavid du Colombier 	contextval,
1747dd7cddfSDavid du Colombier 	etherval,
1757dd7cddfSDavid du Colombier 	ethererrval,
1767dd7cddfSDavid du Colombier 	etherinval,
1777dd7cddfSDavid du Colombier 	etheroutval,
1787dd7cddfSDavid du Colombier 	faultval,
179f86ef3ceSDavid du Colombier 	idleval,
180f86ef3ceSDavid du Colombier 	inintrval,
1817dd7cddfSDavid du Colombier 	intrval,
1827dd7cddfSDavid du Colombier 	loadval,
1837dd7cddfSDavid du Colombier 	memval,
1847dd7cddfSDavid du Colombier 	swapval,
1857dd7cddfSDavid du Colombier 	syscallval,
1867dd7cddfSDavid du Colombier 	tlbmissval,
1877dd7cddfSDavid du Colombier 	tlbpurgeval,
1889a747e4fSDavid du Colombier 	signalval,
189b2495906SDavid du Colombier 	tempval,
1907dd7cddfSDavid du Colombier };
1917dd7cddfSDavid du Colombier 
1927dd7cddfSDavid du Colombier Image	*cols[Ncolor][3];
1937dd7cddfSDavid du Colombier Graph	*graph;
1947dd7cddfSDavid du Colombier Machine	*mach;
1957dd7cddfSDavid du Colombier Font	*mediumfont;
1967dd7cddfSDavid du Colombier char	*mysysname;
197*fee9fd16SDavid du Colombier char	*mycputype;
198b2495906SDavid du Colombier char	argchars[] = "8bceEfiImlnpstwz";
1997dd7cddfSDavid du Colombier int	pids[NPROC];
2007dd7cddfSDavid du Colombier int 	parity;	/* toggled to avoid patterns in textured background */
2017dd7cddfSDavid du Colombier int	nmach;
2027dd7cddfSDavid du Colombier int	ngraph;	/* totaly number is ngraph*nmach */
20380ee5cbfSDavid du Colombier double	scale = 1.0;
20480ee5cbfSDavid du Colombier int	logscale = 0;
20580ee5cbfSDavid du Colombier int	ylabels = 0;
2069a747e4fSDavid du Colombier int	oldsystem = 0;
207186fc3d1SDavid du Colombier int 	sleeptime = 1000;
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier char	*procnames[NPROC] = {"main", "mouse"};
2107dd7cddfSDavid du Colombier 
2117dd7cddfSDavid du Colombier void
killall(char * s)2127dd7cddfSDavid du Colombier killall(char *s)
2137dd7cddfSDavid du Colombier {
2147dd7cddfSDavid du Colombier 	int i, pid;
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier 	pid = getpid();
2177dd7cddfSDavid du Colombier 	for(i=0; i<NPROC; i++)
2187dd7cddfSDavid du Colombier 		if(pids[i] && pids[i]!=pid)
2197dd7cddfSDavid du Colombier 			postnote(PNPROC, pids[i], "kill");
2207dd7cddfSDavid du Colombier 	exits(s);
2217dd7cddfSDavid du Colombier }
2227dd7cddfSDavid du Colombier 
2237dd7cddfSDavid du Colombier void*
emalloc(ulong sz)2247dd7cddfSDavid du Colombier emalloc(ulong sz)
2257dd7cddfSDavid du Colombier {
2267dd7cddfSDavid du Colombier 	void *v;
2277dd7cddfSDavid du Colombier 	v = malloc(sz);
2287dd7cddfSDavid du Colombier 	if(v == nil) {
2297dd7cddfSDavid du Colombier 		fprint(2, "stats: out of memory allocating %ld: %r\n", sz);
2307dd7cddfSDavid du Colombier 		killall("mem");
2317dd7cddfSDavid du Colombier 	}
2327dd7cddfSDavid du Colombier 	memset(v, 0, sz);
2337dd7cddfSDavid du Colombier 	return v;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier void*
erealloc(void * v,ulong sz)2377dd7cddfSDavid du Colombier erealloc(void *v, ulong sz)
2387dd7cddfSDavid du Colombier {
2397dd7cddfSDavid du Colombier 	v = realloc(v, sz);
2407dd7cddfSDavid du Colombier 	if(v == nil) {
2417dd7cddfSDavid du Colombier 		fprint(2, "stats: out of memory reallocating %ld: %r\n", sz);
2427dd7cddfSDavid du Colombier 		killall("mem");
2437dd7cddfSDavid du Colombier 	}
2447dd7cddfSDavid du Colombier 	return v;
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier 
2473e12c5d1SDavid du Colombier char*
estrdup(char * s)2487dd7cddfSDavid du Colombier estrdup(char *s)
2493e12c5d1SDavid du Colombier {
2507dd7cddfSDavid du Colombier 	char *t;
2517dd7cddfSDavid du Colombier 	if((t = strdup(s)) == nil) {
2527dd7cddfSDavid du Colombier 		fprint(2, "stats: out of memory in strdup(%.10s): %r\n", s);
2537dd7cddfSDavid du Colombier 		killall("mem");
2547dd7cddfSDavid du Colombier 	}
2557dd7cddfSDavid du Colombier 	return t;
2563e12c5d1SDavid du Colombier }
2573e12c5d1SDavid du Colombier 
2583e12c5d1SDavid du Colombier void
mkcol(int i,int c0,int c1,int c2)2597dd7cddfSDavid du Colombier mkcol(int i, int c0, int c1, int c2)
2603e12c5d1SDavid du Colombier {
2617dd7cddfSDavid du Colombier 	cols[i][0] = allocimagemix(display, c0, DWhite);
2627dd7cddfSDavid du Colombier 	cols[i][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c1);
2637dd7cddfSDavid du Colombier 	cols[i][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c2);
2647dd7cddfSDavid du Colombier }
2653e12c5d1SDavid du Colombier 
2667dd7cddfSDavid du Colombier void
colinit(void)2677dd7cddfSDavid du Colombier colinit(void)
2687dd7cddfSDavid du Colombier {
2697dd7cddfSDavid du Colombier 	mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font");
2707dd7cddfSDavid du Colombier 	if(mediumfont == nil)
2717dd7cddfSDavid du Colombier 		mediumfont = font;
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	/* Peach */
2747dd7cddfSDavid du Colombier 	mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF);
2757dd7cddfSDavid du Colombier 	/* Aqua */
2767dd7cddfSDavid du Colombier 	mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue);
2777dd7cddfSDavid du Colombier 	/* Yellow */
2787dd7cddfSDavid du Colombier 	mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen);
2797dd7cddfSDavid du Colombier 	/* Green */
2807dd7cddfSDavid du Colombier 	mkcol(3, DPalegreen, DMedgreen, DDarkgreen);
2817dd7cddfSDavid du Colombier 	/* Blue */
2827dd7cddfSDavid du Colombier 	mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF);
2837dd7cddfSDavid du Colombier 	/* Grey */
2847dd7cddfSDavid du Colombier 	cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF);
2857dd7cddfSDavid du Colombier 	cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF);
2867dd7cddfSDavid du Colombier 	cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF);
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier 
2897dd7cddfSDavid du Colombier int
loadbuf(Machine * m,int * fd)2907dd7cddfSDavid du Colombier loadbuf(Machine *m, int *fd)
2917dd7cddfSDavid du Colombier {
2927dd7cddfSDavid du Colombier 	int n;
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier 	if(*fd < 0)
2967dd7cddfSDavid du Colombier 		return 0;
2977dd7cddfSDavid du Colombier 	seek(*fd, 0, 0);
2982e7ae8b5SDavid du Colombier 	n = read(*fd, m->buf, sizeof m->buf-1);
2997dd7cddfSDavid du Colombier 	if(n <= 0){
3007dd7cddfSDavid du Colombier 		close(*fd);
3017dd7cddfSDavid du Colombier 		*fd = -1;
3027dd7cddfSDavid du Colombier 		return 0;
3037dd7cddfSDavid du Colombier 	}
3047dd7cddfSDavid du Colombier 	m->bufp = m->buf;
3057dd7cddfSDavid du Colombier 	m->ebufp = m->buf+n;
3062e7ae8b5SDavid du Colombier 	m->buf[n] = 0;
3077dd7cddfSDavid du Colombier 	return 1;
3087dd7cddfSDavid du Colombier }
3097dd7cddfSDavid du Colombier 
3107dd7cddfSDavid du Colombier void
label(Point p,int dy,char * text)3117dd7cddfSDavid du Colombier label(Point p, int dy, char *text)
3127dd7cddfSDavid du Colombier {
3137dd7cddfSDavid du Colombier 	char *s;
3147dd7cddfSDavid du Colombier 	Rune r[2];
3157dd7cddfSDavid du Colombier 	int w, maxw, maxy;
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	p.x += Labspace;
3187dd7cddfSDavid du Colombier 	maxy = p.y+dy;
3197dd7cddfSDavid du Colombier 	maxw = 0;
3207dd7cddfSDavid du Colombier 	r[1] = '\0';
3217dd7cddfSDavid du Colombier 	for(s=text; *s; ){
3227dd7cddfSDavid du Colombier 		if(p.y+mediumfont->height-Ysqueeze > maxy)
3237dd7cddfSDavid du Colombier 			break;
3247dd7cddfSDavid du Colombier 		w = chartorune(r, s);
3257dd7cddfSDavid du Colombier 		s += w;
3267dd7cddfSDavid du Colombier 		w = runestringwidth(mediumfont, r);
3277dd7cddfSDavid du Colombier 		if(w > maxw)
3287dd7cddfSDavid du Colombier 			maxw = w;
3297dd7cddfSDavid du Colombier 		runestring(screen, p, display->black, ZP, mediumfont, r);
3307dd7cddfSDavid du Colombier 		p.y += mediumfont->height-Ysqueeze;
3317dd7cddfSDavid du Colombier 	}
3327dd7cddfSDavid du Colombier }
3337dd7cddfSDavid du Colombier 
3347dd7cddfSDavid du Colombier Point
paritypt(int x)3357dd7cddfSDavid du Colombier paritypt(int x)
3367dd7cddfSDavid du Colombier {
3377dd7cddfSDavid du Colombier 	return Pt(x+parity, 0);
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier Point
datapoint(Graph * g,int x,uvlong v,uvlong vmax)341b2495906SDavid du Colombier datapoint(Graph *g, int x, uvlong v, uvlong vmax)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier 	Point p;
34480ee5cbfSDavid du Colombier 	double y;
3457dd7cddfSDavid du Colombier 
3467dd7cddfSDavid du Colombier 	p.x = x;
34780ee5cbfSDavid du Colombier 	y = ((double)v)/(vmax*scale);
34880ee5cbfSDavid du Colombier 	if(logscale){
34980ee5cbfSDavid du Colombier 		/*
35080ee5cbfSDavid du Colombier 		 * Arrange scale to cover a factor of 1000.
35180ee5cbfSDavid du Colombier 		 * vmax corresponds to the 100 mark.
35280ee5cbfSDavid du Colombier 		 * 10*vmax is the top of the scale.
35380ee5cbfSDavid du Colombier 		 */
35480ee5cbfSDavid du Colombier 		if(y <= 0.)
35580ee5cbfSDavid du Colombier 			y = 0;
35680ee5cbfSDavid du Colombier 		else{
35780ee5cbfSDavid du Colombier 			y = log10(y);
35880ee5cbfSDavid du Colombier 			/* 1 now corresponds to the top; -2 to the bottom; rescale */
35980ee5cbfSDavid du Colombier 			y = (y+2.)/3.;
36080ee5cbfSDavid du Colombier 		}
36180ee5cbfSDavid du Colombier 	}
362853458f3SDavid du Colombier 	if(y < 0x7fffffff){	/* avoid floating overflow */
36380ee5cbfSDavid du Colombier 		p.y = g->r.max.y - Dy(g->r)*y - Dot;
3647dd7cddfSDavid du Colombier 		if(p.y < g->r.min.y)
3657dd7cddfSDavid du Colombier 			p.y = g->r.min.y;
3667dd7cddfSDavid du Colombier 		if(p.y > g->r.max.y-Dot)
3677dd7cddfSDavid du Colombier 			p.y = g->r.max.y-Dot;
368853458f3SDavid du Colombier 	}else
369853458f3SDavid du Colombier 		p.y = g->r.max.y-Dot;
3707dd7cddfSDavid du Colombier 	return p;
3717dd7cddfSDavid du Colombier }
3727dd7cddfSDavid du Colombier 
3737dd7cddfSDavid du Colombier void
drawdatum(Graph * g,int x,uvlong prev,uvlong v,uvlong vmax)374b2495906SDavid du Colombier drawdatum(Graph *g, int x, uvlong prev, uvlong v, uvlong vmax)
3757dd7cddfSDavid du Colombier {
3767dd7cddfSDavid du Colombier 	int c;
3777dd7cddfSDavid du Colombier 	Point p, q;
3787dd7cddfSDavid du Colombier 
3797dd7cddfSDavid du Colombier 	c = g->colindex;
3807dd7cddfSDavid du Colombier 	p = datapoint(g, x, v, vmax);
3817dd7cddfSDavid du Colombier 	q = datapoint(g, x, prev, vmax);
3827dd7cddfSDavid du Colombier 	if(p.y < q.y){
3837dd7cddfSDavid du Colombier 		draw(screen, Rect(p.x, g->r.min.y, p.x+1, p.y), cols[c][0], nil, paritypt(p.x));
3847dd7cddfSDavid du Colombier 		draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), cols[c][2], nil, ZP);
3857dd7cddfSDavid du Colombier 		draw(screen, Rect(p.x, q.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP);
3867dd7cddfSDavid du Colombier 	}else{
3877dd7cddfSDavid du Colombier 		draw(screen, Rect(p.x, g->r.min.y, p.x+1, q.y), cols[c][0], nil, paritypt(p.x));
3887dd7cddfSDavid du Colombier 		draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), cols[c][2], nil, ZP);
3897dd7cddfSDavid du Colombier 		draw(screen, Rect(p.x, p.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP);
3907dd7cddfSDavid du Colombier 	}
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier void
redraw(Graph * g,uvlong vmax)395b2495906SDavid du Colombier redraw(Graph *g, uvlong vmax)
3967dd7cddfSDavid du Colombier {
3977dd7cddfSDavid du Colombier 	int i, c;
3987dd7cddfSDavid du Colombier 
3997dd7cddfSDavid du Colombier 	c = g->colindex;
4007dd7cddfSDavid du Colombier 	draw(screen, g->r, cols[c][0], nil, paritypt(g->r.min.x));
4017dd7cddfSDavid du Colombier 	for(i=1; i<Dx(g->r); i++)
4027dd7cddfSDavid du Colombier 		drawdatum(g, g->r.max.x-i, g->data[i-1], g->data[i], vmax);
4037dd7cddfSDavid du Colombier 	drawdatum(g, g->r.min.x, g->data[i], g->data[i], vmax);
4047dd7cddfSDavid du Colombier 	g->overflow = 0;
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier 
4077dd7cddfSDavid du Colombier void
update1(Graph * g,uvlong v,uvlong vmax)408b2495906SDavid du Colombier update1(Graph *g, uvlong v, uvlong vmax)
4097dd7cddfSDavid du Colombier {
41031a0f4b7SDavid du Colombier 	char buf[48];
41180ee5cbfSDavid du Colombier 	int overflow;
4127dd7cddfSDavid du Colombier 
4137dd7cddfSDavid du Colombier 	if(g->overflow && g->overtmp!=nil)
4147dd7cddfSDavid du Colombier 		draw(screen, g->overtmp->r, g->overtmp, nil, g->overtmp->r.min);
4157dd7cddfSDavid du Colombier 	draw(screen, g->r, screen, nil, Pt(g->r.min.x+1, g->r.min.y));
4167dd7cddfSDavid du Colombier 	drawdatum(g, g->r.max.x-1, g->data[0], v, vmax);
4177dd7cddfSDavid du Colombier 	memmove(g->data+1, g->data, (g->ndata-1)*sizeof(g->data[0]));
4187dd7cddfSDavid du Colombier 	g->data[0] = v;
4197dd7cddfSDavid du Colombier 	g->overflow = 0;
42080ee5cbfSDavid du Colombier 	if(logscale)
42180ee5cbfSDavid du Colombier 		overflow = (v>10*vmax*scale);
42280ee5cbfSDavid du Colombier 	else
42380ee5cbfSDavid du Colombier 		overflow = (v>vmax*scale);
42480ee5cbfSDavid du Colombier 	if(overflow && g->overtmp!=nil){
4257dd7cddfSDavid du Colombier 		g->overflow = 1;
4267dd7cddfSDavid du Colombier 		draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min);
427b2495906SDavid du Colombier 		sprint(buf, "%llud", v);
4287dd7cddfSDavid du Colombier 		string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, buf);
4297dd7cddfSDavid du Colombier 	}
4307dd7cddfSDavid du Colombier }
4317dd7cddfSDavid du Colombier 
4327dd7cddfSDavid du Colombier /* read one line of text from buffer and process integers */
4337dd7cddfSDavid du Colombier int
readnums(Machine * m,int n,uvlong * a,int spanlines)434b2495906SDavid du Colombier readnums(Machine *m, int n, uvlong *a, int spanlines)
4357dd7cddfSDavid du Colombier {
4367dd7cddfSDavid du Colombier 	int i;
437853458f3SDavid du Colombier 	char *p, *q, *ep;
4387dd7cddfSDavid du Colombier 
4397dd7cddfSDavid du Colombier 	if(spanlines)
4407dd7cddfSDavid du Colombier 		ep = m->ebufp;
4417dd7cddfSDavid du Colombier 	else
4427dd7cddfSDavid du Colombier 		for(ep=m->bufp; ep<m->ebufp; ep++)
4437dd7cddfSDavid du Colombier 			if(*ep == '\n')
4447dd7cddfSDavid du Colombier 				break;
4457dd7cddfSDavid du Colombier 	p = m->bufp;
4467dd7cddfSDavid du Colombier 	for(i=0; i<n && p<ep; i++){
447b2495906SDavid du Colombier 		while(p<ep && (!isascii(*p) || !isdigit(*p)) && *p!='-')
4487dd7cddfSDavid du Colombier 			p++;
4497dd7cddfSDavid du Colombier 		if(p == ep)
4507dd7cddfSDavid du Colombier 			break;
451853458f3SDavid du Colombier 		a[i] = strtoull(p, &q, 10);
452853458f3SDavid du Colombier 		p = q;
4537dd7cddfSDavid du Colombier 	}
4547dd7cddfSDavid du Colombier 	if(ep < m->ebufp)
4557dd7cddfSDavid du Colombier 		ep++;
4567dd7cddfSDavid du Colombier 	m->bufp = ep;
4577dd7cddfSDavid du Colombier 	return i == n;
4587dd7cddfSDavid du Colombier }
4597dd7cddfSDavid du Colombier 
4607dd7cddfSDavid du Colombier /* Network on fd1, mount driver on fd0 */
4617dd7cddfSDavid du Colombier static int
filter(int fd)4627dd7cddfSDavid du Colombier filter(int fd)
4637dd7cddfSDavid du Colombier {
4647dd7cddfSDavid du Colombier 	int p[2];
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier 	if(pipe(p) < 0){
4677dd7cddfSDavid du Colombier 		fprint(2, "stats: can't pipe: %r\n");
4687dd7cddfSDavid du Colombier 		killall("pipe");
4697dd7cddfSDavid du Colombier 	}
4707dd7cddfSDavid du Colombier 
4717dd7cddfSDavid du Colombier 	switch(rfork(RFNOWAIT|RFPROC|RFFDG)) {
4727dd7cddfSDavid du Colombier 	case -1:
4737dd7cddfSDavid du Colombier 		sysfatal("rfork record module");
4747dd7cddfSDavid du Colombier 	case 0:
4757dd7cddfSDavid du Colombier 		dup(fd, 1);
4767dd7cddfSDavid du Colombier 		close(fd);
4777dd7cddfSDavid du Colombier 		dup(p[0], 0);
4787dd7cddfSDavid du Colombier 		close(p[0]);
4797dd7cddfSDavid du Colombier 		close(p[1]);
480f19e7b74SDavid du Colombier 		execl("/bin/aux/fcall", "fcall", nil);
4817dd7cddfSDavid du Colombier 		fprint(2, "stats: can't exec fcall: %r\n");
4827dd7cddfSDavid du Colombier 		killall("fcall");
4837dd7cddfSDavid du Colombier 	default:
4847dd7cddfSDavid du Colombier 		close(fd);
4857dd7cddfSDavid du Colombier 		close(p[0]);
4867dd7cddfSDavid du Colombier 	}
4877dd7cddfSDavid du Colombier 	return p[1];
4887dd7cddfSDavid du Colombier }
4897dd7cddfSDavid du Colombier 
4907dd7cddfSDavid du Colombier /*
4917dd7cddfSDavid du Colombier  * 9fs
4927dd7cddfSDavid du Colombier  */
4937dd7cddfSDavid du Colombier int
connect9fs(char * addr)4947dd7cddfSDavid du Colombier connect9fs(char *addr)
4957dd7cddfSDavid du Colombier {
4969a747e4fSDavid du Colombier 	char dir[256], *na;
4977dd7cddfSDavid du Colombier 	int fd;
4987dd7cddfSDavid du Colombier 
4997dd7cddfSDavid du Colombier 	fprint(2, "connect9fs...");
5007dd7cddfSDavid du Colombier 	na = netmkaddr(addr, 0, "9fs");
5017dd7cddfSDavid du Colombier 
5027dd7cddfSDavid du Colombier 	fprint(2, "dial %s...", na);
5037dd7cddfSDavid du Colombier 	if((fd = dial(na, 0, dir, 0)) < 0)
5047dd7cddfSDavid du Colombier 		return -1;
5057dd7cddfSDavid du Colombier 
5067dd7cddfSDavid du Colombier 	fprint(2, "dir %s...", dir);
5079a747e4fSDavid du Colombier //	if(strstr(dir, "tcp"))
5089a747e4fSDavid du Colombier //		fd = filter(fd);
5097dd7cddfSDavid du Colombier 	return fd;
5107dd7cddfSDavid du Colombier }
5117dd7cddfSDavid du Colombier 
5129a747e4fSDavid du Colombier int
old9p(int fd)5139a747e4fSDavid du Colombier old9p(int fd)
5149a747e4fSDavid du Colombier {
5159a747e4fSDavid du Colombier 	int p[2];
5169a747e4fSDavid du Colombier 
5179a747e4fSDavid du Colombier 	if(pipe(p) < 0)
5189a747e4fSDavid du Colombier 		return -1;
5199a747e4fSDavid du Colombier 
5209a747e4fSDavid du Colombier 	switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
5219a747e4fSDavid du Colombier 	case -1:
5229a747e4fSDavid du Colombier 		return -1;
5239a747e4fSDavid du Colombier 	case 0:
5249a747e4fSDavid du Colombier 		if(fd != 1){
5259a747e4fSDavid du Colombier 			dup(fd, 1);
5269a747e4fSDavid du Colombier 			close(fd);
5279a747e4fSDavid du Colombier 		}
5289a747e4fSDavid du Colombier 		if(p[0] != 0){
5299a747e4fSDavid du Colombier 			dup(p[0], 0);
5309a747e4fSDavid du Colombier 			close(p[0]);
5319a747e4fSDavid du Colombier 		}
5329a747e4fSDavid du Colombier 		close(p[1]);
5339a747e4fSDavid du Colombier 		if(0){
5349a747e4fSDavid du Colombier 			fd = open("/sys/log/cpu", OWRITE);
5359a747e4fSDavid du Colombier 			if(fd != 2){
5369a747e4fSDavid du Colombier 				dup(fd, 2);
5379a747e4fSDavid du Colombier 				close(fd);
5389a747e4fSDavid du Colombier 			}
539f19e7b74SDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-ds", nil);
5409a747e4fSDavid du Colombier 		} else
541f19e7b74SDavid du Colombier 			execl("/bin/srvold9p", "srvold9p", "-s", nil);
5429a747e4fSDavid du Colombier 		return -1;
5439a747e4fSDavid du Colombier 	default:
5449a747e4fSDavid du Colombier 		close(fd);
5459a747e4fSDavid du Colombier 		close(p[0]);
5469a747e4fSDavid du Colombier 	}
5479a747e4fSDavid du Colombier 	return p[1];
5489a747e4fSDavid du Colombier }
5499a747e4fSDavid du Colombier 
5509a747e4fSDavid du Colombier 
5517dd7cddfSDavid du Colombier /*
5527dd7cddfSDavid du Colombier  * exportfs
5537dd7cddfSDavid du Colombier  */
5547dd7cddfSDavid du Colombier int
connectexportfs(char * addr)5557dd7cddfSDavid du Colombier connectexportfs(char *addr)
5567dd7cddfSDavid du Colombier {
5579a747e4fSDavid du Colombier 	char buf[ERRMAX], dir[256], *na;
5587dd7cddfSDavid du Colombier 	int fd, n;
5597dd7cddfSDavid du Colombier 	char *tree;
5609a747e4fSDavid du Colombier 	AuthInfo *ai;
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier 	tree = "/";
5637dd7cddfSDavid du Colombier 	na = netmkaddr(addr, 0, "exportfs");
5647dd7cddfSDavid du Colombier 	if((fd = dial(na, 0, dir, 0)) < 0)
5657dd7cddfSDavid du Colombier 		return -1;
5667dd7cddfSDavid du Colombier 
5679a747e4fSDavid du Colombier 	ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client");
5689a747e4fSDavid du Colombier 	if(ai == nil)
5697dd7cddfSDavid du Colombier 		return -1;
5707dd7cddfSDavid du Colombier 
5717dd7cddfSDavid du Colombier 	n = write(fd, tree, strlen(tree));
5727dd7cddfSDavid du Colombier 	if(n < 0){
5737dd7cddfSDavid du Colombier 		close(fd);
5747dd7cddfSDavid du Colombier 		return -1;
5757dd7cddfSDavid du Colombier 	}
5767dd7cddfSDavid du Colombier 
5777dd7cddfSDavid du Colombier 	strcpy(buf, "can't read tree");
5787dd7cddfSDavid du Colombier 	n = read(fd, buf, sizeof buf - 1);
5797dd7cddfSDavid du Colombier 	if(n!=2 || buf[0]!='O' || buf[1]!='K'){
5807dd7cddfSDavid du Colombier 		buf[sizeof buf - 1] = '\0';
5817dd7cddfSDavid du Colombier 		werrstr("bad remote tree: %s\n", buf);
5827dd7cddfSDavid du Colombier 		close(fd);
5837dd7cddfSDavid du Colombier 		return -1;
5847dd7cddfSDavid du Colombier 	}
5857dd7cddfSDavid du Colombier 
5869a747e4fSDavid du Colombier //	if(strstr(dir, "tcp"))
5879a747e4fSDavid du Colombier //		fd = filter(fd);
5889a747e4fSDavid du Colombier 
5899a747e4fSDavid du Colombier 	if(oldsystem)
5909a747e4fSDavid du Colombier 		return old9p(fd);
5917dd7cddfSDavid du Colombier 
5927dd7cddfSDavid du Colombier 	return fd;
5937dd7cddfSDavid du Colombier }
5947dd7cddfSDavid du Colombier 
5958c1c8807SDavid du Colombier int
readswap(Machine * m,uvlong * a)596b2495906SDavid du Colombier readswap(Machine *m, uvlong *a)
5972e7ae8b5SDavid du Colombier {
5982e7ae8b5SDavid du Colombier 	if(strstr(m->buf, "memory\n")){
5992e7ae8b5SDavid du Colombier 		/* new /dev/swap - skip first 3 numbers */
6002e7ae8b5SDavid du Colombier 		if(!readnums(m, 7, a, 1))
6012e7ae8b5SDavid du Colombier 			return 0;
6022e7ae8b5SDavid du Colombier 		a[0] = a[3];
6032e7ae8b5SDavid du Colombier 		a[1] = a[4];
6042e7ae8b5SDavid du Colombier 		a[2] = a[5];
6052e7ae8b5SDavid du Colombier 		a[3] = a[6];
6062e7ae8b5SDavid du Colombier 		return 1;
6072e7ae8b5SDavid du Colombier 	}
6082e7ae8b5SDavid du Colombier 	return readnums(m, nelem(m->devswap), a, 0);
6092e7ae8b5SDavid du Colombier }
6102e7ae8b5SDavid du Colombier 
611eebedd9aSDavid du Colombier char*
shortname(char * s)612eebedd9aSDavid du Colombier shortname(char *s)
613eebedd9aSDavid du Colombier {
614eebedd9aSDavid du Colombier 	char *p, *e;
615eebedd9aSDavid du Colombier 
616eebedd9aSDavid du Colombier 	p = estrdup(s);
617eebedd9aSDavid du Colombier 	e = strchr(p, '.');
618eebedd9aSDavid du Colombier 	if(e)
619eebedd9aSDavid du Colombier 		*e = 0;
620eebedd9aSDavid du Colombier 	return p;
621eebedd9aSDavid du Colombier }
622eebedd9aSDavid du Colombier 
623eebedd9aSDavid du Colombier int
ilog10(uvlong j)624b2495906SDavid du Colombier ilog10(uvlong j)
625eebedd9aSDavid du Colombier {
626eebedd9aSDavid du Colombier 	int i;
627eebedd9aSDavid du Colombier 
628eebedd9aSDavid du Colombier 	for(i = 0; j >= 10; i++)
629eebedd9aSDavid du Colombier 		j /= 10;
630eebedd9aSDavid du Colombier 	return i;
631eebedd9aSDavid du Colombier }
632eebedd9aSDavid du Colombier 
6332e7ae8b5SDavid du Colombier int
initmach(Machine * m,char * name)6347dd7cddfSDavid du Colombier initmach(Machine *m, char *name)
6357dd7cddfSDavid du Colombier {
6367dd7cddfSDavid du Colombier 	int n, fd;
637b2495906SDavid du Colombier 	uvlong a[MAXNUM];
6387dd7cddfSDavid du Colombier 	char *p, mpt[256], buf[256];
6397dd7cddfSDavid du Colombier 
6407dd7cddfSDavid du Colombier 	p = strchr(name, '!');
6418c1c8807SDavid du Colombier 	if(p)
6427dd7cddfSDavid du Colombier 		p++;
6438c1c8807SDavid du Colombier 	else
6447dd7cddfSDavid du Colombier 		p = name;
6457dd7cddfSDavid du Colombier 	m->name = estrdup(p);
646eebedd9aSDavid du Colombier 	m->shortname = shortname(p);
6477dd7cddfSDavid du Colombier 	m->remote = (strcmp(p, mysysname) != 0);
6487dd7cddfSDavid du Colombier 	if(m->remote == 0)
6497dd7cddfSDavid du Colombier 		strcpy(mpt, "");
6507dd7cddfSDavid du Colombier 	else{
6517dd7cddfSDavid du Colombier 		snprint(mpt, sizeof mpt, "/n/%s", p);
6527dd7cddfSDavid du Colombier 		fd = connectexportfs(name);
6537dd7cddfSDavid du Colombier 		if(fd < 0){
6547dd7cddfSDavid du Colombier 			fprint(2, "can't connect to %s: %r\n", name);
6558c1c8807SDavid du Colombier 			return 0;
6567dd7cddfSDavid du Colombier 		}
6579a747e4fSDavid du Colombier 		/* BUG? need to use amount() now? */
6589a747e4fSDavid du Colombier 		if(mount(fd, -1, mpt, MREPL, "") < 0){
6597dd7cddfSDavid du Colombier 			fprint(2, "stats: mount %s on %s failed (%r); trying /n/sid\n", name, mpt);
6607dd7cddfSDavid du Colombier 			strcpy(mpt, "/n/sid");
6619a747e4fSDavid du Colombier 			if(mount(fd, -1, mpt, MREPL, "") < 0){
6627dd7cddfSDavid du Colombier 				fprint(2, "stats: mount %s on %s failed: %r\n", name, mpt);
6638c1c8807SDavid du Colombier 				return 0;
6647dd7cddfSDavid du Colombier 			}
6657dd7cddfSDavid du Colombier 		}
6667dd7cddfSDavid du Colombier 	}
6677dd7cddfSDavid du Colombier 
6687dd7cddfSDavid du Colombier 	snprint(buf, sizeof buf, "%s/dev/swap", mpt);
6697dd7cddfSDavid du Colombier 	m->swapfd = open(buf, OREAD);
6702e7ae8b5SDavid du Colombier 	if(loadbuf(m, &m->swapfd) && readswap(m, a))
6717dd7cddfSDavid du Colombier 		memmove(m->devswap, a, sizeof m->devswap);
672b2495906SDavid du Colombier 	else{
673b2495906SDavid du Colombier 		m->devswap[Maxswap] = 100;
674b2495906SDavid du Colombier 		m->devswap[Maxmem] = 100;
675b2495906SDavid du Colombier 	}
6767dd7cddfSDavid du Colombier 
6777dd7cddfSDavid du Colombier 	snprint(buf, sizeof buf, "%s/dev/sysstat", mpt);
6787dd7cddfSDavid du Colombier 	m->statsfd = open(buf, OREAD);
6797dd7cddfSDavid du Colombier 	if(loadbuf(m, &m->statsfd)){
6807dd7cddfSDavid du Colombier 		for(n=0; readnums(m, nelem(m->devsysstat), a, 0); n++)
6817dd7cddfSDavid du Colombier 			;
6827dd7cddfSDavid du Colombier 		m->nproc = n;
6837dd7cddfSDavid du Colombier 	}else
6847dd7cddfSDavid du Colombier 		m->nproc = 1;
685eebedd9aSDavid du Colombier 	m->lgproc = ilog10(m->nproc);
6867dd7cddfSDavid du Colombier 
6873432ceaeSDavid du Colombier 	snprint(buf, sizeof buf, "%s/net/ether0/stats", mpt);
6883432ceaeSDavid du Colombier 	m->etherfd = open(buf, OREAD);
6897dd7cddfSDavid du Colombier 	if(loadbuf(m, &m->etherfd) && readnums(m, nelem(m->netetherstats), a, 1))
6907dd7cddfSDavid du Colombier 		memmove(m->netetherstats, a, sizeof m->netetherstats);
69180ee5cbfSDavid du Colombier 
6923432ceaeSDavid du Colombier 	snprint(buf, sizeof buf, "%s/net/ether0/ifstats", mpt);
6933432ceaeSDavid du Colombier 	m->ifstatsfd = open(buf, OREAD);
6949a747e4fSDavid du Colombier 	if(loadbuf(m, &m->ifstatsfd)){
6959a747e4fSDavid du Colombier 		/* need to check that this is a wavelan interface */
6969a747e4fSDavid du Colombier 		if(strncmp(m->buf, "Signal: ", 8) == 0 && readnums(m, nelem(m->netetherifstats), a, 1))
6979a747e4fSDavid du Colombier 			memmove(m->netetherifstats, a, sizeof m->netetherifstats);
6989a747e4fSDavid du Colombier 	}
6999a747e4fSDavid du Colombier 
70080ee5cbfSDavid du Colombier 	snprint(buf, sizeof buf, "%s/mnt/apm/battery", mpt);
70180ee5cbfSDavid du Colombier 	m->batteryfd = open(buf, OREAD);
7029a747e4fSDavid du Colombier 	m->bitsybatfd = -1;
7039a747e4fSDavid du Colombier 	if(m->batteryfd >= 0){
70480ee5cbfSDavid du Colombier 		if(loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0))
70580ee5cbfSDavid du Colombier 			memmove(m->batterystats, a, sizeof(m->batterystats));
7069a747e4fSDavid du Colombier 	}else{
7079a747e4fSDavid du Colombier 		snprint(buf, sizeof buf, "%s/dev/battery", mpt);
7089a747e4fSDavid du Colombier 		m->bitsybatfd = open(buf, OREAD);
7099a747e4fSDavid du Colombier 		if(loadbuf(m, &m->bitsybatfd) && readnums(m, 1, a, 0))
7109a747e4fSDavid du Colombier 			memmove(m->batterystats, a, sizeof(m->batterystats));
7119a747e4fSDavid du Colombier 	}
712b2495906SDavid du Colombier 	snprint(buf, sizeof buf, "%s/dev/cputemp", mpt);
713b2495906SDavid du Colombier 	m->tempfd = open(buf, OREAD);
714b2495906SDavid du Colombier 	if(loadbuf(m, &m->tempfd))
715b2495906SDavid du Colombier 		for(n=0; n < nelem(m->temp) && readnums(m, 2, a, 0); n++)
716b2495906SDavid du Colombier 			 m->temp[n] = a[0];
7178c1c8807SDavid du Colombier 	return 1;
7187dd7cddfSDavid du Colombier }
7197dd7cddfSDavid du Colombier 
7207dd7cddfSDavid du Colombier jmp_buf catchalarm;
7217dd7cddfSDavid du Colombier 
7227dd7cddfSDavid du Colombier void
alarmed(void * a,char * s)7237dd7cddfSDavid du Colombier alarmed(void *a, char *s)
7247dd7cddfSDavid du Colombier {
7257dd7cddfSDavid du Colombier 	if(strcmp(s, "alarm") == 0)
7267dd7cddfSDavid du Colombier 		notejmp(a, catchalarm, 1);
7273e12c5d1SDavid du Colombier 	noted(NDFLT);
7283e12c5d1SDavid du Colombier }
7297dd7cddfSDavid du Colombier 
7307dd7cddfSDavid du Colombier int
needswap(int init)7317dd7cddfSDavid du Colombier needswap(int init)
7327dd7cddfSDavid du Colombier {
7337dd7cddfSDavid du Colombier 	return init | present[Mmem] | present[Mswap];
7347dd7cddfSDavid du Colombier }
7357dd7cddfSDavid du Colombier 
7367dd7cddfSDavid du Colombier 
7377dd7cddfSDavid du Colombier int
needstat(int init)7387dd7cddfSDavid du Colombier needstat(int init)
7397dd7cddfSDavid du Colombier {
740dc5a79c1SDavid du Colombier 	return init | present[Mcontext]  | present[Mfault] | present[Mintr] | present[Mload] | present[Midle] |
741f86ef3ceSDavid du Colombier 		present[Minintr] | present[Msyscall] | present[Mtlbmiss] | present[Mtlbpurge];
7427dd7cddfSDavid du Colombier }
7437dd7cddfSDavid du Colombier 
7447dd7cddfSDavid du Colombier 
7457dd7cddfSDavid du Colombier int
needether(int init)7467dd7cddfSDavid du Colombier needether(int init)
7477dd7cddfSDavid du Colombier {
7487dd7cddfSDavid du Colombier 	return init | present[Mether] | present[Metherin] | present[Metherout] | present[Methererr];
7497dd7cddfSDavid du Colombier }
7507dd7cddfSDavid du Colombier 
75180ee5cbfSDavid du Colombier int
needbattery(int init)75280ee5cbfSDavid du Colombier needbattery(int init)
75380ee5cbfSDavid du Colombier {
75480ee5cbfSDavid du Colombier 	return init | present[Mbattery];
75580ee5cbfSDavid du Colombier }
75680ee5cbfSDavid du Colombier 
7579a747e4fSDavid du Colombier int
needsignal(int init)7589a747e4fSDavid du Colombier needsignal(int init)
7599a747e4fSDavid du Colombier {
7609a747e4fSDavid du Colombier 	return init | present[Msignal];
7619a747e4fSDavid du Colombier }
7629a747e4fSDavid du Colombier 
763b2495906SDavid du Colombier int
needtemp(int init)764b2495906SDavid du Colombier needtemp(int init)
765b2495906SDavid du Colombier {
766b2495906SDavid du Colombier 	return init | present[Mtemp];
767b2495906SDavid du Colombier }
768b2495906SDavid du Colombier 
7697dd7cddfSDavid du Colombier void
readmach(Machine * m,int init)7707dd7cddfSDavid du Colombier readmach(Machine *m, int init)
7717dd7cddfSDavid du Colombier {
7727dd7cddfSDavid du Colombier 	int n, i;
773b2495906SDavid du Colombier 	uvlong a[nelem(m->devsysstat)];
7747dd7cddfSDavid du Colombier 	char buf[32];
7757dd7cddfSDavid du Colombier 
7767dd7cddfSDavid du Colombier 	if(m->remote && (m->disable || setjmp(catchalarm))){
7778c1c8807SDavid du Colombier 		if (m->disable++ >= 5)
7788c1c8807SDavid du Colombier 			m->disable = 0; /* give it another chance */
7797dd7cddfSDavid du Colombier 		memmove(m->devsysstat, m->prevsysstat, sizeof m->devsysstat);
7807dd7cddfSDavid du Colombier 		memmove(m->netetherstats, m->prevetherstats, sizeof m->netetherstats);
7817dd7cddfSDavid du Colombier 		return;
7827dd7cddfSDavid du Colombier 	}
7838c1c8807SDavid du Colombier 	snprint(buf, sizeof buf, "%s", m->name);
7848c1c8807SDavid du Colombier 	if (strcmp(m->name, buf) != 0){
7858c1c8807SDavid du Colombier 		free(m->name);
7868c1c8807SDavid du Colombier 		m->name = estrdup(buf);
787eebedd9aSDavid du Colombier 		free(m->shortname);
788eebedd9aSDavid du Colombier 		m->shortname = shortname(buf);
7898c1c8807SDavid du Colombier 		if(display != nil)	/* else we're still initializing */
7908c1c8807SDavid du Colombier 			eresized(0);
7918c1c8807SDavid du Colombier 	}
7927dd7cddfSDavid du Colombier 	if(m->remote){
7937dd7cddfSDavid du Colombier 		notify(alarmed);
7947dd7cddfSDavid du Colombier 		alarm(5000);
7957dd7cddfSDavid du Colombier 	}
7962e7ae8b5SDavid du Colombier 	if(needswap(init) && loadbuf(m, &m->swapfd) && readswap(m, a))
7977dd7cddfSDavid du Colombier 		memmove(m->devswap, a, sizeof m->devswap);
7987dd7cddfSDavid du Colombier 	if(needstat(init) && loadbuf(m, &m->statsfd)){
7997dd7cddfSDavid du Colombier 		memmove(m->prevsysstat, m->devsysstat, sizeof m->devsysstat);
8007dd7cddfSDavid du Colombier 		memset(m->devsysstat, 0, sizeof m->devsysstat);
8017dd7cddfSDavid du Colombier 		for(n=0; n<m->nproc && readnums(m, nelem(m->devsysstat), a, 0); n++)
8027dd7cddfSDavid du Colombier 			for(i=0; i<nelem(m->devsysstat); i++)
8037dd7cddfSDavid du Colombier 				m->devsysstat[i] += a[i];
8047dd7cddfSDavid du Colombier 	}
8057dd7cddfSDavid du Colombier 	if(needether(init) && loadbuf(m, &m->etherfd) && readnums(m, nelem(m->netetherstats), a, 1)){
8067dd7cddfSDavid du Colombier 		memmove(m->prevetherstats, m->netetherstats, sizeof m->netetherstats);
8077dd7cddfSDavid du Colombier 		memmove(m->netetherstats, a, sizeof m->netetherstats);
8087dd7cddfSDavid du Colombier 	}
8099a747e4fSDavid du Colombier 	if(needsignal(init) && loadbuf(m, &m->ifstatsfd) && strncmp(m->buf, "Signal: ", 8)==0 && readnums(m, nelem(m->netetherifstats), a, 1)){
8109a747e4fSDavid du Colombier 		memmove(m->netetherifstats, a, sizeof m->netetherifstats);
8119a747e4fSDavid du Colombier 	}
81280ee5cbfSDavid du Colombier 	if(needbattery(init) && loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0))
81380ee5cbfSDavid du Colombier 		memmove(m->batterystats, a, sizeof(m->batterystats));
8149a747e4fSDavid du Colombier 	if(needbattery(init) && loadbuf(m, &m->bitsybatfd) && readnums(m, 1, a, 0))
8159a747e4fSDavid du Colombier 		memmove(m->batterystats, a, sizeof(m->batterystats));
816b2495906SDavid du Colombier 	if(needtemp(init) && loadbuf(m, &m->tempfd))
817b2495906SDavid du Colombier 		for(n=0; n < nelem(m->temp) && readnums(m, 2, a, 0); n++)
818b2495906SDavid du Colombier 			 m->temp[n] = a[0];
8197dd7cddfSDavid du Colombier 	if(m->remote){
8207dd7cddfSDavid du Colombier 		alarm(0);
8217dd7cddfSDavid du Colombier 		notify(nil);
8227dd7cddfSDavid du Colombier 	}
8237dd7cddfSDavid du Colombier }
8247dd7cddfSDavid du Colombier 
8257dd7cddfSDavid du Colombier void
memval(Machine * m,uvlong * v,uvlong * vmax,int)826b2495906SDavid du Colombier memval(Machine *m, uvlong *v, uvlong *vmax, int)
8277dd7cddfSDavid du Colombier {
8287dd7cddfSDavid du Colombier 	*v = m->devswap[Mem];
8297dd7cddfSDavid du Colombier 	*vmax = m->devswap[Maxmem];
8307dd7cddfSDavid du Colombier }
8317dd7cddfSDavid du Colombier 
8327dd7cddfSDavid du Colombier void
swapval(Machine * m,uvlong * v,uvlong * vmax,int)833b2495906SDavid du Colombier swapval(Machine *m, uvlong *v, uvlong *vmax, int)
8347dd7cddfSDavid du Colombier {
8357dd7cddfSDavid du Colombier 	*v = m->devswap[Swap];
8367dd7cddfSDavid du Colombier 	*vmax = m->devswap[Maxswap];
8377dd7cddfSDavid du Colombier }
8387dd7cddfSDavid du Colombier 
8397dd7cddfSDavid du Colombier void
contextval(Machine * m,uvlong * v,uvlong * vmax,int init)840b2495906SDavid du Colombier contextval(Machine *m, uvlong *v, uvlong *vmax, int init)
8417dd7cddfSDavid du Colombier {
8427dd7cddfSDavid du Colombier 	*v = m->devsysstat[Context]-m->prevsysstat[Context];
843186fc3d1SDavid du Colombier 	*vmax = sleeptime*m->nproc;
84480ee5cbfSDavid du Colombier 	if(init)
845186fc3d1SDavid du Colombier 		*vmax = sleeptime;
8467dd7cddfSDavid du Colombier }
8477dd7cddfSDavid du Colombier 
848b2495906SDavid du Colombier /*
849b2495906SDavid du Colombier  * bug: need to factor in HZ
850b2495906SDavid du Colombier  */
8517dd7cddfSDavid du Colombier void
intrval(Machine * m,uvlong * v,uvlong * vmax,int init)852b2495906SDavid du Colombier intrval(Machine *m, uvlong *v, uvlong *vmax, int init)
8537dd7cddfSDavid du Colombier {
8547dd7cddfSDavid du Colombier 	*v = m->devsysstat[Interrupt]-m->prevsysstat[Interrupt];
855b2495906SDavid du Colombier 	*vmax = sleeptime*m->nproc*10;
85680ee5cbfSDavid du Colombier 	if(init)
857b2495906SDavid du Colombier 		*vmax = sleeptime*10;
8587dd7cddfSDavid du Colombier }
8597dd7cddfSDavid du Colombier 
8607dd7cddfSDavid du Colombier void
syscallval(Machine * m,uvlong * v,uvlong * vmax,int init)861b2495906SDavid du Colombier syscallval(Machine *m, uvlong *v, uvlong *vmax, int init)
8627dd7cddfSDavid du Colombier {
8637dd7cddfSDavid du Colombier 	*v = m->devsysstat[Syscall]-m->prevsysstat[Syscall];
864186fc3d1SDavid du Colombier 	*vmax = sleeptime*m->nproc;
86580ee5cbfSDavid du Colombier 	if(init)
866186fc3d1SDavid du Colombier 		*vmax = sleeptime;
8677dd7cddfSDavid du Colombier }
8687dd7cddfSDavid du Colombier 
8697dd7cddfSDavid du Colombier void
faultval(Machine * m,uvlong * v,uvlong * vmax,int init)870b2495906SDavid du Colombier faultval(Machine *m, uvlong *v, uvlong *vmax, int init)
8717dd7cddfSDavid du Colombier {
8727dd7cddfSDavid du Colombier 	*v = m->devsysstat[Fault]-m->prevsysstat[Fault];
873186fc3d1SDavid du Colombier 	*vmax = sleeptime*m->nproc;
87480ee5cbfSDavid du Colombier 	if(init)
875186fc3d1SDavid du Colombier 		*vmax = sleeptime;
8767dd7cddfSDavid du Colombier }
8777dd7cddfSDavid du Colombier 
8787dd7cddfSDavid du Colombier void
tlbmissval(Machine * m,uvlong * v,uvlong * vmax,int init)879b2495906SDavid du Colombier tlbmissval(Machine *m, uvlong *v, uvlong *vmax, int init)
8807dd7cddfSDavid du Colombier {
8817dd7cddfSDavid du Colombier 	*v = m->devsysstat[TLBfault]-m->prevsysstat[TLBfault];
882186fc3d1SDavid du Colombier 	*vmax = (sleeptime/1000)*10*m->nproc;
88380ee5cbfSDavid du Colombier 	if(init)
884186fc3d1SDavid du Colombier 		*vmax = (sleeptime/1000)*10;
885*fee9fd16SDavid du Colombier 	if (mycputype && strcmp(mycputype, "mips") == 0)
886*fee9fd16SDavid du Colombier 		*vmax *= 50000;		/* mainly for 16-entry tlbs (rb) */
8877dd7cddfSDavid du Colombier }
8887dd7cddfSDavid du Colombier 
8897dd7cddfSDavid du Colombier void
tlbpurgeval(Machine * m,uvlong * v,uvlong * vmax,int init)890b2495906SDavid du Colombier tlbpurgeval(Machine *m, uvlong *v, uvlong *vmax, int init)
8917dd7cddfSDavid du Colombier {
8927dd7cddfSDavid du Colombier 	*v = m->devsysstat[TLBpurge]-m->prevsysstat[TLBpurge];
893186fc3d1SDavid du Colombier 	*vmax = (sleeptime/1000)*10*m->nproc;
89480ee5cbfSDavid du Colombier 	if(init)
895186fc3d1SDavid du Colombier 		*vmax = (sleeptime/1000)*10;
8967dd7cddfSDavid du Colombier }
8977dd7cddfSDavid du Colombier 
8987dd7cddfSDavid du Colombier void
loadval(Machine * m,uvlong * v,uvlong * vmax,int init)899b2495906SDavid du Colombier loadval(Machine *m, uvlong *v, uvlong *vmax, int init)
9007dd7cddfSDavid du Colombier {
9017dd7cddfSDavid du Colombier 	*v = m->devsysstat[Load];
9027dd7cddfSDavid du Colombier 	*vmax = 1000*m->nproc;
90380ee5cbfSDavid du Colombier 	if(init)
90480ee5cbfSDavid du Colombier 		*vmax = 1000;
9057dd7cddfSDavid du Colombier }
9067dd7cddfSDavid du Colombier 
9077dd7cddfSDavid du Colombier void
idleval(Machine * m,uvlong * v,uvlong * vmax,int)908b2495906SDavid du Colombier idleval(Machine *m, uvlong *v, uvlong *vmax, int)
909dc5a79c1SDavid du Colombier {
910f86ef3ceSDavid du Colombier 	*v = m->devsysstat[Idle]/m->nproc;
911dc5a79c1SDavid du Colombier 	*vmax = 100;
912dc5a79c1SDavid du Colombier }
913dc5a79c1SDavid du Colombier 
914dc5a79c1SDavid du Colombier void
inintrval(Machine * m,uvlong * v,uvlong * vmax,int)915b2495906SDavid du Colombier inintrval(Machine *m, uvlong *v, uvlong *vmax, int)
916f86ef3ceSDavid du Colombier {
917f86ef3ceSDavid du Colombier 	*v = m->devsysstat[InIntr]/m->nproc;
918f86ef3ceSDavid du Colombier 	*vmax = 100;
919f86ef3ceSDavid du Colombier }
920f86ef3ceSDavid du Colombier 
921f86ef3ceSDavid du Colombier void
etherval(Machine * m,uvlong * v,uvlong * vmax,int init)922b2495906SDavid du Colombier etherval(Machine *m, uvlong *v, uvlong *vmax, int init)
9237dd7cddfSDavid du Colombier {
9247dd7cddfSDavid du Colombier 	*v = m->netetherstats[In]-m->prevetherstats[In] + m->netetherstats[Out]-m->prevetherstats[Out];
925186fc3d1SDavid du Colombier 	*vmax = sleeptime*m->nproc;
92680ee5cbfSDavid du Colombier 	if(init)
927186fc3d1SDavid du Colombier 		*vmax = sleeptime;
9287dd7cddfSDavid du Colombier }
9297dd7cddfSDavid du Colombier 
9307dd7cddfSDavid du Colombier void
etherinval(Machine * m,uvlong * v,uvlong * vmax,int init)931b2495906SDavid du Colombier etherinval(Machine *m, uvlong *v, uvlong *vmax, int init)
9327dd7cddfSDavid du Colombier {
9337dd7cddfSDavid du Colombier 	*v = m->netetherstats[In]-m->prevetherstats[In];
934186fc3d1SDavid du Colombier 	*vmax = sleeptime*m->nproc;
93580ee5cbfSDavid du Colombier 	if(init)
936186fc3d1SDavid du Colombier 		*vmax = sleeptime;
9377dd7cddfSDavid du Colombier }
9387dd7cddfSDavid du Colombier 
9397dd7cddfSDavid du Colombier void
etheroutval(Machine * m,uvlong * v,uvlong * vmax,int init)940b2495906SDavid du Colombier etheroutval(Machine *m, uvlong *v, uvlong *vmax, int init)
9417dd7cddfSDavid du Colombier {
9427dd7cddfSDavid du Colombier 	*v = m->netetherstats[Out]-m->prevetherstats[Out];
943186fc3d1SDavid du Colombier 	*vmax = sleeptime*m->nproc;
94480ee5cbfSDavid du Colombier 	if(init)
945186fc3d1SDavid du Colombier 		*vmax = sleeptime;
9467dd7cddfSDavid du Colombier }
9477dd7cddfSDavid du Colombier 
9487dd7cddfSDavid du Colombier void
ethererrval(Machine * m,uvlong * v,uvlong * vmax,int init)949b2495906SDavid du Colombier ethererrval(Machine *m, uvlong *v, uvlong *vmax, int init)
9507dd7cddfSDavid du Colombier {
9517dd7cddfSDavid du Colombier 	int i;
9527dd7cddfSDavid du Colombier 
9537dd7cddfSDavid du Colombier 	*v = 0;
9547dd7cddfSDavid du Colombier 	for(i=Err0; i<nelem(m->netetherstats); i++)
9557dd7cddfSDavid du Colombier 		*v += m->netetherstats[i];
956186fc3d1SDavid du Colombier 	*vmax = (sleeptime/1000)*10*m->nproc;
95780ee5cbfSDavid du Colombier 	if(init)
958186fc3d1SDavid du Colombier 		*vmax = (sleeptime/1000)*10;
95980ee5cbfSDavid du Colombier }
96080ee5cbfSDavid du Colombier 
96180ee5cbfSDavid du Colombier void
batteryval(Machine * m,uvlong * v,uvlong * vmax,int)962b2495906SDavid du Colombier batteryval(Machine *m, uvlong *v, uvlong *vmax, int)
96380ee5cbfSDavid du Colombier {
96480ee5cbfSDavid du Colombier 	*v = m->batterystats[0];
9659a747e4fSDavid du Colombier 	if(m->bitsybatfd >= 0)
9669a747e4fSDavid du Colombier 		*vmax = 184;		// at least on my bitsy...
9679a747e4fSDavid du Colombier 	else
96880ee5cbfSDavid du Colombier 		*vmax = 100;
9697dd7cddfSDavid du Colombier }
9707dd7cddfSDavid du Colombier 
9717dd7cddfSDavid du Colombier void
signalval(Machine * m,uvlong * v,uvlong * vmax,int)972b2495906SDavid du Colombier signalval(Machine *m, uvlong *v, uvlong *vmax, int)
9739a747e4fSDavid du Colombier {
974f86ef3ceSDavid du Colombier 	ulong l;
9759a747e4fSDavid du Colombier 
976186fc3d1SDavid du Colombier 	*vmax = sleeptime;
9779a747e4fSDavid du Colombier 	l = m->netetherifstats[0];
9789a747e4fSDavid du Colombier 	/*
9799a747e4fSDavid du Colombier 	 * Range is seen to be from about -45 (strong) to -95 (weak); rescale
9809a747e4fSDavid du Colombier 	 */
9819a747e4fSDavid du Colombier 	if(l == 0){	/* probably not present */
9829a747e4fSDavid du Colombier 		*v = 0;
9839a747e4fSDavid du Colombier 		return;
9849a747e4fSDavid du Colombier 	}
9859a747e4fSDavid du Colombier 	*v = 20*(l+95);
9869a747e4fSDavid du Colombier }
9879a747e4fSDavid du Colombier 
9889a747e4fSDavid du Colombier void
tempval(Machine * m,uvlong * v,uvlong * vmax,int)989b2495906SDavid du Colombier tempval(Machine *m, uvlong *v, uvlong *vmax, int)
990b2495906SDavid du Colombier {
991b2495906SDavid du Colombier 	ulong l;
992b2495906SDavid du Colombier 
993b2495906SDavid du Colombier 	*vmax = sleeptime;
994b2495906SDavid du Colombier 	l = m->temp[0];
995b2495906SDavid du Colombier 	if(l == ~0 || l == 0)
996b2495906SDavid du Colombier 		*v = 0;
997b2495906SDavid du Colombier 	else
998b2495906SDavid du Colombier 		*v = (l-20)*27;
999b2495906SDavid du Colombier }
1000b2495906SDavid du Colombier 
1001b2495906SDavid du Colombier void
usage(void)10027dd7cddfSDavid du Colombier usage(void)
10037dd7cddfSDavid du Colombier {
10049a747e4fSDavid du Colombier 	fprint(2, "usage: stats [-O] [-S scale] [-LY] [-%s] [machine...]\n", argchars);
10057dd7cddfSDavid du Colombier 	exits("usage");
10067dd7cddfSDavid du Colombier }
10077dd7cddfSDavid du Colombier 
10087dd7cddfSDavid du Colombier void
addgraph(int n)10097dd7cddfSDavid du Colombier addgraph(int n)
10107dd7cddfSDavid du Colombier {
10117dd7cddfSDavid du Colombier 	Graph *g, *ograph;
10127dd7cddfSDavid du Colombier 	int i, j;
10137dd7cddfSDavid du Colombier 	static int nadd;
10147dd7cddfSDavid du Colombier 
10157dd7cddfSDavid du Colombier 	if(n > nelem(menu2str))
10167dd7cddfSDavid du Colombier 		abort();
10177dd7cddfSDavid du Colombier 	/* avoid two adjacent graphs of same color */
10187dd7cddfSDavid du Colombier 	if(ngraph>0 && graph[ngraph-1].colindex==nadd%Ncolor)
10197dd7cddfSDavid du Colombier 		nadd++;
10207dd7cddfSDavid du Colombier 	ograph = graph;
10217dd7cddfSDavid du Colombier 	graph = emalloc(nmach*(ngraph+1)*sizeof(Graph));
10227dd7cddfSDavid du Colombier 	for(i=0; i<nmach; i++)
10237dd7cddfSDavid du Colombier 		for(j=0; j<ngraph; j++)
10247dd7cddfSDavid du Colombier 			graph[i*(ngraph+1)+j] = ograph[i*ngraph+j];
10257dd7cddfSDavid du Colombier 	free(ograph);
10267dd7cddfSDavid du Colombier 	ngraph++;
10277dd7cddfSDavid du Colombier 	for(i=0; i<nmach; i++){
10287dd7cddfSDavid du Colombier 		g = &graph[i*ngraph+(ngraph-1)];
10297dd7cddfSDavid du Colombier 		memset(g, 0, sizeof(Graph));
10307dd7cddfSDavid du Colombier 		g->label = menu2str[n]+Opwid;
10317dd7cddfSDavid du Colombier 		g->newvalue = newvaluefn[n];
10327dd7cddfSDavid du Colombier 		g->update = update1;	/* no other update functions yet */
10337dd7cddfSDavid du Colombier 		g->mach = &mach[i];
10347dd7cddfSDavid du Colombier 		g->colindex = nadd%Ncolor;
10357dd7cddfSDavid du Colombier 	}
10367dd7cddfSDavid du Colombier 	present[n] = 1;
10377dd7cddfSDavid du Colombier 	nadd++;
10387dd7cddfSDavid du Colombier }
10397dd7cddfSDavid du Colombier 
10407dd7cddfSDavid du Colombier void
dropgraph(int which)10417dd7cddfSDavid du Colombier dropgraph(int which)
10427dd7cddfSDavid du Colombier {
10437dd7cddfSDavid du Colombier 	Graph *ograph;
10447dd7cddfSDavid du Colombier 	int i, j, n;
10457dd7cddfSDavid du Colombier 
10467dd7cddfSDavid du Colombier 	if(which > nelem(menu2str))
10477dd7cddfSDavid du Colombier 		abort();
10487dd7cddfSDavid du Colombier 	/* convert n to index in graph table */
10497dd7cddfSDavid du Colombier 	n = -1;
10507dd7cddfSDavid du Colombier 	for(i=0; i<ngraph; i++)
10517dd7cddfSDavid du Colombier 		if(strcmp(menu2str[which]+Opwid, graph[i].label) == 0){
10527dd7cddfSDavid du Colombier 			n = i;
10537dd7cddfSDavid du Colombier 			break;
10547dd7cddfSDavid du Colombier 		}
10557dd7cddfSDavid du Colombier 	if(n < 0){
10567dd7cddfSDavid du Colombier 		fprint(2, "stats: internal error can't drop graph\n");
10577dd7cddfSDavid du Colombier 		killall("error");
10587dd7cddfSDavid du Colombier 	}
10597dd7cddfSDavid du Colombier 	ograph = graph;
10607dd7cddfSDavid du Colombier 	graph = emalloc(nmach*(ngraph-1)*sizeof(Graph));
10617dd7cddfSDavid du Colombier 	for(i=0; i<nmach; i++){
10627dd7cddfSDavid du Colombier 		for(j=0; j<n; j++)
10637dd7cddfSDavid du Colombier 			graph[i*(ngraph-1)+j] = ograph[i*ngraph+j];
10647dd7cddfSDavid du Colombier 		free(ograph[i*ngraph+j].data);
10657dd7cddfSDavid du Colombier 		freeimage(ograph[i*ngraph+j].overtmp);
10667dd7cddfSDavid du Colombier 		for(j++; j<ngraph; j++)
10677dd7cddfSDavid du Colombier 			graph[i*(ngraph-1)+j-1] = ograph[i*ngraph+j];
10687dd7cddfSDavid du Colombier 	}
10697dd7cddfSDavid du Colombier 	free(ograph);
10707dd7cddfSDavid du Colombier 	ngraph--;
10717dd7cddfSDavid du Colombier 	present[which] = 0;
10727dd7cddfSDavid du Colombier }
10737dd7cddfSDavid du Colombier 
10748c1c8807SDavid du Colombier int
addmachine(char * name)10757dd7cddfSDavid du Colombier addmachine(char *name)
10767dd7cddfSDavid du Colombier {
10777dd7cddfSDavid du Colombier 	if(ngraph > 0){
10787dd7cddfSDavid du Colombier 		fprint(2, "stats: internal error: ngraph>0 in addmachine()\n");
10797dd7cddfSDavid du Colombier 		usage();
10807dd7cddfSDavid du Colombier 	}
10817dd7cddfSDavid du Colombier 	if(mach == nil)
10827dd7cddfSDavid du Colombier 		nmach = 0;	/* a little dance to get us started with local machine by default */
10837dd7cddfSDavid du Colombier 	mach = erealloc(mach, (nmach+1)*sizeof(Machine));
10847dd7cddfSDavid du Colombier 	memset(mach+nmach, 0, sizeof(Machine));
10858c1c8807SDavid du Colombier 	if (initmach(mach+nmach, name)){
10867dd7cddfSDavid du Colombier 		nmach++;
10878c1c8807SDavid du Colombier 		return 1;
10888c1c8807SDavid du Colombier 	} else
10898c1c8807SDavid du Colombier 		return 0;
10907dd7cddfSDavid du Colombier }
10917dd7cddfSDavid du Colombier 
10927dd7cddfSDavid du Colombier void
labelstrs(Graph * g,char strs[Nlab][Lablen],int * np)109380ee5cbfSDavid du Colombier labelstrs(Graph *g, char strs[Nlab][Lablen], int *np)
109480ee5cbfSDavid du Colombier {
109580ee5cbfSDavid du Colombier 	int j;
1096b2495906SDavid du Colombier 	uvlong v, vmax;
109780ee5cbfSDavid du Colombier 
109880ee5cbfSDavid du Colombier 	g->newvalue(g->mach, &v, &vmax, 1);
109980ee5cbfSDavid du Colombier 	if(logscale){
110080ee5cbfSDavid du Colombier 		for(j=1; j<=2; j++)
110180ee5cbfSDavid du Colombier 			sprint(strs[j-1], "%g", scale*pow(10., j)*(double)vmax/100.);
110280ee5cbfSDavid du Colombier 		*np = 2;
110380ee5cbfSDavid du Colombier 	}else{
110480ee5cbfSDavid du Colombier 		for(j=1; j<=3; j++)
110580ee5cbfSDavid du Colombier 			sprint(strs[j-1], "%g", scale*(double)j*(double)vmax/4.0);
110680ee5cbfSDavid du Colombier 		*np = 3;
110780ee5cbfSDavid du Colombier 	}
110880ee5cbfSDavid du Colombier }
110980ee5cbfSDavid du Colombier 
111080ee5cbfSDavid du Colombier int
labelwidth(void)111180ee5cbfSDavid du Colombier labelwidth(void)
111280ee5cbfSDavid du Colombier {
111380ee5cbfSDavid du Colombier 	int i, j, n, w, maxw;
111480ee5cbfSDavid du Colombier 	char strs[Nlab][Lablen];
111580ee5cbfSDavid du Colombier 
111680ee5cbfSDavid du Colombier 	maxw = 0;
111780ee5cbfSDavid du Colombier 	for(i=0; i<ngraph; i++){
111880ee5cbfSDavid du Colombier 		/* choose value for rightmost graph */
111980ee5cbfSDavid du Colombier 		labelstrs(&graph[ngraph*(nmach-1)+i], strs, &n);
112080ee5cbfSDavid du Colombier 		for(j=0; j<n; j++){
112180ee5cbfSDavid du Colombier 			w = stringwidth(mediumfont, strs[j]);
112280ee5cbfSDavid du Colombier 			if(w > maxw)
112380ee5cbfSDavid du Colombier 				maxw = w;
112480ee5cbfSDavid du Colombier 		}
112580ee5cbfSDavid du Colombier 	}
112680ee5cbfSDavid du Colombier 	return maxw;
112780ee5cbfSDavid du Colombier }
112880ee5cbfSDavid du Colombier 
112980ee5cbfSDavid du Colombier void
resize(void)11307dd7cddfSDavid du Colombier resize(void)
11317dd7cddfSDavid du Colombier {
113280ee5cbfSDavid du Colombier 	int i, j, k, n, startx, starty, x, y, dx, dy, ly, ondata, maxx, wid, nlab;
11337dd7cddfSDavid du Colombier 	Graph *g;
11347dd7cddfSDavid du Colombier 	Rectangle machr, r;
1135b2495906SDavid du Colombier 	uvlong v, vmax;
113680ee5cbfSDavid du Colombier 	char buf[128], labs[Nlab][Lablen];
11377dd7cddfSDavid du Colombier 
11387dd7cddfSDavid du Colombier 	draw(screen, screen->r, display->white, nil, ZP);
11397dd7cddfSDavid du Colombier 
11407dd7cddfSDavid du Colombier 	/* label left edge */
11417dd7cddfSDavid du Colombier 	x = screen->r.min.x;
11427dd7cddfSDavid du Colombier 	y = screen->r.min.y + Labspace+mediumfont->height+Labspace;
11437dd7cddfSDavid du Colombier 	dy = (screen->r.max.y - y)/ngraph;
11447dd7cddfSDavid du Colombier 	dx = Labspace+stringwidth(mediumfont, "0")+Labspace;
11457dd7cddfSDavid du Colombier 	startx = x+dx+1;
11467dd7cddfSDavid du Colombier 	starty = y;
11477dd7cddfSDavid du Colombier 	for(i=0; i<ngraph; i++,y+=dy){
11487dd7cddfSDavid du Colombier 		draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP);
11497dd7cddfSDavid du Colombier 		draw(screen, Rect(x, y, x+dx, screen->r.max.y), cols[graph[i].colindex][0], nil, paritypt(x));
11507dd7cddfSDavid du Colombier 		label(Pt(x, y), dy, graph[i].label);
11517dd7cddfSDavid du Colombier 		draw(screen, Rect(x+dx, y, x+dx+1, screen->r.max.y), cols[graph[i].colindex][2], nil, ZP);
11527dd7cddfSDavid du Colombier 	}
11537dd7cddfSDavid du Colombier 
11547dd7cddfSDavid du Colombier 	/* label top edge */
11557dd7cddfSDavid du Colombier 	dx = (screen->r.max.x - startx)/nmach;
11567dd7cddfSDavid du Colombier 	for(x=startx, i=0; i<nmach; i++,x+=dx){
11577dd7cddfSDavid du Colombier 		draw(screen, Rect(x-1, starty-1, x, screen->r.max.y), display->black, nil, ZP);
11587dd7cddfSDavid du Colombier 		j = dx/stringwidth(mediumfont, "0");
11597dd7cddfSDavid du Colombier 		n = mach[i].nproc;
1160eebedd9aSDavid du Colombier 		if(n>1 && j>=1+3+mach[i].lgproc){	/* first char of name + (n) */
1161eebedd9aSDavid du Colombier 			j -= 3+mach[i].lgproc;
11627dd7cddfSDavid du Colombier 			if(j <= 0)
11637dd7cddfSDavid du Colombier 				j = 1;
1164eebedd9aSDavid du Colombier 			snprint(buf, sizeof buf, "%.*s(%d)", j, mach[i].shortname, n);
11657dd7cddfSDavid du Colombier 		}else
1166eebedd9aSDavid du Colombier 			snprint(buf, sizeof buf, "%.*s", j, mach[i].shortname);
11677dd7cddfSDavid du Colombier 		string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, mediumfont, buf);
11687dd7cddfSDavid du Colombier 	}
11697dd7cddfSDavid du Colombier 
117080ee5cbfSDavid du Colombier 	maxx = screen->r.max.x;
117180ee5cbfSDavid du Colombier 
117280ee5cbfSDavid du Colombier 	/* label right, if requested */
117380ee5cbfSDavid du Colombier 	if(ylabels && dy>Nlab*(mediumfont->height+1)){
117480ee5cbfSDavid du Colombier 		wid = labelwidth();
117580ee5cbfSDavid du Colombier 		if(wid < (maxx-startx)-30){
117680ee5cbfSDavid du Colombier 			/* else there's not enough room */
117780ee5cbfSDavid du Colombier 			maxx -= 1+Lx+wid;
117880ee5cbfSDavid du Colombier 			draw(screen, Rect(maxx, starty, maxx+1, screen->r.max.y), display->black, nil, ZP);
117980ee5cbfSDavid du Colombier 			y = starty;
118080ee5cbfSDavid du Colombier 			for(j=0; j<ngraph; j++, y+=dy){
118180ee5cbfSDavid du Colombier 				/* choose value for rightmost graph */
118280ee5cbfSDavid du Colombier 				g = &graph[ngraph*(nmach-1)+j];
118380ee5cbfSDavid du Colombier 				labelstrs(g, labs, &nlab);
118480ee5cbfSDavid du Colombier 				r = Rect(maxx+1, y, screen->r.max.x, y+dy-1);
118580ee5cbfSDavid du Colombier 				if(j == ngraph-1)
118680ee5cbfSDavid du Colombier 					r.max.y = screen->r.max.y;
118780ee5cbfSDavid du Colombier 				draw(screen, r, cols[g->colindex][0], nil, paritypt(r.min.x));
118880ee5cbfSDavid du Colombier 				for(k=0; k<nlab; k++){
118980ee5cbfSDavid du Colombier 					ly = y + (dy*(nlab-k)/(nlab+1));
119080ee5cbfSDavid du Colombier 					draw(screen, Rect(maxx+1, ly, maxx+1+Lx, ly+1), display->black, nil, ZP);
119180ee5cbfSDavid du Colombier 					ly -= mediumfont->height/2;
119280ee5cbfSDavid du Colombier 					string(screen, Pt(maxx+1+Lx, ly), display->black, ZP, mediumfont, labs[k]);
119380ee5cbfSDavid du Colombier 				}
119480ee5cbfSDavid du Colombier 			}
119580ee5cbfSDavid du Colombier 		}
119680ee5cbfSDavid du Colombier 	}
119780ee5cbfSDavid du Colombier 
11987dd7cddfSDavid du Colombier 	/* create graphs */
11997dd7cddfSDavid du Colombier 	for(i=0; i<nmach; i++){
120080ee5cbfSDavid du Colombier 		machr = Rect(startx+i*dx, starty, maxx, screen->r.max.y);
12017dd7cddfSDavid du Colombier 		if(i < nmach-1)
12027dd7cddfSDavid du Colombier 			machr.max.x = startx+(i+1)*dx - 1;
12037dd7cddfSDavid du Colombier 		y = starty;
12047dd7cddfSDavid du Colombier 		for(j=0; j<ngraph; j++, y+=dy){
12057dd7cddfSDavid du Colombier 			g = &graph[i*ngraph+j];
12067dd7cddfSDavid du Colombier 			/* allocate data */
12077dd7cddfSDavid du Colombier 			ondata = g->ndata;
12087dd7cddfSDavid du Colombier 			g->ndata = Dx(machr)+1;	/* may be too many if label will be drawn here; so what? */
1209853458f3SDavid du Colombier 			g->data = erealloc(g->data, g->ndata*sizeof(g->data[0]));
12107dd7cddfSDavid du Colombier 			if(g->ndata > ondata)
1211853458f3SDavid du Colombier 				memset(g->data+ondata, 0, (g->ndata-ondata)*sizeof(g->data[0]));
12127dd7cddfSDavid du Colombier 			/* set geometry */
12137dd7cddfSDavid du Colombier 			g->r = machr;
12147dd7cddfSDavid du Colombier 			g->r.min.y = y;
12157dd7cddfSDavid du Colombier 			g->r.max.y = y+dy - 1;
12167dd7cddfSDavid du Colombier 			if(j == ngraph-1)
12177dd7cddfSDavid du Colombier 				g->r.max.y = screen->r.max.y;
12187dd7cddfSDavid du Colombier 			draw(screen, g->r, cols[g->colindex][0], nil, paritypt(g->r.min.x));
12197dd7cddfSDavid du Colombier 			g->overflow = 0;
12207dd7cddfSDavid du Colombier 			r = g->r;
12217dd7cddfSDavid du Colombier 			r.max.y = r.min.y+mediumfont->height;
122231a0f4b7SDavid du Colombier 			r.max.x = r.min.x+stringwidth(mediumfont, "999999999999");
12237dd7cddfSDavid du Colombier 			freeimage(g->overtmp);
12247dd7cddfSDavid du Colombier 			g->overtmp = nil;
12257dd7cddfSDavid du Colombier 			if(r.max.x <= g->r.max.x)
12267dd7cddfSDavid du Colombier 				g->overtmp = allocimage(display, r, screen->chan, 0, -1);
122780ee5cbfSDavid du Colombier 			g->newvalue(g->mach, &v, &vmax, 0);
12287dd7cddfSDavid du Colombier 			redraw(g, vmax);
12297dd7cddfSDavid du Colombier 		}
12307dd7cddfSDavid du Colombier 	}
12317dd7cddfSDavid du Colombier 
12327dd7cddfSDavid du Colombier 	flushimage(display, 1);
12337dd7cddfSDavid du Colombier }
12347dd7cddfSDavid du Colombier 
12357dd7cddfSDavid du Colombier void
eresized(int new)12367dd7cddfSDavid du Colombier eresized(int new)
12377dd7cddfSDavid du Colombier {
12387dd7cddfSDavid du Colombier 	lockdisplay(display);
12397dd7cddfSDavid du Colombier 	if(new && getwindow(display, Refnone) < 0) {
12407dd7cddfSDavid du Colombier 		fprint(2, "stats: can't reattach to window\n");
12417dd7cddfSDavid du Colombier 		killall("reattach");
12427dd7cddfSDavid du Colombier 	}
12437dd7cddfSDavid du Colombier 	resize();
12447dd7cddfSDavid du Colombier 	unlockdisplay(display);
12457dd7cddfSDavid du Colombier }
12467dd7cddfSDavid du Colombier 
12477dd7cddfSDavid du Colombier void
mouseproc(void)12487dd7cddfSDavid du Colombier mouseproc(void)
12497dd7cddfSDavid du Colombier {
12507dd7cddfSDavid du Colombier 	Mouse mouse;
12517dd7cddfSDavid du Colombier 	int i;
12527dd7cddfSDavid du Colombier 
12537dd7cddfSDavid du Colombier 	for(;;){
12547dd7cddfSDavid du Colombier 		mouse = emouse();
12557dd7cddfSDavid du Colombier 		if(mouse.buttons == 4){
12567dd7cddfSDavid du Colombier 			lockdisplay(display);
12577dd7cddfSDavid du Colombier 			for(i=0; i<Nmenu2; i++)
12587dd7cddfSDavid du Colombier 				if(present[i])
12597dd7cddfSDavid du Colombier 					memmove(menu2str[i], "drop ", Opwid);
12607dd7cddfSDavid du Colombier 				else
12617dd7cddfSDavid du Colombier 					memmove(menu2str[i], "add  ", Opwid);
12627dd7cddfSDavid du Colombier 			i = emenuhit(3, &mouse, &menu2);
12637dd7cddfSDavid du Colombier 			if(i >= 0){
12647dd7cddfSDavid du Colombier 				if(!present[i])
12657dd7cddfSDavid du Colombier 					addgraph(i);
12667dd7cddfSDavid du Colombier 				else if(ngraph > 1)
12677dd7cddfSDavid du Colombier 					dropgraph(i);
12687dd7cddfSDavid du Colombier 				resize();
12697dd7cddfSDavid du Colombier 			}
12707dd7cddfSDavid du Colombier 			unlockdisplay(display);
12717dd7cddfSDavid du Colombier 		}
12727dd7cddfSDavid du Colombier 	}
12737dd7cddfSDavid du Colombier }
12747dd7cddfSDavid du Colombier 
12757dd7cddfSDavid du Colombier void
startproc(void (* f)(void),int index)12767dd7cddfSDavid du Colombier startproc(void (*f)(void), int index)
12777dd7cddfSDavid du Colombier {
12787dd7cddfSDavid du Colombier 	int pid;
12797dd7cddfSDavid du Colombier 
12807dd7cddfSDavid du Colombier 	switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){
12817dd7cddfSDavid du Colombier 	case -1:
12827dd7cddfSDavid du Colombier 		fprint(2, "stats: fork failed: %r\n");
12837dd7cddfSDavid du Colombier 		killall("fork failed");
12847dd7cddfSDavid du Colombier 	case 0:
12857dd7cddfSDavid du Colombier 		f();
12867dd7cddfSDavid du Colombier 		fprint(2, "stats: %s process exits\n", procnames[index]);
12877dd7cddfSDavid du Colombier 		if(index >= 0)
12887dd7cddfSDavid du Colombier 			killall("process died");
12897dd7cddfSDavid du Colombier 		exits(nil);
12907dd7cddfSDavid du Colombier 	}
12917dd7cddfSDavid du Colombier 	if(index >= 0)
12927dd7cddfSDavid du Colombier 		pids[index] = pid;
12937dd7cddfSDavid du Colombier }
12947dd7cddfSDavid du Colombier 
12957dd7cddfSDavid du Colombier void
main(int argc,char * argv[])12967dd7cddfSDavid du Colombier main(int argc, char *argv[])
12977dd7cddfSDavid du Colombier {
12987dd7cddfSDavid du Colombier 	int i, j;
1299de8abbc9SDavid du Colombier 	double secs;
1300b2495906SDavid du Colombier 	uvlong v, vmax, nargs;
13017dd7cddfSDavid du Colombier 	char args[100];
13027dd7cddfSDavid du Colombier 
13037dd7cddfSDavid du Colombier 	nmach = 1;
13047dd7cddfSDavid du Colombier 	mysysname = getenv("sysname");
13057dd7cddfSDavid du Colombier 	if(mysysname == nil){
13067dd7cddfSDavid du Colombier 		fprint(2, "stats: can't find $sysname: %r\n");
13077dd7cddfSDavid du Colombier 		exits("sysname");
13087dd7cddfSDavid du Colombier 	}
13097dd7cddfSDavid du Colombier 	mysysname = estrdup(mysysname);
1310*fee9fd16SDavid du Colombier 	mycputype = getenv("cputype");
13117dd7cddfSDavid du Colombier 
13127dd7cddfSDavid du Colombier 	nargs = 0;
13137dd7cddfSDavid du Colombier 	ARGBEGIN{
13143f695129SDavid du Colombier 	case 'T':
1315de8abbc9SDavid du Colombier 		secs = atof(EARGF(usage()));
1316de8abbc9SDavid du Colombier 		if(secs > 0)
1317de8abbc9SDavid du Colombier 			sleeptime = 1000*secs;
13183f695129SDavid du Colombier 		break;
131980ee5cbfSDavid du Colombier 	case 'S':
1320de8abbc9SDavid du Colombier 		scale = atof(EARGF(usage()));
1321de8abbc9SDavid du Colombier 		if(scale <= 0)
132280ee5cbfSDavid du Colombier 			usage();
132380ee5cbfSDavid du Colombier 		break;
132480ee5cbfSDavid du Colombier 	case 'L':
132580ee5cbfSDavid du Colombier 		logscale++;
132680ee5cbfSDavid du Colombier 		break;
132780ee5cbfSDavid du Colombier 	case 'Y':
132880ee5cbfSDavid du Colombier 		ylabels++;
132980ee5cbfSDavid du Colombier 		break;
13309a747e4fSDavid du Colombier 	case 'O':
13319a747e4fSDavid du Colombier 		oldsystem = 1;
13329a747e4fSDavid du Colombier 		break;
13337dd7cddfSDavid du Colombier 	default:
13347dd7cddfSDavid du Colombier 		if(nargs>=sizeof args || strchr(argchars, ARGC())==nil)
13357dd7cddfSDavid du Colombier 			usage();
13367dd7cddfSDavid du Colombier 		args[nargs++] = ARGC();
13377dd7cddfSDavid du Colombier 	}ARGEND
13387dd7cddfSDavid du Colombier 
13397dd7cddfSDavid du Colombier 	if(argc == 0){
13407dd7cddfSDavid du Colombier 		mach = emalloc(nmach*sizeof(Machine));
13417dd7cddfSDavid du Colombier 		initmach(&mach[0], mysysname);
13427dd7cddfSDavid du Colombier 		readmach(&mach[0], 1);
13437dd7cddfSDavid du Colombier 	}else{
13448c1c8807SDavid du Colombier 		for(i=j=0; i<argc; i++){
13458c1c8807SDavid du Colombier 			if (addmachine(argv[i]))
13468c1c8807SDavid du Colombier 				readmach(&mach[j++], 1);
13477dd7cddfSDavid du Colombier 		}
1348a8453668SDavid du Colombier 		if (j == 0)
1349a8453668SDavid du Colombier 			exits("connect");
13507dd7cddfSDavid du Colombier 	}
13517dd7cddfSDavid du Colombier 
13527dd7cddfSDavid du Colombier 	for(i=0; i<nargs; i++)
13537dd7cddfSDavid du Colombier 	switch(args[i]){
13547dd7cddfSDavid du Colombier 	default:
13557dd7cddfSDavid du Colombier 		fprint(2, "stats: internal error: unknown arg %c\n", args[i]);
13567dd7cddfSDavid du Colombier 		usage();
135780ee5cbfSDavid du Colombier 	case 'b':
135880ee5cbfSDavid du Colombier 		addgraph(Mbattery);
135980ee5cbfSDavid du Colombier 		break;
13607dd7cddfSDavid du Colombier 	case 'c':
13617dd7cddfSDavid du Colombier 		addgraph(Mcontext);
13627dd7cddfSDavid du Colombier 		break;
13637dd7cddfSDavid du Colombier 	case 'e':
13647dd7cddfSDavid du Colombier 		addgraph(Mether);
13657dd7cddfSDavid du Colombier 		break;
13667dd7cddfSDavid du Colombier 	case 'E':
13677dd7cddfSDavid du Colombier 		addgraph(Metherin);
13687dd7cddfSDavid du Colombier 		addgraph(Metherout);
13697dd7cddfSDavid du Colombier 		break;
13707dd7cddfSDavid du Colombier 	case 'f':
13717dd7cddfSDavid du Colombier 		addgraph(Mfault);
13727dd7cddfSDavid du Colombier 		break;
13737dd7cddfSDavid du Colombier 	case 'i':
13747dd7cddfSDavid du Colombier 		addgraph(Mintr);
13757dd7cddfSDavid du Colombier 		break;
1376f86ef3ceSDavid du Colombier 	case 'I':
1377f86ef3ceSDavid du Colombier 		addgraph(Mload);
1378f86ef3ceSDavid du Colombier 		addgraph(Midle);
1379f86ef3ceSDavid du Colombier 		addgraph(Minintr);
1380f86ef3ceSDavid du Colombier 		break;
13817dd7cddfSDavid du Colombier 	case 'l':
13827dd7cddfSDavid du Colombier 		addgraph(Mload);
13837dd7cddfSDavid du Colombier 		break;
13847dd7cddfSDavid du Colombier 	case 'm':
13857dd7cddfSDavid du Colombier 		addgraph(Mmem);
13867dd7cddfSDavid du Colombier 		break;
13877dd7cddfSDavid du Colombier 	case 'n':
13887dd7cddfSDavid du Colombier 		addgraph(Metherin);
13897dd7cddfSDavid du Colombier 		addgraph(Metherout);
13907dd7cddfSDavid du Colombier 		addgraph(Methererr);
13917dd7cddfSDavid du Colombier 		break;
13927dd7cddfSDavid du Colombier 	case 'p':
13937dd7cddfSDavid du Colombier 		addgraph(Mtlbpurge);
13947dd7cddfSDavid du Colombier 		break;
13957dd7cddfSDavid du Colombier 	case 's':
13967dd7cddfSDavid du Colombier 		addgraph(Msyscall);
13977dd7cddfSDavid du Colombier 		break;
13987dd7cddfSDavid du Colombier 	case 't':
13997dd7cddfSDavid du Colombier 		addgraph(Mtlbmiss);
14007dd7cddfSDavid du Colombier 		addgraph(Mtlbpurge);
14017dd7cddfSDavid du Colombier 		break;
14029a747e4fSDavid du Colombier 	case '8':
14039a747e4fSDavid du Colombier 		addgraph(Msignal);
14049a747e4fSDavid du Colombier 		break;
14057dd7cddfSDavid du Colombier 	case 'w':
14067dd7cddfSDavid du Colombier 		addgraph(Mswap);
14077dd7cddfSDavid du Colombier 		break;
1408b2495906SDavid du Colombier 	case 'z':
1409b2495906SDavid du Colombier 		addgraph(Mtemp);
1410b2495906SDavid du Colombier 		break;
14117dd7cddfSDavid du Colombier 	}
14127dd7cddfSDavid du Colombier 
14137dd7cddfSDavid du Colombier 	if(ngraph == 0)
14147dd7cddfSDavid du Colombier 		addgraph(Mload);
14157dd7cddfSDavid du Colombier 
14167dd7cddfSDavid du Colombier 	for(i=0; i<nmach; i++)
14177dd7cddfSDavid du Colombier 		for(j=0; j<ngraph; j++)
14187dd7cddfSDavid du Colombier 			graph[i*ngraph+j].mach = &mach[i];
14197dd7cddfSDavid du Colombier 
14207dd7cddfSDavid du Colombier 	if(initdraw(nil, nil, "stats") < 0){
14217dd7cddfSDavid du Colombier 		fprint(2, "stats: initdraw failed: %r\n");
14227dd7cddfSDavid du Colombier 		exits("initdraw");
14237dd7cddfSDavid du Colombier 	}
14247dd7cddfSDavid du Colombier 	colinit();
14257dd7cddfSDavid du Colombier 	einit(Emouse);
14267dd7cddfSDavid du Colombier 	notify(nil);
14277dd7cddfSDavid du Colombier 	startproc(mouseproc, Mouseproc);
14287dd7cddfSDavid du Colombier 	pids[Mainproc] = getpid();
14297dd7cddfSDavid du Colombier 	display->locking = 1;	/* tell library we're using the display lock */
14307dd7cddfSDavid du Colombier 
14317dd7cddfSDavid du Colombier 	resize();
14327dd7cddfSDavid du Colombier 
14337dd7cddfSDavid du Colombier 	unlockdisplay(display); /* display is still locked from initdraw() */
14347dd7cddfSDavid du Colombier 	for(;;){
14357dd7cddfSDavid du Colombier 		for(i=0; i<nmach; i++)
14367dd7cddfSDavid du Colombier 			readmach(&mach[i], 0);
14377dd7cddfSDavid du Colombier 		lockdisplay(display);
14387dd7cddfSDavid du Colombier 		parity = 1-parity;
14397dd7cddfSDavid du Colombier 		for(i=0; i<nmach*ngraph; i++){
144080ee5cbfSDavid du Colombier 			graph[i].newvalue(graph[i].mach, &v, &vmax, 0);
14417dd7cddfSDavid du Colombier 			graph[i].update(&graph[i], v, vmax);
14427dd7cddfSDavid du Colombier 		}
14437dd7cddfSDavid du Colombier 		flushimage(display, 1);
14447dd7cddfSDavid du Colombier 		unlockdisplay(display);
14453f695129SDavid du Colombier 		sleep(sleeptime);
14467dd7cddfSDavid du Colombier 	}
14477dd7cddfSDavid du Colombier }
1448