From 565d91fdf198b88f7c2d72c67cfc6c30341a3596 Mon Sep 17 00:00:00 2001 From: Michal Vyskocil 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,89 @@ 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) { + + FILE _cleanup_fclose_ *f; + char *b; + char _cleanup_free_ *c = NULL; + char _cleanup_strv_free_ **m = NULL; assert(fname); assert(rl); - if (!(f = fopen(fname, "re"))) + f = fopen(fname, "re"); + if (!f) return -errno; while (!feof(f)) { - char l[LINE_MAX], *p, *u; + char l[LINE_MAX], *p, *u, *cs; char **t; if (!fgets(l, sizeof(l), f)) { - if (feof(f)) + if (!feof(f)) + return -errno; + else if (!c) break; + } - r = -errno; - goto finish; + cs = endswith(l, "\\\n"); + if (cs) { + *cs = '\0'; + b = strappend(c, l); + if (!b) + return log_oom(); + + free(c); + c = b; + *l = '\0'; + continue; } - p = strstrip(l); + if (c) { + b = strappend(c, l); + if (!b) + return log_oom(); - if (!*p) - continue; + free(c); + c = b; + } + + p = strstrip(c ? c : l); - if (strchr(COMMENTS, *p)) + if (!*p) { + free(c); + c = NULL; continue; + } - if (!(u = normalize_env_assignment(p))) { - r = log_oom(); - goto finish; + if (strchr(COMMENTS, *p)) { + free(c); + c = NULL; + continue; } + u = normalize_env_assignment(p); + if (!u) + return log_oom(); + + free(c); + c = NULL; + t = strv_append(m, u); free(u); - if (!t) { - r = log_oom(); - goto finish; - } + if (!t) + return log_oom(); strv_free(m); m = t; } - 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) {