]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/specifier.c
Merge pull request #1880 from fsateler/sysctl-doc
[thirdparty/systemd.git] / src / shared / specifier.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
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 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 #include <sys/utsname.h>
24
25 #include "alloc-util.h"
26 #include "hostname-util.h"
27 #include "macro.h"
28 #include "specifier.h"
29 #include "string-util.h"
30 #include "util.h"
31
32 /*
33 * Generic infrastructure for replacing %x style specifiers in
34 * strings. Will call a callback for each replacement.
35 *
36 */
37
38 int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) {
39 char *ret, *t;
40 const char *f;
41 bool percent = false;
42 size_t l;
43 int r;
44
45 assert(text);
46 assert(table);
47
48 l = strlen(text);
49 ret = new(char, l+1);
50 if (!ret)
51 return -ENOMEM;
52
53 t = ret;
54
55 for (f = text; *f; f++, l--) {
56
57 if (percent) {
58 if (*f == '%')
59 *(t++) = '%';
60 else {
61 const Specifier *i;
62
63 for (i = table; i->specifier; i++)
64 if (i->specifier == *f)
65 break;
66
67 if (i->lookup) {
68 _cleanup_free_ char *w = NULL;
69 char *n;
70 size_t k, j;
71
72 r = i->lookup(i->specifier, i->data, userdata, &w);
73 if (r < 0) {
74 free(ret);
75 return r;
76 }
77
78 j = t - ret;
79 k = strlen(w);
80
81 n = new(char, j + k + l + 1);
82 if (!n) {
83 free(ret);
84 return -ENOMEM;
85 }
86
87 memcpy(n, ret, j);
88 memcpy(n + j, w, k);
89
90 free(ret);
91
92 ret = n;
93 t = n + j + k;
94 } else {
95 *(t++) = '%';
96 *(t++) = *f;
97 }
98 }
99
100 percent = false;
101 } else if (*f == '%')
102 percent = true;
103 else
104 *(t++) = *f;
105 }
106
107 *t = 0;
108 *_ret = ret;
109 return 0;
110 }
111
112 /* Generic handler for simple string replacements */
113
114 int specifier_string(char specifier, void *data, void *userdata, char **ret) {
115 char *n;
116
117 n = strdup(strempty(data));
118 if (!n)
119 return -ENOMEM;
120
121 *ret = n;
122 return 0;
123 }
124
125 int specifier_machine_id(char specifier, void *data, void *userdata, char **ret) {
126 sd_id128_t id;
127 char *n;
128 int r;
129
130 r = sd_id128_get_machine(&id);
131 if (r < 0)
132 return r;
133
134 n = new(char, 33);
135 if (!n)
136 return -ENOMEM;
137
138 *ret = sd_id128_to_string(id, n);
139 return 0;
140 }
141
142 int specifier_boot_id(char specifier, void *data, void *userdata, char **ret) {
143 sd_id128_t id;
144 char *n;
145 int r;
146
147 r = sd_id128_get_boot(&id);
148 if (r < 0)
149 return r;
150
151 n = new(char, 33);
152 if (!n)
153 return -ENOMEM;
154
155 *ret = sd_id128_to_string(id, n);
156 return 0;
157 }
158
159 int specifier_host_name(char specifier, void *data, void *userdata, char **ret) {
160 char *n;
161
162 n = gethostname_malloc();
163 if (!n)
164 return -ENOMEM;
165
166 *ret = n;
167 return 0;
168 }
169
170 int specifier_kernel_release(char specifier, void *data, void *userdata, char **ret) {
171 struct utsname uts;
172 char *n;
173 int r;
174
175 r = uname(&uts);
176 if (r < 0)
177 return -errno;
178
179 n = strdup(uts.release);
180 if (!n)
181 return -ENOMEM;
182
183 *ret = n;
184 return 0;
185 }