84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering/***
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering This file is part of systemd.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering Copyright 2010 Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering systemd is free software; you can redistribute it and/or modify it
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering under the terms of the GNU Lesser General Public License as published by
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering (at your option) any later version.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering systemd is distributed in the hope that it will be useful, but
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering Lesser General Public License for more details.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering You should have received a copy of the GNU Lesser General Public License
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering***/
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <errno.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdarg.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdbool.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stddef.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdint.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdlib.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <string.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <syslog.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering#include "escape.h"
b11d6a7bed4d867fb9f6ff4e7eb4ab20fcdc9301Lennart Poettering#include "extract-word.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "log.h"
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include "macro.h"
b11d6a7bed4d867fb9f6ff4e7eb4ab20fcdc9301Lennart Poettering#include "string-util.h"
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering#include "utf8.h"
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringint extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering _cleanup_free_ char *s = NULL;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering size_t allocated = 0, sz = 0;
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger char c;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering int r;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering char quote = 0; /* 0 or ' or " */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering bool backslash = false; /* whether we've just seen a backslash */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering assert(p);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering assert(ret);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Bail early if called after last value or with no input */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (!*p)
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering goto finish_force_terminate;
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger c = **p;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
8372da448f3c738e0154d988538d497f7e2e1f83Filipe Brandenburger if (!separators)
8372da448f3c738e0154d988538d497f7e2e1f83Filipe Brandenburger separators = WHITESPACE;
8372da448f3c738e0154d988538d497f7e2e1f83Filipe Brandenburger
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Parses the first word of a string, and returns it in
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * *ret. Removes all quotes in the process. When parsing fails
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * (because of an uneven number of quotes or similar), leaves
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * the pointer *p at the first invalid character. */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger if (!GREEDY_REALLOC(s, allocated, sz+1))
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger return -ENOMEM;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger for (;; (*p) ++, c = **p) {
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger if (c == 0)
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger goto finish_force_terminate;
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger else if (strchr(separators, c)) {
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger (*p) ++;
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger goto finish_force_next;
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger }
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger } else {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* We found a non-blank character, so we will always
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * want to return a string (even if it is empty),
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * allocate it here. */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (!GREEDY_REALLOC(s, allocated, sz+1))
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return -ENOMEM;
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger break;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger }
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger
93de9eb76d628cf731120d97332e03600c167271Filipe Brandenburger for (;; (*p) ++, c = **p) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (backslash) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (!GREEDY_REALLOC(s, allocated, sz+7))
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return -ENOMEM;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (c == 0) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering (!quote || flags & EXTRACT_RELAX)) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* If we find an unquoted trailing backslash and we're in
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * output.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * Unbalanced quotes will only be allowed in EXTRACT_RELAX
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering s[sz++] = '\\';
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering goto finish_force_terminate;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (flags & EXTRACT_RELAX)
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering goto finish_force_terminate;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return -EINVAL;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (flags & EXTRACT_CUNESCAPE) {
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek bool eight_bit = false;
c932fb71cc90461b88ecdffe47c071d001d78fb4Shawn Landden char32_t u;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek r = cunescape_one(*p, (size_t) -1, &u, &eight_bit);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (r < 0) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (flags & EXTRACT_CUNESCAPE_RELAX) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering s[sz++] = '\\';
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering s[sz++] = c;
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger } else
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger return -EINVAL;
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger } else {
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger (*p) += r - 1;
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek if (eight_bit)
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek s[sz++] = u;
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger else
3565e09594a9cd2786b5682ad13812491e6781c1Zbigniew Jędrzejewski-Szmek sz += utf8_encode_unichar(s + sz, u);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering } else
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering s[sz++] = c;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering backslash = false;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering } else if (quote) { /* inside either single or double quotes */
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger for (;; (*p) ++, c = **p) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger if (c == 0) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger if (flags & EXTRACT_RELAX)
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger goto finish_force_terminate;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger return -EINVAL;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger } else if (c == quote) { /* found the end quote */
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger quote = 0;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger break;
c89f52ac6938374972253d8752ed65f3af0b3ef4Lennart Poettering } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger backslash = true;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger break;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger } else {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger if (!GREEDY_REALLOC(s, allocated, sz+2))
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger return -ENOMEM;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger s[sz++] = c;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering } else {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger for (;; (*p) ++, c = **p) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger if (c == 0)
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger goto finish_force_terminate;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger quote = c;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger break;
c89f52ac6938374972253d8752ed65f3af0b3ef4Lennart Poettering } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger backslash = true;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger break;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger } else if (strchr(separators, c)) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger (*p) ++;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger goto finish_force_next;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger }
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger /* Skip additional coalesced separators. */
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger for (;; (*p) ++, c = **p) {
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger if (c == 0)
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger goto finish_force_terminate;
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger if (!strchr(separators, c))
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger break;
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger }
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger goto finish;
0247447e96f1385cf0c48e3e6b696214fbe36802Filipe Brandenburger
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger } else {
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger if (!GREEDY_REALLOC(s, allocated, sz+2))
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger return -ENOMEM;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger s[sz++] = c;
27fc921b658adc5baa988c4c213888b016a60b18Filipe Brandenburger }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringfinish_force_terminate:
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *p = NULL;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringfinish:
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (!s) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *p = NULL;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *ret = NULL;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return 0;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringfinish_force_next:
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering s[sz] = 0;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *ret = s;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering s = NULL;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return 1;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering}
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringint extract_first_word_and_warn(
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char **p,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering char **ret,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char *separators,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering ExtractFlags flags,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char *unit,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char *filename,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering unsigned line,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char *rvalue) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering /* Try to unquote it, if it fails, warn about it and try again
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering * but this time using EXTRACT_CUNESCAPE_RELAX to keep the
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering * backslashes verbatim in invalid escape sequences. */
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char *save;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering int r;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering save = *p;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering r = extract_first_word(p, ret, separators, flags);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering if (r >= 0)
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering return r;
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *p = save;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering if (r >= 0) {
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering /* It worked this time, hence it must have been an invalid escape sequence we could correct. */
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering return r;
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering }
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering /* If it's still EINVAL; then it must be unbalanced quoting, report this. */
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering if (r == -EINVAL)
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering /* Can be any error, report it */
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering}
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringint extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering va_list ap;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering char **l;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering int n = 0, i, c, r;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Parses a number of words from a string, stripping any
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * quotes if necessary. */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering assert(p);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Count how many words are expected */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering va_start(ap, flags);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering for (;;) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (!va_arg(ap, char **))
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering break;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering n++;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering va_end(ap);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (n <= 0)
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return 0;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Read all words into a temporary array */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering l = newa0(char*, n);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering for (c = 0; c < n; c++) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering r = extract_first_word(p, &l[c], separators, flags);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (r < 0) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering int j;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering for (j = 0; j < c; j++)
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering free(l[j]);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return r;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering if (r == 0)
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering break;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* If we managed to parse all words, return them in the passed
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * in parameters */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering va_start(ap, flags);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering for (i = 0; i < n; i++) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering char **v;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering v = va_arg(ap, char **);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering assert(v);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering *v = l[i];
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering }
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering va_end(ap);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return c;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering}