File parse-multiline-env-file.patch of Package systemd

From 565d91fdf198b88f7c2d72c67cfc6c30341a3596 Mon Sep 17 00:00:00 2001
From: Michal Vyskocil <mvyskocil@suse.cz>
Date: Fri, 18 Jan 2013 10:05:10 +0100
Subject: [PATCH] util: continuation support for load_env_file

Variable definitions can be written on more than one line - if each ends
with a backslash, then is concatenated with a previous one. Only
backslash and unix end of line (\n) are treated as a continuation.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=58083

[zj: squashed two patches together; cleaned up grammar; removed
     comment about ignoring trailing backslash -- it is not ignored.]

Document continuation support in systemd.exec
---
 man/systemd.exec.xml |    8 +++++---
 src/shared/util.c    |   43 ++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 43 insertions(+), 8 deletions(-)

Index: systemd-195/man/systemd.exec.xml
===================================================================
--- systemd-195.orig/man/systemd.exec.xml
+++ systemd-195/man/systemd.exec.xml
@@ -282,9 +282,11 @@
                                 contain new-line separated variable
                                 assignments. Empty lines and lines
                                 starting with ; or # will be ignored,
-                                which may be used for commenting. The
-                                parser strips leading and
-                                trailing whitespace from the values
+                                which may be used for commenting. A line
+                                ending with a backslash will be concatenated
+                                with the following one, allowing multiline variable
+                                definitions. The parser strips leading
+                                and trailing whitespace from the values
                                 of assignments, unless you use
                                 double quotes (").
                                 The
Index: systemd-195/src/shared/util.c
===================================================================
--- systemd-195.orig/src/shared/util.c
+++ systemd-195/src/shared/util.c
@@ -876,69 +876,88 @@ fail:
         return r;
 }
 
-int load_env_file(
-                const char *fname,
-                char ***rl) {
-
-        FILE *f;
-        char **m = NULL;
-        int r;
+int load_env_file(const char *fname, char ***rl) {
+
+        _cleanup_fclose_ FILE *f;
+        _cleanup_strv_free_ char **m = NULL;
+        _cleanup_free_ char *c = NULL;
 
         assert(fname);
         assert(rl);
 
-        if (!(f = fopen(fname, "re")))
+        /* This reads an environment file, but will not complain about
+         * any invalid assignments, that needs to be done by the
+         * caller */
+
+        f = fopen(fname, "re");
+        if (!f)
                 return -errno;
 
         while (!feof(f)) {
-                char l[LINE_MAX], *p, *u;
-                char **t;
+                char l[LINE_MAX], *p, *cs, *b;
 
                 if (!fgets(l, sizeof(l), f)) {
-                        if (feof(f))
-                                break;
+                        if (ferror(f))
+                                return -errno;
+
+                        /* The previous line was a continuation line?
+                         * Let's process it now, before we leave the
+                         * loop */
+                        if (c)
+                                goto process;
 
-                        r = -errno;
-                        goto finish;
+                        break;
                 }
 
-                p = strstrip(l);
+                /* Is this a continuation line? If so, just append
+                 * this to c, and go to next line right-away */
+                cs = endswith(l, "\\\n");
+                if (cs) {
+                        *cs = '\0';
+                        b = strappend(c, l);
+                        if (!b)
+                                return -ENOMEM;
 
-                if (!*p)
+                        free(c);
+                        c = b;
                         continue;
+                }
 
-                if (strchr(COMMENTS, *p))
-                        continue;
+                /* If the previous line was a continuation line,
+                 * append the current line to it */
+                if (c) {
+                        b = strappend(c, l);
+                        if (!b)
+                                return -ENOMEM;
 
-                if (!(u = normalize_env_assignment(p))) {
-                        r = log_oom();
-                        goto finish;
+                        free(c);
+                        c = b;
                 }
 
-                t = strv_append(m, u);
-                free(u);
+        process:
+                p = strstrip(c ? c : l);
 
-                if (!t) {
-                        r = log_oom();
-                        goto finish;
+                if (*p && !strchr(COMMENTS, *p)) {
+                        _cleanup_free_ char *u;
+                        int k;
+
+                        u = normalize_env_assignment(p);
+                        if (!u)
+                                return -ENOMEM;
+
+                        k = strv_extend(&m, u);
+                        if (k < 0)
+                                return -ENOMEM;
                 }
 
-                strv_free(m);
-                m = t;
+                free(c);
+                c = NULL;
         }
 
-        r = 0;
-
         *rl = m;
         m = NULL;
 
-finish:
-        if (f)
-                fclose(f);
-
-        strv_free(m);
-
-        return r;
+        return 0;
 }
 
 int write_env_file(const char *fname, char **l) {
Index: systemd-195/src/shared/strv.c
===================================================================
--- systemd-195.orig/src/shared/strv.c
+++ systemd-195/src/shared/strv.c
@@ -370,6 +370,32 @@ fail:
         return NULL;
 }
 
+int strv_extend(char ***l, const char *value) {
+        char **c;
+        char *v;
+        unsigned n;
+
+        if (!value)
+                return 0;
+
+        v = strdup(value);
+        if (!v)
+                return -ENOMEM;
+
+        n = strv_length(*l);
+        c = realloc(*l, sizeof(char*) * (n + 2));
+        if (!c) {
+                free(v);
+                return -ENOMEM;
+        }
+
+        c[n] = v;
+        c[n+1] = NULL;
+
+        *l = c;
+        return 0;
+}
+
 char **strv_uniq(char **l) {
         char **i;
 
Index: systemd-195/src/shared/strv.h
===================================================================
--- systemd-195.orig/src/shared/strv.h
+++ systemd-195/src/shared/strv.h
@@ -37,6 +37,7 @@ unsigned strv_length(char **l);
 char **strv_merge(char **a, char **b);
 char **strv_merge_concat(char **a, char **b, const char *suffix);
 char **strv_append(char **l, const char *s);
+int strv_extend(char ***l, const char *value);
 
 char **strv_remove(char **l, const char *s);
 char **strv_remove_prefix(char **l, const char *s);
openSUSE Build Service is sponsored by