1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <bio.h> 5 #include <event.h> 6 7 enum {PNCTL=3}; 8 9 static char* rdenv(char*); 10 void newwin(char*); 11 Rectangle screenrect(void); 12 13 int nokill; 14 char *title; 15 16 Image *light; 17 Image *dark; 18 Image *text; 19 20 void 21 initcolor(void) 22 { 23 text = display->black; 24 light = allocimagemix(display, DPalegreen, DWhite); 25 dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen); 26 } 27 28 Rectangle rbar; 29 Point ptext; 30 long n, d; 31 int last; 32 int lastp; 33 34 void 35 drawbar(void) 36 { 37 int i; 38 int p; 39 char buf[10]; 40 41 if(n > d || n < 0 || d <= 0) 42 return; 43 44 i = (Dx(rbar)*(vlong)n)/d; 45 p = (n*100LL)/d; 46 47 if(lastp == p && last == i) 48 return; 49 50 if(lastp != p){ 51 sprint(buf, "%d%%", p); 52 53 stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP); 54 lastp = p; 55 } 56 57 if(last != i){ 58 draw(screen, Rect(rbar.min.x+last, rbar.min.y, rbar.min.x+i, rbar.max.y), 59 dark, nil, ZP); 60 last = i; 61 } 62 flushimage(display, 1); 63 } 64 65 void 66 eresized(int new) 67 { 68 Point p, q; 69 Rectangle r; 70 71 if(new && getwindow(display, Refnone) < 0) 72 fprint(2,"can't reattach to window"); 73 74 r = screen->r; 75 draw(screen, r, light, nil, ZP); 76 p = string(screen, addpt(r.min, Pt(4,4)), text, ZP, 77 display->defaultfont, title); 78 79 p.x = r.min.x+4; 80 p.y += display->defaultfont->height+4; 81 82 q = subpt(r.max, Pt(4,4)); 83 rbar = Rpt(p, q); 84 85 ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4); 86 border(screen, rbar, -2, dark, ZP); 87 last = 0; 88 lastp = -1; 89 90 drawbar(); 91 } 92 93 void 94 bar(Biobuf *b) 95 { 96 char *p, *f[2]; 97 Event e; 98 int k, die, parent, child; 99 100 parent = getpid(); 101 102 die = 0; 103 switch(child = rfork(RFMEM|RFPROC)) { 104 case 0: 105 sleep(1000); 106 while(!die && (k = eread(Ekeyboard|Emouse, &e))) { 107 if(nokill==0 && k == Ekeyboard && (e.kbdc == 0x7F || e.kbdc == 0x03)) { /* del, ctl-c */ 108 die = 1; 109 postnote(PNPROC, parent, "interrupt"); 110 _exits("interrupt"); 111 } 112 } 113 _exits(0); 114 } 115 116 while(!die && (p = Brdline(b, '\n'))) { 117 p[Blinelen(b)-1] = '\0'; 118 if(tokenize(p, f, 2) != 2) 119 continue; 120 n = atol(f[0]); 121 d = atol(f[1]); 122 drawbar(); 123 } 124 postnote(PNCTL, child, "kill"); 125 die = 1; 126 } 127 128 129 void 130 usage(void) 131 { 132 fprint(2, "usage: bargraph [-w minx,miny,maxx,maxy] 'title'\n"); 133 exits("usage"); 134 } 135 136 void 137 main(int argc, char **argv) 138 { 139 Biobuf b; 140 char *p, *q; 141 int lfd; 142 143 p = "0,0,200,40"; 144 145 ARGBEGIN{ 146 case 'w': 147 p = ARGF(); 148 break; 149 case 'k': 150 nokill = 1; 151 break; 152 default: 153 usage(); 154 }ARGEND; 155 156 if(argc != 1) 157 usage(); 158 159 title = argv[0]; 160 161 lfd = dup(0, -1); 162 163 while(q = strchr(p, ',')) 164 *q = ' '; 165 newwin(p); 166 167 initdraw(0, 0, "bar"); 168 initcolor(); 169 170 einit(Emouse|Ekeyboard); 171 172 Binit(&b, lfd, OREAD); 173 eresized(0); 174 bar(&b); 175 } 176 177 178 /* all code below this line should be in the library, but is stolen from colors instead */ 179 static char* 180 rdenv(char *name) 181 { 182 char *v; 183 int fd, size; 184 185 fd = open(name, OREAD); 186 if(fd < 0) 187 return 0; 188 size = seek(fd, 0, 2); 189 v = malloc(size+1); 190 if(v == 0){ 191 fprint(2, "page: can't malloc: %r\n"); 192 exits("no mem"); 193 } 194 seek(fd, 0, 0); 195 read(fd, v, size); 196 v[size] = 0; 197 close(fd); 198 return v; 199 } 200 201 void 202 newwin(char *win) 203 { 204 char *srv, *mntsrv; 205 char spec[100]; 206 int srvfd, cons, pid; 207 208 switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){ 209 case -1: 210 fprint(2, "page: can't fork: %r\n"); 211 exits("no fork"); 212 case 0: 213 break; 214 default: 215 exits(0); 216 } 217 218 srv = rdenv("/env/wsys"); 219 if(srv == 0){ 220 mntsrv = rdenv("/mnt/term/env/wsys"); 221 if(mntsrv == 0){ 222 fprint(2, "page: can't find $wsys\n"); 223 exits("srv"); 224 } 225 srv = malloc(strlen(mntsrv)+10); 226 sprint(srv, "/mnt/term%s", mntsrv); 227 free(mntsrv); 228 pid = 0; /* can't send notes to remote processes! */ 229 }else 230 pid = getpid(); 231 srvfd = open(srv, ORDWR); 232 free(srv); 233 if(srvfd == -1){ 234 fprint(2, "page: can't open %s: %r\n", srv); 235 exits("no srv"); 236 } 237 sprint(spec, "new -r %s", win); 238 if(mount(srvfd, -1, "/mnt/wsys", 0, spec) == -1){ 239 fprint(2, "page: can't mount /mnt/wsys: %r (spec=%s)\n", spec); 240 exits("no mount"); 241 } 242 close(srvfd); 243 unmount("/mnt/acme", "/dev"); 244 bind("/mnt/wsys", "/dev", MBEFORE); 245 cons = open("/dev/cons", OREAD); 246 if(cons==-1){ 247 NoCons: 248 fprint(2, "page: can't open /dev/cons: %r"); 249 exits("no cons"); 250 } 251 dup(cons, 0); 252 close(cons); 253 cons = open("/dev/cons", OWRITE); 254 if(cons==-1) 255 goto NoCons; 256 dup(cons, 1); 257 dup(cons, 2); 258 close(cons); 259 // wctlfd = open("/dev/wctl", OWRITE); 260 } 261 262 Rectangle 263 screenrect(void) 264 { 265 int fd; 266 char buf[12*5]; 267 268 fd = open("/dev/screen", OREAD); 269 if(fd == -1) 270 fd=open("/mnt/term/dev/screen", OREAD); 271 if(fd == -1){ 272 fprint(2, "page: can't open /dev/screen: %r\n"); 273 exits("window read"); 274 } 275 if(read(fd, buf, sizeof buf) != sizeof buf){ 276 fprint(2, "page: can't read /dev/screen: %r\n"); 277 exits("screen read"); 278 } 279 close(fd); 280 return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48)); 281 } 282 283 int 284 postnote(int group, int pid, char *note) 285 { 286 char file[128]; 287 int f, r; 288 289 switch(group) { 290 case PNPROC: 291 sprint(file, "/proc/%d/note", pid); 292 break; 293 case PNGROUP: 294 sprint(file, "/proc/%d/notepg", pid); 295 break; 296 case PNCTL: 297 sprint(file, "/proc/%d/ctl", pid); 298 break; 299 default: 300 return -1; 301 } 302 303 f = open(file, OWRITE); 304 if(f < 0) 305 return -1; 306 307 r = strlen(note); 308 if(write(f, note, r) != r) { 309 close(f); 310 return -1; 311 } 312 close(f); 313 return 0; 314 } 315