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