2 * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/types.h>
37 #include <sys/sysctl.h>
38 #include <sys/sysctl.h>
39 #include <sys/socket.h>
41 #include <net/if_mib.h>
46 #include <X11/XKBlib.h>
58 "Copyright (c) 2009 Teodor Sigaev <teodor@sigaev.ru>. All rights reserved.\n"
59 "blinker - blink by numlock/scroll leds accordingly with network activity\n"
80 datalen = sizeof(data);
81 if (sysctl(name, 5, &data, &datalen, NULL, 0) != 0)
82 tlog(TL_CRIT|TL_EXIT,"sysctl failed: %s", strerror(errno));
88 getifmibdata(int row, struct ifmibdata *data)
99 datalen = sizeof(*data);
102 if ((sysctl(name, 6, data, &datalen, NULL, 0) != 0) && (errno != ENOENT)) {
103 tlog(TL_WARN,"sysctl failed: %s", strerror(errno));
113 typedef struct Blinker {
114 void (*exec)(struct Blinker *, int, int);
126 execKbd(struct Blinker * blinker, int RxAction, int TxAction) {
127 if ( !(blinker->RxOn == RxAction && blinker->TxOn == TxAction) ) {
130 if (ioctl(0, KDGETLED, &flag) == -1)
131 tlog(TL_WARN,"unable to get led's statuses: %s",
135 flag |= blinker->RxLed;
137 flag &= ~blinker->RxLed;
139 flag |= blinker->TxLed;
141 flag &= ~blinker->TxLed;
143 if (ioctl(0, KDSETLED, flag) == -1)
144 tlog(TL_WARN,"unable to set NumLock led: %s",
147 blinker->RxOn = RxAction;
148 blinker->TxOn = TxAction;
154 execXKbd(struct Blinker * blinker, int RxAction, int TxAction) {
155 static XKeyboardControl value;
157 if ( blinker->RxOn != RxAction ) {
158 value.led = blinker->RxLed;
159 value.led_mode = (RxAction) ? LedModeOn : LedModeOff;
160 XChangeKeyboardControl((Display*)blinker->arg, KBLed | KBLedMode, &value);
163 if ( blinker->TxOn != TxAction ) {
164 value.led = blinker->TxLed;
165 value.led_mode = (TxAction) ? LedModeOn : LedModeOff;
166 XChangeKeyboardControl((Display*)blinker->arg, KBLed | KBLedMode, &value);
169 if ( !(blinker->RxOn == RxAction && blinker->TxOn == TxAction) )
171 XFlush((Display*)blinker->arg);
172 blinker->RxOn = RxAction;
173 blinker->TxOn = TxAction;
178 typedef struct statData {
183 static int LetWork = 1;
191 main(int argc, char *argv[]) {
192 keyboard_info_t info;
195 struct ifmibdata data;
196 statData curData = {0,0},
199 while( (i=getopt(argc, argv, "d:h"))!=-1) {
207 opentlog(TL_OPEN_STDERR, TL_INFO, NULL);
208 signal(SIGHUP, stopWork);
209 signal(SIGSTOP, stopWork);
210 signal(SIGINT, stopWork);
212 memset(&blinker, 0, sizeof(blinker));
214 if (ioctl(0, KDGKBINFO, &info) == 0) {
215 blinker.TxLed = LED_CAP;
216 blinker.RxLed = LED_NUM;
217 blinker.exec = execKbd;
220 tlog(TL_WARN,"unable to obtain keyboard information: %s%s",
223 (errno == ENOTTY) ? "; Try X-windows interface." :
231 dpy = XOpenDisplay(NULL);
233 tlog(TL_CRIT|TL_EXIT, "Could not open default display");
235 if ( (xkb= XkbGetMap(dpy,0,XkbUseCoreKbd)) == NULL ||
236 XkbGetIndicatorMap(dpy,XkbAllIndicatorsMask,xkb)!=Success ||
237 XkbGetNames(dpy,XkbAllNamesMask,xkb)!=Success)
238 tlog(TL_CRIT|TL_EXIT, "Fail to get indicator's descriptions");
240 for (i=0;i<XkbNumIndicators;i++) {
241 if (xkb->indicators->phys_indicators & (1<<i)) {
242 char *name = XGetAtomName(dpy, xkb->names->indicators[i]);
243 XkbIndicatorMapPtr map= &xkb->indicators->maps[i];
245 if (name == NULL || *name == '\0')
248 if (strcmp(name, "Caps Lock") == 0)
249 blinker.TxLed = i + 1;
250 else if (strcmp(name, "Num Lock") == 0)
251 blinker.RxLed = i + 1;
255 if (map->flags & XkbIM_NoExplicit) {
257 XkbIndicatorMapPtr newmap = (XkbIndicatorMapPtr)tmalloc(sizeof(XkbIndicatorMapRec));
260 newmap->flags &= ~XkbIM_NoExplicit;
262 if (XkbSetNamedIndicator(dpy, xkb->names->indicators[i], False, False, True, newmap) == False)
263 tlog(TL_WARN,"XkbSetNamedIndicator fails");
268 if (blinker.RxLed == 0 || blinker.TxLed == 0)
269 tlog(TL_CRIT|TL_EXIT, "Fail to identify leds");
272 blinker.exec = execXKbd;
278 * switch off leds - initial state
280 blinker.TxOn = blinker.RxOn = 1;
281 blinker.exec(&blinker, 0, 0);
286 memset(&curData, 0, sizeof(curData));
287 for(i=1;i<=getifnum();i++) {
288 if (getifmibdata(i, &data) != 0)
290 if (data.ifmd_name[0] == 'l' && data.ifmd_name[1] == 'o' )
293 curData.ip += data.ifmd_data.ifi_ipackets;
294 curData.op += data.ifmd_data.ifi_opackets;
299 (curData.ip == oldData.ip) ? 0 : 1, /* Tx */
300 (curData.op == oldData.op) ? 0 : 1 /* Rx */
306 blinker.exec(&blinker, 0, 0);
309 XCloseDisplay((Display*)blinker.arg);