aboutsummaryrefslogtreecommitdiffstats
path: root/conf.c
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-02-05 19:03:25 +0000
committerJonathan McCrohan <jmccrohan@gmail.com>2012-02-05 19:03:25 +0000
commit03dfbc2efa31d3c4fd7e576111883ea488e3e179 (patch)
tree6f227b085f675e294edd98d66ccbf190e898f544 /conf.c
downloadwavemon-03dfbc2efa31d3c4fd7e576111883ea488e3e179.tar.gz
Imported Upstream version 0.6.10upstream/0.6.10
Diffstat (limited to 'conf.c')
-rw-r--r--conf.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/conf.c b/conf.c
new file mode 100644
index 0000000..0d8c396
--- /dev/null
+++ b/conf.c
@@ -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);
+}