17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <ctype.h> 47dd7cddfSDavid du Colombier #include <auth.h> 57dd7cddfSDavid du Colombier #include <fcall.h> 67dd7cddfSDavid du Colombier #include <draw.h> 77dd7cddfSDavid du Colombier #include <event.h> 87dd7cddfSDavid du Colombier #include <ip.h> 9*5a354e27SDavid du Colombier #include "icmp.h" 107dd7cddfSDavid du Colombier 117dd7cddfSDavid du Colombier #define MAXNUM 8 /* maximum number of numbers on data line */ 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier typedef struct Graph Graph; 147dd7cddfSDavid du Colombier typedef struct Machine Machine; 157dd7cddfSDavid du Colombier typedef struct Req Req; 167dd7cddfSDavid du Colombier 177dd7cddfSDavid du Colombier enum { 187dd7cddfSDavid du Colombier Gmsglen = 16, 197dd7cddfSDavid du Colombier }; 207dd7cddfSDavid du Colombier 217dd7cddfSDavid du Colombier struct Graph 227dd7cddfSDavid du Colombier { 237dd7cddfSDavid du Colombier int colindex; 247dd7cddfSDavid du Colombier Rectangle r; 25c93608ccSDavid du Colombier long *data; 267dd7cddfSDavid du Colombier int ndata; 277dd7cddfSDavid du Colombier char *label; 287dd7cddfSDavid du Colombier void (*newvalue)(Machine*, long*, long*, long*); 297dd7cddfSDavid du Colombier void (*update)(Graph*, long, long, long); 307dd7cddfSDavid du Colombier Machine *mach; 317dd7cddfSDavid du Colombier int overflow; 327dd7cddfSDavid du Colombier Image *overtmp; 337dd7cddfSDavid du Colombier int overtmplen; 347dd7cddfSDavid du Colombier char msg[Gmsglen]; 357dd7cddfSDavid du Colombier int cursor; 367dd7cddfSDavid du Colombier int vmax; 377dd7cddfSDavid du Colombier }; 387dd7cddfSDavid du Colombier 397dd7cddfSDavid du Colombier enum 40*5a354e27SDavid du Colombier { 417dd7cddfSDavid du Colombier MSGLEN = 64, 427dd7cddfSDavid du Colombier 437dd7cddfSDavid du Colombier Rttmax = 50, 447dd7cddfSDavid du Colombier }; 457dd7cddfSDavid du Colombier 467dd7cddfSDavid du Colombier struct Req 477dd7cddfSDavid du Colombier { 48*5a354e27SDavid du Colombier int seq; /* sequence number */ 49*5a354e27SDavid du Colombier vlong time; /* time sent */ 507dd7cddfSDavid du Colombier int rtt; 517dd7cddfSDavid du Colombier Req *next; 527dd7cddfSDavid du Colombier }; 537dd7cddfSDavid du Colombier 547dd7cddfSDavid du Colombier struct Machine 557dd7cddfSDavid du Colombier { 567dd7cddfSDavid du Colombier Lock; 577dd7cddfSDavid du Colombier char *name; 587dd7cddfSDavid du Colombier int pingfd; 597dd7cddfSDavid du Colombier int nproc; 607dd7cddfSDavid du Colombier 617dd7cddfSDavid du Colombier int rttmsgs; 627dd7cddfSDavid du Colombier ulong rttsum; 637dd7cddfSDavid du Colombier ulong lastrtt; 647dd7cddfSDavid du Colombier 657dd7cddfSDavid du Colombier int lostmsgs; 667dd7cddfSDavid du Colombier int rcvdmsgs; 677dd7cddfSDavid du Colombier ulong lostavg; 687dd7cddfSDavid du Colombier int unreachable; 697dd7cddfSDavid du Colombier 707dd7cddfSDavid du Colombier ushort seq; 717dd7cddfSDavid du Colombier Req *first; 727dd7cddfSDavid du Colombier Req *last; 737dd7cddfSDavid du Colombier Req *rcvd; 747dd7cddfSDavid du Colombier 757dd7cddfSDavid du Colombier char buf[1024]; 767dd7cddfSDavid du Colombier char *bufp; 777dd7cddfSDavid du Colombier char *ebufp; 787dd7cddfSDavid du Colombier }; 797dd7cddfSDavid du Colombier 807dd7cddfSDavid du Colombier enum 817dd7cddfSDavid du Colombier { 827dd7cddfSDavid du Colombier Ncolor = 6, 837dd7cddfSDavid du Colombier Ysqueeze = 2, /* vertical squeezing of label text */ 847dd7cddfSDavid du Colombier Labspace = 2, /* room around label */ 857dd7cddfSDavid du Colombier Dot = 2, /* height of dot */ 867dd7cddfSDavid du Colombier Opwid = 5, /* strlen("add ") or strlen("drop ") */ 877dd7cddfSDavid du Colombier NPROC = 128, 887dd7cddfSDavid du Colombier NMACH = 32, 897dd7cddfSDavid du Colombier }; 907dd7cddfSDavid du Colombier 917dd7cddfSDavid du Colombier enum Menu2 927dd7cddfSDavid du Colombier { 937dd7cddfSDavid du Colombier Mrtt, 947dd7cddfSDavid du Colombier Mlost, 957dd7cddfSDavid du Colombier Nmenu2, 967dd7cddfSDavid du Colombier }; 977dd7cddfSDavid du Colombier 987dd7cddfSDavid du Colombier char *menu2str[Nmenu2+1] = { 997dd7cddfSDavid du Colombier "add sec rtt", 1007dd7cddfSDavid du Colombier "add % lost ", 1017dd7cddfSDavid du Colombier nil, 1027dd7cddfSDavid du Colombier }; 1037dd7cddfSDavid du Colombier 1047dd7cddfSDavid du Colombier 1057dd7cddfSDavid du Colombier void rttval(Machine*, long*, long*, long*); 1067dd7cddfSDavid du Colombier void lostval(Machine*, long*, long*, long*); 1077dd7cddfSDavid du Colombier 1087dd7cddfSDavid du Colombier Menu menu2 = {menu2str, nil}; 1097dd7cddfSDavid du Colombier int present[Nmenu2]; 1107dd7cddfSDavid du Colombier void (*newvaluefn[Nmenu2])(Machine*, long*, long*, long*) = { 1117dd7cddfSDavid du Colombier rttval, 1127dd7cddfSDavid du Colombier lostval, 1137dd7cddfSDavid du Colombier }; 1147dd7cddfSDavid du Colombier 1157dd7cddfSDavid du Colombier Image *cols[Ncolor][3]; 1167dd7cddfSDavid du Colombier Graph *graph; 1177dd7cddfSDavid du Colombier Machine mach[NMACH]; 1187dd7cddfSDavid du Colombier Font *mediumfont; 1197dd7cddfSDavid du Colombier int pids[NPROC]; 1207dd7cddfSDavid du Colombier int npid; 1217dd7cddfSDavid du Colombier int parity; /* toggled to avoid patterns in textured background */ 1227dd7cddfSDavid du Colombier int nmach; 1237dd7cddfSDavid du Colombier int ngraph; /* totaly number is ngraph*nmach */ 1247dd7cddfSDavid du Colombier long starttime; 1257dd7cddfSDavid du Colombier int pinginterval; 1267dd7cddfSDavid du Colombier 1277dd7cddfSDavid du Colombier void dropgraph(int); 1287dd7cddfSDavid du Colombier void addgraph(int); 1297dd7cddfSDavid du Colombier void startproc(void (*)(void*), void*); 1307dd7cddfSDavid du Colombier void resize(void); 131c93608ccSDavid du Colombier long rttscale(long); 1327dd7cddfSDavid du Colombier int which2index(int); 1337dd7cddfSDavid du Colombier int index2which(int); 1347dd7cddfSDavid du Colombier 1357dd7cddfSDavid du Colombier void 1367dd7cddfSDavid du Colombier killall(char *s) 1377dd7cddfSDavid du Colombier { 1387dd7cddfSDavid du Colombier int i, pid; 1397dd7cddfSDavid du Colombier 1407dd7cddfSDavid du Colombier pid = getpid(); 1417dd7cddfSDavid du Colombier for(i=0; i<NPROC; i++) 1427dd7cddfSDavid du Colombier if(pids[i] && pids[i]!=pid) 1437dd7cddfSDavid du Colombier postnote(PNPROC, pids[i], "kill"); 1447dd7cddfSDavid du Colombier exits(s); 1457dd7cddfSDavid du Colombier } 1467dd7cddfSDavid du Colombier 1477dd7cddfSDavid du Colombier void* 1487dd7cddfSDavid du Colombier emalloc(ulong sz) 1497dd7cddfSDavid du Colombier { 1507dd7cddfSDavid du Colombier void *v; 1517dd7cddfSDavid du Colombier v = malloc(sz); 1527dd7cddfSDavid du Colombier if(v == nil) { 1537dd7cddfSDavid du Colombier fprint(2, "%s: out of memory allocating %ld: %r\n", argv0, sz); 1547dd7cddfSDavid du Colombier killall("mem"); 1557dd7cddfSDavid du Colombier } 1567dd7cddfSDavid du Colombier memset(v, 0, sz); 1577dd7cddfSDavid du Colombier return v; 1587dd7cddfSDavid du Colombier } 1597dd7cddfSDavid du Colombier 1607dd7cddfSDavid du Colombier void* 1617dd7cddfSDavid du Colombier erealloc(void *v, ulong sz) 1627dd7cddfSDavid du Colombier { 1637dd7cddfSDavid du Colombier v = realloc(v, sz); 1647dd7cddfSDavid du Colombier if(v == nil) { 1657dd7cddfSDavid du Colombier fprint(2, "%s: out of memory reallocating %ld: %r\n", argv0, sz); 1667dd7cddfSDavid du Colombier killall("mem"); 1677dd7cddfSDavid du Colombier } 1687dd7cddfSDavid du Colombier return v; 1697dd7cddfSDavid du Colombier } 1707dd7cddfSDavid du Colombier 1717dd7cddfSDavid du Colombier char* 1727dd7cddfSDavid du Colombier estrdup(char *s) 1737dd7cddfSDavid du Colombier { 1747dd7cddfSDavid du Colombier char *t; 1757dd7cddfSDavid du Colombier if((t = strdup(s)) == nil) { 1767dd7cddfSDavid du Colombier fprint(2, "%s: out of memory in strdup(%.10s): %r\n", argv0, s); 1777dd7cddfSDavid du Colombier killall("mem"); 1787dd7cddfSDavid du Colombier } 1797dd7cddfSDavid du Colombier return t; 1807dd7cddfSDavid du Colombier } 1817dd7cddfSDavid du Colombier 1827dd7cddfSDavid du Colombier void 1837dd7cddfSDavid du Colombier mkcol(int i, int c0, int c1, int c2) 1847dd7cddfSDavid du Colombier { 1857dd7cddfSDavid du Colombier cols[i][0] = allocimagemix(display, c0, DWhite); 1867dd7cddfSDavid du Colombier cols[i][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c1); 1877dd7cddfSDavid du Colombier cols[i][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, c2); 1887dd7cddfSDavid du Colombier } 1897dd7cddfSDavid du Colombier 1907dd7cddfSDavid du Colombier void 1917dd7cddfSDavid du Colombier colinit(void) 1927dd7cddfSDavid du Colombier { 1937dd7cddfSDavid du Colombier mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font"); 1947dd7cddfSDavid du Colombier if(mediumfont == nil) 1957dd7cddfSDavid du Colombier mediumfont = font; 1967dd7cddfSDavid du Colombier 1977dd7cddfSDavid du Colombier /* Peach */ 1987dd7cddfSDavid du Colombier mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF); 1997dd7cddfSDavid du Colombier /* Aqua */ 2007dd7cddfSDavid du Colombier mkcol(1, DPalebluegreen, DPalegreygreen, DPurpleblue); 2017dd7cddfSDavid du Colombier /* Yellow */ 2027dd7cddfSDavid du Colombier mkcol(2, DPaleyellow, DDarkyellow, DYellowgreen); 2037dd7cddfSDavid du Colombier /* Green */ 2047dd7cddfSDavid du Colombier mkcol(3, DPalegreen, DMedgreen, DDarkgreen); 2057dd7cddfSDavid du Colombier /* Blue */ 2067dd7cddfSDavid du Colombier mkcol(4, 0x00AAFFFF, 0x00AAFFFF, 0x0088CCFF); 2077dd7cddfSDavid du Colombier /* Grey */ 2087dd7cddfSDavid du Colombier cols[5][0] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xEEEEEEFF); 2097dd7cddfSDavid du Colombier cols[5][1] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0xCCCCCCFF); 2107dd7cddfSDavid du Colombier cols[5][2] = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x888888FF); 2117dd7cddfSDavid du Colombier } 2127dd7cddfSDavid du Colombier 2137dd7cddfSDavid du Colombier int 2147dd7cddfSDavid du Colombier loadbuf(Machine *m, int *fd) 2157dd7cddfSDavid du Colombier { 2167dd7cddfSDavid du Colombier int n; 2177dd7cddfSDavid du Colombier 2187dd7cddfSDavid du Colombier 2197dd7cddfSDavid du Colombier if(*fd < 0) 2207dd7cddfSDavid du Colombier return 0; 2217dd7cddfSDavid du Colombier seek(*fd, 0, 0); 2227dd7cddfSDavid du Colombier n = read(*fd, m->buf, sizeof m->buf); 2237dd7cddfSDavid du Colombier if(n <= 0){ 2247dd7cddfSDavid du Colombier close(*fd); 2257dd7cddfSDavid du Colombier *fd = -1; 2267dd7cddfSDavid du Colombier return 0; 2277dd7cddfSDavid du Colombier } 2287dd7cddfSDavid du Colombier m->bufp = m->buf; 2297dd7cddfSDavid du Colombier m->ebufp = m->buf+n; 2307dd7cddfSDavid du Colombier return 1; 2317dd7cddfSDavid du Colombier } 2327dd7cddfSDavid du Colombier 2337dd7cddfSDavid du Colombier void 2347dd7cddfSDavid du Colombier label(Point p, int dy, char *text) 2357dd7cddfSDavid du Colombier { 2367dd7cddfSDavid du Colombier char *s; 2377dd7cddfSDavid du Colombier Rune r[2]; 2387dd7cddfSDavid du Colombier int w, maxw, maxy; 2397dd7cddfSDavid du Colombier 2407dd7cddfSDavid du Colombier p.x += Labspace; 2417dd7cddfSDavid du Colombier maxy = p.y+dy; 2427dd7cddfSDavid du Colombier maxw = 0; 2437dd7cddfSDavid du Colombier r[1] = '\0'; 2447dd7cddfSDavid du Colombier for(s=text; *s; ){ 2457dd7cddfSDavid du Colombier if(p.y+mediumfont->height-Ysqueeze > maxy) 2467dd7cddfSDavid du Colombier break; 2477dd7cddfSDavid du Colombier w = chartorune(r, s); 2487dd7cddfSDavid du Colombier s += w; 2497dd7cddfSDavid du Colombier w = runestringwidth(mediumfont, r); 2507dd7cddfSDavid du Colombier if(w > maxw) 2517dd7cddfSDavid du Colombier maxw = w; 2527dd7cddfSDavid du Colombier runestring(screen, p, display->black, ZP, mediumfont, r); 2537dd7cddfSDavid du Colombier p.y += mediumfont->height-Ysqueeze; 2547dd7cddfSDavid du Colombier } 2557dd7cddfSDavid du Colombier } 2567dd7cddfSDavid du Colombier 2577dd7cddfSDavid du Colombier void 258c93608ccSDavid du Colombier hashmark(Point p, int dy, long v, long vmax, char *label) 2597dd7cddfSDavid du Colombier { 2607dd7cddfSDavid du Colombier int y; 2617dd7cddfSDavid du Colombier int x; 2627dd7cddfSDavid du Colombier 2637dd7cddfSDavid du Colombier x = p.x + Labspace; 2647dd7cddfSDavid du Colombier y = p.y + (dy*(vmax-v))/vmax; 2657dd7cddfSDavid du Colombier draw(screen, Rect(p.x, y-1, p.x+Labspace, y+1), display->black, nil, ZP); 2667dd7cddfSDavid du Colombier if(dy > 5*mediumfont->height) 2677dd7cddfSDavid du Colombier string(screen, Pt(x, y-mediumfont->height/2), 2687dd7cddfSDavid du Colombier display->black, ZP, mediumfont, label); 2697dd7cddfSDavid du Colombier } 2707dd7cddfSDavid du Colombier 2717dd7cddfSDavid du Colombier void 2727dd7cddfSDavid du Colombier hashmarks(Point p, int dy, int which) 2737dd7cddfSDavid du Colombier { 2747dd7cddfSDavid du Colombier switch(index2which(which)){ 2757dd7cddfSDavid du Colombier case Mrtt: 2767dd7cddfSDavid du Colombier hashmark(p, dy, rttscale(1000000), Rttmax, "1."); 2777dd7cddfSDavid du Colombier hashmark(p, dy, rttscale(100000), Rttmax, "0.1"); 2787dd7cddfSDavid du Colombier hashmark(p, dy, rttscale(10000), Rttmax, "0.01"); 2797dd7cddfSDavid du Colombier hashmark(p, dy, rttscale(1000), Rttmax, "0.001"); 2807dd7cddfSDavid du Colombier break; 2817dd7cddfSDavid du Colombier case Mlost: 2827dd7cddfSDavid du Colombier hashmark(p, dy, 75, 100, " 75%"); 2837dd7cddfSDavid du Colombier hashmark(p, dy, 50, 100, " 50%"); 2847dd7cddfSDavid du Colombier hashmark(p, dy, 25, 100, " 25%"); 2857dd7cddfSDavid du Colombier break; 2867dd7cddfSDavid du Colombier } 2877dd7cddfSDavid du Colombier } 2887dd7cddfSDavid du Colombier 2897dd7cddfSDavid du Colombier Point 2907dd7cddfSDavid du Colombier paritypt(int x) 2917dd7cddfSDavid du Colombier { 2927dd7cddfSDavid du Colombier return Pt(x+parity, 0); 2937dd7cddfSDavid du Colombier } 2947dd7cddfSDavid du Colombier 2957dd7cddfSDavid du Colombier Point 2967dd7cddfSDavid du Colombier datapoint(Graph *g, int x, long v, long vmax) 2977dd7cddfSDavid du Colombier { 2987dd7cddfSDavid du Colombier Point p; 2997dd7cddfSDavid du Colombier 3007dd7cddfSDavid du Colombier p.x = x; 3017dd7cddfSDavid du Colombier p.y = g->r.max.y - Dy(g->r)*v/vmax - Dot; 3027dd7cddfSDavid du Colombier if(p.y < g->r.min.y) 3037dd7cddfSDavid du Colombier p.y = g->r.min.y; 3047dd7cddfSDavid du Colombier if(p.y > g->r.max.y-Dot) 3057dd7cddfSDavid du Colombier p.y = g->r.max.y-Dot; 3067dd7cddfSDavid du Colombier return p; 3077dd7cddfSDavid du Colombier } 3087dd7cddfSDavid du Colombier 3097dd7cddfSDavid du Colombier void 3107dd7cddfSDavid du Colombier drawdatum(Graph *g, int x, long prev, long v, long vmax) 3117dd7cddfSDavid du Colombier { 3127dd7cddfSDavid du Colombier int c; 3137dd7cddfSDavid du Colombier Point p, q; 3147dd7cddfSDavid du Colombier 3157dd7cddfSDavid du Colombier c = g->colindex; 3167dd7cddfSDavid du Colombier p = datapoint(g, x, v, vmax); 3177dd7cddfSDavid du Colombier q = datapoint(g, x, prev, vmax); 3187dd7cddfSDavid du Colombier if(p.y < q.y){ 3197dd7cddfSDavid du Colombier draw(screen, Rect(p.x, g->r.min.y, p.x+1, p.y), cols[c][0], nil, paritypt(p.x)); 3207dd7cddfSDavid du Colombier draw(screen, Rect(p.x, p.y, p.x+1, q.y+Dot), cols[c][2], nil, ZP); 3217dd7cddfSDavid du Colombier draw(screen, Rect(p.x, q.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP); 3227dd7cddfSDavid du Colombier }else{ 3237dd7cddfSDavid du Colombier draw(screen, Rect(p.x, g->r.min.y, p.x+1, q.y), cols[c][0], nil, paritypt(p.x)); 3247dd7cddfSDavid du Colombier draw(screen, Rect(p.x, q.y, p.x+1, p.y+Dot), cols[c][2], nil, ZP); 3257dd7cddfSDavid du Colombier draw(screen, Rect(p.x, p.y+Dot, p.x+1, g->r.max.y), cols[c][1], nil, ZP); 3267dd7cddfSDavid du Colombier } 3277dd7cddfSDavid du Colombier g->vmax = vmax; 3287dd7cddfSDavid du Colombier } 3297dd7cddfSDavid du Colombier 3307dd7cddfSDavid du Colombier void 3317dd7cddfSDavid du Colombier drawmark(Graph *g, int x) 3327dd7cddfSDavid du Colombier { 3337dd7cddfSDavid du Colombier int c; 3347dd7cddfSDavid du Colombier 3357dd7cddfSDavid du Colombier c = (g->colindex+1)&Ncolor; 3367dd7cddfSDavid du Colombier draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[c][2], nil, ZP); 3377dd7cddfSDavid du Colombier } 3387dd7cddfSDavid du Colombier 3397dd7cddfSDavid du Colombier void 3407dd7cddfSDavid du Colombier redraw(Graph *g, int vmax) 3417dd7cddfSDavid du Colombier { 3427dd7cddfSDavid du Colombier int i, c; 3437dd7cddfSDavid du Colombier 3447dd7cddfSDavid du Colombier c = g->colindex; 3457dd7cddfSDavid du Colombier draw(screen, g->r, cols[c][0], nil, paritypt(g->r.min.x)); 3467dd7cddfSDavid du Colombier for(i=1; i<Dx(g->r); i++) 3477dd7cddfSDavid du Colombier drawdatum(g, g->r.max.x-i, g->data[i-1], g->data[i], vmax); 3487dd7cddfSDavid du Colombier drawdatum(g, g->r.min.x, g->data[i], g->data[i], vmax); 3497dd7cddfSDavid du Colombier } 3507dd7cddfSDavid du Colombier 3517dd7cddfSDavid du Colombier void 3527dd7cddfSDavid du Colombier clearmsg(Graph *g) 3537dd7cddfSDavid du Colombier { 3547dd7cddfSDavid du Colombier if(g->overtmp != nil) 3557dd7cddfSDavid du Colombier draw(screen, g->overtmp->r, g->overtmp, nil, g->overtmp->r.min); 3567dd7cddfSDavid du Colombier g->overflow = 0; 3577dd7cddfSDavid du Colombier } 3587dd7cddfSDavid du Colombier 3597dd7cddfSDavid du Colombier void 3607dd7cddfSDavid du Colombier drawmsg(Graph *g, char *msg) 3617dd7cddfSDavid du Colombier { 3627dd7cddfSDavid du Colombier if(g->overtmp == nil) 3637dd7cddfSDavid du Colombier return; 3647dd7cddfSDavid du Colombier 365*5a354e27SDavid du Colombier /* save previous contents of screen */ 3667dd7cddfSDavid du Colombier draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min); 3677dd7cddfSDavid du Colombier 368*5a354e27SDavid du Colombier /* draw message */ 3697dd7cddfSDavid du Colombier if(strlen(msg) > g->overtmplen) 3707dd7cddfSDavid du Colombier msg[g->overtmplen] = 0; 3717dd7cddfSDavid du Colombier string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, msg); 3727dd7cddfSDavid du Colombier } 3737dd7cddfSDavid du Colombier 3747dd7cddfSDavid du Colombier void 3757dd7cddfSDavid du Colombier clearcursor(Graph *g) 3767dd7cddfSDavid du Colombier { 3777dd7cddfSDavid du Colombier int x; 3787dd7cddfSDavid du Colombier long prev; 3797dd7cddfSDavid du Colombier 3807dd7cddfSDavid du Colombier if(g->overtmp == nil) 3817dd7cddfSDavid du Colombier return; 3827dd7cddfSDavid du Colombier 3837dd7cddfSDavid du Colombier if(g->cursor > 0 && g->cursor < g->ndata){ 3847dd7cddfSDavid du Colombier x = g->r.max.x - g->cursor; 3857dd7cddfSDavid du Colombier prev = 0; 3867dd7cddfSDavid du Colombier if(g->cursor > 0) 3877dd7cddfSDavid du Colombier prev = g->data[g->cursor-1]; 3887dd7cddfSDavid du Colombier drawdatum(g, x, prev, g->data[g->cursor], g->vmax); 3897dd7cddfSDavid du Colombier g->cursor = -1; 3907dd7cddfSDavid du Colombier } 3917dd7cddfSDavid du Colombier } 3927dd7cddfSDavid du Colombier 3937dd7cddfSDavid du Colombier void 3947dd7cddfSDavid du Colombier drawcursor(Graph *g, int x) 3957dd7cddfSDavid du Colombier { 3967dd7cddfSDavid du Colombier if(g->overtmp == nil) 3977dd7cddfSDavid du Colombier return; 3987dd7cddfSDavid du Colombier 3997dd7cddfSDavid du Colombier draw(screen, Rect(x, g->r.min.y, x+1, g->r.max.y), cols[g->colindex][2], nil, ZP); 4007dd7cddfSDavid du Colombier } 4017dd7cddfSDavid du Colombier 4027dd7cddfSDavid du Colombier void 4037dd7cddfSDavid du Colombier update1(Graph *g, long v, long vmax, long mark) 4047dd7cddfSDavid du Colombier { 4057dd7cddfSDavid du Colombier char buf[Gmsglen]; 4067dd7cddfSDavid du Colombier 407*5a354e27SDavid du Colombier /* put back screen value sans message */ 4087dd7cddfSDavid du Colombier if(g->overflow || *g->msg){ 4097dd7cddfSDavid du Colombier clearmsg(g); 4107dd7cddfSDavid du Colombier g->overflow = 0; 4117dd7cddfSDavid du Colombier } 4127dd7cddfSDavid du Colombier 4137dd7cddfSDavid du Colombier draw(screen, g->r, screen, nil, Pt(g->r.min.x+1, g->r.min.y)); 4147dd7cddfSDavid du Colombier drawdatum(g, g->r.max.x-1, g->data[0], v, vmax); 4157dd7cddfSDavid du Colombier if(mark) 4167dd7cddfSDavid du Colombier drawmark(g, g->r.max.x-1); 4177dd7cddfSDavid du Colombier memmove(g->data+1, g->data, (g->ndata-1)*sizeof(g->data[0])); 4187dd7cddfSDavid du Colombier g->data[0] = v; 4197dd7cddfSDavid du Colombier if(v>vmax){ 4207dd7cddfSDavid du Colombier g->overflow = 1; 4217dd7cddfSDavid du Colombier sprint(buf, "%ld", v); 4227dd7cddfSDavid du Colombier drawmsg(g, buf); 4237dd7cddfSDavid du Colombier } else if(*g->msg) 4247dd7cddfSDavid du Colombier drawmsg(g, g->msg); 4257dd7cddfSDavid du Colombier 4267dd7cddfSDavid du Colombier if(g->cursor >= 0){ 4277dd7cddfSDavid du Colombier g->cursor++; 4287dd7cddfSDavid du Colombier if(g->cursor >= g->ndata){ 4297dd7cddfSDavid du Colombier g->cursor = -1; 4307dd7cddfSDavid du Colombier if(*g->msg){ 4317dd7cddfSDavid du Colombier clearmsg(g); 4327dd7cddfSDavid du Colombier *g->msg = 0; 4337dd7cddfSDavid du Colombier } 4347dd7cddfSDavid du Colombier } 4357dd7cddfSDavid du Colombier } 4367dd7cddfSDavid du Colombier 4377dd7cddfSDavid du Colombier } 4387dd7cddfSDavid du Colombier 4397dd7cddfSDavid du Colombier void 4407dd7cddfSDavid du Colombier pinglost(Machine *m, Req*) 4417dd7cddfSDavid du Colombier { 4427dd7cddfSDavid du Colombier m->lostmsgs++; 4437dd7cddfSDavid du Colombier } 4447dd7cddfSDavid du Colombier 4457dd7cddfSDavid du Colombier void 4467dd7cddfSDavid du Colombier pingreply(Machine *m, Req *r) 4477dd7cddfSDavid du Colombier { 4487dd7cddfSDavid du Colombier ulong x; 4497dd7cddfSDavid du Colombier 4507dd7cddfSDavid du Colombier x = r->time/1000LL; 4517dd7cddfSDavid du Colombier m->rttsum += x; 4527dd7cddfSDavid du Colombier m->rcvdmsgs++; 4537dd7cddfSDavid du Colombier m->rttmsgs++; 4547dd7cddfSDavid du Colombier } 4557dd7cddfSDavid du Colombier 4567dd7cddfSDavid du Colombier 4577dd7cddfSDavid du Colombier void 4587dd7cddfSDavid du Colombier pingclean(Machine *m, ushort seq, vlong now, int) 4597dd7cddfSDavid du Colombier { 4607dd7cddfSDavid du Colombier Req **l, *r; 4617dd7cddfSDavid du Colombier vlong x, y; 4627dd7cddfSDavid du Colombier 4637dd7cddfSDavid du Colombier y = 10LL*1000000000LL; 4647dd7cddfSDavid du Colombier for(l = &m->first; *l; ){ 4657dd7cddfSDavid du Colombier r = *l; 4667dd7cddfSDavid du Colombier x = now - r->time; 4677dd7cddfSDavid du Colombier if(x > y || r->seq == seq){ 4687dd7cddfSDavid du Colombier *l = r->next; 4697dd7cddfSDavid du Colombier r->time = x; 4707dd7cddfSDavid du Colombier if(r->seq != seq) 4717dd7cddfSDavid du Colombier pinglost(m, r); 4727dd7cddfSDavid du Colombier else 4737dd7cddfSDavid du Colombier pingreply(m, r); 4747dd7cddfSDavid du Colombier free(r); 4757dd7cddfSDavid du Colombier } else 4767dd7cddfSDavid du Colombier l = &(r->next); 4777dd7cddfSDavid du Colombier } 4787dd7cddfSDavid du Colombier } 4797dd7cddfSDavid du Colombier 4807dd7cddfSDavid du Colombier void 4817dd7cddfSDavid du Colombier pingsend(Machine *m) 4827dd7cddfSDavid du Colombier { 4837dd7cddfSDavid du Colombier char buf[128]; 4847dd7cddfSDavid du Colombier Icmp *ip; 4857dd7cddfSDavid du Colombier int i; 4867dd7cddfSDavid du Colombier Req *r; 4879a747e4fSDavid du Colombier char err[ERRMAX]; 4887dd7cddfSDavid du Colombier 4897dd7cddfSDavid du Colombier ip = (Icmp*)buf; 4907dd7cddfSDavid du Colombier 4917dd7cddfSDavid du Colombier r = malloc(sizeof *r); 4927dd7cddfSDavid du Colombier if(r == nil) 4937dd7cddfSDavid du Colombier return; 4947dd7cddfSDavid du Colombier 4957dd7cddfSDavid du Colombier for(i = 32; i < 64; i++) 4967dd7cddfSDavid du Colombier buf[i] = i; 4977dd7cddfSDavid du Colombier ip->type = EchoRequest; 4987dd7cddfSDavid du Colombier ip->code = 0; 4997dd7cddfSDavid du Colombier ip->seq[0] = m->seq; 5007dd7cddfSDavid du Colombier ip->seq[1] = m->seq>>8; 5017dd7cddfSDavid du Colombier r->seq = m->seq; 5027dd7cddfSDavid du Colombier r->next = nil; 5037dd7cddfSDavid du Colombier lock(m); 5047dd7cddfSDavid du Colombier pingclean(m, -1, nsec(), 0); 5057dd7cddfSDavid du Colombier if(m->first == nil) 5067dd7cddfSDavid du Colombier m->first = r; 5077dd7cddfSDavid du Colombier else 5087dd7cddfSDavid du Colombier m->last->next = r; 5097dd7cddfSDavid du Colombier m->last = r; 5107dd7cddfSDavid du Colombier r->time = nsec(); 5117dd7cddfSDavid du Colombier unlock(m); 5127dd7cddfSDavid du Colombier if(write(m->pingfd, ip, MSGLEN) < MSGLEN){ 5139a747e4fSDavid du Colombier errstr(err, sizeof err); 5147dd7cddfSDavid du Colombier if(strstr(err, "unreach")||strstr(err, "exceed")) 5157dd7cddfSDavid du Colombier m->unreachable++; 5167dd7cddfSDavid du Colombier } 5177dd7cddfSDavid du Colombier m->seq++; 5187dd7cddfSDavid du Colombier } 5197dd7cddfSDavid du Colombier 5207dd7cddfSDavid du Colombier void 5217dd7cddfSDavid du Colombier pingrcv(void *arg) 5227dd7cddfSDavid du Colombier { 5237dd7cddfSDavid du Colombier uchar buf[512]; 5247dd7cddfSDavid du Colombier Icmp *ip; 5257dd7cddfSDavid du Colombier ushort x; 5267dd7cddfSDavid du Colombier int i, n, fd; 5277dd7cddfSDavid du Colombier vlong now; 5287dd7cddfSDavid du Colombier Machine *m = arg; 5297dd7cddfSDavid du Colombier 5307dd7cddfSDavid du Colombier ip = (Icmp*)buf; 5317dd7cddfSDavid du Colombier fd = dup(m->pingfd, -1); 5327dd7cddfSDavid du Colombier for(;;){ 5337dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)); 5347dd7cddfSDavid du Colombier now = nsec(); 5357dd7cddfSDavid du Colombier if(n <= 0) 5367dd7cddfSDavid du Colombier continue; 5377dd7cddfSDavid du Colombier if(n < MSGLEN){ 5387dd7cddfSDavid du Colombier print("bad len %d/%d\n", n, MSGLEN); 5397dd7cddfSDavid du Colombier continue; 5407dd7cddfSDavid du Colombier } 5417dd7cddfSDavid du Colombier for(i = 32; i < MSGLEN; i++) 5427dd7cddfSDavid du Colombier if(buf[i] != (i&0xff)) 5437dd7cddfSDavid du Colombier continue; 5447dd7cddfSDavid du Colombier x = (ip->seq[1]<<8)|ip->seq[0]; 5457dd7cddfSDavid du Colombier if(ip->type != EchoReply || ip->code != 0) 5467dd7cddfSDavid du Colombier continue; 5477dd7cddfSDavid du Colombier lock(m); 5487dd7cddfSDavid du Colombier pingclean(m, x, now, ip->ttl); 5497dd7cddfSDavid du Colombier unlock(m); 5507dd7cddfSDavid du Colombier } 5517dd7cddfSDavid du Colombier } 5527dd7cddfSDavid du Colombier 5537dd7cddfSDavid du Colombier void 5547dd7cddfSDavid du Colombier initmach(Machine *m, char *name) 5557dd7cddfSDavid du Colombier { 5567dd7cddfSDavid du Colombier char *p; 5577dd7cddfSDavid du Colombier 5587dd7cddfSDavid du Colombier srand(time(0)); 5597dd7cddfSDavid du Colombier p = strchr(name, '!'); 5607dd7cddfSDavid du Colombier if(p){ 5617dd7cddfSDavid du Colombier p++; 5627dd7cddfSDavid du Colombier m->name = estrdup(p+1); 5637dd7cddfSDavid du Colombier }else 5647dd7cddfSDavid du Colombier p = name; 5657dd7cddfSDavid du Colombier 5667dd7cddfSDavid du Colombier m->name = estrdup(p); 5677dd7cddfSDavid du Colombier m->nproc = 1; 5687dd7cddfSDavid du Colombier m->pingfd = dial(netmkaddr(m->name, "icmp", "1"), 0, 0, 0); 5697dd7cddfSDavid du Colombier if(m->pingfd < 0) 5707dd7cddfSDavid du Colombier sysfatal("dialing %s: %r", m->name); 5717dd7cddfSDavid du Colombier startproc(pingrcv, m); 5727dd7cddfSDavid du Colombier } 5737dd7cddfSDavid du Colombier 574c93608ccSDavid du Colombier long 575c93608ccSDavid du Colombier rttscale(long x) 5767dd7cddfSDavid du Colombier { 5777dd7cddfSDavid du Colombier if(x == 0) 5787dd7cddfSDavid du Colombier return 0; 5797dd7cddfSDavid du Colombier x = 10.0*log10(x) - 20.0; 5807dd7cddfSDavid du Colombier if(x < 0) 5817dd7cddfSDavid du Colombier x = 0; 5827dd7cddfSDavid du Colombier return x; 5837dd7cddfSDavid du Colombier } 5847dd7cddfSDavid du Colombier 585c93608ccSDavid du Colombier double 586c93608ccSDavid du Colombier rttunscale(long x) 5877dd7cddfSDavid du Colombier { 5887dd7cddfSDavid du Colombier double dx; 5897dd7cddfSDavid du Colombier 5907dd7cddfSDavid du Colombier x += 20; 5917dd7cddfSDavid du Colombier dx = x; 5927dd7cddfSDavid du Colombier return pow(10.0, dx/10.0); 5937dd7cddfSDavid du Colombier } 5947dd7cddfSDavid du Colombier 5957dd7cddfSDavid du Colombier void 5967dd7cddfSDavid du Colombier rttval(Machine *m, long *v, long *vmax, long *mark) 5977dd7cddfSDavid du Colombier { 5987dd7cddfSDavid du Colombier ulong x; 5997dd7cddfSDavid du Colombier 6007dd7cddfSDavid du Colombier if(m->rttmsgs == 0){ 6017dd7cddfSDavid du Colombier x = m->lastrtt; 6027dd7cddfSDavid du Colombier } else { 6037dd7cddfSDavid du Colombier x = m->rttsum/m->rttmsgs; 6047dd7cddfSDavid du Colombier m->rttsum = m->rttmsgs = 0; 6057dd7cddfSDavid du Colombier m->lastrtt = x; 6067dd7cddfSDavid du Colombier } 6077dd7cddfSDavid du Colombier 6087dd7cddfSDavid du Colombier *v = rttscale(x); 6097dd7cddfSDavid du Colombier *vmax = Rttmax; 6107dd7cddfSDavid du Colombier *mark = 0; 6117dd7cddfSDavid du Colombier } 6127dd7cddfSDavid du Colombier 6137dd7cddfSDavid du Colombier void 6147dd7cddfSDavid du Colombier lostval(Machine *m, long *v, long *vmax, long *mark) 6157dd7cddfSDavid du Colombier { 6167dd7cddfSDavid du Colombier ulong x; 6177dd7cddfSDavid du Colombier 6187dd7cddfSDavid du Colombier if(m->rcvdmsgs+m->lostmsgs > 0) 6197dd7cddfSDavid du Colombier x = (m->lostavg>>1) + (((m->lostmsgs*100)/(m->lostmsgs + m->rcvdmsgs))>>1); 6207dd7cddfSDavid du Colombier else 6217dd7cddfSDavid du Colombier x = m->lostavg; 6227dd7cddfSDavid du Colombier m->lostavg = x; 6237dd7cddfSDavid du Colombier m->lostmsgs = m->rcvdmsgs = 0; 6247dd7cddfSDavid du Colombier 6257dd7cddfSDavid du Colombier if(m->unreachable){ 6267dd7cddfSDavid du Colombier m->unreachable = 0; 6277dd7cddfSDavid du Colombier *mark = 100; 6287dd7cddfSDavid du Colombier } else 6297dd7cddfSDavid du Colombier *mark = 0; 6307dd7cddfSDavid du Colombier 6317dd7cddfSDavid du Colombier *v = x; 6327dd7cddfSDavid du Colombier *vmax = 100; 6337dd7cddfSDavid du Colombier } 6347dd7cddfSDavid du Colombier 6357dd7cddfSDavid du Colombier jmp_buf catchalarm; 6367dd7cddfSDavid du Colombier 6377dd7cddfSDavid du Colombier void 6387dd7cddfSDavid du Colombier alarmed(void *a, char *s) 6397dd7cddfSDavid du Colombier { 6407dd7cddfSDavid du Colombier if(strcmp(s, "alarm") == 0) 6417dd7cddfSDavid du Colombier notejmp(a, catchalarm, 1); 6427dd7cddfSDavid du Colombier noted(NDFLT); 6437dd7cddfSDavid du Colombier } 6447dd7cddfSDavid du Colombier 6457dd7cddfSDavid du Colombier void 6467dd7cddfSDavid du Colombier usage(void) 6477dd7cddfSDavid du Colombier { 6487dd7cddfSDavid du Colombier fprint(2, "usage: %s machine [machine...]\n", argv0); 6497dd7cddfSDavid du Colombier exits("usage"); 6507dd7cddfSDavid du Colombier } 6517dd7cddfSDavid du Colombier 6527dd7cddfSDavid du Colombier void 6537dd7cddfSDavid du Colombier addgraph(int n) 6547dd7cddfSDavid du Colombier { 6557dd7cddfSDavid du Colombier Graph *g, *ograph; 6567dd7cddfSDavid du Colombier int i, j; 6577dd7cddfSDavid du Colombier static int nadd; 6587dd7cddfSDavid du Colombier 6597dd7cddfSDavid du Colombier if(n > nelem(menu2str)) 6607dd7cddfSDavid du Colombier abort(); 6617dd7cddfSDavid du Colombier /* avoid two adjacent graphs of same color */ 6627dd7cddfSDavid du Colombier if(ngraph>0 && graph[ngraph-1].colindex==nadd%Ncolor) 6637dd7cddfSDavid du Colombier nadd++; 6647dd7cddfSDavid du Colombier ograph = graph; 6657dd7cddfSDavid du Colombier graph = emalloc(nmach*(ngraph+1)*sizeof(Graph)); 6667dd7cddfSDavid du Colombier for(i=0; i<nmach; i++) 6677dd7cddfSDavid du Colombier for(j=0; j<ngraph; j++) 6687dd7cddfSDavid du Colombier graph[i*(ngraph+1)+j] = ograph[i*ngraph+j]; 6697dd7cddfSDavid du Colombier free(ograph); 6707dd7cddfSDavid du Colombier ngraph++; 6717dd7cddfSDavid du Colombier for(i=0; i<nmach; i++){ 6727dd7cddfSDavid du Colombier g = &graph[i*ngraph+(ngraph-1)]; 6737dd7cddfSDavid du Colombier memset(g, 0, sizeof(Graph)); 6747dd7cddfSDavid du Colombier g->label = menu2str[n]+Opwid; 6757dd7cddfSDavid du Colombier g->newvalue = newvaluefn[n]; 6767dd7cddfSDavid du Colombier g->update = update1; /* no other update functions yet */ 6777dd7cddfSDavid du Colombier g->mach = &mach[i]; 6787dd7cddfSDavid du Colombier g->colindex = nadd%Ncolor; 6797dd7cddfSDavid du Colombier } 6807dd7cddfSDavid du Colombier present[n] = 1; 6817dd7cddfSDavid du Colombier nadd++; 6827dd7cddfSDavid du Colombier } 6837dd7cddfSDavid du Colombier 6847dd7cddfSDavid du Colombier int 6857dd7cddfSDavid du Colombier which2index(int which) 6867dd7cddfSDavid du Colombier { 6877dd7cddfSDavid du Colombier int i, n; 6887dd7cddfSDavid du Colombier 6897dd7cddfSDavid du Colombier n = -1; 6907dd7cddfSDavid du Colombier for(i=0; i<ngraph; i++){ 6917dd7cddfSDavid du Colombier if(strcmp(menu2str[which]+Opwid, graph[i].label) == 0){ 6927dd7cddfSDavid du Colombier n = i; 6937dd7cddfSDavid du Colombier break; 6947dd7cddfSDavid du Colombier } 6957dd7cddfSDavid du Colombier } 6967dd7cddfSDavid du Colombier if(n < 0){ 6977dd7cddfSDavid du Colombier fprint(2, "%s: internal error can't drop graph\n", argv0); 6987dd7cddfSDavid du Colombier killall("error"); 6997dd7cddfSDavid du Colombier } 7007dd7cddfSDavid du Colombier return n; 7017dd7cddfSDavid du Colombier } 7027dd7cddfSDavid du Colombier 7037dd7cddfSDavid du Colombier int 7047dd7cddfSDavid du Colombier index2which(int index) 7057dd7cddfSDavid du Colombier { 7067dd7cddfSDavid du Colombier int i, n; 7077dd7cddfSDavid du Colombier 7087dd7cddfSDavid du Colombier n = -1; 7097dd7cddfSDavid du Colombier for(i=0; i<Nmenu2; i++){ 7107dd7cddfSDavid du Colombier if(strcmp(menu2str[i]+Opwid, graph[index].label) == 0){ 7117dd7cddfSDavid du Colombier n = i; 7127dd7cddfSDavid du Colombier break; 7137dd7cddfSDavid du Colombier } 7147dd7cddfSDavid du Colombier } 7157dd7cddfSDavid du Colombier if(n < 0){ 7167dd7cddfSDavid du Colombier fprint(2, "%s: internal error can't identify graph\n", argv0); 7177dd7cddfSDavid du Colombier killall("error"); 7187dd7cddfSDavid du Colombier } 7197dd7cddfSDavid du Colombier return n; 7207dd7cddfSDavid du Colombier } 7217dd7cddfSDavid du Colombier 7227dd7cddfSDavid du Colombier void 7237dd7cddfSDavid du Colombier dropgraph(int which) 7247dd7cddfSDavid du Colombier { 7257dd7cddfSDavid du Colombier Graph *ograph; 7267dd7cddfSDavid du Colombier int i, j, n; 7277dd7cddfSDavid du Colombier 7287dd7cddfSDavid du Colombier if(which > nelem(menu2str)) 7297dd7cddfSDavid du Colombier abort(); 7307dd7cddfSDavid du Colombier /* convert n to index in graph table */ 7317dd7cddfSDavid du Colombier n = which2index(which); 7327dd7cddfSDavid du Colombier ograph = graph; 7337dd7cddfSDavid du Colombier graph = emalloc(nmach*(ngraph-1)*sizeof(Graph)); 7347dd7cddfSDavid du Colombier for(i=0; i<nmach; i++){ 7357dd7cddfSDavid du Colombier for(j=0; j<n; j++) 7367dd7cddfSDavid du Colombier graph[i*(ngraph-1)+j] = ograph[i*ngraph+j]; 7377dd7cddfSDavid du Colombier free(ograph[i*ngraph+j].data); 7387dd7cddfSDavid du Colombier freeimage(ograph[i*ngraph+j].overtmp); 7397dd7cddfSDavid du Colombier for(j++; j<ngraph; j++) 7407dd7cddfSDavid du Colombier graph[i*(ngraph-1)+j-1] = ograph[i*ngraph+j]; 7417dd7cddfSDavid du Colombier } 7427dd7cddfSDavid du Colombier free(ograph); 7437dd7cddfSDavid du Colombier ngraph--; 7447dd7cddfSDavid du Colombier present[which] = 0; 7457dd7cddfSDavid du Colombier } 7467dd7cddfSDavid du Colombier 7477dd7cddfSDavid du Colombier void 7487dd7cddfSDavid du Colombier addmachine(char *name) 7497dd7cddfSDavid du Colombier { 7507dd7cddfSDavid du Colombier if(ngraph > 0){ 7517dd7cddfSDavid du Colombier fprint(2, "%s: internal error: ngraph>0 in addmachine()\n", argv0); 7527dd7cddfSDavid du Colombier usage(); 7537dd7cddfSDavid du Colombier } 7547dd7cddfSDavid du Colombier if(nmach == NMACH) 7557dd7cddfSDavid du Colombier sysfatal("too many machines"); 7567dd7cddfSDavid du Colombier initmach(&mach[nmach++], name); 7577dd7cddfSDavid du Colombier } 7587dd7cddfSDavid du Colombier 7597dd7cddfSDavid du Colombier 7607dd7cddfSDavid du Colombier void 7617dd7cddfSDavid du Colombier resize(void) 7627dd7cddfSDavid du Colombier { 7637dd7cddfSDavid du Colombier int i, j, n, startx, starty, x, y, dx, dy, hashdx, ondata; 7647dd7cddfSDavid du Colombier Graph *g; 7657dd7cddfSDavid du Colombier Rectangle machr, r; 7667dd7cddfSDavid du Colombier long v, vmax, mark; 7677dd7cddfSDavid du Colombier char buf[128]; 7687dd7cddfSDavid du Colombier 7697dd7cddfSDavid du Colombier draw(screen, screen->r, display->white, nil, ZP); 7707dd7cddfSDavid du Colombier 7717dd7cddfSDavid du Colombier /* label left edge */ 7727dd7cddfSDavid du Colombier x = screen->r.min.x; 7737dd7cddfSDavid du Colombier y = screen->r.min.y + Labspace+mediumfont->height+Labspace; 7747dd7cddfSDavid du Colombier dy = (screen->r.max.y - y)/ngraph; 7757dd7cddfSDavid du Colombier dx = Labspace+stringwidth(mediumfont, "0")+Labspace; 7767dd7cddfSDavid du Colombier startx = x+dx+1; 7777dd7cddfSDavid du Colombier starty = y; 7787dd7cddfSDavid du Colombier for(i=0; i<ngraph; i++,y+=dy){ 7797dd7cddfSDavid du Colombier draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP); 7807dd7cddfSDavid du Colombier draw(screen, Rect(x, y, x+dx, screen->r.max.y), cols[graph[i].colindex][0], nil, paritypt(x)); 7817dd7cddfSDavid du Colombier label(Pt(x, y), dy, graph[i].label); 7827dd7cddfSDavid du Colombier draw(screen, Rect(x+dx, y, x+dx+1, screen->r.max.y), cols[graph[i].colindex][2], nil, ZP); 7837dd7cddfSDavid du Colombier } 7847dd7cddfSDavid du Colombier 7857dd7cddfSDavid du Colombier /* label right edge */ 7867dd7cddfSDavid du Colombier dx = Labspace+stringwidth(mediumfont, "0.001")+Labspace; 7877dd7cddfSDavid du Colombier hashdx = dx; 7887dd7cddfSDavid du Colombier x = screen->r.max.x - dx; 7897dd7cddfSDavid du Colombier y = screen->r.min.y + Labspace+mediumfont->height+Labspace; 7907dd7cddfSDavid du Colombier for(i=0; i<ngraph; i++,y+=dy){ 7917dd7cddfSDavid du Colombier draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP); 7927dd7cddfSDavid du Colombier draw(screen, Rect(x, y, x+dx, screen->r.max.y), cols[graph[i].colindex][0], nil, paritypt(x)); 7937dd7cddfSDavid du Colombier hashmarks(Pt(x, y), dy, i); 7947dd7cddfSDavid du Colombier draw(screen, Rect(x+dx, y, x+dx+1, screen->r.max.y), cols[graph[i].colindex][2], nil, ZP); 7957dd7cddfSDavid du Colombier } 7967dd7cddfSDavid du Colombier 7977dd7cddfSDavid du Colombier /* label top edge */ 7987dd7cddfSDavid du Colombier dx = (screen->r.max.x - dx - startx)/nmach; 7997dd7cddfSDavid du Colombier for(x=startx, i=0; i<nmach; i++,x+=dx){ 8007dd7cddfSDavid du Colombier draw(screen, Rect(x-1, starty-1, x, screen->r.max.y), display->black, nil, ZP); 8017dd7cddfSDavid du Colombier j = dx/stringwidth(mediumfont, "0"); 8027dd7cddfSDavid du Colombier n = mach[i].nproc; 8037dd7cddfSDavid du Colombier if(n>1 && j>=1+3+(n>10)+(n>100)){ /* first char of name + (n) */ 8047dd7cddfSDavid du Colombier j -= 3+(n>10)+(n>100); 8057dd7cddfSDavid du Colombier if(j <= 0) 8067dd7cddfSDavid du Colombier j = 1; 8077dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%.*s(%d)", j, mach[i].name, n); 8087dd7cddfSDavid du Colombier }else 8097dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%.*s", j, mach[i].name); 8107dd7cddfSDavid du Colombier string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, 8117dd7cddfSDavid du Colombier mediumfont, buf); 8127dd7cddfSDavid du Colombier } 8137dd7cddfSDavid du Colombier /* draw last vertical line */ 8147dd7cddfSDavid du Colombier draw(screen, 8157dd7cddfSDavid du Colombier Rect(screen->r.max.x-hashdx-1, starty-1, screen->r.max.x-hashdx, screen->r.max.y), 8167dd7cddfSDavid du Colombier display->black, nil, ZP); 8177dd7cddfSDavid du Colombier 8187dd7cddfSDavid du Colombier /* create graphs */ 8197dd7cddfSDavid du Colombier for(i=0; i<nmach; i++){ 8207dd7cddfSDavid du Colombier machr = Rect(startx+i*dx, starty, screen->r.max.x, screen->r.max.y); 8217dd7cddfSDavid du Colombier if(i < nmach-1) 8227dd7cddfSDavid du Colombier machr.max.x = startx+(i+1)*dx - 1; 8237dd7cddfSDavid du Colombier else 8247dd7cddfSDavid du Colombier machr.max.x = screen->r.max.x - hashdx - 1; 8257dd7cddfSDavid du Colombier y = starty; 8267dd7cddfSDavid du Colombier for(j=0; j<ngraph; j++, y+=dy){ 8277dd7cddfSDavid du Colombier g = &graph[i*ngraph+j]; 8287dd7cddfSDavid du Colombier /* allocate data */ 8297dd7cddfSDavid du Colombier ondata = g->ndata; 8307dd7cddfSDavid du Colombier g->ndata = Dx(machr)+1; /* may be too many if label will be drawn here; so what? */ 8317dd7cddfSDavid du Colombier g->data = erealloc(g->data, g->ndata*sizeof(long)); 8327dd7cddfSDavid du Colombier if(g->ndata > ondata) 8337dd7cddfSDavid du Colombier memset(g->data+ondata, 0, (g->ndata-ondata)*sizeof(long)); 8347dd7cddfSDavid du Colombier /* set geometry */ 8357dd7cddfSDavid du Colombier g->r = machr; 8367dd7cddfSDavid du Colombier g->r.min.y = y; 8377dd7cddfSDavid du Colombier g->r.max.y = y+dy - 1; 8387dd7cddfSDavid du Colombier if(j == ngraph-1) 8397dd7cddfSDavid du Colombier g->r.max.y = screen->r.max.y; 8407dd7cddfSDavid du Colombier draw(screen, g->r, cols[g->colindex][0], nil, paritypt(g->r.min.x)); 8417dd7cddfSDavid du Colombier g->overflow = 0; 8427dd7cddfSDavid du Colombier *g->msg = 0; 8437dd7cddfSDavid du Colombier freeimage(g->overtmp); 8447dd7cddfSDavid du Colombier g->overtmp = nil; 8457dd7cddfSDavid du Colombier g->overtmplen = 0; 8467dd7cddfSDavid du Colombier r = g->r; 8477dd7cddfSDavid du Colombier r.max.y = r.min.y+mediumfont->height; 8487dd7cddfSDavid du Colombier n = (g->r.max.x - r.min.x)/stringwidth(mediumfont, "9"); 8497dd7cddfSDavid du Colombier if(n > 4){ 8507dd7cddfSDavid du Colombier if(n > Gmsglen) 8517dd7cddfSDavid du Colombier n = Gmsglen; 8527dd7cddfSDavid du Colombier r.max.x = r.min.x+stringwidth(mediumfont, "9")*n; 8537dd7cddfSDavid du Colombier g->overtmplen = n; 8547dd7cddfSDavid du Colombier g->overtmp = allocimage(display, r, screen->chan, 0, -1); 8557dd7cddfSDavid du Colombier } 8567dd7cddfSDavid du Colombier g->newvalue(g->mach, &v, &vmax, &mark); 8577dd7cddfSDavid du Colombier redraw(g, vmax); 8587dd7cddfSDavid du Colombier } 8597dd7cddfSDavid du Colombier } 8607dd7cddfSDavid du Colombier 8617dd7cddfSDavid du Colombier flushimage(display, 1); 8627dd7cddfSDavid du Colombier } 8637dd7cddfSDavid du Colombier 8647dd7cddfSDavid du Colombier void 8657dd7cddfSDavid du Colombier eresized(int new) 8667dd7cddfSDavid du Colombier { 8677dd7cddfSDavid du Colombier lockdisplay(display); 8687dd7cddfSDavid du Colombier if(new && getwindow(display, Refnone) < 0) { 8697dd7cddfSDavid du Colombier fprint(2, "%s: can't reattach to window\n", argv0); 8707dd7cddfSDavid du Colombier killall("reattach"); 8717dd7cddfSDavid du Colombier } 8727dd7cddfSDavid du Colombier resize(); 8737dd7cddfSDavid du Colombier unlockdisplay(display); 8747dd7cddfSDavid du Colombier } 8757dd7cddfSDavid du Colombier 8767dd7cddfSDavid du Colombier void 8777dd7cddfSDavid du Colombier dobutton2(Mouse *m) 8787dd7cddfSDavid du Colombier { 8797dd7cddfSDavid du Colombier int i; 8807dd7cddfSDavid du Colombier 8817dd7cddfSDavid du Colombier for(i=0; i<Nmenu2; i++) 8827dd7cddfSDavid du Colombier if(present[i]) 8837dd7cddfSDavid du Colombier memmove(menu2str[i], "drop ", Opwid); 8847dd7cddfSDavid du Colombier else 8857dd7cddfSDavid du Colombier memmove(menu2str[i], "add ", Opwid); 8867dd7cddfSDavid du Colombier i = emenuhit(3, m, &menu2); 8877dd7cddfSDavid du Colombier if(i >= 0){ 8887dd7cddfSDavid du Colombier if(!present[i]) 8897dd7cddfSDavid du Colombier addgraph(i); 8907dd7cddfSDavid du Colombier else if(ngraph > 1) 8917dd7cddfSDavid du Colombier dropgraph(i); 8927dd7cddfSDavid du Colombier resize(); 8937dd7cddfSDavid du Colombier } 8947dd7cddfSDavid du Colombier } 8957dd7cddfSDavid du Colombier 8967dd7cddfSDavid du Colombier void 8977dd7cddfSDavid du Colombier dobutton1(Mouse *m) 8987dd7cddfSDavid du Colombier { 8997dd7cddfSDavid du Colombier int i, n, dx, dt; 9007dd7cddfSDavid du Colombier Graph *g; 9017dd7cddfSDavid du Colombier char *e; 9027dd7cddfSDavid du Colombier double f; 9037dd7cddfSDavid du Colombier 9047dd7cddfSDavid du Colombier for(i = 0; i < ngraph*nmach; i++){ 9057dd7cddfSDavid du Colombier if(ptinrect(m->xy, graph[i].r)) 9067dd7cddfSDavid du Colombier break; 9077dd7cddfSDavid du Colombier } 9087dd7cddfSDavid du Colombier if(i == ngraph*nmach) 9097dd7cddfSDavid du Colombier return; 9107dd7cddfSDavid du Colombier 9117dd7cddfSDavid du Colombier g = &graph[i]; 9127dd7cddfSDavid du Colombier if(g->overtmp == nil) 9137dd7cddfSDavid du Colombier return; 9147dd7cddfSDavid du Colombier 915*5a354e27SDavid du Colombier /* clear any previous message and cursor */ 9167dd7cddfSDavid du Colombier if(g->overflow || *g->msg){ 9177dd7cddfSDavid du Colombier clearmsg(g); 9187dd7cddfSDavid du Colombier *g->msg = 0; 9197dd7cddfSDavid du Colombier clearcursor(g); 9207dd7cddfSDavid du Colombier } 9217dd7cddfSDavid du Colombier 9227dd7cddfSDavid du Colombier dx = g->r.max.x - m->xy.x; 9237dd7cddfSDavid du Colombier g->cursor = dx; 9247dd7cddfSDavid du Colombier dt = dx*pinginterval; 9257dd7cddfSDavid du Colombier e = &g->msg[sizeof(g->msg)]; 9267dd7cddfSDavid du Colombier seprint(g->msg, e, "%s", ctime(starttime-dt/1000)+11); 9277dd7cddfSDavid du Colombier g->msg[8] = 0; 9287dd7cddfSDavid du Colombier n = 8; 9297dd7cddfSDavid du Colombier 9307dd7cddfSDavid du Colombier switch(index2which(i)){ 9317dd7cddfSDavid du Colombier case Mrtt: 9327dd7cddfSDavid du Colombier f = rttunscale(g->data[dx]); 9337dd7cddfSDavid du Colombier seprint(g->msg+n, e, " %3.3g", f/1000000); 9347dd7cddfSDavid du Colombier break; 9357dd7cddfSDavid du Colombier case Mlost: 936c93608ccSDavid du Colombier seprint(g->msg+n, e, " %ld%%", g->data[dx]); 9377dd7cddfSDavid du Colombier break; 9387dd7cddfSDavid du Colombier } 9397dd7cddfSDavid du Colombier 9407dd7cddfSDavid du Colombier drawmsg(g, g->msg); 9417dd7cddfSDavid du Colombier drawcursor(g, m->xy.x); 9427dd7cddfSDavid du Colombier } 9437dd7cddfSDavid du Colombier 9447dd7cddfSDavid du Colombier void 9457dd7cddfSDavid du Colombier mouseproc(void*) 9467dd7cddfSDavid du Colombier { 9477dd7cddfSDavid du Colombier Mouse mouse; 9487dd7cddfSDavid du Colombier 9497dd7cddfSDavid du Colombier for(;;){ 9507dd7cddfSDavid du Colombier mouse = emouse(); 9517dd7cddfSDavid du Colombier if(mouse.buttons == 4){ 9527dd7cddfSDavid du Colombier lockdisplay(display); 9537dd7cddfSDavid du Colombier dobutton2(&mouse); 9547dd7cddfSDavid du Colombier unlockdisplay(display); 9557dd7cddfSDavid du Colombier } else if(mouse.buttons == 1){ 9567dd7cddfSDavid du Colombier lockdisplay(display); 9577dd7cddfSDavid du Colombier dobutton1(&mouse); 9587dd7cddfSDavid du Colombier unlockdisplay(display); 9597dd7cddfSDavid du Colombier } 9607dd7cddfSDavid du Colombier } 9617dd7cddfSDavid du Colombier } 9627dd7cddfSDavid du Colombier 9637dd7cddfSDavid du Colombier void 9647dd7cddfSDavid du Colombier startproc(void (*f)(void*), void *arg) 9657dd7cddfSDavid du Colombier { 9667dd7cddfSDavid du Colombier int pid; 9677dd7cddfSDavid du Colombier 9687dd7cddfSDavid du Colombier switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ 9697dd7cddfSDavid du Colombier case -1: 9707dd7cddfSDavid du Colombier fprint(2, "%s: fork failed: %r\n", argv0); 9717dd7cddfSDavid du Colombier killall("fork failed"); 9727dd7cddfSDavid du Colombier case 0: 9737dd7cddfSDavid du Colombier f(arg); 9747dd7cddfSDavid du Colombier killall("process died"); 9757dd7cddfSDavid du Colombier exits(nil); 9767dd7cddfSDavid du Colombier } 9777dd7cddfSDavid du Colombier pids[npid++] = pid; 9787dd7cddfSDavid du Colombier } 9797dd7cddfSDavid du Colombier 9807dd7cddfSDavid du Colombier void 9817dd7cddfSDavid du Colombier main(int argc, char *argv[]) 9827dd7cddfSDavid du Colombier { 9837dd7cddfSDavid du Colombier int i, j; 9847dd7cddfSDavid du Colombier long v, vmax, mark; 9857dd7cddfSDavid du Colombier char flags[10], *f, *p; 9867dd7cddfSDavid du Colombier 9879a747e4fSDavid du Colombier fmtinstall('V', eipfmt); 9887dd7cddfSDavid du Colombier 9897dd7cddfSDavid du Colombier f = flags; 990*5a354e27SDavid du Colombier pinginterval = 5000; /* 5 seconds */ 9917dd7cddfSDavid du Colombier ARGBEGIN{ 9927dd7cddfSDavid du Colombier case 'i': 9937dd7cddfSDavid du Colombier p = ARGF(); 9947dd7cddfSDavid du Colombier if(p == nil) 9957dd7cddfSDavid du Colombier usage(); 9967dd7cddfSDavid du Colombier pinginterval = atoi(p); 9977dd7cddfSDavid du Colombier break; 9987dd7cddfSDavid du Colombier default: 9997dd7cddfSDavid du Colombier if(f - flags >= sizeof(flags)-1) 10007dd7cddfSDavid du Colombier usage(); 10017dd7cddfSDavid du Colombier *f++ = ARGC(); 10027dd7cddfSDavid du Colombier break; 10037dd7cddfSDavid du Colombier }ARGEND 10047dd7cddfSDavid du Colombier *f = 0; 10057dd7cddfSDavid du Colombier 10067dd7cddfSDavid du Colombier for(i=0; i<argc; i++) 10077dd7cddfSDavid du Colombier addmachine(argv[i]); 10087dd7cddfSDavid du Colombier 10097dd7cddfSDavid du Colombier for(f = flags; *f; f++) 10107dd7cddfSDavid du Colombier switch(*f){ 10117dd7cddfSDavid du Colombier case 'l': 10127dd7cddfSDavid du Colombier addgraph(Mlost); 10137dd7cddfSDavid du Colombier break; 10147dd7cddfSDavid du Colombier case 'r': 10157dd7cddfSDavid du Colombier addgraph(Mrtt); 10167dd7cddfSDavid du Colombier break; 10177dd7cddfSDavid du Colombier } 10187dd7cddfSDavid du Colombier 10197dd7cddfSDavid du Colombier if(nmach == 0) 10207dd7cddfSDavid du Colombier usage(); 10217dd7cddfSDavid du Colombier 10227dd7cddfSDavid du Colombier if(ngraph == 0) 10237dd7cddfSDavid du Colombier addgraph(Mrtt); 10247dd7cddfSDavid du Colombier 10257dd7cddfSDavid du Colombier for(i=0; i<nmach; i++) 10267dd7cddfSDavid du Colombier for(j=0; j<ngraph; j++) 10277dd7cddfSDavid du Colombier graph[i*ngraph+j].mach = &mach[i]; 10287dd7cddfSDavid du Colombier 10297dd7cddfSDavid du Colombier if(initdraw(nil, nil, argv0) < 0){ 10307dd7cddfSDavid du Colombier fprint(2, "%s: initdraw failed: %r\n", argv0); 10317dd7cddfSDavid du Colombier exits("initdraw"); 10327dd7cddfSDavid du Colombier } 10337dd7cddfSDavid du Colombier colinit(); 10347dd7cddfSDavid du Colombier einit(Emouse); 10357dd7cddfSDavid du Colombier notify(nil); 10367dd7cddfSDavid du Colombier startproc(mouseproc, 0); 10377dd7cddfSDavid du Colombier display->locking = 1; /* tell library we're using the display lock */ 10387dd7cddfSDavid du Colombier 10397dd7cddfSDavid du Colombier resize(); 10407dd7cddfSDavid du Colombier 10417dd7cddfSDavid du Colombier starttime = time(0); 10427dd7cddfSDavid du Colombier 10437dd7cddfSDavid du Colombier unlockdisplay(display); /* display is still locked from initdraw() */ 10447dd7cddfSDavid du Colombier for(j = 0; ; j++){ 10457dd7cddfSDavid du Colombier lockdisplay(display); 10467dd7cddfSDavid du Colombier if(j == nmach){ 10477dd7cddfSDavid du Colombier parity = 1-parity; 10487dd7cddfSDavid du Colombier j = 0; 10497dd7cddfSDavid du Colombier for(i=0; i<nmach*ngraph; i++){ 10507dd7cddfSDavid du Colombier graph[i].newvalue(graph[i].mach, &v, &vmax, &mark); 10517dd7cddfSDavid du Colombier graph[i].update(&graph[i], v, vmax, mark); 10527dd7cddfSDavid du Colombier } 10537dd7cddfSDavid du Colombier starttime = time(0); 10547dd7cddfSDavid du Colombier } 10557dd7cddfSDavid du Colombier flushimage(display, 1); 10567dd7cddfSDavid du Colombier unlockdisplay(display); 10577dd7cddfSDavid du Colombier pingsend(&mach[j%nmach]); 10587dd7cddfSDavid du Colombier sleep(pinginterval/nmach); 10597dd7cddfSDavid du Colombier } 10607dd7cddfSDavid du Colombier } 1061