1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
22 #include "systemd/sd-id128.h"
24 #include "specifier.h"
25 #include "path-util.h"
27 #include "unit-name.h"
28 #include "unit-printf.h"
30 static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
34 return unit_name_to_prefix_and_instance(u->id);
37 static char *specifier_prefix(char specifier, void *data, void *userdata) {
41 return unit_name_to_prefix(u->id);
44 static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
50 p = unit_name_to_prefix(u->id);
54 r = unit_name_unescape(p);
60 static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
65 return unit_name_unescape(u->instance);
70 static char *specifier_filename(char specifier, void *data, void *userdata) {
75 return unit_name_path_unescape(u->instance);
77 return unit_name_to_path(u->id);
80 static char *specifier_cgroup(char specifier, void *data, void *userdata) {
84 return unit_default_cgroup_path(u);
87 static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
93 return strdup(u->manager->cgroup_hierarchy);
95 if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
106 static char *specifier_runtime(char specifier, void *data, void *userdata) {
110 if (u->manager->running_as == SYSTEMD_USER) {
113 e = getenv("XDG_RUNTIME_DIR");
118 return strdup("/run");
121 static char *specifier_user_name(char specifier, void *data, void *userdata) {
125 const char *username;
127 char *printed = NULL;
131 c = unit_get_exec_context(u);
133 /* get USER env from our own env if set */
135 return getusername_malloc();
137 /* fish username from passwd */
139 r = get_user_creds(&username, &uid, NULL, NULL, NULL);
145 if (asprintf(&printed, "%d", uid) < 0)
149 printed = strdup(username);
156 static char *specifier_user_home(char specifier, void *data, void *userdata) {
160 const char *username, *home;
164 c = unit_get_exec_context(u);
166 /* return HOME if set, otherwise from passwd */
167 if (!c || !c->user) {
170 r = get_home_dir(&h);
178 r = get_user_creds(&username, NULL, NULL, &home, NULL);
185 static char *specifier_user_shell(char specifier, void *data, void *userdata) {
189 const char *username, *shell;
193 c = unit_get_exec_context(u);
195 /* return HOME if set, otherwise from passwd */
196 if (!c || !c->user) {
201 return strdup("/bin/sh");
207 r = get_user_creds(&username, NULL, NULL, NULL, &shell);
209 return strdup("/bin/sh");
211 return strdup(shell);
214 static char *specifier_machine_id(char specifier, void *data, void *userdata) {
219 r = sd_id128_get_machine(&id);
227 return sd_id128_to_string(id, buf);
230 static char *specifier_boot_id(char specifier, void *data, void *userdata) {
235 r = sd_id128_get_boot(&id);
243 return sd_id128_to_string(id, buf);
246 static char *specifier_host_name(char specifier, void *data, void *userdata) {
247 return gethostname_malloc();
250 char *unit_name_printf(Unit *u, const char* format) {
253 * This will use the passed string as format string and
254 * replace the following specifiers:
256 * %n: the full id of the unit (foo@bar.waldo)
257 * %N: the id of the unit without the suffix (foo@bar)
258 * %p: the prefix (foo)
259 * %i: the instance (bar)
262 const Specifier table[] = {
263 { 'n', specifier_string, u->id },
264 { 'N', specifier_prefix_and_instance, NULL },
265 { 'p', specifier_prefix, NULL },
266 { 'i', specifier_string, u->instance },
273 return specifier_printf(format, table, u);
276 char *unit_full_printf(Unit *u, const char *format) {
278 /* This is similar to unit_name_printf() but also supports
279 * unescaping. Also, adds a couple of additional codes:
281 * %f the the instance if set, otherwise the id
282 * %c cgroup path of unit
283 * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
284 * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
285 * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
286 * %u the username of the configured user or running user
287 * %h the homedir of the configured user or running user
288 * %s the shell of the configured user or running user
289 * %m the machine ID of the running system
290 * %b the boot ID of the running system
291 * %H the host name of the running system
294 const Specifier table[] = {
295 { 'n', specifier_string, u->id },
296 { 'N', specifier_prefix_and_instance, NULL },
297 { 'p', specifier_prefix, NULL },
298 { 'P', specifier_prefix_unescaped, NULL },
299 { 'i', specifier_string, u->instance },
300 { 'I', specifier_instance_unescaped, NULL },
302 { 'f', specifier_filename, NULL },
303 { 'c', specifier_cgroup, NULL },
304 { 'r', specifier_cgroup_root, NULL },
305 { 'R', specifier_cgroup_root, NULL },
306 { 't', specifier_runtime, NULL },
307 { 'U', specifier_user_name, NULL },
308 { 'u', specifier_user_name, NULL },
309 { 'h', specifier_user_home, NULL },
310 { 's', specifier_user_shell, NULL },
312 { 'm', specifier_machine_id, NULL },
313 { 'H', specifier_host_name, NULL },
314 { 'b', specifier_boot_id, NULL },
321 return specifier_printf(format, table, u);
324 char **unit_full_printf_strv(Unit *u, char **l) {
328 /* Applies unit_full_printf to every entry in l */
337 for (i = l, j = r; *i; i++, j++) {
338 *j = unit_full_printf(u, *i);
347 for (j--; j >= r; j--)