8 #include <sys/sysctl.h>
9 #include <sys/sysctl.h>
10 #include <sys/socket.h>
12 #include <net/if_mib.h>
17 #include <X11/XKBlib.h>
29 "Copyright (c) 2009 Teodor Sigaev <teodor@sigaev.ru>. All rights reserved.\n"
30 "blinker - blink by numlock/scroll leds accordingly with network activity\n"
51 datalen = sizeof(data);
52 if (sysctl(name, 5, &data, &datalen, NULL, 0) != 0)
53 tlog(TL_CRIT|TL_EXIT,"sysctl failed: %s", strerror(errno));
59 getifmibdata(int row, struct ifmibdata *data)
70 datalen = sizeof(*data);
73 if ((sysctl(name, 6, data, &datalen, NULL, 0) != 0) && (errno != ENOENT)) {
74 tlog(TL_WARN,"sysctl failed: %s", strerror(errno));
84 typedef struct Blinker {
85 void (*exec)(struct Blinker *, int, int);
97 execKbd(struct Blinker * blinker, int RxAction, int TxAction) {
98 if ( !(blinker->RxOn == RxAction && blinker->TxOn == TxAction) ) {
101 if (ioctl(0, KDGETLED, &flag) == -1)
102 tlog(TL_WARN,"unable to get led's statuses: %s",
106 flag |= blinker->RxLed;
108 flag &= ~blinker->RxLed;
110 flag |= blinker->TxLed;
112 flag &= ~blinker->TxLed;
114 if (ioctl(0, KDSETLED, flag) == -1)
115 tlog(TL_WARN,"unable to set NumLock led: %s",
118 blinker->RxOn = RxAction;
119 blinker->TxOn = TxAction;
125 execXKbd(struct Blinker * blinker, int RxAction, int TxAction) {
126 static XKeyboardControl value;
128 if ( blinker->RxOn != RxAction ) {
129 value.led = blinker->RxLed;
130 value.led_mode = (RxAction) ? LedModeOn : LedModeOff;
131 XChangeKeyboardControl((Display*)blinker->arg, KBLed | KBLedMode, &value);
134 if ( blinker->TxOn != TxAction ) {
135 value.led = blinker->TxLed;
136 value.led_mode = (TxAction) ? LedModeOn : LedModeOff;
137 XChangeKeyboardControl((Display*)blinker->arg, KBLed | KBLedMode, &value);
140 if ( !(blinker->RxOn == RxAction && blinker->TxOn == TxAction) )
142 XFlush((Display*)blinker->arg);
143 blinker->RxOn = RxAction;
144 blinker->TxOn = TxAction;
149 typedef struct statData {
154 static int LetWork = 1;
162 main(int argc, char *argv[]) {
163 keyboard_info_t info;
166 struct ifmibdata data;
167 statData curData = {0,0},
170 while( (i=getopt(argc, argv, "d:h"))!=-1) {
178 opentlog(TL_OPEN_STDERR, TL_INFO, NULL);
179 signal(SIGHUP, stopWork);
180 signal(SIGSTOP, stopWork);
181 signal(SIGINT, stopWork);
183 memset(&blinker, 0, sizeof(blinker));
185 if (ioctl(0, KDGKBINFO, &info) == 0) {
186 blinker.TxLed = LED_CAP;
187 blinker.RxLed = LED_NUM;
188 blinker.exec = execKbd;
191 tlog(TL_WARN,"unable to obtain keyboard information: %s%s",
194 (errno == ENOTTY) ? "; Try X-windows interface." :
202 dpy = XOpenDisplay(NULL);
204 tlog(TL_CRIT|TL_EXIT, "Could not open default display");
206 if ( (xkb= XkbGetMap(dpy,0,XkbUseCoreKbd)) == NULL ||
207 XkbGetIndicatorMap(dpy,XkbAllIndicatorsMask,xkb)!=Success ||
208 XkbGetNames(dpy,XkbAllNamesMask,xkb)!=Success)
209 tlog(TL_CRIT|TL_EXIT, "Fail to get indicator's descriptions");
211 for (i=0;i<XkbNumIndicators;i++) {
212 if (xkb->indicators->phys_indicators & (1<<i)) {
213 char *name = XGetAtomName(dpy, xkb->names->indicators[i]);
214 XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
216 if (name == NULL || *name == '\0')
219 if (strcmp(name, "Caps Lock") == 0)
220 blinker.TxLed = i + 1;
221 else if (strcmp(name, "Num Lock") == 0)
222 blinker.RxLed = i + 1;
226 if (map->flags & XkbIM_NoExplicit) {
228 XkbIndicatorMapPtr newmap = (XkbIndicatorMapPtr)tmalloc(sizeof(XkbIndicatorMapRec));
231 newmap->flags &= ~XkbIM_NoExplicit;
233 if (XkbSetNamedIndicator(dpy, xkb->names->indicators[i], False, False, True, newmap) == False)
234 tlog(TL_WARN,"XkbSetNamedIndicator fails");
239 if (blinker.RxLed == 0 || blinker.TxLed == 0)
240 tlog(TL_CRIT|TL_EXIT, "Fail to identify leds");
243 blinker.exec = execXKbd;
249 * switch off leds - initial state
251 blinker.TxOn = blinker.RxOn = 1;
252 blinker.exec(&blinker, 0, 0);
257 memset(&curData, 0, sizeof(curData));
258 for(i=1;i<=getifnum();i++) {
259 if (getifmibdata(i, &data) != 0)
261 if (data.ifmd_name[0] == 'l' && data.ifmd_name[1] == 'o' )
264 curData.ip += data.ifmd_data.ifi_ipackets;
265 curData.op += data.ifmd_data.ifi_opackets;
270 (curData.ip == oldData.ip) ? 0 : 1, /* Tx */
271 (curData.op == oldData.op) ? 0 : 1 /* Rx */
277 blinker.exec(&blinker, 0, 0);
280 XCloseDisplay((Display*)blinker.arg);