#include #include #include #include #include #include typedef struct Vol Vol; enum { Nvols = 128, }; struct Vol { char* mnt; char* vols; int changed; Panel* g; }; int mainstacksize = 23 * 1024; int debug; int vflag; #define dprint if(debug)fprint Panel* gcol; Vol vols[Nvols]; int nvols; char** names; int nnames; int updatevol(char* ln) { char* mnt; char* v; int i; if (ln == nil || *ln == 0) return 0; mnt = ln; v = strchr(ln, '\t'); if (v == nil) return 0; *v++ = 0; dprint(2, "updatevol: %s %s\n", mnt, v); if (nnames){ for (i = 0; i < nnames; i++) if (!strcmp(names[i], mnt)) break; if (i == nnames) return 0; } for (i = 0; i < nvols; i++) if (!strcmp(vols[i].mnt, mnt)){ if (!strcmp(vols[i].vols, v)) return 0; free(vols[i].vols); vols[i].vols = strdup(v); vols[i].changed = 1; return 1; } if (nvols == Nvols){ fprint(2, "%s: too many vols\n", argv0); } else { vols[nvols].mnt = strdup(mnt); vols[nvols].vols = strdup(v); nvols++; } return 0; } int update(void) { static Qid oqid; int p[2]; int tot, n; char out[4096]; char* sc[Nvols*2]; int nsc; Dir* d; int changed, i; int chg; changed = 0; d = dirstat("/dev/vol"); if (d == nil) sysfatal("/dev/vol: %r\n"); if (d->qid.vers == oqid.vers){ free(d); return 0; } oqid = d->qid; if (pipe(p) < 0) sysfatal("pipe: %r"); switch(rfork(RFPROC|RFFDG|RFNOWAIT)){ case -1: sysfatal("rfork: %r"); break; case 0: close(p[0]); dup(p[1], 1); close(p[1]); execl("/bin/vols", "vols", nil); sysfatal("exec vols: %r"); break; default: close(p[1]); for(tot = 0; ; tot +=n){ n = read(p[0], out+tot, sizeof(out) - tot); if (n <= 0) break; } close(p[0]); out[tot] = 0; nsc = gettokens(out, sc, nelem(sc), "\n"); for (i = 0; i < nsc; i++){ chg = updatevol(sc[i]); if (chg && vflag) fprint(2, "%s: changed: %s\n", argv0, sc[i]); changed |= chg; } } return changed; } void updateui(int alert) { int i; char nm[40]; char msg[40]; for (i = 0; i < nvols; i++){ if (vols[i].g == nil){ seprint(nm, nm+40, "label:v%d", i); vols[i].g = createsubpanel(gcol, nm); } seprint(msg, msg+40, "%s: %s", vols[i].mnt, vols[i].vols); openpanel(vols[i].g, OWRITE|OTRUNC); writepanel(vols[i].g, msg, strlen(msg)); closepanel(vols[i].g); openpanelctl(vols[i].g); panelctl(vols[i].g, vols[i].changed ? "font B" : "font R"); closepanelctl(vols[i].g); } if (alert){ for (i = 0; i < nvols; i++){ if (vols[i].changed){ openpanelctl(vols[i].g); panelctl(vols[i].g, "font B"); closepanelctl(vols[i].g); } } openpanelctl(gcol); for (i = 0; i < 3; i++){ panelctl(gcol, "hide"); sleep(500); panelctl(gcol, "show"); sleep(1000); } closepanelctl(gcol); sleep(10 * 1000); for (i = 0; i < nvols; i++){ if (vols[i].changed){ vols[i].changed = 0; openpanelctl(vols[i].g); panelctl(vols[i].g, "font R"); closepanelctl(vols[i].g); } } } } void usage(void) { fprint(2, "usage: %s [-d] [-v] [file...]\n", argv0); exits("usage"); } void omerogone(void) { sysfatal("terminated"); } void threadmain(int argc, char **argv) { ARGBEGIN{ case 'v': vflag = 1; break; case 'd': debug = 1; break; default: usage(); }ARGEND; names = argv; nnames= argc; gcol = createpanel("ovols", "col", nil); if (gcol == nil) sysfatal("createpanel: %r\n"); update(); updateui(0); closepanelctl(gcol); for(;;){ sleep(1000); if (update()) updateui(1); } }