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 char **strv_uniq(char **l) {
376 /* Drops duplicate entries. The first identical string will be
377 * kept, the others dropped */
380 strv_remove(i+1, *i);
385 char **strv_remove(char **l, const char *s) {
393 /* Drops every occurrence of s in the string list, edits
396 for (f = t = l; *f; f++) {
410 char **strv_remove_prefix(char **l, const char *s) {
418 /* Drops every occurrence of a string prefixed with s in the
419 * string list, edits in-place. */
421 for (f = t = l; *f; f++) {
423 if (startswith(*f, s)) {
435 static int env_append(char **r, char ***k, char **a) {
442 /* Add the entries of a to *k unless they already exist in *r
443 * in which case they are overridden instead. This assumes
444 * there is enough space in the r array. */
450 n = strcspn(*a, "=");
455 for (j = r; j < *k; j++)
456 if (strncmp(*j, *a, n) == 0)
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**);
493 va_start(ap, n_lists);
494 for (i = 0; i < n_lists; i++) {
495 l = va_arg(ap, char**);
496 if (env_append(r, &k, l) < 0)
512 static bool env_match(const char *t, const char *pattern) {
516 /* pattern a matches string a
521 * a= does not match a
522 * a=b does not match a=
523 * a=b does not match a
524 * a=b does not match a=c */
526 if (streq(t, pattern))
529 if (!strchr(pattern, '=')) {
530 size_t l = strlen(pattern);
532 return strncmp(t, pattern, l) == 0 && t[l] == '=';
538 char **strv_env_delete(char **x, unsigned n_lists, ...) {
543 /* Deletes every entry from x that is mentioned in the other
555 va_start(ap, n_lists);
556 for (v = 0; v < n_lists; v++) {
559 l = va_arg(ap, char**);
561 if (env_match(*k, *j))
586 char **strv_env_unset(char **l, const char *p) {
595 /* Drops every occurrence of the env var setting p in the
596 * string list. edits in-place. */
598 for (f = t = l; *f; f++) {
600 if (env_match(*f, p)) {
612 char **strv_env_set(char **x, const char *p) {
615 char* m[2] = { (char*) p, NULL };
617 /* Overrides the env var setting of p, returns a new copy */
619 r = new(char*, strv_length(x)+2);
624 if (env_append(r, &k, x) < 0)
627 if (env_append(r, &k, m) < 0)
640 char *strv_env_get_with_length(char **l, const char *name, size_t k) {
646 if (strncmp(*i, name, k) == 0 &&
653 char *strv_env_get(char **l, const char *name) {
654 return strv_env_get_with_length(l, name, strlen(name));
657 char **strv_env_clean(char **l) {
660 for (r = ret = l; *l; l++) {
663 equal = strchr(*l, '=');
665 if (equal && equal[1] == 0) {
678 char **strv_parse_nulstr(const char *s, size_t l) {
680 unsigned c = 0, i = 0;
686 return strv_new(NULL, NULL);
688 for (p = s; p < s + l; p++)
695 v = new0(char*, c+1);
703 e = memchr(p, 0, s + l - p);
705 v[i] = strndup(p, e ? e - p : s + l - p);
724 bool strv_overlap(char **a, char **b) {
737 static int str_compare(const void *_a, const void *_b) {
738 const char **a = (const char**) _a, **b = (const char**) _b;
740 return strcmp(*a, *b);
743 char **strv_sort(char **l) {
748 qsort(l, strv_length(l), sizeof(char*), str_compare);