]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/replace-var.c
tree-wide: use mfree more
[thirdparty/systemd.git] / src / basic / replace-var.c
CommitLineData
6e6fb527
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2012 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
11c3a366
TA
20#include <errno.h>
21#include <stddef.h>
22#include <stdlib.h>
6e6fb527
LP
23#include <string.h>
24
b5efdb8a 25#include "alloc-util.h"
6e6fb527 26#include "macro.h"
6e6fb527 27#include "replace-var.h"
b11d6a7b 28#include "string-util.h"
6e6fb527
LP
29
30/*
31 * Generic infrastructure for replacing @FOO@ style variables in
32 * strings. Will call a callback for each replacement.
33 */
34
35static int get_variable(const char *b, char **r) {
36 size_t k;
37 char *t;
38
39 assert(b);
40 assert(r);
41
42 if (*b != '@')
43 return 0;
44
4b549144 45 k = strspn(b + 1, UPPERCASE_LETTERS "_");
6e6fb527
LP
46 if (k <= 0 || b[k+1] != '@')
47 return 0;
48
49 t = strndup(b + 1, k);
50 if (!t)
51 return -ENOMEM;
52
53 *r = t;
54 return 1;
55}
56
57char *replace_var(const char *text, char *(*lookup)(const char *variable, void*userdata), void *userdata) {
58 char *r, *t;
59 const char *f;
60 size_t l;
61
62 assert(text);
63 assert(lookup);
64
65 l = strlen(text);
66 r = new(char, l+1);
67 if (!r)
68 return NULL;
69
70 f = text;
71 t = r;
72 while (*f) {
73 _cleanup_free_ char *v = NULL, *n = NULL;
74 char *a;
75 int k;
76 size_t skip, d, nl;
77
78 k = get_variable(f, &v);
79 if (k < 0)
80 goto oom;
81 if (k == 0) {
82 *(t++) = *(f++);
83 continue;
84 }
85
86 n = lookup(v, userdata);
87 if (!n)
88 goto oom;
89
90 skip = strlen(v) + 2;
91
92 d = t - r;
93 nl = l - skip + strlen(n);
94 a = realloc(r, nl + 1);
95 if (!a)
96 goto oom;
97
98 l = nl;
99 r = a;
100 t = r + d;
101
102 t = stpcpy(t, n);
103 f += skip;
104 }
105
106 *t = 0;
107 return r;
108
109oom:
6b430fdb 110 return mfree(r);
6e6fb527 111}