Line data Source code
1 : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2 :
3 : /***
4 : This file is part of systemd.
5 :
6 : Copyright 2012 Lennart Poettering
7 :
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.
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 : Lesser General Public License for more details.
17 :
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/>.
20 : ***/
21 :
22 : #include <string.h>
23 :
24 : #include "macro.h"
25 : #include "util.h"
26 : #include "replace-var.h"
27 : #include "def.h"
28 :
29 : /*
30 : * Generic infrastructure for replacing @FOO@ style variables in
31 : * strings. Will call a callback for each replacement.
32 : */
33 :
34 42 : static int get_variable(const char *b, char **r) {
35 : size_t k;
36 : char *t;
37 :
38 42 : assert(b);
39 42 : assert(r);
40 :
41 42 : if (*b != '@')
42 30 : return 0;
43 :
44 12 : k = strspn(b + 1, UPPERCASE_LETTERS "_");
45 12 : if (k <= 0 || b[k+1] != '@')
46 10 : return 0;
47 :
48 2 : t = strndup(b + 1, k);
49 2 : if (!t)
50 0 : return -ENOMEM;
51 :
52 2 : *r = t;
53 2 : return 1;
54 : }
55 :
56 1 : char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata) {
57 : char *r, *t;
58 : const char *f;
59 : size_t l;
60 :
61 1 : assert(text);
62 1 : assert(lookup);
63 :
64 1 : l = strlen(text);
65 1 : r = new(char, l+1);
66 1 : if (!r)
67 0 : return NULL;
68 :
69 1 : f = text;
70 1 : t = r;
71 44 : while (*f) {
72 84 : _cleanup_free_ char *v = NULL, *n = NULL;
73 : char *a;
74 : int k;
75 : size_t skip, d, nl;
76 :
77 42 : k = get_variable(f, &v);
78 42 : if (k < 0)
79 0 : goto oom;
80 42 : if (k == 0) {
81 40 : *(t++) = *(f++);
82 40 : continue;
83 : }
84 :
85 2 : n = lookup(v, userdata);
86 2 : if (!n)
87 0 : goto oom;
88 :
89 2 : skip = strlen(v) + 2;
90 :
91 2 : d = t - r;
92 2 : nl = l - skip + strlen(n);
93 2 : a = realloc(r, nl + 1);
94 2 : if (!a)
95 0 : goto oom;
96 :
97 2 : l = nl;
98 2 : r = a;
99 2 : t = r + d;
100 :
101 2 : t = stpcpy(t, n);
102 2 : f += skip;
103 : }
104 :
105 1 : *t = 0;
106 1 : return r;
107 :
108 : oom:
109 0 : free(r);
110 0 : return NULL;
111 : }
|