]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/specifier.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / shared / specifier.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
9e2f7c11
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
9e2f7c11
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
9e2f7c11 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
9e2f7c11
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
a8fbdf54
TA
21#include <errno.h>
22#include <stdbool.h>
23#include <stddef.h>
24#include <stdlib.h>
9e2f7c11 25#include <string.h>
6aaa8c2f 26#include <sys/utsname.h>
9e2f7c11 27
a8fbdf54
TA
28#include "sd-id128.h"
29
b5efdb8a 30#include "alloc-util.h"
07630cea 31#include "hostname-util.h"
9e2f7c11 32#include "macro.h"
b5efdb8a 33#include "specifier.h"
07630cea 34#include "string-util.h"
9e2f7c11
LP
35
36/*
37 * Generic infrastructure for replacing %x style specifiers in
38 * strings. Will call a callback for each replacement.
39 *
40 */
41
19f6d710
LP
42int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) {
43 char *ret, *t;
9e2f7c11
LP
44 const char *f;
45 bool percent = false;
46 size_t l;
19f6d710 47 int r;
9e2f7c11
LP
48
49 assert(text);
50 assert(table);
51
52 l = strlen(text);
19f6d710
LP
53 ret = new(char, l+1);
54 if (!ret)
55 return -ENOMEM;
9e2f7c11 56
19f6d710 57 t = ret;
9e2f7c11
LP
58
59 for (f = text; *f; f++, l--) {
60
61 if (percent) {
62 if (*f == '%')
63 *(t++) = '%';
64 else {
65 const Specifier *i;
66
67 for (i = table; i->specifier; i++)
68 if (i->specifier == *f)
69 break;
70
71 if (i->lookup) {
19f6d710
LP
72 _cleanup_free_ char *w = NULL;
73 char *n;
9e2f7c11
LP
74 size_t k, j;
75
19f6d710
LP
76 r = i->lookup(i->specifier, i->data, userdata, &w);
77 if (r < 0) {
78 free(ret);
79 return r;
9e2f7c11
LP
80 }
81
19f6d710 82 j = t - ret;
9e2f7c11
LP
83 k = strlen(w);
84
7ae03f36
LP
85 n = new(char, j + k + l + 1);
86 if (!n) {
19f6d710
LP
87 free(ret);
88 return -ENOMEM;
9e2f7c11
LP
89 }
90
19f6d710 91 memcpy(n, ret, j);
9e2f7c11
LP
92 memcpy(n + j, w, k);
93
19f6d710 94 free(ret);
9e2f7c11 95
19f6d710 96 ret = n;
9e2f7c11
LP
97 t = n + j + k;
98 } else {
99 *(t++) = '%';
100 *(t++) = *f;
101 }
102 }
103
104 percent = false;
105 } else if (*f == '%')
106 percent = true;
107 else
108 *(t++) = *f;
109 }
110
038492ae
FS
111 /* if string ended with a stray %, also end with % */
112 if (percent)
113 *(t++) = '%';
114
9e2f7c11 115 *t = 0;
19f6d710
LP
116 *_ret = ret;
117 return 0;
9e2f7c11
LP
118}
119
120/* Generic handler for simple string replacements */
121
19f6d710
LP
122int specifier_string(char specifier, void *data, void *userdata, char **ret) {
123 char *n;
124
125 n = strdup(strempty(data));
126 if (!n)
127 return -ENOMEM;
128
129 *ret = n;
130 return 0;
9e2f7c11 131}
d848b9cb 132
19f6d710 133int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) {
d848b9cb 134 sd_id128_t id;
19f6d710 135 char *n;
d848b9cb
ZJS
136 int r;
137
138 r = sd_id128_get_machine(&id);
139 if (r < 0)
19f6d710 140 return r;
d848b9cb 141
19f6d710
LP
142 n = new(char, 33);
143 if (!n)
144 return -ENOMEM;
d848b9cb 145
19f6d710
LP
146 *ret = sd_id128_to_string(id, n);
147 return 0;
d848b9cb
ZJS
148}
149
19f6d710 150int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
d848b9cb 151 sd_id128_t id;
19f6d710 152 char *n;
d848b9cb
ZJS
153 int r;
154
155 r = sd_id128_get_boot(&id);
156 if (r < 0)
19f6d710 157 return r;
d848b9cb 158
19f6d710
LP
159 n = new(char, 33);
160 if (!n)
161 return -ENOMEM;
d848b9cb 162
19f6d710
LP
163 *ret = sd_id128_to_string(id, n);
164 return 0;
d848b9cb
ZJS
165}
166
19f6d710
LP
167int specifier_host_name(char specifier, void *data, void *userdata, char **ret) {
168 char *n;
169
170 n = gethostname_malloc();
171 if (!n)
172 return -ENOMEM;
173
174 *ret = n;
175 return 0;
d848b9cb 176}
6aaa8c2f 177
19f6d710 178int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) {
6aaa8c2f 179 struct utsname uts;
19f6d710 180 char *n;
6aaa8c2f
ZJS
181 int r;
182
183 r = uname(&uts);
184 if (r < 0)
19f6d710
LP
185 return -errno;
186
187 n = strdup(uts.release);
188 if (!n)
189 return -ENOMEM;
6aaa8c2f 190
19f6d710
LP
191 *ret = n;
192 return 0;
6aaa8c2f 193}