extract-word.c revision 84ac7bea360cd369df26910e9685a7eed2327088
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/***
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2010 Lennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering***/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
a9cdc94f7ff40f22a3cf9472f612a80730a1b010Dave Reisner#include "utf8.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "util.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#include "extract-word.h"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *s = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering size_t allocated = 0, sz = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char quote = 0; /* 0 or ' or " */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool backslash = false; /* whether we've just seen a backslash */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool separator = false; /* whether we've just seen a separator */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering bool start = true; /* false means we're looking at a value */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(p);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(ret);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
0affed79d2e30013f07cb94e6f07e3fcb81c02faLennart Poettering if (!separators)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering separators = WHITESPACE;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Bail early if called after last value or with no input */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!*p)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Parses the first word of a string, and returns it in
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * *ret. Removes all quotes in the process. When parsing fails
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * (because of an uneven number of quotes or similar), leaves
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * the pointer *p at the first invalid character. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (;;) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char c = **p;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (start) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
1b12a7b5896f94bdf33b3a6661ebabd761ea6adcHarald Hoyer if (!GREEDY_REALLOC(s, allocated, sz+1))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (c == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else if (strchr(separators, c)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p) ++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_next;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering continue;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* We found a non-blank character, so we will always
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * want to return a string (even if it is empty),
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * allocate it here. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!GREEDY_REALLOC(s, allocated, sz+1))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering start = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (backslash) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!GREEDY_REALLOC(s, allocated, sz+7))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (c == 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (!quote || flags & EXTRACT_RELAX)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* If we find an unquoted trailing backslash and we're in
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * output.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * Unbalanced quotes will only be allowed in EXTRACT_RELAX
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = '\\';
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_RELAX)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_CUNESCAPE) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint32_t u;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = cunescape_one(*p, (size_t) -1, &c, &u);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_CUNESCAPE_RELAX) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = '\\';
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = c;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto end_escape;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p) += r - 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (c != 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = c; /* normal explicit char */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sz += utf8_encode_unichar(s + sz, u); /* unicode chars we'll encode as utf8 */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = c;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringend_escape:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering backslash = false;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (quote) { /* inside either single or double quotes */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (c == 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_RELAX)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -EINVAL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (c == quote) /* found the end quote */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering quote = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else if (c == '\\')
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering backslash = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!GREEDY_REALLOC(s, allocated, sz+2))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = c;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else if (separator) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (c == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!strchr(separators, c))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (c == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_terminate;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering quote = c;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else if (c == '\\')
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering backslash = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else if (strchr(separators, c)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p) ++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering goto finish_force_next;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering separator = true;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering } else {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!GREEDY_REALLOC(s, allocated, sz+2))
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek return -ENOMEM;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz++] = c;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (*p) ++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish_force_terminate:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *p = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!s) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *p = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *ret = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringfinish_force_next:
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s[sz] = 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *ret = s;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering s = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint extract_first_word_and_warn(
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char **p,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char **ret,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *separators,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering ExtractFlags flags,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *unit,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *filename,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering unsigned line,
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *rvalue) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Try to unquote it, if it fails, warn about it and try again but this
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * time using EXTRACT_CUNESCAPE_RELAX to keep the backslashes verbatim
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * in invalid escape sequences. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering const char *save;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering save = *p;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = extract_first_word(p, ret, separators, flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0 && !(flags & EXTRACT_CUNESCAPE_RELAX)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering *p = save;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting in command line, ignoring: \"%s\"", rvalue);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering else
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid escape sequences in command line: \"%s\"", rvalue);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering va_list ap;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char **l;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int n = 0, i, c, r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Parses a number of words from a string, stripping any
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * quotes if necessary. */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(p);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Count how many words are expected */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering va_start(ap, flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (;;) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (!va_arg(ap, char **))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering n++;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering va_end(ap);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (n <= 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Read all words into a temporary array */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l = newa0(char*, n);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (c = 0; c < n; c++) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = extract_first_word(p, &l[c], separators, flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r < 0) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering int j;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (j = 0; j < c; j++)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering free(l[j]);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return r;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (r == 0)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering break;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* If we managed to parse all words, return them in the passed
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * in parameters */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering va_start(ap, flags);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (i = 0; i < n; i++) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering char **v;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering v = va_arg(ap, char **);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering assert(v);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna *v = l[i];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering }
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering va_end(ap);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return c;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering}
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering