chiark / gitweb /
Revert "Implement SocketUser= and SocketGroup= for [Socket]"
[elogind.git] / src / core / unit-printf.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 "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
30 static 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
37 static 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
44 static 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
60 static 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
70 static 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
80 static 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
87 static 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
106 static char *specifier_runtime(char specifier, void *data, void *userdata) {
107         Unit *u = userdata;
108         assert(u);
109
110         if (u->manager->running_as == SYSTEMD_USER) {
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
121 static char *specifier_user_name(char specifier, void *data, void *userdata) {
122         Unit *u = userdata;
123         ExecContext *c;
124         int r;
125         const char *username;
126
127         assert(u);
128
129         c = unit_get_exec_context(u);
130         if (!c)
131                 return NULL;
132
133         /* get USER env from our own env if set */
134         if (!c->user)
135                 return getusername_malloc();
136
137         /* fish username from passwd */
138         username = c->user;
139         r = get_user_creds(&username, NULL, NULL, NULL, NULL);
140         if (r < 0)
141                 return NULL;
142
143         return strdup(username);
144 }
145
146 static char *specifier_user_home(char specifier, void *data, void *userdata) {
147         Unit *u = userdata;
148         ExecContext *c;
149         int r;
150         const char *username, *home;
151
152         assert(u);
153
154         c = unit_get_exec_context(u);
155         if (!c)
156                 return NULL;
157
158         /* return HOME if set, otherwise from passwd */
159         if (!c->user) {
160                 char *h;
161
162                 r = get_home_dir(&h);
163                 if (r < 0)
164                         return NULL;
165
166                 return h;
167         }
168
169         username = c->user;
170         r = get_user_creds(&username, NULL, NULL, &home, NULL);
171         if (r < 0)
172                return NULL;
173
174         return strdup(home);
175 }
176
177 static char *specifier_user_shell(char specifier, void *data, void *userdata) {
178         Unit *u = userdata;
179         ExecContext *c;
180         int r;
181         const char *username, *shell;
182
183         assert(u);
184
185         c = unit_get_exec_context(u);
186         if (!c)
187                 return NULL;
188
189         /* return HOME if set, otherwise from passwd */
190         if (!c->user) {
191                 char *sh;
192
193                 r = get_shell(&sh);
194                 if (r < 0)
195                         return strdup("/bin/sh");
196
197                 return sh;
198         }
199
200         username = c->user;
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
208 static 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
224 static 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
240 static char *specifier_host_name(char specifier, void *data, void *userdata) {
241         return gethostname_malloc();
242 }
243
244 char *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
270 char *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
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
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 },
304
305                 { 'm', specifier_machine_id,          NULL },
306                 { 'H', specifier_host_name,           NULL },
307                 { 'b', specifier_boot_id,             NULL },
308                 { 0, NULL, NULL }
309         };
310
311         assert(u);
312         assert(format);
313
314         return specifier_printf(format, table, u);
315 }
316
317 char **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
339 fail:
340         for (j--; j >= r; j--)
341                 free(*j);
342
343         free(r);
344
345         return NULL;
346 }