summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-02-16 09:56:29 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-02-19 15:02:13 +0100
commit9ecdba8cb75dd9c529ad3a869b25c36752fad90c (patch)
treefe1272b98a6a3cca28f8ec610c55aeccf0467a94 /src/shared
parentb48382e4e0fe5064d73b4916a06424afe0f6c511 (diff)
downloadsystemd-9ecdba8cb75dd9c529ad3a869b25c36752fad90c.tar.gz
Move config_parse_join_controllers to shared, add test
config_parse_join_controllers would free the destination argument on failure, which is contrary to our normal style, where failed parsing has no effect. Moving it to shared also allows a test to be added.
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/conf-parser.c105
-rw-r--r--src/shared/conf-parser.h1
2 files changed, 106 insertions, 0 deletions
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index daddb7cf20..5c033e0ec0 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -1021,3 +1021,108 @@ int config_parse_ip_port(
return 0;
}
+
+int config_parse_join_controllers(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ****ret = data;
+ const char *whole_rvalue = rvalue;
+ unsigned n = 0;
+ _cleanup_(strv_free_freep) char ***controllers = NULL;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(ret);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ char **l;
+ int r;
+
+ r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, whole_rvalue);
+ return r;
+ }
+ if (r == 0)
+ break;
+
+ l = strv_split(word, ",");
+ if (!l)
+ return log_oom();
+ strv_uniq(l);
+
+ if (strv_length(l) <= 1) {
+ strv_free(l);
+ continue;
+ }
+
+ if (!controllers) {
+ controllers = new(char**, 2);
+ if (!controllers) {
+ strv_free(l);
+ return log_oom();
+ }
+
+ controllers[0] = l;
+ controllers[1] = NULL;
+
+ n = 1;
+ } else {
+ char ***a;
+ char ***t;
+
+ t = new0(char**, n+2);
+ if (!t) {
+ strv_free(l);
+ return log_oom();
+ }
+
+ n = 0;
+
+ for (a = controllers; *a; a++)
+ if (strv_overlap(*a, l)) {
+ if (strv_extend_strv(&l, *a, false) < 0) {
+ strv_free(l);
+ strv_free_free(t);
+ return log_oom();
+ }
+
+ } else {
+ char **c;
+
+ c = strv_copy(*a);
+ if (!c) {
+ strv_free(l);
+ strv_free_free(t);
+ return log_oom();
+ }
+
+ t[n++] = c;
+ }
+
+ t[n++] = strv_uniq(l);
+
+ strv_free_free(controllers);
+ controllers = t;
+ }
+ }
+ if (!isempty(rvalue))
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
+
+ strv_free_free(*ret);
+ *ret = controllers;
+ controllers = NULL;
+
+ return 0;
+}
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 8cbb569696..908f530713 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -157,6 +157,7 @@ int config_parse_signal(GENERIC_PARSER_ARGS);
int config_parse_personality(GENERIC_PARSER_ARGS);
int config_parse_ifname(GENERIC_PARSER_ARGS);
int config_parse_ip_port(GENERIC_PARSER_ARGS);
+int config_parse_join_controllers(GENERIC_PARSER_ARGS);
#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
int function(GENERIC_PARSER_ARGS) { \