/* $Id: wmwlmon.c,v 1.41 2008/05/13 09:26:22 hacki Exp $ */ /* * Copyright (c) 2005, 2006 Marcus Glocker * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include "wl.h" #include "xutils.h" #include "bitmaps/wmwlmon_mask.xbm" #include "bitmaps/wmwlmon_master.xpm" /* * defines */ #define DELAY 10000 #define NWIDLENP 52 #define NWIDLENC 8 /* * prototypes */ int main(int, char **); void usage(int); void signal_handler(const int); void debugloop(char *); void draw_nwid(char *, int); void draw_string(const char *, const int, const int); void draw_signal(const int, const int); int scroll_lcd(const int, const int, const int, const int, const int, const char *); int scroll_bounce(const int, const int, const int, const int, const int, const char *); int scroll_fade(const int, const int, const int, const int, const int, const char *); /* * global variables for this file */ static const char *version = "1.0"; volatile sig_atomic_t quit = 0; char TimeColor[30] = "#ffff00"; char BackgroundColor[30] = "#181818"; struct coordinates { int x; int y; int w; int h; } fonts[128] = { { 60, 102, 6, 8 }, /* Dec 0 nul NOTUSED */ { 60, 102, 6, 8 }, /* Dec 1 soh NOTUSED */ { 60, 102, 6, 8 }, /* Dec 2 stx NOTUSED */ { 60, 102, 6, 8 }, /* Dec 3 etx NOTUSED */ { 60, 102, 6, 8 }, /* Dec 4 eot NOTUSED */ { 60, 102, 6, 8 }, /* Dec 5 enq NOTUSED */ { 60, 102, 6, 8 }, /* Dec 6 ack NOTUSED */ { 60, 102, 6, 8 }, /* Dec 7 bel NOTUSED */ { 60, 102, 6, 8 }, /* Dec 8 bs NOTUSED */ { 60, 102, 6, 8 }, /* Dec 9 ht NOTUSED */ { 60, 102, 6, 8 }, /* Dec 10 nl NOTUSED */ { 60, 102, 6, 8 }, /* Dec 11 vt NOTUSED */ { 60, 102, 6, 8 }, /* Dec 12 np NOTUSED */ { 60, 102, 6, 8 }, /* Dec 13 cr NOTUSED */ { 60, 102, 6, 8 }, /* Dec 14 so NOTUSED */ { 60, 102, 6, 8 }, /* Dec 15 si NOTUSED */ { 60, 102, 6, 8 }, /* Dec 16 dle NOTUSED */ { 60, 102, 6, 8 }, /* Dec 17 dc1 NOTUSED */ { 60, 102, 6, 8 }, /* Dec 18 dc2 NOTUSED */ { 60, 102, 6, 8 }, /* Dec 19 dc3 NOTUSED */ { 60, 102, 6, 8 }, /* Dec 20 dc4 NOTUSED */ { 60, 102, 6, 8 }, /* Dec 21 nak NOTUSED */ { 60, 102, 6, 8 }, /* Dec 22 syn NOTUSED */ { 60, 102, 6, 8 }, /* Dec 23 etb NOTUSED */ { 60, 102, 6, 8 }, /* Dec 24 can NOTUSED */ { 60, 102, 6, 8 }, /* Dec 25 em NOTUSED */ { 60, 102, 6, 8 }, /* Dec 26 sub NOTUSED */ { 60, 102, 6, 8 }, /* Dec 27 esc NOTUSED */ { 60, 102, 6, 8 }, /* Dec 28 fs NOTUSED */ { 60, 102, 6, 8 }, /* Dec 29 gs NOTUSED */ { 60, 102, 6, 8 }, /* Dec 30 rs NOTUSED */ { 60, 102, 6, 8 }, /* Dec 31 us NOTUSED */ { 60, 102, 6, 8 }, /* Dec 32 sp NOTUSED */ { 66, 102, 6, 8 }, /* Dec 33 '!' */ { 72, 102, 6, 8 }, /* Dec 34 '"' */ { 78, 102, 6, 8 }, /* Dec 35 '#' */ { 60, 102, 6, 8 }, /* Dec 36 '$' NOTUSED */ { 90, 101, 6, 8 }, /* Dec 37 '%' */ { 96, 102, 6, 8 }, /* Dec 38 '&' */ { 102, 102, 6, 8 }, /* Dec 39 ''' */ { 108, 102, 6, 8 }, /* Dec 40 '(' */ { 114, 102, 6, 8 }, /* Dec 41 ')' */ { 120, 102, 6, 8 }, /* Dec 42 '*' */ { 126, 102, 6, 8 }, /* Dec 43 '+' */ { 132, 102, 6, 8 }, /* Dec 44 ',' */ { 138, 102, 6, 8 }, /* Dec 45 '-' */ { 144, 102, 6, 8 }, /* Dec 46 '.' */ { 150, 102, 6, 8 }, /* Dec 47 '/' */ { 0, 102, 6, 6 }, /* Dec 48 '0' */ { 6, 102, 6, 6 }, /* Dec 49 '1' */ { 12, 102, 6, 6 }, /* Dec 50 '2' */ { 18, 102, 6, 6 }, /* Dec 51 '3' */ { 24, 102, 6, 6 }, /* Dec 52 '4' */ { 30, 102, 6, 6 }, /* Dec 53 '5' */ { 36, 102, 6, 6 }, /* Dec 54 '6' */ { 42, 102, 6, 6 }, /* Dec 55 '7' */ { 48, 102, 6, 6 }, /* Dec 56 '8' */ { 54, 102, 6, 6 }, /* Dec 57 '9' */ { 0, 112, 6, 8 }, /* Dec 58 ':' */ { 6, 113, 6, 8 }, /* Dec 59 ';' */ { 12, 112, 6, 8 }, /* Dec 60 '<'*/ { 18, 112, 6, 8 }, /* Dec 61 '='*/ { 24, 112, 6, 8 }, /* Dec 62 '>'*/ { 30, 112, 6, 8 }, /* Dec 63 '?'*/ { 36, 112, 6, 8 }, /* Dec 64 '@'*/ { 0, 79, 6, 8 }, /* Dec 65 'A' */ { 6, 79, 6, 8 }, /* Dec 66 'B' */ { 12, 79, 6, 8 }, /* Dec 67 'C' */ { 18, 79, 6, 8 }, /* Dec 68 'D' */ { 24, 79, 6, 8 }, /* Dec 69 'E' */ { 30, 79, 6, 8 }, /* Dec 70 'F' */ { 36, 79, 6, 8 }, /* Dec 71 'G' */ { 42, 79, 6, 8 }, /* Dec 72 'H' */ { 48, 79, 6, 8 }, /* Dec 73 'I' */ { 54, 79, 6, 8 }, /* Dec 74 'J' */ { 60, 79, 6, 8 }, /* Dec 75 'K' */ { 66, 79, 6, 8 }, /* Dec 76 'L' */ { 72, 79, 6, 8 }, /* Dec 77 'M' */ { 78, 79, 6, 8 }, /* Dec 78 'N' */ { 84, 79, 6, 8 }, /* Dec 79 'O' */ { 90, 79, 6, 8 }, /* Dec 80 'P' */ { 96, 79, 6, 8 }, /* Dec 81 'Q' */ { 102, 79, 6, 8 }, /* Dec 82 'R' */ { 108, 79, 6, 8 }, /* Dec 83 'S' */ { 114, 79, 6, 8 }, /* Dec 84 'T' */ { 120, 79, 6, 8 }, /* Dec 85 'U' */ { 126, 79, 6, 8 }, /* Dec 86 'V' */ { 132, 79, 6, 8 }, /* Dec 87 'W' */ { 138, 79, 6, 8 }, /* Dec 88 'X' */ { 144, 79, 6, 8 }, /* Dec 89 'Y' */ { 150, 79, 6, 8 }, /* Dec 90 'Z' */ { 42, 112, 6, 8 }, /* Dec 91 '[' */ { 48, 112, 6, 8 }, /* Dec 92 '\' */ { 54, 112, 6, 8 }, /* Dec 93 ']' */ { 60, 112, 6, 8 }, /* Dec 94 '^' */ { 66, 113, 6, 8 }, /* Dec 95 '_' */ { 72, 112, 6, 8 }, /* Dec 96 '`' */ { 0, 90, 6, 8 }, /* Dec 97 'a' */ { 6, 90, 6, 8 }, /* Dec 98 'b' */ { 12, 90, 6, 8 }, /* Dec 99 'c' */ { 18, 90, 6, 8 }, /* Dec 100 'd' */ { 24, 90, 6, 8 }, /* Dec 101 'e' */ { 30, 90, 6, 8 }, /* Dec 102 'f' */ { 36, 90, 6, 8 }, /* Dec 103 'g' */ { 42, 90, 6, 8 }, /* Dec 104 'h' */ { 48, 90, 6, 8 }, /* Dec 105 'i' */ { 54, 90, 6, 8 }, /* Dec 106 'j' */ { 60, 90, 6, 8 }, /* Dec 107 'k' */ { 66, 90, 6, 8 }, /* Dec 108 'l' */ { 72, 90, 6, 8 }, /* Dec 109 'm' */ { 78, 90, 6, 8 }, /* Dec 110 'n' */ { 84, 90, 6, 8 }, /* Dec 111 'o' */ { 90, 90, 6, 8 }, /* Dec 112 'p' */ { 96, 90, 6, 8 }, /* Dec 113 'q' */ { 102, 90, 6, 8 }, /* Dec 114 'r' */ { 108, 90, 6, 8 }, /* Dec 115 's' */ { 114, 90, 6, 8 }, /* Dec 116 't' */ { 120, 90, 6, 8 }, /* Dec 117 'u' */ { 126, 90, 6, 8 }, /* Dec 118 'v' */ { 132, 90, 6, 8 }, /* Dec 119 'w' */ { 138, 90, 6, 8 }, /* Dec 120 'x' */ { 144, 90, 6, 8 }, /* Dec 121 'y' */ { 150, 90, 6, 8 }, /* Dec 122 'z' */ { 78, 112, 6, 8 }, /* Dec 123 '{' */ { 84, 112, 6, 8 }, /* Dec 124 '|' */ { 90, 112, 6, 8 }, /* Dec 125 '}' */ { 60, 112, 6, 8 }, /* Dec 126 '~' */ { 60, 102, 6, 8 } /* Dec 127 del NOTUSED */ }; /* * usage */ void usage(int mode) { extern char *__progname; if (mode) { fprintf(stderr, "%s %s\n", __progname, version); exit(1); } fprintf(stderr, "usage: %s ", __progname); fprintf(stderr, "[-Dhvw] [-i interface] [-s scrolling] "); fprintf(stderr, "[-display display]\n\n"); fprintf(stderr, "options:\n"); fprintf(stderr, " -D\t\t: Debug mode.\n"); fprintf(stderr, " -h\t\t: This help.\n"); fprintf(stderr, " -v\t\t: Shows version.\n"); fprintf(stderr, " -w\t\t: Enable WaveLAN compatibility.\n"); fprintf(stderr, " -i\t\t: Set interface.\n"); fprintf(stderr, " -s\t\t: Network ID scrolling.\n"); fprintf(stderr, " \t\t 0 = Disable 1 = LCD (default) 2 = Bounce "); fprintf(stderr, "3 = Fade\n"); fprintf(stderr, " -display\t: Set display name.\n"); exit(1); } /* * signal handler */ void signal_handler(const int sig) { switch (sig) { case SIGINT: /* FALLTHROUGH */ case SIGTERM: quit = 1; break; case SIGCHLD: /* ignore */ break; case SIGHUP: /* ignore */ break; case SIGQUIT: /* ignore */ break; case SIGALRM: /* ignore */ break; case SIGPIPE: /* ignore */ break; default: /* ignore */ break; } } /* * main() * wireless monitor wmdockapp * Return: * 0 */ int main(int argc, char *argv[]) { int i, r, ch, opt_wavelan = 0; int opt_debug = 0, nic_status = 1, opt_scroll = 1; char *opt_interface = NULL, *opt_display = NULL; char *nwid = NULL, *speed = NULL, *status = NULL; char sig[4], chn[4]; #ifdef __OpenBSD__ const char *errstr; #endif XEvent event; /* * get command line options */ /* keep the old good -display tradition */ for (i = 0; i < argc; i++) { if (!strcmp(argv[i], "-display")) argv[i] = "-d"; } while ((ch = getopt(argc, argv, "Dd:hi:s:vw")) != -1) { switch (ch) { case 'D': opt_debug = 1; break; case 'd': opt_display = strdup(optarg); break; case 'i': opt_interface = strdup(optarg); break; case 's': #ifdef __OpenBSD__ opt_scroll = strtonum(optarg, 0, 3, &errstr); if (errstr) usage(0); #else opt_scroll = strtol(optarg, 0, 10); #endif break; case 'v': usage(1); break; case 'w': opt_wavelan = 1; break; case 'h': /* FALLTHROUGH */ default: usage(0); /* NOTREACHED */ } } /* * get interface */ if (opt_interface == NULL) { /* scan for interface */ opt_interface = get_first_wnic(); if (opt_interface == NULL) { fprintf(stderr, "No wireless interface found\n"); exit(1); } } else { /* check defined interface */ if (!check_nic(opt_interface)) { fprintf(stderr, "%s: no such interface\n", opt_interface); exit(1); } else { if (get_wep(opt_interface) == -1) { fprintf(stderr, "%s: not a wireless ", opt_interface); fprintf(stderr, "interface\n"); exit(1); } } } /* is the interface wi? */ if ((strncmp(opt_interface, "wi", 2) == 0) && isdigit(opt_interface[2])) opt_wavelan = 1; /* * install signal handler */ signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGCHLD, signal_handler); signal(SIGHUP, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGALRM, signal_handler); signal(SIGPIPE, signal_handler); /* * run in debug mode */ if (opt_debug) debugloop(opt_interface); /* does not return */ /* * init X window */ initXwindow(opt_display); /* * open X window */ openXwindow(argc, argv, wmwlmon_master, wmwlmon_mask_bits, wmwlmon_mask_width, wmwlmon_mask_height); /* * main loop */ for (i = 100; !quit; i++) { /* * get wirless network state and draw it */ if (i == 100) { /* reset all */ i = 0; copyXPMArea(65, 0, 64, 64, 0, 0); /* check if interface still exists */ nic_status = check_nic(opt_interface); if (!nic_status) continue; /* interface name */ draw_string(opt_interface, 6, 7); /* network status */ status = get_status(opt_interface); if (!strcmp(status, "active")) copyXPMArea(0, 67, 4, 4, 53, 8); /* network id */ nwid = get_nwid(opt_interface); /* speed */ speed = get_speed(opt_interface); if (speed != NULL) { copyXPMArea(28, 67, 23, 8, 29, 36); if (strlen(speed) == 1) draw_string(speed, 18, 36); if (strlen(speed) == 2) draw_string(speed, 12, 36); if (strlen(speed) == 3) draw_string(speed, 6, 36); } /* signal strength */ if (opt_wavelan) r = get_wi_signal(opt_interface); else r = get_signal(opt_interface, nwid); if (r > 0) { copyXPMArea(15, 67, 10, 6, 30, 29); snprintf(sig, sizeof(sig), "%d", r); if (strlen(sig) == 1) draw_string(sig, 18, 29); if (strlen(sig) == 2) draw_string(sig, 12, 29); if (strlen(sig) == 3) draw_string(sig, 6, 29); if (speed != NULL) draw_signal(atoi(speed), r); } /* channel */ r = get_channel(opt_interface); if (r > 0) { copyXPMArea(61, 67, 10, 6, 30, 44); snprintf(chn, sizeof(sig), "%d", r); if (strlen(chn) == 1) draw_string(chn, 18, 44); if (strlen(chn) == 2) draw_string(chn, 12, 44); if (strlen(chn) == 3) draw_string(chn, 6, 44); } /* wep */ r = get_wep(opt_interface); if (r > 0) copyXPMArea(54, 67, 4, 6, 48, 44); } if (nwid != NULL && i % 2 == 0 && nic_status) { /* reset nwid area */ copyXPMArea(70, 50, 54, 9, 5, 50); draw_nwid(nwid, opt_scroll); } /* * process pending X events */ while (XPending(display)) { XNextEvent(display, &event); switch(event.type) { case Expose: RedrawWindow(); break; } } /* * redraw */ RedrawWindow(); usleep(DELAY); } exit(0); } void debugloop(char *interface) { char *status, *nwid, *speed; int r; /* * debug loop */ while (!quit) { /* check if interface still exists */ if (!check_nic(interface)) { printf("NIC gone!\n"); sleep(2); continue; } /* interface name */ printf("NIC:\t %s\n", interface); /* network status */ status = get_status(interface); if (status != NULL) printf("Status:\t %s\n", status); /* network id */ nwid = get_nwid(interface); if (nwid != NULL) printf("NwID:\t %s\n", nwid); /* speed */ speed = get_speed(interface); if (speed != NULL) printf("Speed:\t %s Mbps\n", speed); /* signal strength */ r = get_signal(interface, nwid); if (r > 0) printf("Signal:\t %d dB\n", r); /* channel */ r = get_channel(interface); if (r > 0) printf("Channel: %d\n", r); /* wep */ r = get_wep(interface); if (r > 0) printf("WEP:\t enabled\n"); else printf("WEP:\t disabled\n"); printf("\n"); sleep(2); } exit(0); } void draw_nwid(char *nwid, int scroll) { static int offset = 0; static char *save_nwid; char network_id_cut[NWIDLENC + 1]; if (strlen(nwid) > NWIDLENC) { if (save_nwid == NULL || strcmp(nwid, save_nwid)) { free(save_nwid); if ((save_nwid = strdup(nwid)) == NULL) err(1, NULL); offset = 0; } switch (scroll) { case 0: /* off */ strlcpy(network_id_cut, nwid, sizeof(network_id_cut)); draw_string(network_id_cut, 6, 51); break; case 1: /* lcd */ offset = scroll_lcd(0, 124, 6, 51, offset, nwid); break; case 2: /* bounce */ offset = scroll_bounce(0, 124, 6, 51, offset, nwid); break; case 3: /* fade */ offset = scroll_fade(0, 124, 6, 51, offset, nwid); break; } } else draw_string(nwid, 6, 51); } /* * draw string */ void draw_string(const char *string, const int x, const int y) { int c, i, offset; for (i = 0, offset = x; string[i] != '\0'; i++) { c = string[i]; copyXPMArea(fonts[c].x, fonts[c].y, fonts[c].w, fonts[c].h, offset, y); offset += fonts[c].w; } } /* * calculate the signal strength in percents and draw it */ void draw_signal(const int speed, const int signal) { int i, bars, loop, offset; float have, need; bars = 26; need = speed / 1.10; have = (signal * bars) / need; if (have >= bars) loop = bars; else loop = floor(have); for (i = 0, offset = 6; i < loop; i++, offset += 2) copyXPMArea(10, 67, 1, 6, offset, 21); } /* * scroll_lcd() * scrolls a string from left to right separated by a space * Return: * offset = success */ int scroll_lcd(const int src_x, const int src_y, const int dst_x, const int dst_y, const int offset, const char *nwid) { int len, pos, frame; /* copy offset */ pos = offset; /* draw network id */ if (pos == src_x) { copyXPMArea(0, 132, 160, 8, src_x, src_y); draw_string(nwid, src_x, src_y); } /* calculate image length */ len = (strlen(nwid) + 1) * 6; /* reached end of source, reset */ if (pos == len) pos = src_x; /* copy scroll frame to destination */ frame = len - pos; if (frame >= NWIDLENP) copyXPMArea(pos, src_y, NWIDLENP, 8, dst_x, dst_y); else { copyXPMArea(pos, src_y, frame, 8, dst_x, dst_y); copyXPMArea(src_x, src_y, NWIDLENP - frame, 8, dst_x + frame, dst_y); } /* move to next pixel */ pos++; return (pos); } /* * scroll_bounce() * scrolls a string from left to right and bounces back from right to left * Return: * offset = success */ int scroll_bounce(const int src_x, const int src_y, const int dst_x, const int dst_y, const int offset, const char *nwid) { int len, pos, frame; static int delay = 0, direction = 0; /* copy offset */ pos = offset; /* draw network id */ if (pos == src_x) { copyXPMArea(0, 132, 160, 8, src_x, src_y); draw_string(nwid, src_x, src_y); } /* calculate image length */ len = strlen(nwid) * 6; /* delay */ if (delay > 0) { if (direction == 0) copyXPMArea(pos - 1, src_y, NWIDLENP, 8, dst_x, dst_y); if (direction == 1) copyXPMArea(pos + 1, src_y, NWIDLENP, 8, dst_x, dst_y); delay--; return (pos); } /* start */ if (pos == src_x) { delay = 10; direction = 0; } /* end */ frame = len - pos; if (frame == NWIDLENP) { delay = 10; direction = 1; } /* copy scroll frame to destination */ copyXPMArea(pos, src_y, NWIDLENP, 8, dst_x, dst_y); /* move to next pixel */ if (direction == 0) pos++; if (direction == 1) pos--; return (pos); } /* * scroll_fade() * scrolls a string from left to right, fading it out and begins again * Return: * offset = success */ int scroll_fade(const int src_x, const int src_y, const int dst_x, const int dst_y, const int offset, const char *nwid) { int len, pos, frame; static int delay = 0; /* copy offset */ pos = offset; /* draw network id */ if (pos == src_x) { copyXPMArea(0, 132, 160, 8, src_x, src_y); draw_string(nwid, src_x, src_y); } /* calculate image length */ len = (strlen(nwid) + 1) * 6; /* delay */ if (delay > 0) { copyXPMArea(pos - 1, src_y, NWIDLENP, 8, dst_x, dst_y); delay--; return (pos); } /* end */ if (pos == len) pos = src_x; /* start */ if (pos == src_x) delay = 10; /* copy scroll frame to destination */ frame = len - pos; if (frame >= NWIDLENP) copyXPMArea(pos, src_y, NWIDLENP, 8, dst_x, dst_y); else copyXPMArea(pos, src_y, frame, 8, dst_x, dst_y); /* move to next pixel */ pos++; return (pos); }