summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-10-27 02:30:28 +0000
committerNick Mathewson <nickm@torproject.org>2004-10-27 02:30:28 +0000
commita24eb4db917c2a73904d750149db54ed27cb89cb (patch)
tree0deb910abeb44e716dd772d5d55cb80497f42b3f
parent2f420070e0cd5117a3f6b0bb5360929e91be5721 (diff)
downloadtor-a24eb4db917c2a73904d750149db54ed27cb89cb.tar.gz
tor-a24eb4db917c2a73904d750149db54ed27cb89cb.zip
Re-write configuration option lookup code: use a table, not a big if( || || || ||). Deprecate unoffical abbrevs and abbrevs not on the command line.
svn:r2594
-rw-r--r--src/or/config.c259
1 files changed, 144 insertions, 115 deletions
diff --git a/src/or/config.c b/src/or/config.c
index d12b5e9dba..fa73d8d8af 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -26,6 +26,93 @@ typedef enum config_type_t {
CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
} config_type_t;
+/*DOCDOC*/
+typedef struct config_abbrev_t {
+ char *abbreviated;
+ char *full;
+} config_abbrev_t;
+
+static config_abbrev_t config_abbrevs[] = {
+ { "l", "LogLevel" },
+ { NULL, NULL },
+};
+
+typedef struct config_var_t {
+ char *name;
+ config_type_t type;
+ off_t var_offset;
+} config_var_t;
+
+#define STRUCT_OFFSET(tp, member) ((off_t) &(((tp*)0)->member))
+#define VAR(name,conftype,member) \
+ { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member) }
+#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0 }
+
+static config_var_t config_vars[] = {
+ VAR("Address", STRING, Address),
+ VAR("AllowUnverifiedNodes",CSV, AllowUnverifiedNodes),
+ VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir),
+ VAR("BandwidthRate", UINT, BandwidthRate),
+ VAR("BandwidthBurst", UINT, BandwidthBurst),
+ VAR("ClientOnly", BOOL, ClientOnly),
+ VAR("ContactInfo", STRING, ContactInfo),
+ VAR("DebugLogFile", STRING, DebugLogFile),
+ VAR("DataDirectory", STRING, DataDirectory),
+ VAR("DirPort", UINT, DirPort),
+ VAR("DirBindAddress", LINELIST, DirBindAddress),
+ VAR("DirFetchPostPeriod", UINT, DirFetchPostPeriod),
+ VAR("DirPolicy", LINELIST, DirPolicy),
+ VAR("DirServer", LINELIST, DirServers),
+ VAR("ExitNodes", STRING, ExitNodes),
+ VAR("EntryNodes", STRING, EntryNodes),
+ VAR("StrictExitNodes", BOOL, StrictExitNodes),
+ VAR("StrictEntryNodes", BOOL, StrictEntryNodes),
+ VAR("ExitPolicy", LINELIST, ExitPolicy),
+ VAR("ExcludeNodes", STRING, ExcludeNodes),
+ VAR("FascistFirewall", BOOL, FascistFirewall),
+ VAR("FirewallPorts", CSV, FirewallPorts),
+ VAR("MyFamily", STRING, MyFamily),
+ VAR("NodeFamily", LINELIST, NodeFamilies),
+ VAR("Group", STRING, Group),
+ VAR("HttpProxy", STRING, HttpProxy),
+ VAR("HiddenServiceDir", LINELIST, RendConfigLines),
+ VAR("HiddenServicePort", LINELIST, RendConfigLines),
+ VAR("HiddenServiceNodes", LINELIST, RendConfigLines),
+ VAR("HiddenServiceExcludeNodes", LINELIST, RendConfigLines),
+ VAR("IgnoreVersion", BOOL, IgnoreVersion),
+ VAR("KeepalivePeriod", UINT, KeepalivePeriod),
+ VAR("LogLevel", LINELIST, LogOptions),
+ VAR("LogFile", LINELIST, LogOptions),
+ OBSOLETE("LinkPadding"),
+ VAR("MaxConn", UINT, MaxConn),
+ VAR("MaxOnionsPending", UINT, MaxOnionsPending),
+ VAR("Nickname", STRING, Nickname),
+ VAR("NewCircuitPeriod", UINT, NewCircuitPeriod),
+ VAR("NumCpus", UINT, NumCpus),
+ VAR("ORPort", UINT, ORPort),
+ VAR("ORBindAddress", LINELIST, ORBindAddress),
+ VAR("OutboundBindAddress", STRING, OutboundBindAddress),
+ VAR("PidFile", STRING, PidFile),
+ VAR("PathlenCoinWeight", DOUBLE, PathlenCoinWeight),
+ VAR("RedirectExit", LINELIST, RedirectExit),
+ OBSOLETE("RouterFile"),
+ VAR("RunAsDaemon", BOOL, RunAsDaemon),
+ VAR("RunTesting", BOOL, RunTesting),
+ VAR("RecommendedVersions", LINELIST, RecommendedVersions),
+ VAR("RendNodes", STRING, RendNodes),
+ VAR("RendExcludeNodes", STRING, RendExcludeNodes),
+ VAR("SocksPort", UINT, SocksPort),
+ VAR("SocksBindAddress", LINELIST, SocksBindAddress),
+ VAR("SocksPolicy", LINELIST, SocksPolicy),
+ VAR("SysLog", LINELIST, LogOptions),
+ OBSOLETE("TrafficShaping"),
+ VAR("User", STRING, User),
+ { NULL, NULL, NULL }
+};
+#undef VAR
+#undef OBSOLETE
+
+
/** Largest allowed config line */
#define CONFIG_LINE_T_MAXLEN 4096
@@ -37,7 +124,21 @@ static int config_assign(or_options_t *options, struct config_line_t *list);
static int parse_dir_server_line(const char *line);
static int parse_redirect_line(or_options_t *options,
struct config_line_t *line);
+static const char *expand_abbrev(const char *option);
+static config_var_t *config_find_option(const char *key);
+/** DOCDOC */
+static const char *
+expand_abbrev(const char *option)
+{
+ int i;
+ for (i=0; config_abbrevs[i].abbreviated; ++i) {
+ /* Abbreviations aren't casei. */
+ if (!strcmp(option,config_abbrevs[i].abbreviated))
+ return config_abbrevs[i].full;
+ }
+ return option;
+}
/** Helper: Read a list of configuration options from the command line. */
static struct config_line_t *
@@ -61,7 +162,7 @@ config_get_commandlines(int argc, char **argv)
while(*s == '-')
s++;
- new->key = tor_strdup(s);
+ new->key = tor_strdup(expand_abbrev(s));
new->value = tor_strdup(argv[i+1]);
log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
@@ -132,30 +233,44 @@ config_free_lines(struct config_line_t *front)
}
}
-/** Search the linked list <b>c</b> for any option whose key is <b>key</b>.
- * If such an option is found, interpret it as of type <b>type</b>, and store
- * the result in <b>arg</b>. If the option is misformatted, log a warning and
- * skip it.
- */
+static config_var_t *config_find_option(const char *key)
+{
+ int i;
+ for (i=0; config_vars[i].name; ++i) {
+ if (!strcasecmp(key, config_vars[i].name)) {
+ return &config_vars[i];
+ } else if (!strncasecmp(key, config_vars[i].name, strlen(key))) {
+ log_fn(LOG_WARN, "The abbreviation '%s' is deprecated. "
+ "Tell Nick and Roger to make it official, or just use '%s' instead",
+ key, config_vars[i].name);
+ return &config_vars[i];
+ }
+ }
+ return NULL;
+}
+
static int
-config_compare(struct config_line_t *c, const char *key,
- config_type_t type, void *arg)
+config_assign_line(or_options_t *options, struct config_line_t *c)
{
int i, ok;
+ config_var_t *var;
+ void *lvalue;
- if (strncasecmp(c->key, key, strlen(c->key)))
- return 0;
+ var = config_find_option(c->key);
+ if (!var) {
+ log_fn(LOG_WARN, "Unknown option '%s'. Failing.", c->key);
+ return -1;
+ }
- if (strcasecmp(c->key, key)) {
+ /* Put keyword into canonical case. */
+ if (strcmp(var->name, c->key)) {
tor_free(c->key);
- c->key = tor_strdup(key);
+ c->key = tor_strdup(var->name);
}
- /* it's a match. cast and assign. */
- log_fn(LOG_DEBUG, "Recognized keyword '%s' as %s, using value '%s'.",
- c->key, key, c->value);
+ lvalue = ((void*)options) + var->var_offset;
+ switch(var->type) {
- switch(type) {
case CONFIG_TYPE_UINT:
i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
if (!ok) {
@@ -163,7 +278,7 @@ config_compare(struct config_line_t *c, const char *key,
c->key,c->value);
return 0;
}
- *(int *)arg = i;
+ *(int *)lvalue = i;
break;
case CONFIG_TYPE_BOOL:
@@ -172,23 +287,23 @@ config_compare(struct config_line_t *c, const char *key,
log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1. Skipping.", c->key);
return 0;
}
- *(int *)arg = i;
+ *(int *)lvalue = i;
break;
case CONFIG_TYPE_STRING:
- tor_free(*(char **)arg);
- *(char **)arg = tor_strdup(c->value);
+ tor_free(*(char **)lvalue);
+ *(char **)lvalue = tor_strdup(c->value);
break;
case CONFIG_TYPE_DOUBLE:
- *(double *)arg = atof(c->value);
+ *(double *)lvalue = atof(c->value);
break;
case CONFIG_TYPE_CSV:
- if (*(smartlist_t**)arg == NULL)
- *(smartlist_t**)arg = smartlist_create();
+ if (*(smartlist_t**)lvalue == NULL)
+ *(smartlist_t**)lvalue = smartlist_create();
- smartlist_split_string(*(smartlist_t**)arg, c->value, ",",
+ smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
break;
@@ -196,8 +311,8 @@ config_compare(struct config_line_t *c, const char *key,
/* Note: this reverses the order that the lines appear in. That's
* just fine, since we build up the list of lines reversed in the
* first place. */
- *(struct config_line_t**)arg =
- config_line_prepend(*(struct config_line_t**)arg, c->key, c->value);
+ *(struct config_line_t**)lvalue =
+ config_line_prepend(*(struct config_line_t**)lvalue, c->key, c->value);
break;
case CONFIG_TYPE_OBSOLETE:
@@ -205,7 +320,7 @@ config_compare(struct config_line_t *c, const char *key,
break;
}
- return 1;
+ return 0;
}
/** Iterate through the linked list of options <b>list</b>.
@@ -216,94 +331,8 @@ static int
config_assign(or_options_t *options, struct config_line_t *list)
{
while (list) {
- if (
-
- /* order matters here! abbreviated arguments use the first match. */
-
- /* string options */
- config_compare(list, "Address", CONFIG_TYPE_STRING, &options->Address) ||
- config_compare(list, "AllowUnverifiedNodes", CONFIG_TYPE_CSV, &options->AllowUnverifiedNodes) ||
- config_compare(list, "AuthoritativeDirectory",CONFIG_TYPE_BOOL, &options->AuthoritativeDir) ||
-
- config_compare(list, "BandwidthRate", CONFIG_TYPE_UINT, &options->BandwidthRate) ||
- config_compare(list, "BandwidthBurst", CONFIG_TYPE_UINT, &options->BandwidthBurst) ||
-
- config_compare(list, "ClientOnly", CONFIG_TYPE_BOOL, &options->ClientOnly) ||
- config_compare(list, "ContactInfo", CONFIG_TYPE_STRING, &options->ContactInfo) ||
-
- config_compare(list, "DebugLogFile", CONFIG_TYPE_STRING, &options->DebugLogFile) ||
- config_compare(list, "DataDirectory", CONFIG_TYPE_STRING, &options->DataDirectory) ||
- config_compare(list, "DirPort", CONFIG_TYPE_UINT, &options->DirPort) ||
- config_compare(list, "DirBindAddress", CONFIG_TYPE_LINELIST, &options->DirBindAddress) ||
- config_compare(list, "DirFetchPostPeriod",CONFIG_TYPE_UINT, &options->DirFetchPostPeriod) ||
- config_compare(list, "DirPolicy", CONFIG_TYPE_LINELIST, &options->DirPolicy) ||
- config_compare(list, "DirServer", CONFIG_TYPE_LINELIST, &options->DirServers) ||
-
- config_compare(list, "ExitNodes", CONFIG_TYPE_STRING, &options->ExitNodes) ||
- config_compare(list, "EntryNodes", CONFIG_TYPE_STRING, &options->EntryNodes) ||
- config_compare(list, "StrictExitNodes", CONFIG_TYPE_BOOL, &options->StrictExitNodes) ||
- config_compare(list, "StrictEntryNodes", CONFIG_TYPE_BOOL, &options->StrictEntryNodes) ||
- config_compare(list, "ExitPolicy", CONFIG_TYPE_LINELIST, &options->ExitPolicy) ||
- config_compare(list, "ExcludeNodes", CONFIG_TYPE_STRING, &options->ExcludeNodes) ||
-
- config_compare(list, "FascistFirewall",CONFIG_TYPE_BOOL, &options->FascistFirewall) ||
- config_compare(list, "FirewallPorts",CONFIG_TYPE_CSV, &options->FirewallPorts) ||
- config_compare(list, "MyFamily", CONFIG_TYPE_STRING, &options->MyFamily) ||
- config_compare(list, "NodeFamily", CONFIG_TYPE_LINELIST, &options->NodeFamilies) ||
-
- config_compare(list, "Group", CONFIG_TYPE_STRING, &options->Group) ||
-
- config_compare(list, "HttpProxy", CONFIG_TYPE_STRING, &options->HttpProxy) ||
- config_compare(list, "HiddenServiceDir", CONFIG_TYPE_LINELIST, &options->RendConfigLines)||
- config_compare(list, "HiddenServicePort", CONFIG_TYPE_LINELIST, &options->RendConfigLines)||
- config_compare(list, "HiddenServiceNodes", CONFIG_TYPE_LINELIST, &options->RendConfigLines)||
- config_compare(list, "HiddenServiceExcludeNodes", CONFIG_TYPE_LINELIST, &options->RendConfigLines)||
-
- config_compare(list, "IgnoreVersion", CONFIG_TYPE_BOOL, &options->IgnoreVersion) ||
-
- config_compare(list, "KeepalivePeriod",CONFIG_TYPE_UINT, &options->KeepalivePeriod) ||
-
- config_compare(list, "LogLevel", CONFIG_TYPE_LINELIST, &options->LogOptions) ||
- config_compare(list, "LogFile", CONFIG_TYPE_LINELIST, &options->LogOptions) ||
- config_compare(list, "LinkPadding", CONFIG_TYPE_OBSOLETE, NULL) ||
-
- config_compare(list, "MaxConn", CONFIG_TYPE_UINT, &options->MaxConn) ||
- config_compare(list, "MaxOnionsPending",CONFIG_TYPE_UINT, &options->MaxOnionsPending) ||
-
- config_compare(list, "Nickname", CONFIG_TYPE_STRING, &options->Nickname) ||
- config_compare(list, "NewCircuitPeriod",CONFIG_TYPE_UINT, &options->NewCircuitPeriod) ||
- config_compare(list, "NumCpus", CONFIG_TYPE_UINT, &options->NumCpus) ||
-
- config_compare(list, "ORPort", CONFIG_TYPE_UINT, &options->ORPort) ||
- config_compare(list, "ORBindAddress", CONFIG_TYPE_LINELIST, &options->ORBindAddress) ||
- config_compare(list, "OutboundBindAddress",CONFIG_TYPE_STRING, &options->OutboundBindAddress) ||
-
- config_compare(list, "PidFile", CONFIG_TYPE_STRING, &options->PidFile) ||
- config_compare(list, "PathlenCoinWeight",CONFIG_TYPE_DOUBLE, &options->PathlenCoinWeight) ||
-
- config_compare(list, "RedirectExit", CONFIG_TYPE_LINELIST, &options->RedirectExit) ||
- config_compare(list, "RouterFile", CONFIG_TYPE_OBSOLETE, NULL) ||
- config_compare(list, "RunAsDaemon", CONFIG_TYPE_BOOL, &options->RunAsDaemon) ||
- config_compare(list, "RunTesting", CONFIG_TYPE_BOOL, &options->RunTesting) ||
- config_compare(list, "RecommendedVersions",CONFIG_TYPE_LINELIST, &options->RecommendedVersions) ||
- config_compare(list, "RendNodes", CONFIG_TYPE_STRING, &options->RendNodes) ||
- config_compare(list, "RendExcludeNodes",CONFIG_TYPE_STRING, &options->RendExcludeNodes) ||
-
- config_compare(list, "SocksPort", CONFIG_TYPE_UINT, &options->SocksPort) ||
- config_compare(list, "SocksBindAddress",CONFIG_TYPE_LINELIST,&options->SocksBindAddress) ||
- config_compare(list, "SocksPolicy", CONFIG_TYPE_LINELIST,&options->SocksPolicy) ||
- config_compare(list, "SysLog", CONFIG_TYPE_LINELIST,&options->LogOptions) ||
- config_compare(list, "TrafficShaping", CONFIG_TYPE_OBSOLETE, NULL) ||
-
- config_compare(list, "User", CONFIG_TYPE_STRING, &options->User)
-
- ) {
- /* then we're ok. it matched something. */
- } else {
- log_fn(LOG_WARN,"Unknown keyword '%s'. Failing.",list->key);
+ if (config_assign_line(options, list))
return -1;
- }
-
list = list->next;
}
@@ -534,7 +563,7 @@ static char *get_windows_conf_root(void)
if (is_set)
return path;
-
+
/* Find X:\documents and settings\username\applicatation data\ .
* We would use SHGetSpecialFolder path, but that wasn't added until IE4.
*/