Initial revision
authorteodor <teodor>
Tue, 1 Dec 2009 17:12:21 +0000 (17:12 +0000)
committerteodor <teodor>
Tue, 1 Dec 2009 17:12:21 +0000 (17:12 +0000)
Makefile [new file with mode: 0644]
blinker.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..57ec13d
--- /dev/null
+++ b/blinker.c
@@ -0,0 +1,284 @@
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/kbio.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_mib.h>
+
+#ifdef USE_X
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+#endif
+
+#include <tlog.h>
+#include <tmalloc.h>
+
+extern char *optarg;
+
+static void
+usage()
+{
+       fputs(
+               "Copyright (c) 2009 Teodor Sigaev <teodor@sigaev.ru>. 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;i<XkbNumIndicators;i++) {
+                       if (xkb->indicators->phys_indicators & (1<<i)) {
+                               char *name = XGetAtomName(dpy, xkb->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;
+}