diff options
author | Jonathan McCrohan <jmccrohan@gmail.com> | 2012-02-05 19:03:25 +0000 |
---|---|---|
committer | Jonathan McCrohan <jmccrohan@gmail.com> | 2012-02-05 19:03:25 +0000 |
commit | 03dfbc2efa31d3c4fd7e576111883ea488e3e179 (patch) | |
tree | 6f227b085f675e294edd98d66ccbf190e898f544 /conf.c | |
download | wavemon-6d314215d33f4a69a984b853156c2191c7f171f2.tar.gz |
Imported Upstream version 0.6.10upstream/0.6.10
Diffstat (limited to '')
-rw-r--r-- | conf.c | 545 |
1 files changed, 545 insertions, 0 deletions
@@ -0,0 +1,545 @@ +/* + * wavemon - a wireless network monitoring aplication + * + * Copyright (c) 2001-2002 Jan Morgenstern <jan@jm-music.de> + * + * wavemon is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2, or (at your option) any later + * version. + * + * wavemon is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with wavemon; see the file COPYING. If not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include "wavemon.h" +#include <pwd.h> +#include <sys/types.h> + +/* GLOBALS */ +struct wavemon_conf conf; +int conf_items; /* index into array storing menu items */ +static int if_list; /* index into array of WiFi interface names */ + +static void version(void) +{ + printf("wavemon wireless monitor %s\n", PACKAGE_VERSION); + printf("Distributed under the terms of the GPLv3.\n"); +} + +static void usage(void) +{ + printf("Usage: wavemon [ -dhlrv ] [ -i ifname ]\n\n"); + printf(" -d Dump the current device status to stdout and exit\n"); + printf(" -h This help screen\n"); + printf(" -i <ifname> Use specified network interface (default: auto)\n"); + printf(" -r Generate random levels (for testing purposes)\n"); + printf(" -v Print version number and exit\n\n"); +} + +static void getargs(int argc, char *argv[]) +{ + int arg, tmp; + + while ((arg = getopt(argc, argv, "dhi:rv")) >= 0) + switch (arg) { + case 'd': + dump_parameters(); + exit(EXIT_SUCCESS); + case 'h': + usage(); + exit(EXIT_SUCCESS); + case 'i': + if ((tmp = ll_scan(if_list, "S", optarg)) >= 0) { + strncpy(conf.ifname, ll_get(if_list, tmp), + sizeof(conf.ifname)); + break; + } + err_quit("no wireless extensions found on '%s'", optarg); + case 'r': + conf.random = true; + break; + case 'v': + version(); + exit(EXIT_SUCCESS); + default: + /* bad argument. bad bad */ + exit(EXIT_FAILURE); + } +} + +/* Return full path of rcfile. Allocates string which must bee free()-d. */ +static char *get_confname(void) +{ + char *full_path, *homedir = getenv("HOME"); + struct passwd *pw; + + if (homedir == NULL) { + pw = getpwuid(getuid()); + if (pw == NULL) + err_quit("can not determine $HOME"); + homedir = pw->pw_dir; + } + full_path = malloc(strlen(homedir) + strlen(CFNAME) + 3); + sprintf(full_path, "%s/%s", homedir, CFNAME); + + return full_path; +} + +static void read_cf(void) +{ + char tmp[0x100], lv[0x20], rv[0x20]; + struct conf_item *ci = NULL; + FILE *fd; + size_t len; + int lnum, found, v_int; + char *lp, *conv_err; + char *cfname = get_confname(); + + if (access(cfname, F_OK) != 0) + goto done; + + fd = fopen(cfname, "r"); + if (fd == NULL) + err_sys("can not read configuration file '%s'", cfname); + + for (lnum = 1; fgets(tmp, sizeof(tmp), fd); lnum++) { + + lp = tmp + strspn(tmp, " "); + if (*lp == '#' || *lp == '\n') + continue; + + len = strcspn(lp, " ="); + if (len > sizeof(lv)) + err_quit("parse error in %s, line %d: identifier too long", + cfname, lnum); + strncpy(lv, lp, len); + lv[len] = '\0'; + lp += len; + + ll_reset(conf_items); + for (found = 0; !found && (ci = ll_getall(conf_items)); ) + found = (ci->type != t_sep && ci->type != t_func && + strcasecmp(ci->cfname, lv) == 0); + if (!found) { + err_msg("%s, line %d: ignoring unknown identifier '%s'", + cfname, lnum, lv); + continue; + } + + lp += strspn(lp, " "); + if (*lp++ != '=') + err_quit("parse error in %s, line %d: missing '=' operator in assignment", + cfname, lnum); + lp += strspn(lp, " "); + + len = strcspn(lp, " \n"); + if (len > sizeof(rv)) + err_quit("parse error in %s, line %d: argument too long", cfname, lnum); + else if (*lp == '\n') + err_quit("parse error in %s, line %d: argument expected", cfname, lnum); + strncpy(rv, lp, len); + rv[len] = '\0'; + + switch (ci->type) { + case t_int: + v_int = strtol(rv, &conv_err, 10); + if (*conv_err != '\0') { + err_quit("parse error in %s, line %d: integer value expected, '%s' found instead", + cfname, lnum, rv); + } else if (v_int > ci->max) { + err_quit("parse error in %s, line %d: value exceeds maximum of %d", + cfname, lnum, (int)ci->max); + } else if (v_int < ci->min) { + err_quit("parse error in %s, line %d: value is below minimum of %d", + cfname, lnum, (int)ci->min); + } else { + *ci->v.i = v_int; + } + break; + case t_string: + if (strlen(rv) > ci->max) + err_quit("parse error in %s, line %d: argument too long (max %d chars)", + cfname, lnum, ci->max); + strncpy(ci->v.s, rv, LISTVAL_MAX); + break; + case t_switch: + if (!strcasecmp(rv, "on") || !strcasecmp(rv, "yes") || + !strcasecmp(rv, "enabled") || !strcasecmp(rv, "1")) { + *(ci->v.b) = 1; + } else if (!strcasecmp(rv, "off") || !strcasecmp(rv, "no") || + !strcasecmp(rv, "disabled") || !strcasecmp(rv, "0")) { + *(ci->v.b) = 0; + } else { + err_quit("parse error in %s, line %d: boolean expected, '%s' found instead", + cfname, lnum, rv); + } + break; + case t_list: + v_int = ll_scan(ci->list, "S", rv); + if (v_int < 0) + err_quit("parse error in %s, line %d: '%s' is not a valid argument here", + cfname, lnum, rv); + *ci->v.b = v_int; + break; + case t_listval: + v_int = ll_scan(ci->list, "S", rv); + if (v_int < 0) + err_quit("parse error in %s, line %d: '%s' is not a valid argument here", + cfname, lnum, rv); + strncpy(ci->v.s, ll_get(ci->list, v_int), LISTVAL_MAX); + break; + case t_sep: /* These two cases are missing from the enum, they are not handled */ + case t_func: /* To pacify gcc -Wall, fall through here */ + break; + } + } + fclose(fd); +done: + free(cfname); +} + +static void write_cf(void) +{ + char tmp[0x100], rv[0x40]; + struct conf_item *ci = NULL; + char *lp, *cp; + int add, i; + FILE *fd; + char *cfname = get_confname(); + int cfld = ll_create(); + + if (access(cfname, F_OK) == 0) { + fd = fopen(cfname, "r"); + if (fd == NULL) + err_sys("can not read configuration file '%s'", cfname); + while (fgets(tmp, sizeof(tmp), fd)) + ll_push(cfld, "s", tmp); + fclose(fd); + } + + for (ll_reset(conf_items); (ci = ll_getall(conf_items)); ) { + if (ci->type != t_sep && ci->type != t_func && + (!ci->dep || (ci->dep && *ci->dep))) { + switch (ci->type) { + case t_int: + sprintf(rv, "%d", *ci->v.i); + break; + case t_string: /* fall through */ + case t_listval: + strcpy(rv, ci->v.s); + break; + case t_switch: + sprintf(rv, "%s", *ci->v.b ? "on" : "off"); + break; + case t_list: + sprintf(rv, "%s", (char *)ll_get(ci->list, *ci->v.b)); + str_tolower(rv); + break; + /* Fall through, the rest are dummy statements to pacify gcc -Wall */ + case t_sep: + case t_func: + break; + } + + add = 1; + + for (i = 0; i < ll_size(cfld); i++) { + lp = ll_get(cfld, i); + cp = lp += strspn(lp, " "); + if (!strncasecmp(cp, ci->cfname, strcspn(cp, " =")) + && strlen(ci->cfname) == strcspn(cp, " =")) { + add = 0; + cp += strcspn(cp, "=") + 1; + cp += strspn(cp, " "); + strncpy(tmp, cp, strcspn(cp, " #\n")); + if (strcasecmp(tmp, rv)) { + strncpy(tmp, lp, strcspn(lp, " =")); + tmp[strcspn(lp, " =")] = '\0'; + strcat(tmp, " = "); + strcat(tmp, rv); + strcat(tmp, "\n"); + ll_replace(cfld, i, "s", tmp); + } + } + } + + if (add) { + strcpy(tmp, ci->cfname); + strcat(tmp, " = "); + strcat(tmp, rv); + strcat(tmp, "\n"); + ll_push(cfld, "s", tmp); + } + } + } + + fd = fopen(cfname, "w"); + if (fd == NULL) + err_sys("can not write to configuration file '%s'", cfname); + + for (ll_reset(cfld); (lp = ll_getall(cfld)); ) + fputs(lp, fd); + fclose(fd); + + ll_destroy(cfld); + free(cfname); +} + +static void init_conf_items(void) +{ + struct conf_item *item; + + conf_items = ll_create(); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Interface"); + item->type = t_sep; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Interface"); + item->cfname = strdup("interface"); + item->type = t_listval; + item->v.s = conf.ifname; + item->max = 10; + item->list = if_list; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Statistics updates"); + item->cfname = strdup("stat_updates"); + item->type = t_int; + item->v.i = &conf.stat_iv; + item->min = 10; + item->max = 4000; + item->inc = 10; + item->unit = strdup("ms"); + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Histogram update cycles"); + item->cfname = strdup("lhist_slot_size"); + item->type = t_int; + item->v.i = &conf.slotsize; + item->min = 1; + item->max = 64; + item->inc = 1; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Level meter smoothness"); + item->cfname = strdup("meter_smoothness"); + item->type = t_int; + item->v.i = &conf.meter_decay; + item->min = 0; + item->max = 99; + item->inc = 1; + item->unit = strdup("%"); + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Dynamic info updates"); + item->cfname = strdup("info_updates"); + item->type = t_int; + item->v.i = &conf.info_iv; + item->min = 1; + item->max = 60; + item->inc = 1; + item->unit = strdup("s"); + ll_push(conf_items, "*", item); + + /* level scale items */ + item = calloc(1, sizeof(*item)); + item->type = t_sep; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Level scales"); + item->type = t_sep; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Override scale autodetect"); + item->cfname = strdup("override_auto_scale"); + item->type = t_switch; + item->v.b = &conf.override_bounds; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Minimum signal level"); + item->cfname = strdup("min_signal_level"); + item->type = t_int; + item->v.i = &conf.sig_min; + item->min = -128; + item->max = -60; + item->inc = 1; + item->unit = strdup("dBm"); + item->dep = &conf.override_bounds; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Maximum signal level"); + item->cfname = strdup("max_signal_level"); + item->type = t_int; + item->v.i = &conf.sig_max; + item->min = -59; + item->max = 120; + item->inc = 1; + item->unit = strdup("dBm"); + item->dep = &conf.override_bounds; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Minimum noise level"); + item->cfname = strdup("min_noise_level"); + item->type = t_int; + item->v.i = &conf.noise_min; + item->min = -128; + item->max = -60; + item->inc = 1; + item->unit = strdup("dBm"); + item->dep = &conf.override_bounds; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Maximum noise level"); + item->cfname = strdup("max_noise_level"); + item->type = t_int; + item->v.i = &conf.noise_max; + item->min = -60; + item->max = 120; + item->inc = 1; + item->unit = strdup("dBm"); + item->dep = &conf.override_bounds; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Random signals"); + item->cfname = strdup("random"); + item->type = t_switch; + item->v.b = &conf.random; + ll_push(conf_items, "*", item); + + /* thresholds */ + item = calloc(1, sizeof(*item)); + item->name = strdup("Low threshold action"); + item->cfname = strdup("lo_threshold_action"); + item->type = t_list; + item->v.b = &conf.lthreshold_action; + item->list = ll_create(); + ll_push(item->list, "s", "Disabled"); + ll_push(item->list, "s", "Beep"); + ll_push(item->list, "s", "Flash"); + ll_push(item->list, "s", "Beep+Flash"); + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Low threshold"); + item->cfname = strdup("lo_threshold"); + item->type = t_int; + item->v.i = &conf.lthreshold; + item->min = -120; + item->max = -60; + item->inc = 1; + item->unit = strdup("dBm"); + item->dep = &conf.lthreshold_action; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("High threshold action"); + item->cfname = strdup("hi_threshold_action"); + item->type = t_list; + item->v.b = &conf.hthreshold_action; + item->list = ll_create(); + ll_push(item->list, "s", "Disabled"); + ll_push(item->list, "s", "Beep"); + ll_push(item->list, "s", "Flash"); + ll_push(item->list, "s", "Beep+Flash"); + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("High threshold"); + item->cfname = strdup("hi_threshold"); + item->type = t_int; + item->v.i = &conf.hthreshold; + item->min = -59; + item->max = 120; + item->inc = 1; + item->unit = strdup("dBm"); + item->dep = &conf.hthreshold_action; + ll_push(conf_items, "*", item); + + /* start-up items */ + item = calloc(1, sizeof(*item)); + item->type = t_sep; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Startup"); + item->type = t_sep; + ll_push(conf_items, "*", item); + + item = calloc(1, sizeof(*item)); + item->name = strdup("Startup screen"); + item->cfname = strdup("startup_screen"); + item->type = t_list; + item->v.b = &conf.startup_scr; + item->list = ll_create(); + ll_push(item->list, "s", "Info"); + ll_push(item->list, "s", "Histogram"); + ll_push(item->list, "s", "Access points"); + ll_push(conf_items, "*", item); + + /* separator (dummy entry) */ + item = calloc(1, sizeof(*item)); + item->type = t_sep; + ll_push(conf_items, "*", item); + + /* functions */ + item = calloc(1, sizeof(*item)); + item->name = strdup("Save configuration"); + item->type = t_func; + item->v.fp = write_cf; + ll_push(conf_items, "*", item); +} + +static void set_defaults(void) +{ + strncpy(conf.ifname, ll_get(if_list, 0), sizeof(conf.ifname)); + + conf.stat_iv = 100; + conf.info_iv = 10; + conf.slotsize = 4; + conf.meter_decay = 0; + + conf.override_bounds = false; + conf.random = false; + + conf.sig_min = -102; + conf.sig_max = 10; + conf.noise_min = -102; + conf.noise_max = 10; + + + conf.lthreshold_action = TA_DISABLED; + conf.lthreshold = -80; + conf.hthreshold_action = TA_DISABLED; + conf.hthreshold = -10; + + conf.startup_scr = 0; +} + +void getconf(int argc, char *argv[]) +{ + if_list = iw_get_interface_list(); + set_defaults(); + init_conf_items(); + read_cf(); + getargs(argc, argv); +} |