/* * Russ Cox, 17 August 1997 * rsc@research.att.com * * this program lets you watch the front panel of the * modem racks remotely. just look, no touching. * * window '0 160 160 300' tcm bait-nmc1 * window '0 300 160 440' tcm bait-nmc2 * window '0 440 100 580' tcm -n 6 usrnmc-lh * * remember: * We don't understand the software, and sometimes we don't understand * the hardware, but we can *see* the blinking lights! */ #include #include #include #include "a1.h" extern void chat(char *, ...); enum { Nlights = 7, Ncards = 13, }; int nmodem = Ncards-1; int lights[Ncards][Nlights]; Rectangle rlight[Ncards][Nlights]; Bitmap *clr[3]; Bitmap *black, *white; int nfd; int chatty; int timeint = 15; char *usage = "%s host [-c n b a] [-t secs] [-n nmodem]\n"; char *host; void getlights(void); void drawlights(void); void main(int argc, char **argv) { int i, pid; Rectangle r; int c[3] = {204, 0x10, 0xfc}; /* fb/colors */ ARGBEGIN{ case 'n': nmodem = atoi(ARGF()); if(nmodem > Ncards-1) nmodem = Ncards-1; break; case 'c': for(i=0; i<3; i++) c[0] = atoi(ARGF()); break; case 't': timeint = atoi(ARGF()); break; default: fprint(2, usage, argv0); exits("usage"); }ARGEND; if(argc != 1) { fprint(2, usage, argv0); exits("usage"); } if((nfd = dial(netmkaddr(argv[0], "udp", "161"), 0, 0, 0)) < 0) { fprint(2, "cannot dial: %r\n"); exits("dial"); } host = argv[0]; getlights(); binit(0,0,0); einit(Emouse); r.min = (Point){0,0}; r.max = (Point){1,1}; for(i=0; i<3; i++) { clr[i] = balloc(r, 3); point(clr[i], r.min, c[i], S); } black = balloc(r, 3); white = balloc(r, 3); point(black, r.min, 0xff, S); point(white, r.min, 0, S); ereshaped(screen.r); pid = rfork(RFMEM|RFPROC); if(pid == 0) { for(;;) { sleep(timeint*1000); getlights(); drawlights(); } exits(0); } else if(pid < 0) { fprint(2, "cannot rfork: %r\n"); exits("rfork"); } else for(;;){ emouse(); } } void drawlights(void) { int i, j; for(i=0; i= 0 && lights[i][j] <= 3) { texture(&screen, rlight[i][j], clr[lights[i][j]], S); } } bflush(); } void ereshaped(Rectangle r) { int i, j, y, ht, wid; Point pw, textpt, p; Rectangle box; char msg[10]; /* clear screen */ screen.r = r; bitblt(&screen, screen.r.min, &screen, r, Zero); /* add host label in upper corner */ p = (Point){5,5}; p = add(p, screen.r.min); string(&screen, p, font, host, S); /* width of card slots */ wid = (Dx(r) - 10 - (nmodem))/(nmodem+1); pw = (Point){wid+1, 0}; /* height of card slots */ p = strsize(font, "0"); y = p.y; ht = (Dy(r) - 10 - 2*y)/(Nlights); /* box is the first card */ /* cards are wid pixels wide black + 1 pixel white */ box.min = add(screen.r.min, (Point){5, 5+2*y}); box.max = add(screen.r.min, (Point){5+wid, 5+2*y+ht*Nlights}); /* label first card */ strcpy(msg, "1"); textpt = add(box.min, (Point){(wid/2-p.x/2), -y}); string(&screen, textpt, font, msg, S); /* draw card */ texture(&screen, box, black, S); /* set up card 1, light 1 */ rlight[0][0].min = add((Point){wid/4, ht/8}, box.min); rlight[0][0].max = add((Point){wid/2, ht*3/4}, rlight[0][0].min); /* all the other lights on the card are just offsets */ for(i=1; ivers = 0; s->private = 0; s->type = Pget; s->estat = s->eindex = 0; s->npdu = 3; for(i=0, pdu=s->pdu; i<3; i++, pdu++) { /* you are not expected to understand this */ sprint(pdu->objid, "1.3.6.1.4.1.429.1.1.3.%d.0", i+5); pdu->type = Anull; } memset(lights, 0, sizeof lights); if(dosnmp(nfd, s, s) < 0) return; if(s->estat) { chat("error in snmp pkt"); return; } pdu = &s->pdu[1]; if(pdu->len < (Ncards)*6) { chat("pdu too short"); return; } for(i=0; is[nybble/2]; if((nybble%2)==0) bits >>= 4; else bits &= 0x0f; switch(bits){ case 1: /* busy */ lights[i][j] = 2; break; case 3: /* answering */ lights[i][j] = 1; break; case 0: /* nothing */ lights[i][j] = 0; break; default: lights[i][j] = 0; break; } chat("%c", lights[i][j]); } chat("..."); } }