Move config line parsing function to confline.c

This commit is contained in:
Nick Mathewson
2017-03-31 10:27:40 -04:00
parent c2947dbb86
commit b6f22524ee
4 changed files with 134 additions and 135 deletions
+131
View File
@@ -183,3 +183,134 @@ config_count_key(const config_line_t *a, const char *key)
return n;
}
/** Given a string containing part of a configuration file or similar format,
* advance past comments and whitespace and try to parse a single line. If we
* parse a line successfully, set *<b>key_out</b> to a new string holding the
* key portion and *<b>value_out</b> to a new string holding the value portion
* of the line, and return a pointer to the start of the next line. If we run
* out of data, return a pointer to the end of the string. If we encounter an
* error, return NULL and set *<b>err_out</b> (if provided) to an error
* message.
*/
const char *
parse_config_line_from_str_verbose(const char *line, char **key_out,
char **value_out,
const char **err_out)
{
/*
See torrc_format.txt for a description of the (silly) format this parses.
*/
const char *key, *val, *cp;
int continuation = 0;
tor_assert(key_out);
tor_assert(value_out);
*key_out = *value_out = NULL;
key = val = NULL;
/* Skip until the first keyword. */
while (1) {
while (TOR_ISSPACE(*line))
++line;
if (*line == '#') {
while (*line && *line != '\n')
++line;
} else {
break;
}
}
if (!*line) { /* End of string? */
*key_out = *value_out = NULL;
return line;
}
/* Skip until the next space or \ followed by newline. */
key = line;
while (*line && !TOR_ISSPACE(*line) && *line != '#' &&
! (line[0] == '\\' && line[1] == '\n'))
++line;
*key_out = tor_strndup(key, line-key);
/* Skip until the value. */
while (*line == ' ' || *line == '\t')
++line;
val = line;
/* Find the end of the line. */
if (*line == '\"') { // XXX No continuation handling is done here
if (!(line = unescape_string(line, value_out, NULL))) {
if (err_out)
*err_out = "Invalid escape sequence in quoted string";
return NULL;
}
while (*line == ' ' || *line == '\t')
++line;
if (*line == '\r' && *(++line) == '\n')
++line;
if (*line && *line != '#' && *line != '\n') {
if (err_out)
*err_out = "Excess data after quoted string";
return NULL;
}
} else {
/* Look for the end of the line. */
while (*line && *line != '\n' && (*line != '#' || continuation)) {
if (*line == '\\' && line[1] == '\n') {
continuation = 1;
line += 2;
} else if (*line == '#') {
do {
++line;
} while (*line && *line != '\n');
if (*line == '\n')
++line;
} else {
++line;
}
}
if (*line == '\n') {
cp = line++;
} else {
cp = line;
}
/* Now back cp up to be the last nonspace character */
while (cp>val && TOR_ISSPACE(*(cp-1)))
--cp;
tor_assert(cp >= val);
/* Now copy out and decode the value. */
*value_out = tor_strndup(val, cp-val);
if (continuation) {
char *v_out, *v_in;
v_out = v_in = *value_out;
while (*v_in) {
if (*v_in == '#') {
do {
++v_in;
} while (*v_in && *v_in != '\n');
if (*v_in == '\n')
++v_in;
} else if (v_in[0] == '\\' && v_in[1] == '\n') {
v_in += 2;
} else {
*v_out++ = *v_in++;
}
}
*v_out = '\0';
}
}
if (*line == '#') {
do {
++line;
} while (*line && *line != '\n');
}
while (TOR_ISSPACE(*line)) ++line;
return line;
}
+3 -1
View File
@@ -40,6 +40,8 @@ int config_lines_eq(config_line_t *a, config_line_t *b);
int config_count_key(const config_line_t *a, const char *key);
int config_get_lines(const char *string, config_line_t **result, int extended);
void config_free_lines(config_line_t *front);
const char *parse_config_line_from_str_verbose(const char *line,
char **key_out, char **value_out,
const char **err_out);
#endif
-131
View File
@@ -3045,137 +3045,6 @@ unescape_string(const char *s, char **result, size_t *size_out)
}
}
/** Given a string containing part of a configuration file or similar format,
* advance past comments and whitespace and try to parse a single line. If we
* parse a line successfully, set *<b>key_out</b> to a new string holding the
* key portion and *<b>value_out</b> to a new string holding the value portion
* of the line, and return a pointer to the start of the next line. If we run
* out of data, return a pointer to the end of the string. If we encounter an
* error, return NULL and set *<b>err_out</b> (if provided) to an error
* message.
*/
const char *
parse_config_line_from_str_verbose(const char *line, char **key_out,
char **value_out,
const char **err_out)
{
/*
See torrc_format.txt for a description of the (silly) format this parses.
*/
const char *key, *val, *cp;
int continuation = 0;
tor_assert(key_out);
tor_assert(value_out);
*key_out = *value_out = NULL;
key = val = NULL;
/* Skip until the first keyword. */
while (1) {
while (TOR_ISSPACE(*line))
++line;
if (*line == '#') {
while (*line && *line != '\n')
++line;
} else {
break;
}
}
if (!*line) { /* End of string? */
*key_out = *value_out = NULL;
return line;
}
/* Skip until the next space or \ followed by newline. */
key = line;
while (*line && !TOR_ISSPACE(*line) && *line != '#' &&
! (line[0] == '\\' && line[1] == '\n'))
++line;
*key_out = tor_strndup(key, line-key);
/* Skip until the value. */
while (*line == ' ' || *line == '\t')
++line;
val = line;
/* Find the end of the line. */
if (*line == '\"') { // XXX No continuation handling is done here
if (!(line = unescape_string(line, value_out, NULL))) {
if (err_out)
*err_out = "Invalid escape sequence in quoted string";
return NULL;
}
while (*line == ' ' || *line == '\t')
++line;
if (*line == '\r' && *(++line) == '\n')
++line;
if (*line && *line != '#' && *line != '\n') {
if (err_out)
*err_out = "Excess data after quoted string";
return NULL;
}
} else {
/* Look for the end of the line. */
while (*line && *line != '\n' && (*line != '#' || continuation)) {
if (*line == '\\' && line[1] == '\n') {
continuation = 1;
line += 2;
} else if (*line == '#') {
do {
++line;
} while (*line && *line != '\n');
if (*line == '\n')
++line;
} else {
++line;
}
}
if (*line == '\n') {
cp = line++;
} else {
cp = line;
}
/* Now back cp up to be the last nonspace character */
while (cp>val && TOR_ISSPACE(*(cp-1)))
--cp;
tor_assert(cp >= val);
/* Now copy out and decode the value. */
*value_out = tor_strndup(val, cp-val);
if (continuation) {
char *v_out, *v_in;
v_out = v_in = *value_out;
while (*v_in) {
if (*v_in == '#') {
do {
++v_in;
} while (*v_in && *v_in != '\n');
if (*v_in == '\n')
++v_in;
} else if (v_in[0] == '\\' && v_in[1] == '\n') {
v_in += 2;
} else {
*v_out++ = *v_in++;
}
}
*v_out = '\0';
}
}
if (*line == '#') {
do {
++line;
} while (*line && *line != '\n');
}
while (TOR_ISSPACE(*line)) ++line;
return line;
}
/** Expand any homedir prefix on <b>filename</b>; return a newly allocated
* string. */
char *
-3
View File
@@ -389,9 +389,6 @@ char *read_file_to_str_until_eof(int fd, size_t max_bytes_to_read,
size_t *sz_out)
ATTR_MALLOC;
const char *unescape_string(const char *s, char **result, size_t *size_out);
const char *parse_config_line_from_str_verbose(const char *line,
char **key_out, char **value_out,
const char **err_out);
char *expand_filename(const char *filename);
MOCK_DECL(struct smartlist_t *, tor_listdir, (const char *dirname));
int path_is_relative(const char *filename);