From: teodor Date: Tue, 1 Dec 2009 17:12:21 +0000 (+0000) Subject: Initial revision X-Git-Tag: start~1 X-Git-Url: http://sigaev.ru/git/gitweb.cgi?a=commitdiff_plain;h=ea23cea9269ca3f72ee17a92b6d88bf60e33bbd2;p=blinker.git Initial revision --- ea23cea9269ca3f72ee17a92b6d88bf60e33bbd2 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b00c963 --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +CC=gcc +AR=ar rcv +RANLIB=ranlib +LD=ld -x -shared + +ifndef OS +OS=$(shell uname) +endif + + +INCLUDE=-I. -I../tedtools -I/usr/X11R6/include +CFLAGS=-Wall -g -O2 -pedantic -ansi -D$(OS) -DUSE_X +LIB=-L../tedtools -ltedtools -L/usr/local/lib -lX11 + +ifeq ($(OS), Linux) +CFLAGS+= -D_GNU_SOURCE -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 +endif + +PROGS=blinker + +.SUFFIXES: .o.c + +all: $(PROGS) + +blinker: blinker.o + $(CC) -o $@ $< $(LIB) + +.c.o: + $(CC) $(CFLAGS) $(INCLUDE) -c $< + + +clean: + rm -rf $(PROGS) *.o + rm -rf *core *gmon* nohup.out + diff --git a/blinker.c b/blinker.c new file mode 100644 index 0000000..57ec13d --- /dev/null +++ b/blinker.c @@ -0,0 +1,284 @@ +#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; +}