]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/unit-printf.c
core: move ManagerRunningAs to shared
[thirdparty/systemd.git] / src / core / unit-printf.c
CommitLineData
41f9172f
LP
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 "systemd/sd-id128.h"
23#include "unit.h"
24#include "specifier.h"
25#include "path-util.h"
26#include "strv.h"
27#include "unit-name.h"
28#include "unit-printf.h"
29
30static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
31 Unit *u = userdata;
32 assert(u);
33
34 return unit_name_to_prefix_and_instance(u->id);
35}
36
37static char *specifier_prefix(char specifier, void *data, void *userdata) {
38 Unit *u = userdata;
39 assert(u);
40
41 return unit_name_to_prefix(u->id);
42}
43
44static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
45 Unit *u = userdata;
46 char *p, *r;
47
48 assert(u);
49
50 p = unit_name_to_prefix(u->id);
51 if (!p)
52 return NULL;
53
54 r = unit_name_unescape(p);
55 free(p);
56
57 return r;
58}
59
60static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
61 Unit *u = userdata;
62 assert(u);
63
64 if (u->instance)
65 return unit_name_unescape(u->instance);
66
67 return strdup("");
68}
69
70static char *specifier_filename(char specifier, void *data, void *userdata) {
71 Unit *u = userdata;
72 assert(u);
73
74 if (u->instance)
75 return unit_name_path_unescape(u->instance);
76
77 return unit_name_to_path(u->id);
78}
79
80static char *specifier_cgroup(char specifier, void *data, void *userdata) {
81 Unit *u = userdata;
82 assert(u);
83
84 return unit_default_cgroup_path(u);
85}
86
87static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
88 Unit *u = userdata;
89 char *p;
90 assert(u);
91
92 if (specifier == 'r')
93 return strdup(u->manager->cgroup_hierarchy);
94
95 if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
96 return strdup("");
97
98 if (streq(p, "/")) {
99 free(p);
100 return strdup("");
101 }
102
103 return p;
104}
105
106static char *specifier_runtime(char specifier, void *data, void *userdata) {
107 Unit *u = userdata;
108 assert(u);
109
67445f4e 110 if (u->manager->running_as == SYSTEMD_USER) {
41f9172f
LP
111 const char *e;
112
113 e = getenv("XDG_RUNTIME_DIR");
114 if (e)
115 return strdup(e);
116 }
117
118 return strdup("/run");
119}
120
121static char *specifier_user_name(char specifier, void *data, void *userdata) {
3ef63c31
LP
122 Unit *u = userdata;
123 ExecContext *c;
41f9172f
LP
124 int r;
125 const char *username;
126
6569cae1
LP
127 assert(u);
128
3ef63c31
LP
129 c = unit_get_exec_context(u);
130 if (!c)
131 return NULL;
132
41f9172f 133 /* get USER env from our own env if set */
3ef63c31 134 if (!c->user)
41f9172f
LP
135 return getusername_malloc();
136
137 /* fish username from passwd */
3ef63c31 138 username = c->user;
41f9172f
LP
139 r = get_user_creds(&username, NULL, NULL, NULL, NULL);
140 if (r < 0)
141 return NULL;
142
143 return strdup(username);
144}
145
146static char *specifier_user_home(char specifier, void *data, void *userdata) {
3ef63c31
LP
147 Unit *u = userdata;
148 ExecContext *c;
41f9172f
LP
149 int r;
150 const char *username, *home;
151
6569cae1
LP
152 assert(u);
153
3ef63c31
LP
154 c = unit_get_exec_context(u);
155 if (!c)
156 return NULL;
157
41f9172f 158 /* return HOME if set, otherwise from passwd */
3ef63c31 159 if (!c->user) {
41f9172f
LP
160 char *h;
161
162 r = get_home_dir(&h);
163 if (r < 0)
164 return NULL;
165
166 return h;
167 }
168
3ef63c31 169 username = c->user;
41f9172f
LP
170 r = get_user_creds(&username, NULL, NULL, &home, NULL);
171 if (r < 0)
172 return NULL;
173
174 return strdup(home);
175}
176
177static char *specifier_user_shell(char specifier, void *data, void *userdata) {
3ef63c31
LP
178 Unit *u = userdata;
179 ExecContext *c;
41f9172f
LP
180 int r;
181 const char *username, *shell;
182
6569cae1
LP
183 assert(u);
184
3ef63c31
LP
185 c = unit_get_exec_context(u);
186 if (!c)
187 return NULL;
188
41f9172f 189 /* return HOME if set, otherwise from passwd */
3ef63c31 190 if (!c->user) {
41f9172f
LP
191 char *sh;
192
193 r = get_shell(&sh);
194 if (r < 0)
195 return strdup("/bin/sh");
196
197 return sh;
198 }
199
3ef63c31 200 username = c->user;
41f9172f
LP
201 r = get_user_creds(&username, NULL, NULL, NULL, &shell);
202 if (r < 0)
203 return strdup("/bin/sh");
204
205 return strdup(shell);
206}
207
6569cae1
LP
208static char *specifier_machine_id(char specifier, void *data, void *userdata) {
209 sd_id128_t id;
210 char *buf;
211 int r;
212
213 r = sd_id128_get_machine(&id);
214 if (r < 0)
215 return NULL;
216
217 buf = new(char, 33);
218 if (!buf)
219 return NULL;
220
221 return sd_id128_to_string(id, buf);
222}
223
224static char *specifier_boot_id(char specifier, void *data, void *userdata) {
225 sd_id128_t id;
226 char *buf;
227 int r;
228
229 r = sd_id128_get_boot(&id);
230 if (r < 0)
231 return NULL;
232
233 buf = new(char, 33);
234 if (!buf)
235 return NULL;
236
237 return sd_id128_to_string(id, buf);
238}
239
240static char *specifier_host_name(char specifier, void *data, void *userdata) {
241 return gethostname_malloc();
242}
243
41f9172f
LP
244char *unit_name_printf(Unit *u, const char* format) {
245
246 /*
247 * This will use the passed string as format string and
248 * replace the following specifiers:
249 *
250 * %n: the full id of the unit (foo@bar.waldo)
251 * %N: the id of the unit without the suffix (foo@bar)
252 * %p: the prefix (foo)
253 * %i: the instance (bar)
254 */
255
256 const Specifier table[] = {
257 { 'n', specifier_string, u->id },
258 { 'N', specifier_prefix_and_instance, NULL },
259 { 'p', specifier_prefix, NULL },
260 { 'i', specifier_string, u->instance },
261 { 0, NULL, NULL }
262 };
263
264 assert(u);
265 assert(format);
266
267 return specifier_printf(format, table, u);
268}
269
270char *unit_full_printf(Unit *u, const char *format) {
271
272 /* This is similar to unit_name_printf() but also supports
273 * unescaping. Also, adds a couple of additional codes:
274 *
275 * %f the the instance if set, otherwise the id
276 * %c cgroup path of unit
277 * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
278 * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
279 * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
280 * %u the username of the configured user or running user
281 * %h the homedir of the configured user or running user
282 * %s the shell of the configured user or running user
6569cae1
LP
283 * %m the machine ID of the running system
284 * %b the boot ID of the running system
285 * %H the host name of the running system
41f9172f
LP
286 */
287
288 const Specifier table[] = {
289 { 'n', specifier_string, u->id },
290 { 'N', specifier_prefix_and_instance, NULL },
291 { 'p', specifier_prefix, NULL },
292 { 'P', specifier_prefix_unescaped, NULL },
293 { 'i', specifier_string, u->instance },
294 { 'I', specifier_instance_unescaped, NULL },
295
296 { 'f', specifier_filename, NULL },
297 { 'c', specifier_cgroup, NULL },
298 { 'r', specifier_cgroup_root, NULL },
299 { 'R', specifier_cgroup_root, NULL },
300 { 't', specifier_runtime, NULL },
301 { 'u', specifier_user_name, NULL },
302 { 'h', specifier_user_home, NULL },
303 { 's', specifier_user_shell, NULL },
6569cae1
LP
304
305 { 'm', specifier_machine_id, NULL },
306 { 'H', specifier_host_name, NULL },
307 { 'b', specifier_boot_id, NULL },
41f9172f
LP
308 { 0, NULL, NULL }
309 };
310
311 assert(u);
312 assert(format);
313
314 return specifier_printf(format, table, u);
315}
316
317char **unit_full_printf_strv(Unit *u, char **l) {
318 size_t n;
319 char **r, **i, **j;
320
321 /* Applies unit_full_printf to every entry in l */
322
323 assert(u);
324
325 n = strv_length(l);
326 r = new(char*, n+1);
327 if (!r)
328 return NULL;
329
330 for (i = l, j = r; *i; i++, j++) {
331 *j = unit_full_printf(u, *i);
332 if (!*j)
333 goto fail;
334 }
335
336 *j = NULL;
337 return r;
338
339fail:
340 for (j--; j >= r; j--)
341 free(*j);
342
343 free(r);
344
345 return NULL;
346}