Initial dockapps git repo
[dockapps.git] / wmifinfo-0.06 / wmifinfo.c
blob9c6b8a7f4ef8d61ae074328cd8841660ed556d24
2 #include <stdio.h>
3 #include <unistd.h>
4 #ifdef linux
5 #include <getopt.h>
6 #endif
7 #include <stdlib.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <time.h>
11 #include <X11/X.h>
12 #include <X11/xpm.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
17 #include <net/if.h>
18 #if defined(__OpenBSD__)
19 #include <net/if_dl.h>
20 #include <net/if_types.h>
21 #include <net/route.h>
22 #include <sys/param.h>
23 #include <sys/sysctl.h>
24 #include <netinet/if_ether.h>
25 #include <net/if_ieee80211.h>
26 #include <dev/ic/if_wi_ieee.h>
27 #include <dev/ic/if_wireg.h>
28 #include <dev/ic/if_wi_hostap.h>
29 #define ROUNDUP(a) \
30 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
31 #endif
32 #include <signal.h>
33 #include <sys/wait.h>
34 #include <sys/types.h>
35 #include <errno.h>
36 #ifdef ENABLE_NWN_SUPPORT
37 #include "nwn.h"
38 #endif
40 #include "xutils.h"
41 #include "bitmaps/wmifinfo_led.xbm"
42 #include "bitmaps/wmifinfo_led.xpm"
43 #include "bitmaps/wmifinfo_lcd.xbm"
44 #include "bitmaps/wmifinfo_lcd.xpm"
46 #define MAXIFS 10
47 #ifdef linux
48 #define DELAY 1000000L
49 #else
50 #define DELAY 100000L
51 #endif
52 #define MODE_LED 1
53 #define MODE_LCD 2
55 struct ifinfo_t {
56 char id[16];
57 int state;
58 char hw[6];
59 uint32_t ip;
60 uint32_t nm;
61 uint32_t gw;
62 int sl;
63 int bytes;
66 struct font_t {
67 char *chars;
68 int sx;
69 int sy;
70 int dx;
71 int dy;
72 int charspline;
76 char LabelColor[30] = "#79bdbf";
77 char WindGustColor[30] = "#ff0000";
78 char DataColor[30] = "#ffbf50";
79 char BackColor[30] = "#181818";
80 char StationTimeColor[30] = "#c5a6ff";
82 struct font_t font1 = { " 0123456789ABCDEF", 64, 74, 4, 5, 17};
83 struct font_t font2 = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789: ", 1, 65, 5, 7, 26};
85 char *exec_dflt = "echo Use the -u and -d options for setting ifup/ifdown commands.";
86 char *exec_up;
87 char *exec_down;
89 int mode = MODE_LED;
90 char startif[16] = "";
91 char ifname[MAXIFS][16];
92 int ifaces;
93 int ifno = 0;
94 struct ifinfo_t ifinfo;
95 int fd = 0;
96 struct ifconf ifc;
97 volatile int exec_busy=0;
100 void parse_cmdline(int argc, char *argv[]);
101 void ButtonPressEvent(XButtonEvent *);
102 char *strupper(char *str);
103 void getifnames(void);
104 int getifinfo(char *ifname, struct ifinfo_t *info);
109 void drawtext(char *str, struct font_t *font, int x, int y)
111 int i = 0;
112 int ix, iy;
113 char *p;
115 while(str[i]) {
116 p = strchr(font->chars, str[i]);
117 ix = (p) ? (p - font->chars) : 0;
119 iy = (ix / font->charspline);
120 ix = (ix % font->charspline);
122 copyXPMArea( font->sx + ix * font->dx,
123 font->sy + iy * font->dy,
124 font->dx,
125 font->dy,
126 x + font->dx * i,
129 i++;
134 void drawipaddr(uint32_t a, int linenum)
136 char buf[4];
137 int i;
138 uint32_t addr = ntohl(a);
140 for(i=0; i<4; i++) {
141 snprintf(buf, 4, "%3d", (addr >> ((3-i)*8)) & 255);
142 drawtext(buf, &font1, 5 + i*14, 19 + linenum*9);
146 void drawhwaddr(unsigned char *addr)
148 char buf[4];
149 int i;
151 for(i=0; i<6; i++) {
152 snprintf(buf, 4, "%02X", addr[i]);
153 drawtext(buf, &font1, 6 + i*9, 46);
157 int main(int argc, char *argv[])
160 XEvent event;
161 char buf[16];
162 int d=0;
163 int pifno=-1;
164 int lastbytes=0;
165 struct timeval tv;
166 fd_set fds;
167 int x;
168 int prev_exec_busy=0;
170 exec_up = exec_dflt;
171 exec_down = exec_dflt;
173 parse_cmdline(argc, argv);
175 initXwindow(argc, argv);
177 if(mode == MODE_LED) {
178 openXwindow(argc, argv, wmifinfo_led_xpm, wmifinfo_led_bits,
179 wmifinfo_led_width, wmifinfo_led_height, BackColor,
180 LabelColor, WindGustColor, DataColor, StationTimeColor);
181 } else {
182 openXwindow(argc, argv, wmifinfo_lcd_xpm, wmifinfo_lcd_bits,
183 wmifinfo_lcd_width, wmifinfo_lcd_height, BackColor,
184 LabelColor, WindGustColor, DataColor, StationTimeColor);
187 // Initialize global variables
189 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
190 ifc.ifc_len = sizeof(struct ifreq) * 10;
191 ifc.ifc_buf = malloc(ifc.ifc_len);
193 while(1) {
195 while (XPending(display)) {
196 XNextEvent(display, &event);
198 switch (event.type) {
199 case Expose:
200 RedrawWindow();
201 break;
202 case ButtonPress:
203 ButtonPressEvent(&event.xbutton);
204 break;
205 case ButtonRelease:
206 break;
211 if ((d++ == 3) || (ifno != pifno) || (exec_busy != prev_exec_busy)) {
213 d=0;
215 copyXPMArea(64, 0, 64, 64, 0, 0);
216 getifnames();
218 if(ifaces>0) {
219 ifno = ifno % ifaces;
221 getifinfo(ifname[ifno], &ifinfo);
223 if(ifno != pifno) lastbytes = ifinfo.bytes;
225 sprintf(buf, "%-7s", ifinfo.id);
226 strupper(buf);
227 drawtext(buf, &font2, 6, 4);
229 if(memcmp(ifinfo.hw, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
230 drawhwaddr(ifinfo.hw);
233 if(ifinfo.ip) drawipaddr(ifinfo.ip, 0);
234 if(ifinfo.nm) drawipaddr(ifinfo.nm, 1);
235 if(ifinfo.gw) drawipaddr(ifinfo.gw, 2);
237 // WLAN signal level
239 #ifdef linux
240 x = ifinfo.sl/4;
241 #elif defined(__OpenBSD__)
242 x = ifinfo.sl/7;
243 #endif
244 if(x>13) x=13;
245 copyXPMArea(4, 82, x*4, 4, 6, 53);
247 // LED
249 x=0;
250 if(exec_busy) {
251 x=0;
252 } else {
253 if(ifinfo.state) x += 8;
254 if(lastbytes == ifinfo.bytes) x+= 16;
256 copyXPMArea(64 + x, 81, 8, 8, 50, 4);
257 lastbytes = ifinfo.bytes;
261 RedrawWindow();
262 prev_exec_busy = exec_busy;
263 pifno = ifno;
266 #ifdef linux
267 tv.tv_sec = 0;
268 tv.tv_usec = DELAY;
270 FD_ZERO(&fds);
271 FD_SET(ConnectionNumber(display), &fds);
273 select(ConnectionNumber(display)+1, &fds, NULL, NULL, &tv);
274 #elif defined(__OpenBSD__)
275 usleep(DELAY);
276 #endif
282 void print_usage()
284 printf(
285 "usage: wmifinfo [-lh] [-i interface]\n"
286 " -d <cmd> Command to exec for iface-down\n"
287 " -i <interface> Start with given interface, if available\n"
288 " -l LCD display mode\n"
289 " -h Print this help\n"
290 " -u <cmd> Command to exec for iface-up\n"
291 " -v Show version info and exit\n"
296 void print_version()
298 printf("%s version %s, compile-time options: ", NAME, VERSION);
300 #ifdef ENABLE_NWN_SUPPORT
301 printf("ENABLE NWN SUPPORT ");
302 #endif
304 printf("\n");
307 void parse_cmdline(int argc, char *argv[])
309 int c;
311 while((c = getopt(argc, argv, "d:i:lhu:v")) != EOF) {
312 switch(c) {
313 case 'd' :
314 exec_down = strdup(optarg);
315 break;
316 case 'i' :
317 strncpy(startif, optarg, sizeof(startif));
318 break;
319 case 'l' :
320 mode = MODE_LCD;
321 break;
322 case 'h' :
323 print_usage();
324 exit(0);
325 case 'u' :
326 exec_up = strdup(optarg);
327 break;
328 case 'v' :
329 print_version();
330 exit(0);
336 void sigchldhandler(int a)
338 wait(NULL);
339 exec_busy = 0;
342 void exec_cmd(char *cmd)
344 int pid;
346 signal(SIGCHLD, sigchldhandler);
348 if(exec_busy) return;
349 exec_busy=1;
351 pid=fork();
352 if(pid == 0) {
353 system(cmd);
354 exit(0);
357 return;
360 void ButtonPressEvent(XButtonEvent * xev)
362 char buf[256];
364 if (xev->type != ButtonPress) return;
366 switch (xev->button) {
367 case Button1:
369 ifno++;
370 break;
372 case Button2:
373 case Button3:
375 if(ifinfo.state == 0) {
376 sprintf(buf, exec_up, ifinfo.id);
377 } else {
378 sprintf(buf, exec_down, ifinfo.id);
381 exec_cmd(buf);
383 break;
388 char *strupper(char *str)
391 int i;
393 for (i = 0; i < strlen(str); i++)
394 str[i] = toupper(str[i]);
396 return str;
401 int getifinfo(char *ifname, struct ifinfo_t *info)
403 struct ifreq ifr;
404 int r;
405 struct sockaddr_in *sa;
407 #ifdef linux
408 static FILE *froute = NULL;
409 static FILE *fwireless = NULL;
410 static FILE *fdev = NULL;
411 #elif defined(__OpenBSD__)
412 struct ifreq ibuf[32];
413 struct ifconf ifc;
414 struct ifreq *ifrp, *ifend;
415 #endif
417 char parent[16];
418 char buf[1024];
419 char *p;
420 char a[16];
421 int b,c,d;
423 #ifdef linux
424 if(froute == NULL) froute = fopen("/proc/net/route", "r");
425 if(fwireless == NULL) fwireless = fopen("/proc/net/wireless", "r");
426 if(fdev == NULL) fdev = fopen("/proc/net/dev", "r");
427 #endif
430 strcpy(parent, ifname);
431 p=strchr(parent, ':');
432 if(p) *p=0;
434 strcpy(info->id, ifname);
436 strcpy(ifr.ifr_name, ifname);
438 // Get status (UP/DOWN)
440 if(ioctl(fd, SIOCGIFFLAGS, &ifr) != -1) {
441 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
442 info->state = (ifr.ifr_flags & 1) ? 1 : 0;
443 } else {
444 info->state = 0;
447 // Get mac address
449 #ifdef linux
450 if(ioctl(fd, SIOCGIFHWADDR, &ifr) != -1) {
451 memcpy(info->hw, ifr.ifr_hwaddr.sa_data, 6);
452 } else {
453 memset(info->hw, 0, 6);
455 #elif defined(__OpenBSD__)
456 ifc.ifc_len = sizeof(ibuf);
457 ifc.ifc_buf = (caddr_t) ibuf;
458 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1 ||
459 ifc.ifc_len < sizeof(struct ifreq)) {
460 memset(info->hw, 0, 6);
461 } else {
462 /* Search interface configuration list for link layer address. */
463 ifrp = ibuf;
464 ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
465 while (ifrp < ifend) {
466 /* Look for interface */
467 if (strcmp(ifname, ifrp->ifr_name) == 0 &&
468 ifrp->ifr_addr.sa_family == AF_LINK &&
469 ((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
470 memcpy(info->hw, LLADDR((struct sockaddr_dl *) &ifrp->ifr_addr), 6);
471 break;
473 /* Bump interface config pointer */
474 r = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
475 if (r < sizeof(*ifrp))
476 r = sizeof(*ifrp);
477 ifrp = (struct ifreq *) ((char *) ifrp + r);
480 #endif
482 // Get IP address
484 if(ioctl(fd, SIOCGIFADDR, &ifr) != -1) {
485 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
486 info->ip = sa->sin_addr.s_addr;
487 } else {
488 info->ip = 0;
491 // Get netmask
493 if(ioctl(fd, SIOCGIFNETMASK, &ifr) != -1) {
494 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
495 info->nm = sa->sin_addr.s_addr;
496 } else {
497 info->nm = 0;
500 // Get default gateway if on this interface
502 info->gw = 0;
503 #ifdef linux
504 if(froute != NULL) {
505 fseek(froute, 0, 0);
507 while(fgets(buf, sizeof(buf), froute)) {
508 r = sscanf(buf, "%s %x %x", a, &b, &c);
510 if((strcmp(a, info->id) == 0) && (b == 0)) {
511 info->gw = c;
516 #elif defined(__OpenBSD__)
518 struct rt_msghdr *rtm = NULL;
519 char *buf = NULL, *next, *lim = NULL;
520 size_t needed;
521 int mib[6];
522 struct sockaddr *sa;
523 struct sockaddr_in *sin;
525 mib[0] = CTL_NET;
526 mib[1] = PF_ROUTE;
527 mib[2] = 0;
528 mib[3] = AF_INET;
529 mib[4] = NET_RT_DUMP;
530 mib[5] = 0;
531 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) {
532 perror("route-sysctl-estimate");
533 exit(1);
535 if (needed > 0) {
536 if ((buf = malloc(needed)) == 0) {
537 printf("out of space\n");
538 exit(1);
540 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) {
541 perror("sysctl of routing table");
542 exit(1);
544 lim = buf + needed;
547 if (buf) {
548 for (next = buf; next < lim; next += rtm->rtm_msglen) {
549 rtm = (struct rt_msghdr *)next;
550 sa = (struct sockaddr *)(rtm + 1);
551 sin = (struct sockaddr_in *)sa;
553 if (sin->sin_addr.s_addr == 0) {
554 sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
555 sin = (struct sockaddr_in *)sa;
556 info->gw = sin->sin_addr.s_addr;
557 break;
560 free(buf);
563 #endif
565 // Get wireless link status if wireless
567 info->sl = 0;
568 #ifdef linux
569 if(fwireless != NULL) {
570 fseek(fwireless, 0, 0);
572 while(fgets(buf, sizeof(buf), fwireless)) {
573 r = sscanf(buf, "%s %d %d ", a, &b, &c);
574 if(strchr(a, ':')) *(strchr(a, ':')) = 0;
575 if(strcmp(a, parent) == 0) {
576 info->sl = c;
581 #ifdef ENABLE_NWN_SUPPORT
582 info->sl = nwn_get_link(parent);
583 #endif
584 #elif defined(__OpenBSD__)
586 struct wi_req wreq;
587 struct ifreq ifr;
589 wreq.wi_len = WI_MAX_DATALEN;
590 wreq.wi_type = WI_RID_COMMS_QUALITY;
592 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
593 ifr.ifr_data = (caddr_t)&wreq;
595 if (ioctl(fd, SIOCGWAVELAN, &ifr) != -1)
596 info->sl = letoh16(wreq.wi_val[0]);
598 #endif
600 // Get Total tx/rx bytes
602 #ifdef linux
603 if(fdev != NULL) {
604 fseek(fdev, 0, 0);
606 while(fgets(buf, sizeof(buf), fdev)) {
607 r = sscanf(buf, "%s %d %d %d %d %d %d %d %d %d", a, &b, &d,&d,&d,&d,&d,&d,&d, &c);
608 if(strchr(a, ':')) *(strchr(a, ':')) = 0;
609 if(strcmp(a, parent) == 0) {
610 info->bytes = b + c;
614 #endif
616 return(0);
620 void addifname(char *name)
622 int i;
624 if(strcmp(name, "lo") == 0) return;
625 if(strncmp(name, "vlan", 4) == 0) return;
627 for(i=0; i<ifaces; i++) {
628 if(strcmp(ifname[i], name) == 0) return;
631 strcpy(ifname[ifaces], name);
633 if(strcasecmp(name, startif) == 0) {
634 ifno = ifaces;
635 startif[0] = 0;
638 ifaces++;
640 return;
645 * get list of interfaces. First read /proc/net/dev, then do a SIOCGIFCONF
648 void getifnames(void)
650 #ifdef linux
651 FILE *f;
652 char buf[128];
653 char *p1, *p2;
654 int ifcount;
655 int i;
657 ifaces = 0;
659 f = fopen("/proc/net/dev", "r");
661 if(f == NULL) {
662 fprintf(stderr, "Can't open /proc/net/dev\n");
663 exit(1);
666 fgets(buf, sizeof(buf),f);
667 while(fgets(buf, sizeof(buf), f)) {
668 p1=buf;
669 while(*p1 == ' ') p1++;
670 p2=p1;
671 while(*p2 && (*p2 != ':')) p2++;
672 if(*p2 == ':') {
673 *p2=0;
674 addifname(p1);
678 fclose(f);
680 ifc.ifc_len = sizeof(struct ifreq) * 10;
682 if(ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
683 fprintf(stderr, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno));
684 exit(1);
687 ifcount = ifc.ifc_len / sizeof(struct ifreq);
689 for(i=0; i<ifcount; i++) {
690 addifname(ifc.ifc_req[i].ifr_name);
692 #elif defined(__OpenBSD__)
693 struct ifreq ibuf[32];
694 struct ifconf ifc;
695 struct ifreq *ifrp, *ifend;
696 int r;
698 ifaces = 0;
700 ifc.ifc_len = sizeof(ibuf);
701 ifc.ifc_buf = (caddr_t) ibuf;
702 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1 ||
703 ifc.ifc_len < sizeof(struct ifreq)) {
704 fprintf(stderr, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno));
705 exit(1);
707 /* Search interface configuration list for link layer address. */
708 ifrp = ibuf;
709 ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
710 while (ifrp < ifend) {
711 if (ifrp->ifr_addr.sa_family == AF_LINK &&
712 ((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
713 addifname(ifrp->ifr_name);
715 /* Bump interface config pointer */
716 r = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
717 if (r < sizeof(*ifrp))
718 r = sizeof(*ifrp);
719 ifrp = (struct ifreq *) ((char *) ifrp + r);
721 #endif