/* * LOADAV.C * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * LOADAV [frequency] Connect to remote UNIX system and display * load average. Default is every 5 minutes. * * frequency in seconds, default is every 60 seconds * */ #include "defs.h" #include int __stdargs CXBRK(void); short Deemu[] = { DMSTRT, 0, 0, DMNW , 0, 10, 2, 2, -80, 40, 0xFFFF, DMEND , 0, 0 }; #define DMNWOFF 4 #define NA 0 #define GWIDTH (sizeof(Graph)/sizeof(Graph[0])) #define GDEPTH (sizeof(GMap)/sizeof(GMap[0])) #define GMASK (GWIDTH-1) uword GMax[] = { 2*256, 50 }; uword GIncr[]= { 2*256, 20 }; uword GMap[2] = { 0, 1 }; uword Graph[1024][GDEPTH]; /* 5Min,#users. */ uword Gi; ubyte Scr[128]; ubyte Initial; ubyte Title[128]; extern void updatewindow(); NW Nw = { 0, 0, 320, 50, -1, -1, NEWSIZE|CLOSEWINDOW, WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|NOCAREREFRESH, NULL, NULL, Title, NULL, NULL, 32, 18, -1, -1, WBENCHSCREEN }; WIN *Win; RP *Rp; extern int Enable_Abort; struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; void clearwindow ARGS((void)); void updatewindow ARGS((char *)); void main ARGS((int, char **)); int brk() { return(0); } void main(ac,av) char *av[]; { void *chan = NULL; short numsecs = 60; long imask, tmask, dmask, mask; char notdone = 1; char *host = NULL; PORT *TimPort = CreatePort(NULL, 0); IOT Iot; onbreak(brk); sprintf(Title, "LoadAv V%s%s", VERSION, LOADAV_VERSION); { short i; for (i = 1; i < ac; ++i) { if (strncmp(av[i], "-N", 2) == 0) { host = av[i]+2; continue; } numsecs = atoi(av[i]); } } Iot.tr_node.io_Device = NULL; if (OpenDevice("timer.device", UNIT_VBLANK, (IOR *)&Iot, 0)) goto fail; Iot.tr_node.io_Command = TR_ADDREQUEST; Iot.tr_node.io_Message.mn_ReplyPort = TimPort; Iot.tr_time.tv_micro = 1; Iot.tr_time.tv_secs = 0; SendIO((IOR *)&Iot); #ifndef LATTICE Enable_Abort = 0; #endif IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0); GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0); chan = DOpen(host, PORT_LOADAV, 25, 25); if (chan == NULL) { puts("no connect"); goto fail; } InitDeemuNW(Deemu+DMNWOFF, &Nw); Win = OpenWindow(&Nw); if (Win == NULL) { puts("Unable to open window"); goto fail; } Rp = Win->RPort; imask = 1 << Win->UserPort->mp_SigBit; dmask = 1 << ((PORT *)chan)->mp_SigBit; tmask = 1 << TimPort->mp_SigBit; clearwindow(); while (notdone) { mask = Wait(imask|dmask|tmask|SIGBREAKF_CTRL_C); if (mask & SIGBREAKF_CTRL_C) notdone = 0; if (mask & imask) { IMESS *im; while (im = (IMESS *)GetMsg(Win->UserPort)) { switch(im->Class) { case NEWSIZE: clearwindow(); break; case CLOSEWINDOW: notdone = 0; break; } ReplyMsg((MSG *)im); } } if (mask & dmask) { char dummy; if ((dummy = DNRead(chan, &dummy, 1)) != 0) notdone = 0; } while (mask & tmask) { /* while just so we can break */ char len = 0; if (GetMsg(TimPort)) { Iot.tr_time.tv_micro = 0; Iot.tr_time.tv_secs = numsecs; SendIO((IOR *)&Iot); if (DWrite(chan, &len, 1) == 1 && DRead(chan, &len, 1) == 1) { if (len < sizeof(Title) && DRead(chan, Title, len) == len) { Title[len] = 0; updatewindow(Title); SetWindowTitles(Win, Title, (char *)-1); break; } } notdone = 0; } break; } } fail: if (Iot.tr_node.io_Device) { AbortIO((IOR *)&Iot); WaitIO((IOR *)&Iot); CloseDevice((IOR *)&Iot); } DeletePort(TimPort); if (Win) CloseWindow(Win); if (chan) DClose(chan); if (IntuitionBase) CloseLibrary((LIB *)IntuitionBase); if (GfxBase) CloseLibrary((LIB *)GfxBase); } /* * Graphics routines. ************************************************ */ short WOx, WOy, Ww, Wh; void clearwindow() { short i, j, d; WOx = Win->BorderLeft; WOy = Win->BorderTop; Ww = Win->Width - Win->BorderRight - Win->BorderLeft; Wh = Win->Height- Win->BorderTop - Win->BorderBottom; SetAPen(Rp, 0); RectFill(Rp, WOx, WOy, Ww + WOx, Wh + WOy); WOx += 2; WOy += 2; Ww -= 4; Wh -= 4; /* * Redraw the graph. Scale values relative to GMax[?] and Wh. * * ypos = (WOy + Wh) - (Wh * value / GMax[d]) * */ for (d = 0; d < GDEPTH; ++d) { char move = 1; SetAPen(Rp, (d & 1) ? 3 : 1); for (i = Ww - 1, j = Gi - 1; i >= 0; --i, --j) { uword value = Wh * Graph[j&GMASK][d] / GMax[GMap[d]]; (move) ? Move(Rp, WOx + i, WOy + Wh - value - 1) : Draw(Rp, WOx + i, WOy + Wh - value - 1) ; move = 0; } } } /* * 5:44pm up 2 days, 22:30, 37 users, load average: 5.98, 7.93, 7.97 * 7 mins, */ void updatewindow(str) char *str; { short d; char refresh = 0; uword ary[GDEPTH]; { long nusers, i1, f1, i5, f5; char *ptr = str; while (strncmp(ptr, "users", 5) && *ptr) ++ptr; while (*--ptr == ' ' && ptr != str) --ptr; while (*--ptr != ' ' && ptr != str) --ptr; nusers = atoi(ptr+1); while (strncmp(ptr, "load", 4) && *ptr) ++ptr; sscanf(ptr, "load average: %ld.%ld, %ld.%ld,", &i1, &f1, &i5, &f5 ); /* ary[0] = (i1 << 8) | ((f1 << 8) / 100); */ ary[0] = (i5 << 8) | ((f5 << 8) / 100); ary[1] = nusers; } for (d = 0; d < GDEPTH; ++d) { while (ary[d] > GMax[GMap[d]] && ary[d] < 65000) { GMax[GMap[d]] += GIncr[GMap[d]]; refresh = 1; } Graph[Gi][d] = ary[d]; } if (!Initial) { short i; Initial = 1; for (i = 0; i < GWIDTH; ++i) { for (d = 0; d < GDEPTH; ++d) Graph[i][d] = Graph[Gi][d]; } } Gi = (Gi + 1) & GMASK; if (refresh) { clearwindow(); return; } ScrollRaster(Rp, 1, 0, WOx, WOy, WOx + Ww - 1, WOy + Wh - 1); for (d = 0; d < GDEPTH; ++d) { uword value1 = Wh * Graph[(Gi-2)&GMASK][d] / GMax[GMap[d]]; uword value2 = Wh * Graph[(Gi-1)&GMASK][d] / GMax[GMap[d]]; SetAPen(Rp, (d & 1) ? 3 : 1); Move(Rp, Ww + WOx - 2, WOy + Wh - value1 - 1); Draw(Rp, Ww + WOx - 1, WOy + Wh - value2 - 1); } }