#include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_X #include #include #include #endif #include #include extern char *optarg; static void usage() { fputs( "Copyright (c) 2009 Teodor Sigaev . All rights reserved.\n" "blinker - blink by numlock/scroll leds accordingly with network activity\n" "./blinker\n", stdout ); exit(1); } static unsigned int getifnum(void) { u_int data = 0; size_t datalen = 0; static int name[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT }; datalen = sizeof(data); if (sysctl(name, 5, &data, &datalen, NULL, 0) != 0) tlog(TL_CRIT|TL_EXIT,"sysctl failed: %s", strerror(errno)); return data; } static int getifmibdata(int row, struct ifmibdata *data) { size_t datalen = 0; static int name[] = { CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, 0, IFDATA_GENERAL }; datalen = sizeof(*data); name[4] = row; if ((sysctl(name, 6, data, &datalen, NULL, 0) != 0) && (errno != ENOENT)) { tlog(TL_WARN,"sysctl failed: %s", strerror(errno)); return -1; } return 0; } #define LED_ON 0x01 #define LED_OFF 0x02 typedef struct Blinker { void (*exec)(struct Blinker *, int, int); int TxLed; int RxLed; int unused1:12, RxOn:2, TxOn:2, unused2:16; void *arg; } Blinker; static void execKbd(struct Blinker * blinker, int RxAction, int TxAction) { if ( !(blinker->RxOn == RxAction && blinker->TxOn == TxAction) ) { int flag = 0; if (ioctl(0, KDGETLED, &flag) == -1) tlog(TL_WARN,"unable to get led's statuses: %s", strerror(errno)); if (RxAction) flag |= blinker->RxLed; else flag &= ~blinker->RxLed; if (TxAction) flag |= blinker->TxLed; else flag &= ~blinker->TxLed; if (ioctl(0, KDSETLED, flag) == -1) tlog(TL_WARN,"unable to set NumLock led: %s", strerror(errno)); blinker->RxOn = RxAction; blinker->TxOn = TxAction; } } #ifdef USE_X static void execXKbd(struct Blinker * blinker, int RxAction, int TxAction) { static XKeyboardControl value; if ( blinker->RxOn != RxAction ) { value.led = blinker->RxLed; value.led_mode = (RxAction) ? LedModeOn : LedModeOff; XChangeKeyboardControl((Display*)blinker->arg, KBLed | KBLedMode, &value); } if ( blinker->TxOn != TxAction ) { value.led = blinker->TxLed; value.led_mode = (TxAction) ? LedModeOn : LedModeOff; XChangeKeyboardControl((Display*)blinker->arg, KBLed | KBLedMode, &value); } if ( !(blinker->RxOn == RxAction && blinker->TxOn == TxAction) ) { XFlush((Display*)blinker->arg); blinker->RxOn = RxAction; blinker->TxOn = TxAction; } } #endif typedef struct statData { u_int64_t ip; u_int64_t op; } statData; static int LetWork = 1; static void stopWork(int s) { LetWork = 0; } int main(int argc, char *argv[]) { keyboard_info_t info; int i; Blinker blinker; struct ifmibdata data; statData curData = {0,0}, oldData = {0,0}; while( (i=getopt(argc, argv, "d:h"))!=-1) { switch(i) { case 'h': default: usage(); } } opentlog(TL_OPEN_STDERR, TL_INFO, NULL); signal(SIGHUP, stopWork); signal(SIGSTOP, stopWork); signal(SIGINT, stopWork); memset(&blinker, 0, sizeof(blinker)); if (ioctl(0, KDGKBINFO, &info) == 0) { blinker.TxLed = LED_CAP; blinker.RxLed = LED_NUM; blinker.exec = execKbd; } else { tlog(TL_WARN,"unable to obtain keyboard information: %s%s", strerror(errno), #ifdef USE_X (errno == ENOTTY) ? "; Try X-windows interface." : #endif "" ); /* ENOTTY */ #ifdef USE_X { Display *dpy; XkbDescPtr xkb; dpy = XOpenDisplay(NULL); if (dpy == NULL) tlog(TL_CRIT|TL_EXIT, "Could not open default display"); if ( (xkb= XkbGetMap(dpy,0,XkbUseCoreKbd)) == NULL || XkbGetIndicatorMap(dpy,XkbAllIndicatorsMask,xkb)!=Success || XkbGetNames(dpy,XkbAllNamesMask,xkb)!=Success) tlog(TL_CRIT|TL_EXIT, "Fail to get indicator's descriptions"); for (i=0;iindicators->phys_indicators & (1<names->indicators[i]); XkbIndicatorMapPtr map= &xkb->indicators->maps[i]; if (name == NULL || *name == '\0') continue; if (strcmp(name, "Caps Lock") == 0) blinker.TxLed = i + 1; else if (strcmp(name, "Num Lock") == 0) blinker.RxLed = i + 1; else continue; if (map->flags & XkbIM_NoExplicit) { /* allow control */ XkbIndicatorMapPtr newmap = (XkbIndicatorMapPtr)tmalloc(sizeof(XkbIndicatorMapRec)); *newmap = *map; newmap->flags &= ~XkbIM_NoExplicit; if (XkbSetNamedIndicator(dpy, xkb->names->indicators[i], False, False, True, newmap) == False) tlog(TL_WARN,"XkbSetNamedIndicator fails"); } } } if (blinker.RxLed == 0 || blinker.TxLed == 0) tlog(TL_CRIT|TL_EXIT, "Fail to identify leds"); blinker.arg = dpy; blinker.exec = execXKbd; } #endif } /* * switch off leds - initial state */ blinker.TxOn = blinker.RxOn = 1; blinker.exec(&blinker, 0, 0); while(LetWork) { oldData = curData; memset(&curData, 0, sizeof(curData)); for(i=1;i<=getifnum();i++) { if (getifmibdata(i, &data) != 0) continue; if (data.ifmd_name[0] == 'l' && data.ifmd_name[1] == 'o' ) continue; curData.ip += data.ifmd_data.ifi_ipackets; curData.op += data.ifmd_data.ifi_opackets; } blinker.exec( &blinker, (curData.ip == oldData.ip) ? 0 : 1, /* Tx */ (curData.op == oldData.op) ? 0 : 1 /* Rx */ ); usleep(10000); } blinker.exec(&blinker, 0, 0); #ifdef USE_X if (blinker.arg) XCloseDisplay((Display*)blinker.arg); #endif return 0; }