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 void strv_freep(char ***l) {
75 char **strv_copy(char **l) {
78 k = r = new(char*, strv_length(l)+1);
84 if (!(*k = strdup(*l)))
91 for (k--; k >= r; k--)
99 unsigned strv_length(char **l) {
111 char **strv_new_ap(const char *x, va_list ap) {
114 unsigned n = 0, i = 0;
117 /* As a special trick we ignore all listed strings that equal
118 * (const char*) -1. This is supposed to be used with the
119 * STRV_IFNOTNULL() macro to include possibly NULL strings in
120 * the string list. */
123 n = x == (const char*) -1 ? 0 : 1;
126 while ((s = va_arg(aq, const char*))) {
127 if (s == (const char*) -1)
141 if (x != (const char*) -1) {
148 while ((s = va_arg(ap, const char*))) {
150 if (s == (const char*) -1)
176 char **strv_new(const char *x, ...) {
181 r = strv_new_ap(x, ap);
187 char **strv_merge(char **a, char **b) {
196 r = new(char*, strv_length(a) + strv_length(b) + 1);
200 for (k = r; *a; k++, a++) {
206 for (; *b; k++, b++) {
220 char **strv_merge_concat(char **a, char **b, const char *suffix) {
223 /* Like strv_merge(), but appends suffix to all strings in b, before adding */
228 r = new(char*, strv_length(a) + strv_length(b) + 1);
234 for (; *a; k++, a++) {
240 for (; *b; k++, b++) {
241 *k = strappend(*b, suffix);
255 char **strv_split(const char *s, const char *separator) {
265 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
268 if (!(r = new(char*, n+1)))
272 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
273 if (!(r[i++] = strndup(w, l))) {
282 char **strv_split_quoted(const char *s) {
292 FOREACH_WORD_QUOTED(w, l, s, state)
295 if (!(r = new(char*, n+1)))
299 FOREACH_WORD_QUOTED(w, l, s, state)
300 if (!(r[i++] = cunescape_length(w, l))) {
309 char *strv_join(char **l, const char *separator) {
317 k = strlen(separator);
326 if (!(r = new(char, n+1)))
332 e = stpcpy(e, separator);
342 char **strv_append(char **l, const char *s) {
346 return strv_new(s, NULL);
351 r = new(char*, strv_length(l)+2);
355 for (k = r; *l; k++, l++)
356 if (!(*k = strdup(*l)))
359 if (!(*(k++) = strdup(s)))
366 for (k--; k >= r; k--)
374 char **strv_uniq(char **l) {
377 /* Drops duplicate entries. The first identical string will be
378 * kept, the others dropped */
381 strv_remove(i+1, *i);
386 char **strv_remove(char **l, const char *s) {
394 /* Drops every occurrence of s in the string list, edits
397 for (f = t = l; *f; f++) {
411 char **strv_remove_prefix(char **l, const char *s) {
419 /* Drops every occurrence of a string prefixed with s in the
420 * string list, edits in-place. */
422 for (f = t = l; *f; f++) {
424 if (startswith(*f, s)) {
436 static int env_append(char **r, char ***k, char **a) {
443 /* Add the entries of a to *k unless they already exist in *r
444 * in which case they are overridden instead. This assumes
445 * there is enough space in the r array. */
451 n = strcspn(*a, "=");
456 for (j = r; j < *k; j++)
457 if (strncmp(*j, *a, n) == 0)
465 if (!(*j = strdup(*a)))
472 char **strv_env_merge(unsigned n_lists, ...) {
478 /* Merges an arbitrary number of environment sets */
480 va_start(ap, n_lists);
481 for (i = 0; i < n_lists; i++) {
482 l = va_arg(ap, char**);
487 if (!(r = new(char*, n+1)))
492 va_start(ap, n_lists);
493 for (i = 0; i < n_lists; i++) {
494 l = va_arg(ap, char**);
495 if (env_append(r, &k, l) < 0)
507 for (k--; k >= r; k--)
515 static bool env_match(const char *t, const char *pattern) {
519 /* pattern a matches string a
524 * a= does not match a
525 * a=b does not match a=
526 * a=b does not match a
527 * a=b does not match a=c */
529 if (streq(t, pattern))
532 if (!strchr(pattern, '=')) {
533 size_t l = strlen(pattern);
535 return strncmp(t, pattern, l) == 0 && t[l] == '=';
541 char **strv_env_delete(char **x, unsigned n_lists, ...) {
546 /* Deletes every entry from x that is mentioned in the other
558 va_start(ap, n_lists);
559 for (v = 0; v < n_lists; v++) {
562 l = va_arg(ap, char**);
564 if (env_match(*k, *j))
589 char **strv_env_unset(char **l, const char *p) {
598 /* Drops every occurrence of the env var setting p in the
599 * string list. edits in-place. */
601 for (f = t = l; *f; f++) {
603 if (env_match(*f, p)) {
615 char **strv_env_set(char **x, const char *p) {
618 char* m[2] = { (char*) p, NULL };
620 /* Overrides the env var setting of p, returns a new copy */
622 if (!(r = new(char*, strv_length(x)+2)))
626 if (env_append(r, &k, x) < 0)
629 if (env_append(r, &k, m) < 0)
637 for (k--; k >= r; k--)
646 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
652 if (strncmp(*i, name, k) == 0 &&
659 char *strv_env_get(char **l, const char *name) {
660 return strv_env_get_with_length(l, name, strlen(name));
663 char **strv_env_clean(char **l) {
666 for (r = ret = l; *l; l++) {
669 equal = strchr(*l, '=');
671 if (equal && equal[1] == 0) {
684 char **strv_parse_nulstr(const char *s, size_t l) {
686 unsigned c = 0, i = 0;
692 return strv_new(NULL, NULL);
694 for (p = s; p < s + l; p++)
701 if (!(v = new0(char*, c+1)))
708 e = memchr(p, 0, s + l - p);
710 if (!(v[i++] = strndup(p, e ? e - p : s + l - p))) {
726 bool strv_overlap(char **a, char **b) {
739 static int str_compare(const void *_a, const void *_b) {
740 const char **a = (const char**) _a, **b = (const char**) _b;
742 return strcmp(*a, *b);
745 char **strv_sort(char **l) {
750 qsort(l, strv_length(l), sizeof(char*), str_compare);