mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
Add the ability to append and clear linelist options from cmdline
This will be important for getting stuff to work right across zones.
This commit is contained in:
parent
9ce5801e22
commit
73436a1d6f
@ -7,6 +7,12 @@
|
|||||||
the user to override list options (like exit policies and
|
the user to override list options (like exit policies and
|
||||||
ports to listen on) from the command line, rather than simply
|
ports to listen on) from the command line, rather than simply
|
||||||
appending to the list.
|
appending to the list.
|
||||||
|
- You can get the old (appending) command-line behavior for "list"
|
||||||
|
"list" options, by prefixing the option name with a "+".
|
||||||
|
- You can remove all the values for a "list" option from the command
|
||||||
|
line without adding any new ones by prefixing the option name
|
||||||
|
with a "/".
|
||||||
|
|
||||||
|
|
||||||
o Minor bugfixes:
|
o Minor bugfixes:
|
||||||
- Restore behavior of overriding SocksPort, ORPort, and similar
|
- Restore behavior of overriding SocksPort, ORPort, and similar
|
||||||
|
@ -1728,6 +1728,9 @@ config_get_commandlines(int argc, char **argv, config_line_t **result)
|
|||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
while (i < argc) {
|
while (i < argc) {
|
||||||
|
unsigned command = CONFIG_LINE_NORMAL;
|
||||||
|
int want_arg = 1;
|
||||||
|
|
||||||
if (!strcmp(argv[i],"-f") ||
|
if (!strcmp(argv[i],"-f") ||
|
||||||
!strcmp(argv[i],"--hash-password")) {
|
!strcmp(argv[i],"--hash-password")) {
|
||||||
i += 2; /* command-line option with argument. ignore them. */
|
i += 2; /* command-line option with argument. ignore them. */
|
||||||
@ -1745,13 +1748,6 @@ config_get_commandlines(int argc, char **argv, config_line_t **result)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == argc-1) {
|
|
||||||
log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
|
|
||||||
argv[i]);
|
|
||||||
config_free_lines(front);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*new = tor_malloc_zero(sizeof(config_line_t));
|
*new = tor_malloc_zero(sizeof(config_line_t));
|
||||||
s = argv[i];
|
s = argv[i];
|
||||||
|
|
||||||
@ -1760,15 +1756,33 @@ config_get_commandlines(int argc, char **argv, config_line_t **result)
|
|||||||
s++;
|
s++;
|
||||||
if (*s == '-')
|
if (*s == '-')
|
||||||
s++;
|
s++;
|
||||||
|
/* Figure out the command, if any. */
|
||||||
|
if (*s == '+') {
|
||||||
|
s++;
|
||||||
|
command = CONFIG_LINE_APPEND;
|
||||||
|
} else if (*s == '/') {
|
||||||
|
s++;
|
||||||
|
command = CONFIG_LINE_CLEAR;
|
||||||
|
/* A 'clear' command has no argument. */
|
||||||
|
want_arg = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (want_arg && i == argc-1) {
|
||||||
|
log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
|
||||||
|
argv[i]);
|
||||||
|
config_free_lines(front);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
(*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
|
(*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
|
||||||
(*new)->value = tor_strdup(argv[i+1]);
|
(*new)->value = want_arg ? tor_strdup(argv[i+1]) : tor_strdup("");
|
||||||
|
(*new)->command = command;
|
||||||
(*new)->next = NULL;
|
(*new)->next = NULL;
|
||||||
log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
|
log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
|
||||||
(*new)->key, (*new)->value);
|
(*new)->key, (*new)->value);
|
||||||
|
|
||||||
new = &((*new)->next);
|
new = &((*new)->next);
|
||||||
i += 2;
|
i += want_arg ? 2 : 1;
|
||||||
}
|
}
|
||||||
*result = front;
|
*result = front;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1796,9 +1810,12 @@ config_line_append(config_line_t **lst,
|
|||||||
/** Helper: parse the config string and strdup into key/value
|
/** Helper: parse the config string and strdup into key/value
|
||||||
* strings. Set *result to the list, or NULL if parsing the string
|
* strings. Set *result to the list, or NULL if parsing the string
|
||||||
* failed. Return 0 on success, -1 on failure. Warn and ignore any
|
* failed. Return 0 on success, -1 on failure. Warn and ignore any
|
||||||
* misformatted lines. */
|
* misformatted lines.
|
||||||
|
*
|
||||||
|
* If <b>extended</b> is set, then treat keys beginning with / and with + as
|
||||||
|
* indicating "clear" and "append" respectively. */
|
||||||
int
|
int
|
||||||
config_get_lines(const char *string, config_line_t **result)
|
config_get_lines(const char *string, config_line_t **result, int extended)
|
||||||
{
|
{
|
||||||
config_line_t *list = NULL, **next;
|
config_line_t *list = NULL, **next;
|
||||||
char *k, *v;
|
char *k, *v;
|
||||||
@ -1814,6 +1831,22 @@ config_get_lines(const char *string, config_line_t **result)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (k && v) {
|
if (k && v) {
|
||||||
|
unsigned command = CONFIG_LINE_NORMAL;
|
||||||
|
if (extended) {
|
||||||
|
if (k[0] == '+') {
|
||||||
|
char *k_new = tor_strdup(k+1);
|
||||||
|
tor_free(k);
|
||||||
|
k = k_new;
|
||||||
|
command = CONFIG_LINE_APPEND;
|
||||||
|
} else if (k[0] == '/') {
|
||||||
|
char *k_new = tor_strdup(k+1);
|
||||||
|
tor_free(k);
|
||||||
|
k = k_new;
|
||||||
|
tor_free(v);
|
||||||
|
v = tor_strdup("");
|
||||||
|
command = CONFIG_LINE_CLEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* This list can get long, so we keep a pointer to the end of it
|
/* This list can get long, so we keep a pointer to the end of it
|
||||||
* rather than using config_line_append over and over and getting
|
* rather than using config_line_append over and over and getting
|
||||||
* n^2 performance. */
|
* n^2 performance. */
|
||||||
@ -1821,6 +1854,7 @@ config_get_lines(const char *string, config_line_t **result)
|
|||||||
(*next)->key = k;
|
(*next)->key = k;
|
||||||
(*next)->value = v;
|
(*next)->value = v;
|
||||||
(*next)->next = NULL;
|
(*next)->next = NULL;
|
||||||
|
(*next)->command = command;
|
||||||
next = &((*next)->next);
|
next = &((*next)->next);
|
||||||
} else {
|
} else {
|
||||||
tor_free(k);
|
tor_free(k);
|
||||||
@ -2140,8 +2174,9 @@ config_assign_line(const config_format_t *fmt, or_options_t *options,
|
|||||||
if (!strlen(c->value)) {
|
if (!strlen(c->value)) {
|
||||||
/* reset or clear it, then return */
|
/* reset or clear it, then return */
|
||||||
if (!clear_first) {
|
if (!clear_first) {
|
||||||
if (var->type == CONFIG_TYPE_LINELIST ||
|
if ((var->type == CONFIG_TYPE_LINELIST ||
|
||||||
var->type == CONFIG_TYPE_LINELIST_S) {
|
var->type == CONFIG_TYPE_LINELIST_S) &&
|
||||||
|
c->command != CONFIG_LINE_CLEAR) {
|
||||||
/* We got an empty linelist from the torrc or command line.
|
/* We got an empty linelist from the torrc or command line.
|
||||||
As a special case, call this an error. Warn and ignore. */
|
As a special case, call this an error. Warn and ignore. */
|
||||||
log_warn(LD_CONFIG,
|
log_warn(LD_CONFIG,
|
||||||
@ -2151,6 +2186,8 @@ config_assign_line(const config_format_t *fmt, or_options_t *options,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
|
||||||
|
option_reset(fmt, options, var, use_defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
|
if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
|
||||||
@ -4454,7 +4491,7 @@ options_init_from_string(const char *cf,
|
|||||||
newoptions->command_arg = command_arg;
|
newoptions->command_arg = command_arg;
|
||||||
|
|
||||||
/* get config lines, assign them */
|
/* get config lines, assign them */
|
||||||
retval = config_get_lines(cf, &cl);
|
retval = config_get_lines(cf, &cl, 1);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
err = SETOPT_ERR_PARSE;
|
err = SETOPT_ERR_PARSE;
|
||||||
goto err;
|
goto err;
|
||||||
@ -4505,7 +4542,7 @@ options_init_from_string(const char *cf,
|
|||||||
newoptions->command_arg = command_arg;
|
newoptions->command_arg = command_arg;
|
||||||
|
|
||||||
/* Assign all options a second time. */
|
/* Assign all options a second time. */
|
||||||
retval = config_get_lines(cf, &cl);
|
retval = config_get_lines(cf, &cl, 1);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
err = SETOPT_ERR_PARSE;
|
err = SETOPT_ERR_PARSE;
|
||||||
goto err;
|
goto err;
|
||||||
@ -6190,7 +6227,7 @@ or_state_load(void)
|
|||||||
if (contents) {
|
if (contents) {
|
||||||
config_line_t *lines=NULL;
|
config_line_t *lines=NULL;
|
||||||
int assign_retval;
|
int assign_retval;
|
||||||
if (config_get_lines(contents, &lines)<0)
|
if (config_get_lines(contents, &lines, 0)<0)
|
||||||
goto done;
|
goto done;
|
||||||
assign_retval = config_assign(&state_format, new_state,
|
assign_retval = config_assign(&state_format, new_state,
|
||||||
lines, 0, 0, &errmsg);
|
lines, 0, 0, &errmsg);
|
||||||
|
@ -23,7 +23,7 @@ const char *escaped_safe_str_client(const char *address);
|
|||||||
const char *escaped_safe_str(const char *address);
|
const char *escaped_safe_str(const char *address);
|
||||||
const char *get_version(void);
|
const char *get_version(void);
|
||||||
|
|
||||||
int config_get_lines(const char *string, config_line_t **result);
|
int config_get_lines(const char *string, config_line_t **result, int extended);
|
||||||
void config_free_lines(config_line_t *front);
|
void config_free_lines(config_line_t *front);
|
||||||
setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
|
setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
|
||||||
int clear_first, char **msg);
|
int clear_first, char **msg);
|
||||||
|
@ -737,7 +737,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
|
|||||||
SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp));
|
SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp));
|
||||||
smartlist_free(entries);
|
smartlist_free(entries);
|
||||||
|
|
||||||
if (config_get_lines(config, &lines) < 0) {
|
if (config_get_lines(config, &lines, 0) < 0) {
|
||||||
log_warn(LD_CONTROL,"Controller gave us config lines we can't parse.");
|
log_warn(LD_CONTROL,"Controller gave us config lines we can't parse.");
|
||||||
connection_write_str_to_buf("551 Couldn't parse configuration\r\n",
|
connection_write_str_to_buf("551 Couldn't parse configuration\r\n",
|
||||||
conn);
|
conn);
|
||||||
|
@ -232,7 +232,7 @@ dirserv_load_fingerprint_file(void)
|
|||||||
}
|
}
|
||||||
tor_free(fname);
|
tor_free(fname);
|
||||||
|
|
||||||
result = config_get_lines(cf, &front);
|
result = config_get_lines(cf, &front, 0);
|
||||||
tor_free(cf);
|
tor_free(cf);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
log_warn(LD_CONFIG, "Error reading from fingerprint file");
|
log_warn(LD_CONFIG, "Error reading from fingerprint file");
|
||||||
|
@ -2841,6 +2841,8 @@ typedef struct port_cfg_t {
|
|||||||
/** Appends to previous configuration for the same option, even if we
|
/** Appends to previous configuration for the same option, even if we
|
||||||
* would ordinary replace it. */
|
* would ordinary replace it. */
|
||||||
#define CONFIG_LINE_APPEND 1
|
#define CONFIG_LINE_APPEND 1
|
||||||
|
/* Removes all previous configuration for an option. */
|
||||||
|
#define CONFIG_LINE_CLEAR 2
|
||||||
|
|
||||||
/** A linked list of lines in a config file. */
|
/** A linked list of lines in a config file. */
|
||||||
typedef struct config_line_t {
|
typedef struct config_line_t {
|
||||||
@ -2848,7 +2850,7 @@ typedef struct config_line_t {
|
|||||||
char *value;
|
char *value;
|
||||||
struct config_line_t *next;
|
struct config_line_t *next;
|
||||||
/** What special treatment (if any) does this line require? */
|
/** What special treatment (if any) does this line require? */
|
||||||
unsigned int command:1;
|
unsigned int command:2;
|
||||||
/** If true, subsequent assignments to this linelist should replace
|
/** If true, subsequent assignments to this linelist should replace
|
||||||
* it, not extend it. Set only on the first item in a linelist in an
|
* it, not extend it. Set only on the first item in a linelist in an
|
||||||
* or_options_t. */
|
* or_options_t. */
|
||||||
|
Loading…
Reference in New Issue
Block a user