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