wmbattery: move labels to the beginning of the line.
[dockapps.git] / wmifinfo / wmifinfo.c
blob1f5c8b90eb7e7778d5e379bea3b44a0ebf33e42e
1 /*
2 * $Id: wmifinfo.c,v 1.4 2004/07/11 12:00:46 ico Exp $
3 */
5 #include <stdio.h>
6 #include <unistd.h>
7 #ifdef linux
8 #include <getopt.h>
9 #endif
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <time.h>
14 #include <X11/X.h>
15 #include <X11/xpm.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <sys/ioctl.h>
19 #include <sys/socket.h>
20 #include <net/if.h>
21 #if defined(__OpenBSD__)
22 #include <net/if_dl.h>
23 #include <net/if_types.h>
24 #include <net/route.h>
25 #include <sys/param.h>
26 #include <sys/sysctl.h>
27 #include <netinet/if_ether.h>
28 #include <net/if_ieee80211.h>
29 #include <dev/ic/if_wi_ieee.h>
30 #include <dev/ic/if_wireg.h>
31 #include <dev/ic/if_wi_hostap.h>
32 #define ROUNDUP(a) \
33 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
34 #endif
35 #include <signal.h>
36 #include <sys/wait.h>
37 #include <sys/types.h>
38 #include <errno.h>
39 #ifdef ENABLE_NWN_SUPPORT
40 #include "nwn.h"
41 #endif
43 #include "xutils.h"
44 #include "bitmaps/wmifinfo_led.xbm"
45 #include "bitmaps/wmifinfo_led.xpm"
46 #include "bitmaps/wmifinfo_lcd.xbm"
47 #include "bitmaps/wmifinfo_lcd.xpm"
49 #define MAXIFS 10
50 #ifdef linux
51 #define DELAY 1000000L
52 #define USEC_PER_SEC 1000000L
53 #else
54 #define DELAY 100000L
55 #endif
56 #define MODE_LED 1
57 #define MODE_LCD 2
59 struct ifinfo_t {
60 char id[16];
61 int state;
62 unsigned char hw[6];
63 uint32_t ip;
64 uint32_t nm;
65 uint32_t gw;
66 int sl;
67 int bytes;
70 struct font_t {
71 char *chars;
72 int sx;
73 int sy;
74 int dx;
75 int dy;
76 int charspline;
80 char LabelColor[30] = "#79bdbf";
81 char WindGustColor[30] = "#ff0000";
82 char DataColor[30] = "#ffbf50";
83 char BackColor[30] = "#181818";
84 char StationTimeColor[30] = "#c5a6ff";
86 struct font_t font1 = { " 0123456789ABCDEF", 64, 74, 4, 5, 17};
87 struct font_t font2 = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789: ", 1, 65, 5, 7, 26};
89 char *exec_dflt = "echo Use the -u and -d options for setting ifup/ifdown commands.";
90 char *exec_up;
91 char *exec_down;
93 int mode = MODE_LED;
94 char startif[16] = "";
95 char ifname[MAXIFS][16];
96 int ifaces;
97 int ifno = 0;
98 struct ifinfo_t ifinfo;
99 int fd = 0;
100 struct ifconf ifc;
101 volatile int exec_busy=0;
104 void parse_cmdline(int argc, char *argv[]);
105 void ButtonPressEvent(XButtonEvent *);
106 char *strupper(char *str);
107 void getifnames(void);
108 int getifinfo(char *ifname, struct ifinfo_t *info);
113 void drawtext(char *str, struct font_t *font, int x, int y)
115 int i = 0;
116 int ix, iy;
117 char *p;
119 while(str[i]) {
120 p = strchr(font->chars, str[i]);
121 ix = (p) ? (p - font->chars) : 0;
123 iy = (ix / font->charspline);
124 ix = (ix % font->charspline);
126 copyXPMArea( font->sx + ix * font->dx,
127 font->sy + iy * font->dy,
128 font->dx,
129 font->dy,
130 x + font->dx * i,
133 i++;
138 void drawipaddr(uint32_t a, int linenum)
140 char buf[4];
141 int i;
142 uint32_t addr = ntohl(a);
144 for(i=0; i<4; i++) {
145 snprintf(buf, 4, "%3d", (addr >> ((3-i)*8)) & 255);
146 drawtext(buf, &font1, 5 + i*14, 19 + linenum*9);
150 void drawhwaddr(unsigned char *addr)
152 char buf[4];
153 int i;
155 for(i=0; i<6; i++) {
156 snprintf(buf, 4, "%02X", addr[i]);
157 drawtext(buf, &font1, 6 + i*9, 46);
161 int main(int argc, char *argv[])
164 XEvent event;
165 char buf[16];
166 int d=0;
167 int pifno=-1;
168 int lastbytes=0;
169 struct timeval tv;
170 fd_set fds;
171 int x;
172 int prev_exec_busy=0;
174 exec_up = exec_dflt;
175 exec_down = exec_dflt;
177 parse_cmdline(argc, argv);
179 initXwindow(argc, argv);
181 if(mode == MODE_LED) {
182 openXwindow(argc, argv, (char **) wmifinfo_led_xpm,
183 (char*) wmifinfo_led_bits, wmifinfo_led_width,
184 wmifinfo_led_height, BackColor, LabelColor,
185 WindGustColor, DataColor, StationTimeColor);
186 } else {
187 openXwindow(argc, argv, (char **) wmifinfo_lcd_xpm,
188 (char*) wmifinfo_lcd_bits, wmifinfo_lcd_width,
189 wmifinfo_lcd_height, BackColor, LabelColor,
190 WindGustColor, DataColor, StationTimeColor);
193 /* Initialize global variables */
195 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
196 ifc.ifc_len = sizeof(struct ifreq) * 10;
197 ifc.ifc_buf = malloc(ifc.ifc_len);
199 while(1) {
201 while (XPending(display)) {
202 XNextEvent(display, &event);
204 switch (event.type) {
205 case Expose:
206 RedrawWindow();
207 break;
208 case ButtonPress:
209 ButtonPressEvent(&event.xbutton);
210 break;
211 case ButtonRelease:
212 break;
217 if ((d++ == 3) || (ifno != pifno) || (exec_busy != prev_exec_busy)) {
219 d=0;
221 copyXPMArea(64, 0, 64, 64, 0, 0);
222 getifnames();
224 if(ifaces>0) {
225 ifno = ifno % ifaces;
227 getifinfo(ifname[ifno], &ifinfo);
229 if(ifno != pifno) lastbytes = ifinfo.bytes;
231 sprintf(buf, "%-7s", ifinfo.id);
232 strupper(buf);
233 drawtext(buf, &font2, 6, 4);
235 if(memcmp(ifinfo.hw, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
236 drawhwaddr(ifinfo.hw);
239 if(ifinfo.ip) drawipaddr(ifinfo.ip, 0);
240 if(ifinfo.nm) drawipaddr(ifinfo.nm, 1);
241 if(ifinfo.gw) drawipaddr(ifinfo.gw, 2);
243 /* WLAN signal level */
245 #ifdef linux
246 x = ifinfo.sl/4;
247 #elif defined(__OpenBSD__)
248 x = ifinfo.sl/7;
249 #endif
250 if(x>13) x=13;
251 copyXPMArea(4, 82, x*4, 4, 6, 53);
253 /* LED */
255 x=0;
256 if(exec_busy) {
257 x=0;
258 } else {
259 if(ifinfo.state) x += 8;
260 if(lastbytes == ifinfo.bytes) x+= 16;
262 copyXPMArea(64 + x, 81, 8, 8, 50, 4);
263 lastbytes = ifinfo.bytes;
267 RedrawWindow();
268 prev_exec_busy = exec_busy;
269 pifno = ifno;
272 #ifdef linux
273 tv.tv_sec = DELAY / USEC_PER_SEC;
274 tv.tv_usec = DELAY - (tv.tv_sec * USEC_PER_SEC);
276 FD_ZERO(&fds);
277 FD_SET(ConnectionNumber(display), &fds);
279 select(ConnectionNumber(display)+1, &fds, NULL, NULL, &tv);
280 #elif defined(__OpenBSD__)
281 usleep(DELAY);
282 #endif
288 void print_usage()
290 printf(
291 "usage: wmifinfo [-lh] [-i interface]\n"
292 " -d <cmd> Command to exec for iface-down\n"
293 " -i <interface> Start with given interface, if available\n"
294 " -l LCD display mode\n"
295 " -h Print this help\n"
296 " -u <cmd> Command to exec for iface-up\n"
297 " -v Show version info and exit\n"
302 void print_version()
304 printf("%s version %s, compile-time options: ", NAME, VERSION);
306 #ifdef ENABLE_NWN_SUPPORT
307 printf("ENABLE NWN SUPPORT ");
308 #endif
310 printf("\n");
313 void parse_cmdline(int argc, char *argv[])
315 int c;
317 while((c = getopt(argc, argv, "d:i:lhu:v")) != EOF) {
318 switch(c) {
319 case 'd' :
320 exec_down = strdup(optarg);
321 break;
322 case 'i' :
323 strncpy(startif, optarg, sizeof(startif));
324 break;
325 case 'l' :
326 mode = MODE_LCD;
327 break;
328 case 'h' :
329 print_usage();
330 exit(0);
331 case 'u' :
332 exec_up = strdup(optarg);
333 break;
334 case 'v' :
335 print_version();
336 exit(0);
342 void sigchldhandler(int a)
344 wait(NULL);
345 exec_busy = 0;
348 void exec_cmd(char *cmd)
350 int pid;
352 signal(SIGCHLD, sigchldhandler);
354 if(exec_busy) return;
355 exec_busy=1;
357 pid=fork();
358 if(pid == 0) {
359 if (system(cmd) == -1) {
360 fprintf(stderr, "%s failed\n", cmd);
361 exit(1);
363 exit(0);
366 return;
369 void ButtonPressEvent(XButtonEvent * xev)
371 char buf[256];
373 if (xev->type != ButtonPress) return;
375 switch (xev->button) {
376 case Button1:
378 ifno++;
379 break;
381 case Button2:
382 case Button3:
384 if(ifinfo.state == 0) {
385 sprintf(buf, exec_up, ifinfo.id);
386 } else {
387 sprintf(buf, exec_down, ifinfo.id);
390 exec_cmd(buf);
392 break;
397 char *strupper(char *str)
400 int i;
402 for (i = 0; i < strlen(str); i++)
403 str[i] = toupper(str[i]);
405 return str;
410 int getifinfo(char *ifname, struct ifinfo_t *info)
412 struct ifreq ifr;
413 struct sockaddr_in *sa;
415 #ifdef linux
416 static FILE *froute = NULL;
417 static FILE *fwireless = NULL;
418 static FILE *fdev = NULL;
419 #elif defined(__OpenBSD__)
420 struct ifreq ibuf[32];
421 struct ifconf ifc;
422 struct ifreq *ifrp, *ifend;
423 #endif
425 char parent[16];
426 char buf[1024];
427 char *p;
428 char a[16];
429 int b,c,d;
431 #ifdef linux
432 if(froute == NULL) froute = fopen("/proc/net/route", "r");
433 if(fwireless == NULL) fwireless = fopen("/proc/net/wireless", "r");
434 if(fdev == NULL) fdev = fopen("/proc/net/dev", "r");
435 #endif
438 strcpy(parent, ifname);
439 p=strchr(parent, ':');
440 if(p) *p=0;
442 strcpy(info->id, ifname);
444 strcpy(ifr.ifr_name, ifname);
446 /* Get status (UP/DOWN) */
448 if(ioctl(fd, SIOCGIFFLAGS, &ifr) != -1) {
449 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
450 info->state = (ifr.ifr_flags & 1) ? 1 : 0;
451 } else {
452 info->state = 0;
455 /* Get mac address */
457 #ifdef linux
458 if(ioctl(fd, SIOCGIFHWADDR, &ifr) != -1) {
459 memcpy(info->hw, ifr.ifr_hwaddr.sa_data, 6);
460 } else {
461 memset(info->hw, 0, 6);
463 #elif defined(__OpenBSD__)
464 ifc.ifc_len = sizeof(ibuf);
465 ifc.ifc_buf = (caddr_t) ibuf;
466 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1 ||
467 ifc.ifc_len < sizeof(struct ifreq)) {
468 memset(info->hw, 0, 6);
469 } else {
470 /* Search interface configuration list for link layer address. */
471 ifrp = ibuf;
472 ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
473 while (ifrp < ifend) {
474 /* Look for interface */
475 if (strcmp(ifname, ifrp->ifr_name) == 0 &&
476 ifrp->ifr_addr.sa_family == AF_LINK &&
477 ((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
478 memcpy(info->hw, LLADDR((struct sockaddr_dl *) &ifrp->ifr_addr), 6);
479 break;
481 /* Bump interface config pointer */
482 r = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
483 if (r < sizeof(*ifrp))
484 r = sizeof(*ifrp);
485 ifrp = (struct ifreq *) ((char *) ifrp + r);
488 #endif
490 /* Get IP address */
492 if(ioctl(fd, SIOCGIFADDR, &ifr) != -1) {
493 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
494 info->ip = sa->sin_addr.s_addr;
495 } else {
496 info->ip = 0;
499 /* Get netmask */
501 if(ioctl(fd, SIOCGIFNETMASK, &ifr) != -1) {
502 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
503 info->nm = sa->sin_addr.s_addr;
504 } else {
505 info->nm = 0;
508 /* Get default gateway if on this interface */
510 info->gw = 0;
511 #ifdef linux
512 if(froute != NULL) {
513 fseek(froute, 0, 0);
515 while(fgets(buf, sizeof(buf), froute)) {
516 sscanf(buf, "%s %x %x", a, (unsigned int *) &b,
517 (unsigned int *) &c);
519 if((strcmp(a, info->id) == 0) && (b == 0)) {
520 info->gw = c;
525 #elif defined(__OpenBSD__)
527 struct rt_msghdr *rtm = NULL;
528 char *buf = NULL, *next, *lim = NULL;
529 size_t needed;
530 int mib[6];
531 struct sockaddr *sa;
532 struct sockaddr_in *sin;
534 mib[0] = CTL_NET;
535 mib[1] = PF_ROUTE;
536 mib[2] = 0;
537 mib[3] = AF_INET;
538 mib[4] = NET_RT_DUMP;
539 mib[5] = 0;
540 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) {
541 perror("route-sysctl-estimate");
542 exit(1);
544 if (needed > 0) {
545 if ((buf = malloc(needed)) == 0) {
546 printf("out of space\n");
547 exit(1);
549 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) {
550 perror("sysctl of routing table");
551 exit(1);
553 lim = buf + needed;
556 if (buf) {
557 for (next = buf; next < lim; next += rtm->rtm_msglen) {
558 rtm = (struct rt_msghdr *)next;
559 sa = (struct sockaddr *)(rtm + 1);
560 sin = (struct sockaddr_in *)sa;
562 if (sin->sin_addr.s_addr == 0) {
563 sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
564 sin = (struct sockaddr_in *)sa;
565 info->gw = sin->sin_addr.s_addr;
566 break;
569 free(buf);
572 #endif
574 /* Get wireless link status if wireless */
576 info->sl = 0;
577 #ifdef linux
578 if(fwireless != NULL) {
579 fseek(fwireless, 0, 0);
581 while(fgets(buf, sizeof(buf), fwireless)) {
582 sscanf(buf, "%s %d %d ", a, &b, &c);
583 if(strchr(a, ':')) *(strchr(a, ':')) = 0;
584 if(strcmp(a, parent) == 0) {
585 info->sl = c;
590 #ifdef ENABLE_NWN_SUPPORT
591 if (info->sl == 0) {
592 info->sl = nwn_get_link(parent);
594 #endif
595 #elif defined(__OpenBSD__)
597 struct wi_req wreq;
598 struct ifreq ifr;
600 wreq.wi_len = WI_MAX_DATALEN;
601 wreq.wi_type = WI_RID_COMMS_QUALITY;
603 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
604 ifr.ifr_data = (caddr_t)&wreq;
606 if (ioctl(fd, SIOCGWAVELAN, &ifr) != -1)
607 info->sl = letoh16(wreq.wi_val[0]);
609 #endif
611 /* Get Total tx/rx bytes */
613 #ifdef linux
614 if(fdev != NULL) {
615 fseek(fdev, 0, 0);
617 while(fgets(buf, sizeof(buf), fdev)) {
618 sscanf(buf, "%s %d %d %d %d %d %d %d %d %d", a, &b, &d,&d,&d,&d,&d,&d,&d, &c);
619 if(strchr(a, ':')) *(strchr(a, ':')) = 0;
620 if(strcmp(a, parent) == 0) {
621 info->bytes = b + c;
625 #endif
627 return(0);
631 void addifname(char *name)
633 int i;
635 if(strcmp(name, "lo") == 0) return;
636 if(strncmp(name, "vlan", 4) == 0) return;
638 for(i=0; i<ifaces; i++) {
639 if(strcmp(ifname[i], name) == 0) return;
642 strcpy(ifname[ifaces], name);
645 ifaces++;
647 return;
652 * get list of interfaces. First read /proc/net/dev, then do a SIOCGIFCONF
655 void getifnames(void)
657 char pifname[MAXIFS][16];
658 int pifaces;
659 int i,j;
660 int isnew;
661 #ifdef linux
662 FILE *f;
663 char buf[128];
664 char *p1, *p2;
665 int ifcount;
666 #endif
669 * Copy list of interface names and clean the old list
672 for(i=0; i<ifaces; i++) strncpy(pifname[i], ifname[i], sizeof(pifname[i]));
673 pifaces = ifaces;
674 ifaces = 0;
676 #ifdef linux
677 f = fopen("/proc/net/dev", "r");
679 if(f == NULL) {
680 fprintf(stderr, "Can't open /proc/net/dev\n");
681 exit(1);
684 while(fgets(buf, sizeof(buf), f)) {
685 p1=buf;
686 while(*p1 == ' ') p1++;
687 p2=p1;
688 while(*p2 && (*p2 != ':')) p2++;
689 if(*p2 == ':') {
690 *p2=0;
691 addifname(p1);
695 fclose(f);
697 ifc.ifc_len = sizeof(struct ifreq) * 10;
699 if(ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
700 fprintf(stderr, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno));
701 exit(1);
704 ifcount = ifc.ifc_len / sizeof(struct ifreq);
706 for(i=0; i<ifcount; i++) {
707 addifname(ifc.ifc_req[i].ifr_name);
709 #endif
710 #ifdef __OpenBSD__
711 struct ifreq ibuf[32];
712 struct ifconf ifc;
713 struct ifreq *ifrp, *ifend;
714 int r;
716 ifc.ifc_len = sizeof(ibuf);
717 ifc.ifc_buf = (caddr_t) ibuf;
718 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1 ||
719 ifc.ifc_len < sizeof(struct ifreq)) {
720 fprintf(stderr, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno));
721 exit(1);
723 /* Search interface configuration list for link layer address. */
724 ifrp = ibuf;
725 ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
726 while (ifrp < ifend) {
727 if (ifrp->ifr_addr.sa_family == AF_LINK &&
728 ((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
729 addifname(ifrp->ifr_name);
731 /* Bump interface config pointer */
732 r = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
733 if (r < sizeof(*ifrp))
734 r = sizeof(*ifrp);
735 ifrp = (struct ifreq *) ((char *) ifrp + r);
737 #endif
740 * Check if the new list contains interfaces that were not in the old list. If a new
741 * interface is found, make it the current one to display. (-i will override)
744 for(i=0; i<ifaces; i++) {
745 isnew = 1;
746 for(j=0; j<pifaces; j++) if(strcmp(ifname[i], pifname[j]) == 0) isnew = 0;
747 if(isnew) ifno = i;
750 for(i=0; i<ifaces; i++) {
751 if(strcasecmp(ifname[i], startif) == 0) {
752 ifno = i;
753 startif[0] = 0;