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