]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/unit-printf.c
core: remove ManagerRunningAs enum
[thirdparty/systemd.git] / src / core / unit-printf.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 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
20 #include "alloc-util.h"
21 #include "cgroup-util.h"
22 #include "formats-util.h"
23 #include "macro.h"
24 #include "specifier.h"
25 #include "string-util.h"
26 #include "strv.h"
27 #include "unit-name.h"
28 #include "unit-printf.h"
29 #include "unit.h"
30 #include "user-util.h"
31
32 static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
33 Unit *u = userdata;
34
35 assert(u);
36
37 return unit_name_to_prefix_and_instance(u->id, ret);
38 }
39
40 static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) {
41 Unit *u = userdata;
42
43 assert(u);
44
45 return unit_name_to_prefix(u->id, ret);
46 }
47
48 static int specifier_prefix_unescaped(char specifier, void *data, void *userdata, char **ret) {
49 _cleanup_free_ char *p = NULL;
50 Unit *u = userdata;
51 int r;
52
53 assert(u);
54
55 r = unit_name_to_prefix(u->id, &p);
56 if (r < 0)
57 return r;
58
59 return unit_name_unescape(p, ret);
60 }
61
62 static int specifier_instance_unescaped(char specifier, void *data, void *userdata, char **ret) {
63 Unit *u = userdata;
64
65 assert(u);
66
67 return unit_name_unescape(strempty(u->instance), ret);
68 }
69
70 static int specifier_filename(char specifier, void *data, void *userdata, char **ret) {
71 Unit *u = userdata;
72
73 assert(u);
74
75 if (u->instance)
76 return unit_name_path_unescape(u->instance, ret);
77 else
78 return unit_name_to_path(u->id, ret);
79 }
80
81 static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
82 Unit *u = userdata;
83 char *n;
84
85 assert(u);
86
87 if (u->cgroup_path)
88 n = strdup(u->cgroup_path);
89 else
90 n = unit_default_cgroup_path(u);
91 if (!n)
92 return -ENOMEM;
93
94 *ret = n;
95 return 0;
96 }
97
98 static int specifier_cgroup_root(char specifier, void *data, void *userdata, char **ret) {
99 Unit *u = userdata;
100 char *n;
101
102 assert(u);
103
104 n = strdup(u->manager->cgroup_root);
105 if (!n)
106 return -ENOMEM;
107
108 *ret = n;
109 return 0;
110 }
111
112 static int specifier_cgroup_slice(char specifier, void *data, void *userdata, char **ret) {
113 Unit *u = userdata;
114 char *n;
115
116 assert(u);
117
118 if (UNIT_ISSET(u->slice)) {
119 Unit *slice;
120
121 slice = UNIT_DEREF(u->slice);
122
123 if (slice->cgroup_path)
124 n = strdup(slice->cgroup_path);
125 else
126 n = unit_default_cgroup_path(slice);
127 } else
128 n = strdup(u->manager->cgroup_root);
129 if (!n)
130 return -ENOMEM;
131
132 *ret = n;
133 return 0;
134 }
135
136 static int specifier_runtime(char specifier, void *data, void *userdata, char **ret) {
137 Unit *u = userdata;
138 const char *e;
139 char *n = NULL;
140
141 assert(u);
142
143 if (MANAGER_IS_SYSTEM(u->manager))
144 e = "/run";
145 else {
146 e = getenv("XDG_RUNTIME_DIR");
147 if (!e)
148 return -EOPNOTSUPP;
149 }
150
151 n = strdup(e);
152 if (!n)
153 return -ENOMEM;
154
155 *ret = n;
156 return 0;
157 }
158
159 static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
160 char *t;
161
162 /* If we are UID 0 (root), this will not result in NSS,
163 * otherwise it might. This is good, as we want to be able to
164 * run this in PID 1, where our user ID is 0, but where NSS
165 * lookups are not allowed. */
166
167 t = getusername_malloc();
168 if (!t)
169 return -ENOMEM;
170
171 *ret = t;
172 return 0;
173 }
174
175 static int specifier_user_id(char specifier, void *data, void *userdata, char **ret) {
176
177 if (asprintf(ret, UID_FMT, getuid()) < 0)
178 return -ENOMEM;
179
180 return 0;
181 }
182
183 static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
184
185 /* On PID 1 (which runs as root) this will not result in NSS,
186 * which is good. See above */
187
188 return get_home_dir(ret);
189 }
190
191 static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
192
193 /* On PID 1 (which runs as root) this will not result in NSS,
194 * which is good. See above */
195
196 return get_shell(ret);
197 }
198
199 int unit_name_printf(Unit *u, const char* format, char **ret) {
200
201 /*
202 * This will use the passed string as format string and
203 * replace the following specifiers:
204 *
205 * %n: the full id of the unit (foo@bar.waldo)
206 * %N: the id of the unit without the suffix (foo@bar)
207 * %p: the prefix (foo)
208 * %i: the instance (bar)
209 */
210
211 const Specifier table[] = {
212 { 'n', specifier_string, u->id },
213 { 'N', specifier_prefix_and_instance, NULL },
214 { 'p', specifier_prefix, NULL },
215 { 'i', specifier_string, u->instance },
216 { 0, NULL, NULL }
217 };
218
219 assert(u);
220 assert(format);
221 assert(ret);
222
223 return specifier_printf(format, table, u, ret);
224 }
225
226 int unit_full_printf(Unit *u, const char *format, char **ret) {
227
228 /* This is similar to unit_name_printf() but also supports
229 * unescaping. Also, adds a couple of additional codes:
230 *
231 * %f the instance if set, otherwise the id
232 * %c cgroup path of unit
233 * %r where units in this slice are placed in the cgroup tree
234 * %R the root of this systemd's instance tree
235 * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
236 * %U the UID of the running user
237 * %u the username of the running user
238 * %h the homedir of the running user
239 * %s the shell of the running user
240 * %m the machine ID of the running system
241 * %H the host name of the running system
242 * %b the boot ID of the running system
243 * %v `uname -r` of the running system
244 */
245
246 const Specifier table[] = {
247 { 'n', specifier_string, u->id },
248 { 'N', specifier_prefix_and_instance, NULL },
249 { 'p', specifier_prefix, NULL },
250 { 'P', specifier_prefix_unescaped, NULL },
251 { 'i', specifier_string, u->instance },
252 { 'I', specifier_instance_unescaped, NULL },
253
254 { 'f', specifier_filename, NULL },
255 { 'c', specifier_cgroup, NULL },
256 { 'r', specifier_cgroup_slice, NULL },
257 { 'R', specifier_cgroup_root, NULL },
258 { 't', specifier_runtime, NULL },
259
260 { 'U', specifier_user_id, NULL },
261 { 'u', specifier_user_name, NULL },
262 { 'h', specifier_user_home, NULL },
263 { 's', specifier_user_shell, NULL },
264
265 { 'm', specifier_machine_id, NULL },
266 { 'H', specifier_host_name, NULL },
267 { 'b', specifier_boot_id, NULL },
268 { 'v', specifier_kernel_release, NULL },
269 {}
270 };
271
272 assert(u);
273 assert(format);
274 assert(ret);
275
276 return specifier_printf(format, table, u, ret);
277 }
278
279 int unit_full_printf_strv(Unit *u, char **l, char ***ret) {
280 size_t n;
281 char **r, **i, **j;
282 int q;
283
284 /* Applies unit_full_printf to every entry in l */
285
286 assert(u);
287
288 n = strv_length(l);
289 r = new(char*, n+1);
290 if (!r)
291 return -ENOMEM;
292
293 for (i = l, j = r; *i; i++, j++) {
294 q = unit_full_printf(u, *i, j);
295 if (q < 0)
296 goto fail;
297 }
298
299 *j = NULL;
300 *ret = r;
301 return 0;
302
303 fail:
304 for (j--; j >= r; j--)
305 free(*j);
306
307 free(r);
308 return q;
309 }