📄 gping.c
字号:
m->unreachable++; } m->seq++;}voidpingrcv(void *arg){ uchar buf[512]; Icmp *ip; ushort x; int i, n, fd; vlong now; Machine *m = arg; ip = (Icmp*)buf; fd = dup(m->pingfd, -1); for(;;){ n = read(fd, buf, sizeof(buf)); now = nsec(); if(n <= 0) continue; if(n < MSGLEN){ print("bad len %d/%d\n", n, MSGLEN); continue; } for(i = 32; i < MSGLEN; i++) if(buf[i] != (i&0xff)) continue; x = (ip->seq[1]<<8)|ip->seq[0]; if(ip->type != EchoReply || ip->code != 0) continue; lock(m); pingclean(m, x, now, ip->ttl); unlock(m); }}voidinitmach(Machine *m, char *name){ char *p; srand(time(0)); p = strchr(name, '!'); if(p){ p++; m->name = estrdup(p+1); }else p = name; m->name = estrdup(p); m->nproc = 1; m->pingfd = dial(netmkaddr(m->name, "icmp", "1"), 0, 0, 0); if(m->pingfd < 0) sysfatal("dialing %s: %r", m->name); startproc(pingrcv, m);}ulongrttscale(ulong x){ if(x == 0) return 0; x = 10.0*log10(x) - 20.0; if(x < 0) x = 0; return x;}ulongrttunscale(ulong x){ double dx; x += 20; dx = x; return pow(10.0, dx/10.0);}voidrttval(Machine *m, long *v, long *vmax, long *mark){ ulong x; if(m->rttmsgs == 0){ x = m->lastrtt; } else { x = m->rttsum/m->rttmsgs; m->rttsum = m->rttmsgs = 0; m->lastrtt = x; } *v = rttscale(x); *vmax = Rttmax; *mark = 0;}voidlostval(Machine *m, long *v, long *vmax, long *mark){ ulong x; if(m->rcvdmsgs+m->lostmsgs > 0) x = (m->lostavg>>1) + (((m->lostmsgs*100)/(m->lostmsgs + m->rcvdmsgs))>>1); else x = m->lostavg; m->lostavg = x; m->lostmsgs = m->rcvdmsgs = 0; if(m->unreachable){ m->unreachable = 0; *mark = 100; } else *mark = 0; *v = x; *vmax = 100;}jmp_buf catchalarm;voidalarmed(void *a, char *s){ if(strcmp(s, "alarm") == 0) notejmp(a, catchalarm, 1); noted(NDFLT);}voidusage(void){ fprint(2, "usage: %s machine [machine...]\n", argv0); exits("usage");}voidaddgraph(int n){ Graph *g, *ograph; int i, j; static int nadd; if(n > nelem(menu2str)) abort(); /* avoid two adjacent graphs of same color */ if(ngraph>0 && graph[ngraph-1].colindex==nadd%Ncolor) nadd++; ograph = graph; graph = emalloc(nmach*(ngraph+1)*sizeof(Graph)); for(i=0; i<nmach; i++) for(j=0; j<ngraph; j++) graph[i*(ngraph+1)+j] = ograph[i*ngraph+j]; free(ograph); ngraph++; for(i=0; i<nmach; i++){ g = &graph[i*ngraph+(ngraph-1)]; memset(g, 0, sizeof(Graph)); g->label = menu2str[n]+Opwid; g->newvalue = newvaluefn[n]; g->update = update1; /* no other update functions yet */ g->mach = &mach[i]; g->colindex = nadd%Ncolor; } present[n] = 1; nadd++;}intwhich2index(int which){ int i, n; n = -1; for(i=0; i<ngraph; i++){ if(strcmp(menu2str[which]+Opwid, graph[i].label) == 0){ n = i; break; } } if(n < 0){ fprint(2, "%s: internal error can't drop graph\n", argv0); killall("error"); } return n;}intindex2which(int index){ int i, n; n = -1; for(i=0; i<Nmenu2; i++){ if(strcmp(menu2str[i]+Opwid, graph[index].label) == 0){ n = i; break; } } if(n < 0){ fprint(2, "%s: internal error can't identify graph\n", argv0); killall("error"); } return n;}voiddropgraph(int which){ Graph *ograph; int i, j, n; if(which > nelem(menu2str)) abort(); /* convert n to index in graph table */ n = which2index(which); ograph = graph; graph = emalloc(nmach*(ngraph-1)*sizeof(Graph)); for(i=0; i<nmach; i++){ for(j=0; j<n; j++) graph[i*(ngraph-1)+j] = ograph[i*ngraph+j]; free(ograph[i*ngraph+j].data); freeimage(ograph[i*ngraph+j].overtmp); for(j++; j<ngraph; j++) graph[i*(ngraph-1)+j-1] = ograph[i*ngraph+j]; } free(ograph); ngraph--; present[which] = 0;}voidaddmachine(char *name){ if(ngraph > 0){ fprint(2, "%s: internal error: ngraph>0 in addmachine()\n", argv0); usage(); } if(nmach == NMACH) sysfatal("too many machines"); initmach(&mach[nmach++], name);}voidresize(void){ int i, j, n, startx, starty, x, y, dx, dy, hashdx, ondata; Graph *g; Rectangle machr, r; long v, vmax, mark; char buf[128]; draw(screen, screen->r, display->white, nil, ZP); /* label left edge */ x = screen->r.min.x; y = screen->r.min.y + Labspace+mediumfont->height+Labspace; dy = (screen->r.max.y - y)/ngraph; dx = Labspace+stringwidth(mediumfont, "0")+Labspace; startx = x+dx+1; starty = y; for(i=0; i<ngraph; i++,y+=dy){ draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP); draw(screen, Rect(x, y, x+dx, screen->r.max.y), cols[graph[i].colindex][0], nil, paritypt(x)); label(Pt(x, y), dy, graph[i].label); draw(screen, Rect(x+dx, y, x+dx+1, screen->r.max.y), cols[graph[i].colindex][2], nil, ZP); } /* label right edge */ dx = Labspace+stringwidth(mediumfont, "0.001")+Labspace; hashdx = dx; x = screen->r.max.x - dx; y = screen->r.min.y + Labspace+mediumfont->height+Labspace; for(i=0; i<ngraph; i++,y+=dy){ draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP); draw(screen, Rect(x, y, x+dx, screen->r.max.y), cols[graph[i].colindex][0], nil, paritypt(x)); hashmarks(Pt(x, y), dy, i); draw(screen, Rect(x+dx, y, x+dx+1, screen->r.max.y), cols[graph[i].colindex][2], nil, ZP); } /* label top edge */ dx = (screen->r.max.x - dx - startx)/nmach; for(x=startx, i=0; i<nmach; i++,x+=dx){ draw(screen, Rect(x-1, starty-1, x, screen->r.max.y), display->black, nil, ZP); j = dx/stringwidth(mediumfont, "0"); n = mach[i].nproc; if(n>1 && j>=1+3+(n>10)+(n>100)){ /* first char of name + (n) */ j -= 3+(n>10)+(n>100); if(j <= 0) j = 1; snprint(buf, sizeof buf, "%.*s(%d)", j, mach[i].name, n); }else snprint(buf, sizeof buf, "%.*s", j, mach[i].name); string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, mediumfont, buf); } /* draw last vertical line */ draw(screen, Rect(screen->r.max.x-hashdx-1, starty-1, screen->r.max.x-hashdx, screen->r.max.y), display->black, nil, ZP); /* create graphs */ for(i=0; i<nmach; i++){ machr = Rect(startx+i*dx, starty, screen->r.max.x, screen->r.max.y); if(i < nmach-1) machr.max.x = startx+(i+1)*dx - 1; else machr.max.x = screen->r.max.x - hashdx - 1; y = starty; for(j=0; j<ngraph; j++, y+=dy){ g = &graph[i*ngraph+j]; /* allocate data */ ondata = g->ndata; g->ndata = Dx(machr)+1; /* may be too many if label will be drawn here; so what? */ g->data = erealloc(g->data, g->ndata*sizeof(long)); if(g->ndata > ondata) memset(g->data+ondata, 0, (g->ndata-ondata)*sizeof(long)); /* set geometry */ g->r = machr; g->r.min.y = y; g->r.max.y = y+dy - 1; if(j == ngraph-1) g->r.max.y = screen->r.max.y; draw(screen, g->r, cols[g->colindex][0], nil, paritypt(g->r.min.x)); g->overflow = 0; *g->msg = 0; freeimage(g->overtmp); g->overtmp = nil; g->overtmplen = 0; r = g->r; r.max.y = r.min.y+mediumfont->height; n = (g->r.max.x - r.min.x)/stringwidth(mediumfont, "9"); if(n > 4){ if(n > Gmsglen) n = Gmsglen; r.max.x = r.min.x+stringwidth(mediumfont, "9")*n; g->overtmplen = n; g->overtmp = allocimage(display, r, screen->chan, 0, -1); } g->newvalue(g->mach, &v, &vmax, &mark); redraw(g, vmax); } } flushimage(display, 1);}voideresized(int new){ lockdisplay(display); if(new && getwindow(display, Refnone) < 0) { fprint(2, "%s: can't reattach to window\n", argv0); killall("reattach"); } resize(); unlockdisplay(display);}voiddobutton2(Mouse *m){ int i; for(i=0; i<Nmenu2; i++) if(present[i]) memmove(menu2str[i], "drop ", Opwid); else memmove(menu2str[i], "add ", Opwid); i = emenuhit(3, m, &menu2); if(i >= 0){ if(!present[i]) addgraph(i); else if(ngraph > 1) dropgraph(i); resize(); }}voiddobutton1(Mouse *m){ int i, n, dx, dt; Graph *g; char *e; double f; for(i = 0; i < ngraph*nmach; i++){ if(ptinrect(m->xy, graph[i].r)) break; } if(i == ngraph*nmach) return; g = &graph[i]; if(g->overtmp == nil) return; // clear any previous message and cursor if(g->overflow || *g->msg){ clearmsg(g); *g->msg = 0; clearcursor(g); } dx = g->r.max.x - m->xy.x; g->cursor = dx; dt = dx*pinginterval; e = &g->msg[sizeof(g->msg)]; seprint(g->msg, e, "%s", ctime(starttime-dt/1000)+11); g->msg[8] = 0; n = 8; switch(index2which(i)){ case Mrtt: f = rttunscale(g->data[dx]); seprint(g->msg+n, e, " %3.3g", f/1000000); break; case Mlost: seprint(g->msg+n, e, " %d%%", g->data[dx]); break; } drawmsg(g, g->msg); drawcursor(g, m->xy.x);}voidmouseproc(void*){ Mouse mouse; for(;;){ mouse = emouse(); if(mouse.buttons == 4){ lockdisplay(display); dobutton2(&mouse); unlockdisplay(display); } else if(mouse.buttons == 1){ lockdisplay(display); dobutton1(&mouse); unlockdisplay(display); } }}voidstartproc(void (*f)(void*), void *arg){ int pid; switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: fprint(2, "%s: fork failed: %r\n", argv0); killall("fork failed"); case 0: f(arg); killall("process died"); exits(nil); } pids[npid++] = pid;}voidmain(int argc, char *argv[]){ int i, j; long v, vmax, mark; char flags[10], *f, *p; fmtinstall('V', eipfmt); f = flags; pinginterval = 5000; // 5 seconds ARGBEGIN{ case 'i': p = ARGF(); if(p == nil) usage(); pinginterval = atoi(p); break; default: if(f - flags >= sizeof(flags)-1) usage(); *f++ = ARGC(); break; }ARGEND *f = 0; for(i=0; i<argc; i++) addmachine(argv[i]); for(f = flags; *f; f++) switch(*f){ case 'l': addgraph(Mlost); break; case 'r': addgraph(Mrtt); break; } if(nmach == 0) usage(); if(ngraph == 0) addgraph(Mrtt); for(i=0; i<nmach; i++) for(j=0; j<ngraph; j++) graph[i*ngraph+j].mach = &mach[i]; if(initdraw(nil, nil, argv0) < 0){ fprint(2, "%s: initdraw failed: %r\n", argv0); exits("initdraw"); } colinit(); einit(Emouse); notify(nil); startproc(mouseproc, 0); display->locking = 1; /* tell library we're using the display lock */ resize(); starttime = time(0); unlockdisplay(display); /* display is still locked from initdraw() */ for(j = 0; ; j++){ lockdisplay(display); if(j == nmach){ parity = 1-parity; j = 0; for(i=0; i<nmach*ngraph; i++){ graph[i].newvalue(graph[i].mach, &v, &vmax, &mark); graph[i].update(&graph[i], v, vmax, mark); } starttime = time(0); } flushimage(display, 1); unlockdisplay(display); pingsend(&mach[j%nmach]); sleep(pinginterval/nmach); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -