wmifinfo: Remove C++ style comments.
[dockapps.git] / wmifinfo / wmifinfo.c
blobadb323dc77a4691e9e71ce780f2e6a72db60b133
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 #else
53 #define DELAY 100000L
54 #endif
55 #define MODE_LED 1
56 #define MODE_LCD 2
58 struct ifinfo_t {
59 char id[16];
60 int state;
61 unsigned char hw[6];
62 uint32_t ip;
63 uint32_t nm;
64 uint32_t gw;
65 int sl;
66 int bytes;
69 struct font_t {
70 char *chars;
71 int sx;
72 int sy;
73 int dx;
74 int dy;
75 int charspline;
79 char LabelColor[30] = "#79bdbf";
80 char WindGustColor[30] = "#ff0000";
81 char DataColor[30] = "#ffbf50";
82 char BackColor[30] = "#181818";
83 char StationTimeColor[30] = "#c5a6ff";
85 struct font_t font1 = { " 0123456789ABCDEF", 64, 74, 4, 5, 17};
86 struct font_t font2 = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789: ", 1, 65, 5, 7, 26};
88 char *exec_dflt = "echo Use the -u and -d options for setting ifup/ifdown commands.";
89 char *exec_up;
90 char *exec_down;
92 int mode = MODE_LED;
93 char startif[16] = "";
94 char ifname[MAXIFS][16];
95 int ifaces;
96 int ifno = 0;
97 struct ifinfo_t ifinfo;
98 int fd = 0;
99 struct ifconf ifc;
100 volatile int exec_busy=0;
103 void parse_cmdline(int argc, char *argv[]);
104 void ButtonPressEvent(XButtonEvent *);
105 char *strupper(char *str);
106 void getifnames(void);
107 int getifinfo(char *ifname, struct ifinfo_t *info);
112 void drawtext(char *str, struct font_t *font, int x, int y)
114 int i = 0;
115 int ix, iy;
116 char *p;
118 while(str[i]) {
119 p = strchr(font->chars, str[i]);
120 ix = (p) ? (p - font->chars) : 0;
122 iy = (ix / font->charspline);
123 ix = (ix % font->charspline);
125 copyXPMArea( font->sx + ix * font->dx,
126 font->sy + iy * font->dy,
127 font->dx,
128 font->dy,
129 x + font->dx * i,
132 i++;
137 void drawipaddr(uint32_t a, int linenum)
139 char buf[4];
140 int i;
141 uint32_t addr = ntohl(a);
143 for(i=0; i<4; i++) {
144 snprintf(buf, 4, "%3d", (addr >> ((3-i)*8)) & 255);
145 drawtext(buf, &font1, 5 + i*14, 19 + linenum*9);
149 void drawhwaddr(unsigned char *addr)
151 char buf[4];
152 int i;
154 for(i=0; i<6; i++) {
155 snprintf(buf, 4, "%02X", addr[i]);
156 drawtext(buf, &font1, 6 + i*9, 46);
160 int main(int argc, char *argv[])
163 XEvent event;
164 char buf[16];
165 int d=0;
166 int pifno=-1;
167 int lastbytes=0;
168 struct timeval tv;
169 fd_set fds;
170 int x;
171 int prev_exec_busy=0;
173 exec_up = exec_dflt;
174 exec_down = exec_dflt;
176 parse_cmdline(argc, argv);
178 initXwindow(argc, argv);
180 if(mode == MODE_LED) {
181 openXwindow(argc, argv, (char **) wmifinfo_led_xpm,
182 (char*) wmifinfo_led_bits, wmifinfo_led_width,
183 wmifinfo_led_height, BackColor, LabelColor,
184 WindGustColor, DataColor, StationTimeColor);
185 } else {
186 openXwindow(argc, argv, (char **) wmifinfo_lcd_xpm,
187 (char*) wmifinfo_lcd_bits, wmifinfo_lcd_width,
188 wmifinfo_lcd_height, BackColor, LabelColor,
189 WindGustColor, DataColor, StationTimeColor);
192 /* Initialize global variables */
194 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
195 ifc.ifc_len = sizeof(struct ifreq) * 10;
196 ifc.ifc_buf = malloc(ifc.ifc_len);
198 while(1) {
200 while (XPending(display)) {
201 XNextEvent(display, &event);
203 switch (event.type) {
204 case Expose:
205 RedrawWindow();
206 break;
207 case ButtonPress:
208 ButtonPressEvent(&event.xbutton);
209 break;
210 case ButtonRelease:
211 break;
216 if ((d++ == 3) || (ifno != pifno) || (exec_busy != prev_exec_busy)) {
218 d=0;
220 copyXPMArea(64, 0, 64, 64, 0, 0);
221 getifnames();
223 if(ifaces>0) {
224 ifno = ifno % ifaces;
226 getifinfo(ifname[ifno], &ifinfo);
228 if(ifno != pifno) lastbytes = ifinfo.bytes;
230 sprintf(buf, "%-7s", ifinfo.id);
231 strupper(buf);
232 drawtext(buf, &font2, 6, 4);
234 if(memcmp(ifinfo.hw, "\x00\x00\x00\x00\x00\x00", 6) != 0) {
235 drawhwaddr(ifinfo.hw);
238 if(ifinfo.ip) drawipaddr(ifinfo.ip, 0);
239 if(ifinfo.nm) drawipaddr(ifinfo.nm, 1);
240 if(ifinfo.gw) drawipaddr(ifinfo.gw, 2);
242 /* WLAN signal level */
244 #ifdef linux
245 x = ifinfo.sl/4;
246 #elif defined(__OpenBSD__)
247 x = ifinfo.sl/7;
248 #endif
249 if(x>13) x=13;
250 copyXPMArea(4, 82, x*4, 4, 6, 53);
252 /* LED */
254 x=0;
255 if(exec_busy) {
256 x=0;
257 } else {
258 if(ifinfo.state) x += 8;
259 if(lastbytes == ifinfo.bytes) x+= 16;
261 copyXPMArea(64 + x, 81, 8, 8, 50, 4);
262 lastbytes = ifinfo.bytes;
266 RedrawWindow();
267 prev_exec_busy = exec_busy;
268 pifno = ifno;
271 #ifdef linux
272 tv.tv_sec = 0;
273 tv.tv_usec = DELAY;
275 FD_ZERO(&fds);
276 FD_SET(ConnectionNumber(display), &fds);
278 select(ConnectionNumber(display)+1, &fds, NULL, NULL, &tv);
279 #elif defined(__OpenBSD__)
280 usleep(DELAY);
281 #endif
287 void print_usage()
289 printf(
290 "usage: wmifinfo [-lh] [-i interface]\n"
291 " -d <cmd> Command to exec for iface-down\n"
292 " -i <interface> Start with given interface, if available\n"
293 " -l LCD display mode\n"
294 " -h Print this help\n"
295 " -u <cmd> Command to exec for iface-up\n"
296 " -v Show version info and exit\n"
301 void print_version()
303 printf("%s version %s, compile-time options: ", NAME, VERSION);
305 #ifdef ENABLE_NWN_SUPPORT
306 printf("ENABLE NWN SUPPORT ");
307 #endif
309 printf("\n");
312 void parse_cmdline(int argc, char *argv[])
314 int c;
316 while((c = getopt(argc, argv, "d:i:lhu:v")) != EOF) {
317 switch(c) {
318 case 'd' :
319 exec_down = strdup(optarg);
320 break;
321 case 'i' :
322 strncpy(startif, optarg, sizeof(startif));
323 break;
324 case 'l' :
325 mode = MODE_LCD;
326 break;
327 case 'h' :
328 print_usage();
329 exit(0);
330 case 'u' :
331 exec_up = strdup(optarg);
332 break;
333 case 'v' :
334 print_version();
335 exit(0);
341 void sigchldhandler(int a)
343 wait(NULL);
344 exec_busy = 0;
347 void exec_cmd(char *cmd)
349 int pid;
351 signal(SIGCHLD, sigchldhandler);
353 if(exec_busy) return;
354 exec_busy=1;
356 pid=fork();
357 if(pid == 0) {
358 if (system(cmd) == -1) {
359 fprintf(stderr, "%s failed\n", cmd);
360 exit(1);
362 exit(0);
365 return;
368 void ButtonPressEvent(XButtonEvent * xev)
370 char buf[256];
372 if (xev->type != ButtonPress) return;
374 switch (xev->button) {
375 case Button1:
377 ifno++;
378 break;
380 case Button2:
381 case Button3:
383 if(ifinfo.state == 0) {
384 sprintf(buf, exec_up, ifinfo.id);
385 } else {
386 sprintf(buf, exec_down, ifinfo.id);
389 exec_cmd(buf);
391 break;
396 char *strupper(char *str)
399 int i;
401 for (i = 0; i < strlen(str); i++)
402 str[i] = toupper(str[i]);
404 return str;
409 int getifinfo(char *ifname, struct ifinfo_t *info)
411 struct ifreq ifr;
412 struct sockaddr_in *sa;
414 #ifdef linux
415 static FILE *froute = NULL;
416 static FILE *fwireless = NULL;
417 static FILE *fdev = NULL;
418 #elif defined(__OpenBSD__)
419 struct ifreq ibuf[32];
420 struct ifconf ifc;
421 struct ifreq *ifrp, *ifend;
422 #endif
424 char parent[16];
425 char buf[1024];
426 char *p;
427 char a[16];
428 int b,c,d;
430 #ifdef linux
431 if(froute == NULL) froute = fopen("/proc/net/route", "r");
432 if(fwireless == NULL) fwireless = fopen("/proc/net/wireless", "r");
433 if(fdev == NULL) fdev = fopen("/proc/net/dev", "r");
434 #endif
437 strcpy(parent, ifname);
438 p=strchr(parent, ':');
439 if(p) *p=0;
441 strcpy(info->id, ifname);
443 strcpy(ifr.ifr_name, ifname);
445 /* Get status (UP/DOWN) */
447 if(ioctl(fd, SIOCGIFFLAGS, &ifr) != -1) {
448 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
449 info->state = (ifr.ifr_flags & 1) ? 1 : 0;
450 } else {
451 info->state = 0;
454 /* Get mac address */
456 #ifdef linux
457 if(ioctl(fd, SIOCGIFHWADDR, &ifr) != -1) {
458 memcpy(info->hw, ifr.ifr_hwaddr.sa_data, 6);
459 } else {
460 memset(info->hw, 0, 6);
462 #elif defined(__OpenBSD__)
463 ifc.ifc_len = sizeof(ibuf);
464 ifc.ifc_buf = (caddr_t) ibuf;
465 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1 ||
466 ifc.ifc_len < sizeof(struct ifreq)) {
467 memset(info->hw, 0, 6);
468 } else {
469 /* Search interface configuration list for link layer address. */
470 ifrp = ibuf;
471 ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
472 while (ifrp < ifend) {
473 /* Look for interface */
474 if (strcmp(ifname, ifrp->ifr_name) == 0 &&
475 ifrp->ifr_addr.sa_family == AF_LINK &&
476 ((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
477 memcpy(info->hw, LLADDR((struct sockaddr_dl *) &ifrp->ifr_addr), 6);
478 break;
480 /* Bump interface config pointer */
481 r = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
482 if (r < sizeof(*ifrp))
483 r = sizeof(*ifrp);
484 ifrp = (struct ifreq *) ((char *) ifrp + r);
487 #endif
489 /* Get IP address */
491 if(ioctl(fd, SIOCGIFADDR, &ifr) != -1) {
492 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
493 info->ip = sa->sin_addr.s_addr;
494 } else {
495 info->ip = 0;
498 /* Get netmask */
500 if(ioctl(fd, SIOCGIFNETMASK, &ifr) != -1) {
501 sa = (struct sockaddr_in *)&(ifr.ifr_addr);
502 info->nm = sa->sin_addr.s_addr;
503 } else {
504 info->nm = 0;
507 /* Get default gateway if on this interface */
509 info->gw = 0;
510 #ifdef linux
511 if(froute != NULL) {
512 fseek(froute, 0, 0);
514 while(fgets(buf, sizeof(buf), froute)) {
515 sscanf(buf, "%s %x %x", a, &b, &c);
517 if((strcmp(a, info->id) == 0) && (b == 0)) {
518 info->gw = c;
523 #elif defined(__OpenBSD__)
525 struct rt_msghdr *rtm = NULL;
526 char *buf = NULL, *next, *lim = NULL;
527 size_t needed;
528 int mib[6];
529 struct sockaddr *sa;
530 struct sockaddr_in *sin;
532 mib[0] = CTL_NET;
533 mib[1] = PF_ROUTE;
534 mib[2] = 0;
535 mib[3] = AF_INET;
536 mib[4] = NET_RT_DUMP;
537 mib[5] = 0;
538 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) {
539 perror("route-sysctl-estimate");
540 exit(1);
542 if (needed > 0) {
543 if ((buf = malloc(needed)) == 0) {
544 printf("out of space\n");
545 exit(1);
547 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) {
548 perror("sysctl of routing table");
549 exit(1);
551 lim = buf + needed;
554 if (buf) {
555 for (next = buf; next < lim; next += rtm->rtm_msglen) {
556 rtm = (struct rt_msghdr *)next;
557 sa = (struct sockaddr *)(rtm + 1);
558 sin = (struct sockaddr_in *)sa;
560 if (sin->sin_addr.s_addr == 0) {
561 sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
562 sin = (struct sockaddr_in *)sa;
563 info->gw = sin->sin_addr.s_addr;
564 break;
567 free(buf);
570 #endif
572 /* Get wireless link status if wireless */
574 info->sl = 0;
575 #ifdef linux
576 if(fwireless != NULL) {
577 fseek(fwireless, 0, 0);
579 while(fgets(buf, sizeof(buf), fwireless)) {
580 sscanf(buf, "%s %d %d ", a, &b, &c);
581 if(strchr(a, ':')) *(strchr(a, ':')) = 0;
582 if(strcmp(a, parent) == 0) {
583 info->sl = c;
588 #ifdef ENABLE_NWN_SUPPORT
589 if (info->sl == 0) {
590 info->sl = nwn_get_link(parent);
592 #endif
593 #elif defined(__OpenBSD__)
595 struct wi_req wreq;
596 struct ifreq ifr;
598 wreq.wi_len = WI_MAX_DATALEN;
599 wreq.wi_type = WI_RID_COMMS_QUALITY;
601 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
602 ifr.ifr_data = (caddr_t)&wreq;
604 if (ioctl(fd, SIOCGWAVELAN, &ifr) != -1)
605 info->sl = letoh16(wreq.wi_val[0]);
607 #endif
609 /* Get Total tx/rx bytes */
611 #ifdef linux
612 if(fdev != NULL) {
613 fseek(fdev, 0, 0);
615 while(fgets(buf, sizeof(buf), fdev)) {
616 sscanf(buf, "%s %d %d %d %d %d %d %d %d %d", a, &b, &d,&d,&d,&d,&d,&d,&d, &c);
617 if(strchr(a, ':')) *(strchr(a, ':')) = 0;
618 if(strcmp(a, parent) == 0) {
619 info->bytes = b + c;
623 #endif
625 return(0);
629 void addifname(char *name)
631 int i;
633 if(strcmp(name, "lo") == 0) return;
634 if(strncmp(name, "vlan", 4) == 0) return;
636 for(i=0; i<ifaces; i++) {
637 if(strcmp(ifname[i], name) == 0) return;
640 strcpy(ifname[ifaces], name);
643 ifaces++;
645 return;
650 * get list of interfaces. First read /proc/net/dev, then do a SIOCGIFCONF
653 void getifnames(void)
655 char pifname[MAXIFS][16];
656 int pifaces;
657 int i,j;
658 int isnew;
661 * Copy list of interface names and clean the old list
664 for(i=0; i<ifaces; i++) strncpy(pifname[i], ifname[i], sizeof(pifname[i]));
665 pifaces = ifaces;
666 ifaces = 0;
668 #ifdef linux
669 FILE *f;
670 char buf[128];
671 char *p1, *p2;
672 int ifcount;
674 f = fopen("/proc/net/dev", "r");
676 if(f == NULL) {
677 fprintf(stderr, "Can't open /proc/net/dev\n");
678 exit(1);
681 while(fgets(buf, sizeof(buf), f)) {
682 p1=buf;
683 while(*p1 == ' ') p1++;
684 p2=p1;
685 while(*p2 && (*p2 != ':')) p2++;
686 if(*p2 == ':') {
687 *p2=0;
688 addifname(p1);
692 fclose(f);
694 ifc.ifc_len = sizeof(struct ifreq) * 10;
696 if(ioctl(fd, SIOCGIFCONF, &ifc) == -1) {
697 fprintf(stderr, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno));
698 exit(1);
701 ifcount = ifc.ifc_len / sizeof(struct ifreq);
703 for(i=0; i<ifcount; i++) {
704 addifname(ifc.ifc_req[i].ifr_name);
706 #endif
707 #ifdef __OpenBSD__
708 struct ifreq ibuf[32];
709 struct ifconf ifc;
710 struct ifreq *ifrp, *ifend;
711 int r;
713 ifc.ifc_len = sizeof(ibuf);
714 ifc.ifc_buf = (caddr_t) ibuf;
715 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) == -1 ||
716 ifc.ifc_len < sizeof(struct ifreq)) {
717 fprintf(stderr, "SIOCGIFCONF : Can't get list of interfaces : %s\n", strerror(errno));
718 exit(1);
720 /* Search interface configuration list for link layer address. */
721 ifrp = ibuf;
722 ifend = (struct ifreq *) ((char *) ibuf + ifc.ifc_len);
723 while (ifrp < ifend) {
724 if (ifrp->ifr_addr.sa_family == AF_LINK &&
725 ((struct sockaddr_dl *) &ifrp->ifr_addr)->sdl_type == IFT_ETHER) {
726 addifname(ifrp->ifr_name);
728 /* Bump interface config pointer */
729 r = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
730 if (r < sizeof(*ifrp))
731 r = sizeof(*ifrp);
732 ifrp = (struct ifreq *) ((char *) ifrp + r);
734 #endif
737 * Check if the new list contains interfaces that were not in the old list. If a new
738 * interface is found, make it the current one to display. (-i will override)
741 for(i=0; i<ifaces; i++) {
742 isnew = 1;
743 for(j=0; j<pifaces; j++) if(strcmp(ifname[i], pifname[j]) == 0) isnew = 0;
744 if(isnew) ifno = i;
747 for(i=0; i<ifaces; i++) {
748 if(strcasecmp(ifname[i], startif) == 0) {
749 ifno = i;
750 startif[0] = 0;