chiark / gitweb /
service: allow configuration of more than one Exec command in one line
[elogind.git] / src / load-fragment.c
index 591b73d01b8de8f0e8b2abbce890d2de10be9e7a..c3909e9563432830e284c81acc33ccc13307f6db 100644 (file)
@@ -41,7 +41,6 @@
 #include "unit-name.h"
 
 #define COMMENTS "#;\n"
 #include "unit-name.h"
 
 #define COMMENTS "#;\n"
-#define LINE_MAX 4096
 
 static int config_parse_deps(
                 const char *filename,
 
 static int config_parse_deps(
                 const char *filename,
@@ -62,7 +61,7 @@ static int config_parse_deps(
         assert(lvalue);
         assert(rvalue);
 
         assert(lvalue);
         assert(rvalue);
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 char *t, *k;
                 int r;
 
                 char *t, *k;
                 int r;
 
@@ -104,7 +103,7 @@ static int config_parse_names(
         assert(rvalue);
         assert(data);
 
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 char *t, *k;
                 int r;
 
                 char *t, *k;
                 int r;
 
@@ -365,73 +364,94 @@ static int config_parse_exec(
                 void *data,
                 void *userdata) {
 
                 void *data,
                 void *userdata) {
 
-        ExecCommand **e = data, *nce = NULL;
-        char **n;
-        char *w;
+        ExecCommand **e = data, *nce;
+        char *path, **n;
         unsigned k;
         unsigned k;
-        size_t l;
-        char *state, *path = NULL;
-        bool honour_argv0, write_to_path;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
+        assert(e);
 
         /* We accept an absolute path as first argument, or
          * alternatively an absolute prefixed with @ to allow
          * overriding of argv[0]. */
 
 
         /* We accept an absolute path as first argument, or
          * alternatively an absolute prefixed with @ to allow
          * overriding of argv[0]. */
 
-        honour_argv0 = rvalue[0] == '@';
+        for (;;) {
+                char *w;
+                size_t l;
+                char *state;
+                bool honour_argv0, write_to_path;
 
 
-        if (rvalue[honour_argv0 ? 1 : 0] != '/') {
-                log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
-                return -EINVAL;
-        }
+                path = NULL;
+                nce = NULL;
+                n = NULL;
 
 
-        k = 0;
-        FOREACH_WORD_QUOTED(w, l, rvalue, state)
-                k++;
+                rvalue += strspn(rvalue, WHITESPACE);
 
 
-        if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
-                return -ENOMEM;
+                if (rvalue[0] == 0)
+                        break;
 
 
-        k = 0;
-        write_to_path = honour_argv0;
-        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
-                if (write_to_path) {
-                        if (!(path = strndup(w+1, l-1)))
-                                goto fail;
-                        write_to_path = false;
-                } else {
-                        if (!(n[k++] = strndup(w, l)))
-                                goto fail;
+                honour_argv0 = rvalue[0] == '@';
+
+                if (rvalue[honour_argv0 ? 1 : 0] != '/') {
+                        log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
+                        return -EINVAL;
                 }
                 }
-        }
 
 
-        n[k] = NULL;
+                k = 0;
+                FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+                        if (strncmp(w, ";", l) == 0)
+                                break;
 
 
-        if (!n[0]) {
-                log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
-                strv_free(n);
-                return -EINVAL;
-        }
+                        k++;
+                }
 
 
-        if (!path)
-                if (!(path = strdup(n[0])))
-                        goto fail;
+                if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
+                        return -ENOMEM;
+
+                k = 0;
+                write_to_path = honour_argv0;
+                FOREACH_WORD_QUOTED(w, l, rvalue, state) {
+                        if (strncmp(w, ";", l) == 0)
+                                break;
+
+                        if (write_to_path) {
+                                if (!(path = cunescape_length(w+1, l-1)))
+                                        goto fail;
+                                write_to_path = false;
+                        } else {
+                                if (!(n[k++] = cunescape_length(w, l)))
+                                        goto fail;
+                        }
+                }
+
+                n[k] = NULL;
+
+                if (!n[0]) {
+                        log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
+                        strv_free(n);
+                        return -EINVAL;
+                }
 
 
-        assert(path_is_absolute(path));
+                if (!path)
+                        if (!(path = strdup(n[0])))
+                                goto fail;
+
+                assert(path_is_absolute(path));
+
+                if (!(nce = new0(ExecCommand, 1)))
+                        goto fail;
 
 
-        if (!(nce = new0(ExecCommand, 1)))
-                goto fail;
+                nce->argv = n;
+                nce->path = path;
 
 
-        nce->argv = n;
-        nce->path = path;
+                path_kill_slashes(nce->path);
 
 
-        path_kill_slashes(nce->path);
+                exec_command_append_list(e, nce);
 
 
-        exec_command_append_list(e, nce);
+                rvalue = state;
+        }
 
         return 0;
 
 
         return 0;
 
@@ -690,7 +710,7 @@ static int config_parse_cpu_affinity(
         assert(rvalue);
         assert(data);
 
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 char *t;
                 int r;
                 unsigned cpu;
                 char *t;
                 int r;
                 unsigned cpu;
@@ -767,7 +787,7 @@ static int config_parse_secure_bits(
         assert(rvalue);
         assert(data);
 
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 if (first_word(w, "keep-caps"))
                         c->secure_bits |= SECURE_KEEP_CAPS;
                 else if (first_word(w, "keep-caps-locked"))
                 if (first_word(w, "keep-caps"))
                         c->secure_bits |= SECURE_KEEP_CAPS;
                 else if (first_word(w, "keep-caps-locked"))
@@ -808,7 +828,7 @@ static int config_parse_bounding_set(
         assert(rvalue);
         assert(data);
 
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 char *t;
                 int r;
                 cap_value_t cap;
                 char *t;
                 int r;
                 cap_value_t cap;
@@ -903,11 +923,11 @@ static int config_parse_cgroup(
         size_t l;
         char *state;
 
         size_t l;
         char *state;
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 char *t;
                 int r;
 
                 char *t;
                 int r;
 
-                if (!(t = strndup(w, l)))
+                if (!(t = cunescape_length(w, l)))
                         return -ENOMEM;
 
                 r = unit_add_cgroup_from_text(u, t);
                         return -ENOMEM;
 
                 r = unit_add_cgroup_from_text(u, t);
@@ -968,7 +988,7 @@ static int config_parse_mount_flags(
         assert(rvalue);
         assert(data);
 
         assert(rvalue);
         assert(data);
 
-        FOREACH_WORD(w, l, rvalue, state) {
+        FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                 if (strncmp(w, "shared", l) == 0)
                         flags |= MS_SHARED;
                 else if (strncmp(w, "slave", l) == 0)
                 if (strncmp(w, "shared", l) == 0)
                         flags |= MS_SHARED;
                 else if (strncmp(w, "slave", l) == 0)