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);
83 for (; *l; k++, l++) {
95 unsigned strv_length(char **l) {
107 char **strv_new_ap(const char *x, va_list ap) {
110 unsigned n = 0, i = 0;
113 /* As a special trick we ignore all listed strings that equal
114 * (const char*) -1. This is supposed to be used with the
115 * STRV_IFNOTNULL() macro to include possibly NULL strings in
116 * the string list. */
119 n = x == (const char*) -1 ? 0 : 1;
122 while ((s = va_arg(aq, const char*))) {
123 if (s == (const char*) -1)
137 if (x != (const char*) -1) {
144 while ((s = va_arg(ap, const char*))) {
146 if (s == (const char*) -1)
166 char **strv_new(const char *x, ...) {
171 r = strv_new_ap(x, ap);
177 char **strv_merge(char **a, char **b) {
186 r = new(char*, strv_length(a) + strv_length(b) + 1);
190 for (k = r; *a; k++, a++) {
196 for (; *b; k++, b++) {
210 char **strv_merge_concat(char **a, char **b, const char *suffix) {
213 /* Like strv_merge(), but appends suffix to all strings in b, before adding */
218 r = new(char*, strv_length(a) + strv_length(b) + 1);
224 for (; *a; k++, a++) {
230 for (; *b; k++, b++) {
231 *k = strappend(*b, suffix);
245 char **strv_split(const char *s, const char *separator) {
255 FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
263 FOREACH_WORD_SEPARATOR(w, l, s, separator, state) {
264 r[i] = strndup(w, l);
277 char **strv_split_quoted(const char *s) {
287 FOREACH_WORD_QUOTED(w, l, s, state)
295 FOREACH_WORD_QUOTED(w, l, s, state) {
296 r[i] = cunescape_length(w, l);
308 char *strv_join(char **l, const char *separator) {
316 k = strlen(separator);
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++) {
373 int strv_extend(char ***l, const char *value) {
379 c = strv_append(*l, value);
388 char **strv_uniq(char **l) {
391 /* Drops duplicate entries. The first identical string will be
392 * kept, the others dropped */
395 strv_remove(i+1, *i);
400 char **strv_remove(char **l, const char *s) {
408 /* Drops every occurrence of s in the string list, edits
411 for (f = t = l; *f; f++) {
425 char **strv_remove_prefix(char **l, const char *s) {
433 /* Drops every occurrence of a string prefixed with s in the
434 * string list, edits in-place. */
436 for (f = t = l; *f; f++) {
438 if (startswith(*f, s)) {
450 static int env_append(char **r, char ***k, char **a) {
457 /* Add the entries of a to *k unless they already exist in *r
458 * in which case they are overridden instead. This assumes
459 * there is enough space in the r array. */
465 n = strcspn(*a, "=");
470 for (j = r; j < *k; j++)
471 if (strncmp(*j, *a, n) == 0)
487 char **strv_env_merge(unsigned n_lists, ...) {
493 /* Merges an arbitrary number of environment sets */
495 va_start(ap, n_lists);
496 for (i = 0; i < n_lists; i++) {
497 l = va_arg(ap, char**);
508 va_start(ap, n_lists);
509 for (i = 0; i < n_lists; i++) {
510 l = va_arg(ap, char**);
511 if (env_append(r, &k, l) < 0)
527 static bool env_match(const char *t, const char *pattern) {
531 /* pattern a matches string a
536 * a= does not match a
537 * a=b does not match a=
538 * a=b does not match a
539 * a=b does not match a=c */
541 if (streq(t, pattern))
544 if (!strchr(pattern, '=')) {
545 size_t l = strlen(pattern);
547 return strncmp(t, pattern, l) == 0 && t[l] == '=';
553 char **strv_env_delete(char **x, unsigned n_lists, ...) {
558 /* Deletes every entry from x that is mentioned in the other
570 va_start(ap, n_lists);
571 for (v = 0; v < n_lists; v++) {
574 l = va_arg(ap, char**);
576 if (env_match(*k, *j))
601 char **strv_env_unset(char **l, const char *p) {
610 /* Drops every occurrence of the env var setting p in the
611 * string list. edits in-place. */
613 for (f = t = l; *f; f++) {
615 if (env_match(*f, p)) {
627 char **strv_env_set(char **x, const char *p) {
630 char* m[2] = { (char*) p, NULL };
632 /* Overrides the env var setting of p, returns a new copy */
634 r = new(char*, strv_length(x)+2);
639 if (env_append(r, &k, x) < 0)
642 if (env_append(r, &k, m) < 0)
655 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
661 if (strncmp(*i, name, k) == 0 &&
668 char *strv_env_get(char **l, const char *name) {
669 return strv_env_get_with_length(l, name, strlen(name));
672 char **strv_env_clean(char **l) {
675 for (r = ret = l; *l; l++) {
678 equal = strchr(*l, '=');
680 if (equal && equal[1] == 0) {
693 char **strv_parse_nulstr(const char *s, size_t l) {
695 unsigned c = 0, i = 0;
701 return strv_new(NULL, NULL);
703 for (p = s; p < s + l; p++)
710 v = new0(char*, c+1);
718 e = memchr(p, 0, s + l - p);
720 v[i] = strndup(p, e ? e - p : s + l - p);
739 bool strv_overlap(char **a, char **b) {
752 static int str_compare(const void *_a, const void *_b) {
753 const char **a = (const char**) _a, **b = (const char**) _b;
755 return strcmp(*a, *b);
758 char **strv_sort(char **l) {
763 qsort(l, strv_length(l), sizeof(char*), str_compare);