]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/replace-var.c
tree-wide: remove Lennart's copyright lines
[thirdparty/systemd.git] / src / basic / replace-var.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
6e6fb527 2
11c3a366
TA
3#include <errno.h>
4#include <stddef.h>
5#include <stdlib.h>
6e6fb527
LP
6#include <string.h>
7
b5efdb8a 8#include "alloc-util.h"
6e6fb527 9#include "macro.h"
6e6fb527 10#include "replace-var.h"
b11d6a7b 11#include "string-util.h"
6e6fb527
LP
12
13/*
14 * Generic infrastructure for replacing @FOO@ style variables in
15 * strings. Will call a callback for each replacement.
16 */
17
18static int get_variable(const char *b, char **r) {
19 size_t k;
20 char *t;
21
22 assert(b);
23 assert(r);
24
25 if (*b != '@')
26 return 0;
27
4b549144 28 k = strspn(b + 1, UPPERCASE_LETTERS "_");
6e6fb527
LP
29 if (k <= 0 || b[k+1] != '@')
30 return 0;
31
32 t = strndup(b + 1, k);
33 if (!t)
34 return -ENOMEM;
35
36 *r = t;
37 return 1;
38}
39
2d5dece8 40char *replace_var(const char *text, char *(*lookup)(const char *variable, void *userdata), void *userdata) {
6e6fb527
LP
41 char *r, *t;
42 const char *f;
43 size_t l;
44
45 assert(text);
46 assert(lookup);
47
48 l = strlen(text);
49 r = new(char, l+1);
50 if (!r)
51 return NULL;
52
53 f = text;
54 t = r;
55 while (*f) {
56 _cleanup_free_ char *v = NULL, *n = NULL;
57 char *a;
58 int k;
59 size_t skip, d, nl;
60
61 k = get_variable(f, &v);
62 if (k < 0)
63 goto oom;
64 if (k == 0) {
65 *(t++) = *(f++);
66 continue;
67 }
68
69 n = lookup(v, userdata);
70 if (!n)
71 goto oom;
72
73 skip = strlen(v) + 2;
74
75 d = t - r;
76 nl = l - skip + strlen(n);
77 a = realloc(r, nl + 1);
78 if (!a)
79 goto oom;
80
81 l = nl;
82 r = a;
83 t = r + d;
84
85 t = stpcpy(t, n);
86 f += skip;
87 }
88
89 *t = 0;
90 return r;
91
92oom:
6b430fdb 93 return mfree(r);
6e6fb527 94}