1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
31 char *strv_find(char **l, const char *name) {
43 char *strv_find_prefix(char **l, const char *name) {
49 if (startswith(*i, name))
55 void strv_free(char **l) {
67 char **strv_copy(char **l) {
70 k = r = new(char*, strv_length(l)+1);
76 if (!(*k = strdup(*l)))
83 for (k--; k >= r; k--)
91 unsigned strv_length(char **l) {
103 char **strv_new_ap(const char *x, va_list ap) {
106 unsigned n = 0, i = 0;
109 /* As a special trick we ignore all listed strings that equal
110 * (const char*) -1. This is supposed to be used with the
111 * STRV_IFNOTNULL() macro to include possibly NULL strings in
112 * the string list. */
115 n = x == (const char*) -1 ? 0 : 1;
118 while ((s = va_arg(aq, const char*))) {
119 if (s == (const char*) -1)
133 if (x != (const char*) -1) {
140 while ((s = va_arg(ap, const char*))) {
142 if (s == (const char*) -1)
168 char **strv_new(const char *x, ...) {
173 r = strv_new_ap(x, ap);
179 char **strv_merge(char **a, char **b) {
188 r = new(char*, strv_length(a) + strv_length(b) + 1);
192 for (k = r; *a; k++, a++) {
198 for (; *b; k++, b++) {
212 char **strv_merge_concat(char **a, char **b, const char *suffix) {
215 /* Like strv_merge(), but appends suffix to all strings in b, before adding */
220 r = new(char*, strv_length(a) + strv_length(b) + 1);
226 for (; *a; k++, a++) {
232 for (; *b; k++, b++) {
233 *k = strappend(*b, suffix);
247 char **strv_split(const char *s, const char *separator) {
257 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
260 if (!(r = new(char*, n+1)))
264 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
265 if (!(r[i++] = strndup(w, l))) {
274 char **strv_split_quoted(const char *s) {
284 FOREACH_WORD_QUOTED(w, l, s, state)
287 if (!(r = new(char*, n+1)))
291 FOREACH_WORD_QUOTED(w, l, s, state)
292 if (!(r[i++] = cunescape_length(w, l))) {
301 char *strv_join(char **l, const char *separator) {
309 k = strlen(separator);
318 if (!(r = new(char, n+1)))
324 e = stpcpy(e, separator);
334 char **strv_append(char **l, const char *s) {
338 return strv_new(s, NULL);
343 r = new(char*, strv_length(l)+2);
347 for (k = r; *l; k++, l++)
348 if (!(*k = strdup(*l)))
351 if (!(*(k++) = strdup(s)))
358 for (k--; k >= r; k--)
366 char **strv_uniq(char **l) {
369 /* Drops duplicate entries. The first identical string will be
370 * kept, the others dropped */
373 strv_remove(i+1, *i);
378 char **strv_remove(char **l, const char *s) {
386 /* Drops every occurrence of s in the string list, edits
389 for (f = t = l; *f; f++) {
403 char **strv_remove_prefix(char **l, const char *s) {
411 /* Drops every occurrence of a string prefixed with s in the
412 * string list, edits in-place. */
414 for (f = t = l; *f; f++) {
416 if (startswith(*f, s)) {
428 static int env_append(char **r, char ***k, char **a) {
435 /* Add the entries of a to *k unless they already exist in *r
436 * in which case they are overridden instead. This assumes
437 * there is enough space in the r array. */
443 n = strcspn(*a, "=");
448 for (j = r; j < *k; j++)
449 if (strncmp(*j, *a, n) == 0)
457 if (!(*j = strdup(*a)))
464 char **strv_env_merge(unsigned n_lists, ...) {
470 /* Merges an arbitrary number of environment sets */
472 va_start(ap, n_lists);
473 for (i = 0; i < n_lists; i++) {
474 l = va_arg(ap, char**);
479 if (!(r = new(char*, n+1)))
484 va_start(ap, n_lists);
485 for (i = 0; i < n_lists; i++) {
486 l = va_arg(ap, char**);
487 if (env_append(r, &k, l) < 0)
499 for (k--; k >= r; k--)
507 static bool env_match(const char *t, const char *pattern) {
511 /* pattern a matches string a
516 * a= does not match a
517 * a=b does not match a=
518 * a=b does not match a
519 * a=b does not match a=c */
521 if (streq(t, pattern))
524 if (!strchr(pattern, '=')) {
525 size_t l = strlen(pattern);
527 return strncmp(t, pattern, l) == 0 && t[l] == '=';
533 char **strv_env_delete(char **x, unsigned n_lists, ...) {
538 /* Deletes every entry from x that is mentioned in the other
550 va_start(ap, n_lists);
551 for (v = 0; v < n_lists; v++) {
554 l = va_arg(ap, char**);
556 if (env_match(*k, *j))
581 char **strv_env_unset(char **l, const char *p) {
590 /* Drops every occurrence of the env var setting p in the
591 * string list. edits in-place. */
593 for (f = t = l; *f; f++) {
595 if (env_match(*f, p)) {
607 char **strv_env_set(char **x, const char *p) {
610 char* m[2] = { (char*) p, NULL };
612 /* Overrides the env var setting of p, returns a new copy */
614 if (!(r = new(char*, strv_length(x)+2)))
618 if (env_append(r, &k, x) < 0)
621 if (env_append(r, &k, m) < 0)
629 for (k--; k >= r; k--)
638 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
644 if (strncmp(*i, name, k) == 0 &&
651 char *strv_env_get(char **l, const char *name) {
652 return strv_env_get_with_length(l, name, strlen(name));
655 char **strv_env_clean(char **l) {
658 for (r = ret = l; *l; l++) {
661 equal = strchr(*l, '=');
663 if (equal && equal[1] == 0) {
676 char **strv_parse_nulstr(const char *s, size_t l) {
678 unsigned c = 0, i = 0;
684 return strv_new(NULL, NULL);
686 for (p = s; p < s + l; p++)
693 if (!(v = new0(char*, c+1)))
700 e = memchr(p, 0, s + l - p);
702 if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
718 bool strv_overlap(char **a, char **b) {