355 lines · 6.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <draw.h>#include <bio.h>#include <event.h> enum {PNCTL=3}; static char* rdenv(char*);int newwin(char*);Rectangle screenrect(void); int nokill;int textmode;char *title; Image *light;Image *dark;Image *text; voidinitcolor(void){	text = display->black;	light = allocimagemix(display, DPalegreen, DWhite);	dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);} Rectangle rbar;Point ptext;vlong n, d;int last;int lastp = -1;int first = 1; char backup[80]; voiddrawbar(void){	int i, j;	int p;	char buf[200], bar[100];	static char lastbar[100]; 	if(n > d || n < 0 || d <= 0)		return; 	i = (Dx(rbar)*n)/d;	p = (n*100LL)/d; 	if(textmode){		bar[0] = '|';		for(j=0; j<i; j++)			bar[j+1] = '#';		for(; j<60; j++)			bar[j+1] = '-';		bar[61] = '|';		bar[62] = ' ';		sprint(bar+63, "%3d%% ", p);		for(i=0; bar[i]==lastbar[i] && bar[i]; i++)			;		memset(buf, '\b', strlen(lastbar)-i);		strcpy(buf+strlen(lastbar)-i, bar+i);		if(buf[0])			write(1, buf, strlen(buf));		strcpy(lastbar, bar);		return;	}		if(lastp == p && last == i)		return; 	if(lastp != p){		sprint(buf, "%d%%", p);				stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP);		lastp = p;	} 	if(last != i){		draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y),			dark, nil, ZP);		last = i;	}	flushimage(display, 1);} voideresized(int new){	Point p, q;	Rectangle r; 	if(new && getwindow(display, Refnone) < 0)		fprint(2,"can't reattach to window"); 	r = screen->r;	draw(screen, r, light, nil, ZP);	p = string(screen, addpt(r.min, Pt(4,4)), text, ZP,		display->defaultfont, title); 	p.x = r.min.x+4;	p.y += display->defaultfont->height+4; 	q = subpt(r.max, Pt(4,4));	rbar = Rpt(p, q); 	ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4);	border(screen, rbar, -2, dark, ZP);	last = 0;	lastp = -1; 	drawbar();} voidbar(Biobuf *b){	char *p, *f[2];	Event e;	int k, die, parent, child; 	parent = getpid(); 	die = 0;	if(textmode)		child = -1;	else	switch(child = rfork(RFMEM|RFPROC)) {	case 0:		sleep(1000);		while(!die && (k = eread(Ekeyboard|Emouse, &e))) {			if(nokill==0 && k == Ekeyboard && (e.kbdc == 0x7F || e.kbdc == 0x03)) { /* del, ctl-c */				die = 1;				postnote(PNPROC, parent, "interrupt");				_exits("interrupt");			}		}		_exits(0);	} 	while(!die && (p = Brdline(b, '\n'))) {		p[Blinelen(b)-1] = '\0';		if(tokenize(p, f, 2) != 2)			continue;		n = strtoll(f[0], 0, 0);		d = strtoll(f[1], 0, 0);		drawbar();	}	postnote(PNCTL, child, "kill");}  voidusage(void){	fprint(2, "usage: bargraph [-kt] [-w minx,miny,maxx,maxy] 'title'\n");	exits("usage");} voidmain(int argc, char **argv){	Biobuf b;	char *p, *q;	int lfd; 	p = "0,0,200,60";		ARGBEGIN{	case 'w':		p = ARGF();		break;	case 't':		textmode = 1;		break;	case 'k':		nokill = 1;		break;	default:		usage();	}ARGEND; 	if(argc != 1)		usage(); 	title = argv[0]; 	lfd = dup(0, -1); 	while(q = strchr(p, ','))		*q = ' ';	Binit(&b, lfd, OREAD);	if(textmode || newwin(p) < 0){		textmode = 1;		rbar = Rect(0, 0, 60, 1);	}else{		initdraw(0, 0, "bar");		initcolor();		einit(Emouse|Ekeyboard);		eresized(0);	}	bar(&b);}  /* all code below this line should be in the library, but is stolen from colors instead */static char*rdenv(char *name){	char *v;	int fd, size; 	fd = open(name, OREAD);	if(fd < 0)		return 0;	size = seek(fd, 0, 2);	v = malloc(size+1);	if(v == 0){		fprint(2, "%s: can't malloc: %r\n", argv0);		exits("no mem");	}	seek(fd, 0, 0);	read(fd, v, size);	v[size] = 0;	close(fd);	return v;} intnewwin(char *win){	char *srv, *mntsrv;	char spec[100];	int srvfd, cons, pid; 	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){	case -1:		fprint(2, "bargraph: can't fork: %r\n");		return -1;	case 0:		break;	default:		exits(0);	} 	srv = rdenv("/env/wsys");	if(srv == 0){		mntsrv = rdenv("/mnt/term/env/wsys");		if(mntsrv == 0){			fprint(2, "bargraph: can't find $wsys\n");			return -1;		}		srv = malloc(strlen(mntsrv)+10);		sprint(srv, "/mnt/term%s", mntsrv);		free(mntsrv);		pid  = 0;			/* can't send notes to remote processes! */	}else		pid = getpid();	USED(pid);	srvfd = open(srv, ORDWR);	free(srv);	if(srvfd == -1){		fprint(2, "bargraph: can't open %s: %r\n", srv);		return -1;	}	sprint(spec, "new -r %s", win);	if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){		fprint(2, "bargraph: can't mount /mnt/wsys: %r (spec=%s)\n", spec);		return -1;	}	close(srvfd);	unmount("/mnt/acme", "/dev");	bind("/mnt/wsys", "/dev", MBEFORE);	cons = open("/dev/cons", OREAD);	if(cons==-1){	NoCons:		fprint(2, "bargraph: can't open /dev/cons: %r");		return -1;	}	dup(cons, 0);	close(cons);	cons = open("/dev/cons", OWRITE);	if(cons==-1)		goto NoCons;	dup(cons, 1);	dup(cons, 2);	close(cons);//	wctlfd = open("/dev/wctl", OWRITE);	return 0;} Rectanglescreenrect(void){	int fd;	char buf[12*5]; 	fd = open("/dev/screen", OREAD);	if(fd == -1)		fd=open("/mnt/term/dev/screen", OREAD);	if(fd == -1){		fprint(2, "%s: can't open /dev/screen: %r\n", argv0);		exits("window read");	}	if(read(fd, buf, sizeof buf) != sizeof buf){		fprint(2, "%s: can't read /dev/screen: %r\n", argv0);		exits("screen read");	}	close(fd);	return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));} intpostnote(int group, int pid, char *note){	char file[128];	int f, r; 	switch(group) {	case PNPROC:		sprint(file, "/proc/%d/note", pid);		break;	case PNGROUP:		sprint(file, "/proc/%d/notepg", pid);		break;	case PNCTL:		sprint(file, "/proc/%d/ctl", pid);		break;	default:		return -1;	} 	f = open(file, OWRITE);	if(f < 0)		return -1; 	r = strlen(note);	if(write(f, note, r) != r) {		close(f);		return -1;	}	close(f);	return 0;}