chiark / gitweb /
manager: print process name for all SIGCHLD received
[elogind.git] / strv.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
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   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "util.h"
29 #include "strv.h"
30
31 char *strv_find(char **l, const char *name) {
32         char **i;
33
34         assert(l);
35         assert(name);
36
37         STRV_FOREACH(i, l)
38                 if (streq(*i, name))
39                         return *i;
40
41         return NULL;
42 }
43
44 void strv_free(char **l) {
45         char **k;
46
47         if (!l)
48                 return;
49
50         for (k = l; *k; k++)
51                 free(*k);
52
53         free(l);
54 }
55
56 char **strv_copy(char **l) {
57         char **r, **k;
58
59         if (!(r = new(char*, strv_length(l)+1)))
60                 return NULL;
61
62         for (k = r; *l; k++, l++)
63                 if (!(*k = strdup(*l)))
64                         goto fail;
65
66         *k = NULL;
67         return r;
68
69 fail:
70         for (k--, l--; k >= r; k--, l--)
71                 free(*k);
72
73         return NULL;
74 }
75
76 unsigned strv_length(char **l) {
77         unsigned n = 0;
78
79         if (!l)
80                 return 0;
81
82         for (; *l; l++)
83                 n++;
84
85         return n;
86 }
87
88 char **strv_new(const char *x, ...) {
89         const char *s;
90         char **a;
91         unsigned n = 0, i = 0;
92         va_list ap;
93
94         if (x) {
95                 n = 1;
96
97                 va_start(ap, x);
98
99                 while (va_arg(ap, const char*))
100                         n++;
101
102                 va_end(ap);
103         }
104
105         if (!(a = new(char*, n+1)))
106                 return NULL;
107
108         if (x) {
109                 if (!(a[i] = strdup(x))) {
110                         free(a);
111                         return NULL;
112                 }
113
114                 i++;
115
116                 va_start(ap, x);
117
118                 while ((s = va_arg(ap, const char*))) {
119                         if (!(a[i] = strdup(s)))
120                                 goto fail;
121
122                         i++;
123                 }
124
125                 va_end(ap);
126         }
127
128         a[i] = NULL;
129         return a;
130
131 fail:
132
133         for (; i > 0; i--)
134                 if (a[i-1])
135                         free(a[i-1]);
136
137         free(a);
138         return NULL;
139 }
140
141 char **strv_merge(char **a, char **b) {
142         char **r, **k;
143
144         if (!a)
145                 return strv_copy(b);
146
147         if (!b)
148                 return strv_copy(a);
149
150         if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
151                 return NULL;
152
153         for (k = r; *a; k++, a++)
154                 if (!(*k = strdup(*a)))
155                         goto fail;
156         for (; *b; k++, b++)
157                 if (!(*k = strdup(*b)))
158                         goto fail;
159
160         *k = NULL;
161         return r;
162
163 fail:
164         for (k--; k >= r; k--)
165                 free(*k);
166
167         free(r);
168
169         return NULL;
170 }
171
172 char **strv_merge_concat(char **a, char **b, const char *suffix) {
173         char **r, **k;
174
175         /* Like strv_merge(), but appends suffix to all strings in b, before adding */
176
177         if (!b)
178                 return strv_copy(a);
179
180         if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
181                 return NULL;
182
183         for (k = r; *a; k++, a++)
184                 if (!(*k = strdup(*a)))
185                         goto fail;
186         for (; *b; k++, b++)
187                 if (!(*k = strappend(*b, suffix)))
188                         goto fail;
189
190         *k = NULL;
191         return r;
192
193 fail:
194         for (k--; k >= r; k--)
195                 free(*k);
196
197         free(r);
198
199         return NULL;
200
201 }
202
203 char **strv_split(const char *s, const char *separator) {
204         char *state;
205         char *w;
206         size_t l;
207         unsigned n, i;
208         char **r;
209
210         assert(s);
211
212         n = 0;
213         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
214                 n++;
215
216         if (!(r = new(char*, n+1)))
217                 return NULL;
218
219         i = 0;
220         FOREACH_WORD_SEPARATOR(w, l, s, separator, state)
221                 if (!(r[i++] = strndup(w, l))) {
222                         strv_free(r);
223                         return NULL;
224                 }
225
226         r[i] = NULL;
227         return r;
228 }
229
230 char **strv_split_quoted(const char *s) {
231         char *state;
232         char *w;
233         size_t l;
234         unsigned n, i;
235         char **r;
236
237         assert(s);
238
239         n = 0;
240         FOREACH_WORD_QUOTED(w, l, s, state)
241                 n++;
242
243         if (!(r = new(char*, n+1)))
244                 return NULL;
245
246         i = 0;
247         FOREACH_WORD_QUOTED(w, l, s, state)
248                 if (!(r[i++] = strndup(w, l))) {
249                         strv_free(r);
250                         return NULL;
251                 }
252
253         r[i] = NULL;
254         return r;
255 }
256
257 char *strv_join(char **l, const char *separator) {
258         char *r, *e;
259         char **s;
260         size_t n, k;
261
262         if (!separator)
263                 separator = " ";
264
265         k = strlen(separator);
266
267         n = 0;
268         STRV_FOREACH(s, l) {
269                 if (n != 0)
270                         n += k;
271                 n += strlen(*s);
272         }
273
274         if (!(r = new(char, n+1)))
275                 return NULL;
276
277         e = r;
278         STRV_FOREACH(s, l) {
279                 if (e != r)
280                         e = stpcpy(e, separator);
281
282                 e = stpcpy(e, *s);
283         }
284
285         *e = 0;
286
287         return r;
288 }
289
290 char **strv_append(char **l, const char *s) {
291         char **r, **k;
292
293         if (!l)
294                 return strv_new(s, NULL);
295
296         if (!s)
297                 return strv_copy(l);
298
299         if (!(r = new(char*, strv_length(l)+2)))
300                 return NULL;
301
302         for (k = r; *l; k++, l++)
303                 if (!(*k = strdup(*l)))
304                         goto fail;
305
306         if (!(*(k++) = strdup(s)))
307                 goto fail;
308
309         *k = NULL;
310         return r;
311
312 fail:
313         for (k--; k >= r; k--)
314                 free(*k);
315
316         free(r);
317
318         return NULL;
319 }
320
321 char **strv_uniq(char **l) {
322         char **i;
323
324         /* Drops duplicate entries. The first identical string will be
325          * kept, the others dropped */
326
327         STRV_FOREACH(i, l)
328                 strv_remove(i+1, *i);
329
330         return l;
331 }
332
333 char **strv_remove(char **l, const char *s) {
334         char **f, **t;
335
336         if (!l)
337                 return NULL;
338
339         /* Drops every occurence of s in the string list */
340
341         for (f = t = l; *f; f++) {
342
343                 if (streq(*f, s)) {
344                         free(*f);
345                         continue;
346                 }
347
348                 *(t++) = *f;
349         }
350
351         *t = NULL;
352         return l;
353 }
354
355 static int env_append(char **r, char ***k, char **a) {
356         assert(r);
357         assert(k);
358         assert(a);
359
360         /* Add the entries of a to *k unless they already exist in *r
361          * in which case they are overriden instead. This assumes
362          * there is enough space in the r */
363
364         for (; *a; a++) {
365                 char **j;
366                 size_t n = strcspn(*a, "=") + 1;
367
368                 for (j = r; j < *k; j++)
369                         if (strncmp(*j, *a, n) == 0)
370                                 break;
371
372                 if (j >= *k)
373                         (*k)++;
374                 else
375                         free(*j);
376
377                 if (!(*j = strdup(*a)))
378                         return -ENOMEM;
379         }
380
381         return 0;
382 }
383
384 char **strv_env_merge(char **x, ...) {
385         size_t n = 0;
386         char **l, **k, **r;
387         va_list ap;
388
389         /* Merges an arbitrary number of environment sets */
390
391         if (x) {
392                 n += strv_length(x);
393
394                 va_start(ap, x);
395                 while ((l = va_arg(ap, char**)))
396                         n += strv_length(l);
397                 va_end(ap);
398         }
399
400
401         if (!(r = new(char*, n+1)))
402                 return NULL;
403
404         k = r;
405
406         if (x) {
407                 if (env_append(r, &k, x) < 0)
408                         goto fail;
409
410                 va_start(ap, x);
411                 while ((l = va_arg(ap, char**)))
412                         if (env_append(r, &k, l) < 0)
413                                 goto fail;
414                 va_end(ap);
415         }
416
417         *k = NULL;
418
419         return r;
420
421 fail:
422         for (k--; k >= r; k--)
423                 free(*k);
424
425         free(r);
426
427         return NULL;
428 }