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 #include "cgroup-util.h"
33 static int specifier_prefix_and_instance(char specifier, void *data, void *userdata, char **ret) {
39 n = unit_name_to_prefix_and_instance(u->id);
47 static int specifier_prefix(char specifier, void *data, void *userdata, char **ret) {
53 n = unit_name_to_prefix(u->id);
61 static int specifier_prefix_unescaped(char specifier, void *data, void *userdata, char **ret) {
63 _cleanup_free_ char *p = NULL;
68 p = unit_name_to_prefix(u->id);
72 n = unit_name_unescape(p);
80 static int specifier_instance_unescaped(char specifier, void *data, void *userdata, char **ret) {
87 n = unit_name_unescape(u->instance);
98 static int specifier_filename(char specifier, void *data, void *userdata, char **ret) {
105 n = unit_name_path_unescape(u->instance);
107 n = unit_name_to_path(u->id);
116 static int specifier_cgroup(char specifier, void *data, void *userdata, char **ret) {
122 n = unit_default_cgroup_path(u);
130 static int specifier_cgroup_root(char specifier, void *data, void *userdata, char **ret) {
138 slice = unit_slice_name(u);
139 if (specifier == 'R' || !slice)
140 n = strdup(u->manager->cgroup_root);
142 _cleanup_free_ char *p = NULL;
144 r = cg_slice_to_path(slice, &p);
148 n = strjoin(u->manager->cgroup_root, "/", p, NULL);
157 static int specifier_runtime(char specifier, void *data, void *userdata, char **ret) {
163 if (u->manager->running_as == SYSTEMD_USER) {
166 e = getenv("XDG_RUNTIME_DIR");
184 static int specifier_user_name(char specifier, void *data, void *userdata, char **ret) {
188 const char *username;
189 _cleanup_free_ char *tmp = NULL;
191 char *printed = NULL;
195 c = unit_get_exec_context(u);
200 /* get USER env from env or our own uid */
201 username = tmp = getusername_malloc();
203 /* fish username from passwd */
204 r = get_user_creds(&username, &uid, NULL, NULL, NULL);
210 if (asprintf(&printed, "%d", uid) < 0)
214 printed = strdup(username);
225 static int specifier_user_home(char specifier, void *data, void *userdata, char **ret) {
229 const char *username, *home;
234 c = unit_get_exec_context(u);
236 /* return HOME if set, otherwise from passwd */
237 if (!c || !c->user) {
240 r = get_home_dir(&h);
249 r = get_user_creds(&username, NULL, NULL, &home, NULL);
261 static int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) {
265 const char *username, *shell;
270 c = unit_get_exec_context(u);
277 /* return /bin/sh for root, otherwise the value from passwd */
278 r = get_user_creds(&username, NULL, NULL, NULL, &shell);
290 int unit_name_printf(Unit *u, const char* format, char **ret) {
293 * This will use the passed string as format string and
294 * replace the following specifiers:
296 * %n: the full id of the unit (foo@bar.waldo)
297 * %N: the id of the unit without the suffix (foo@bar)
298 * %p: the prefix (foo)
299 * %i: the instance (bar)
302 const Specifier table[] = {
303 { 'n', specifier_string, u->id },
304 { 'N', specifier_prefix_and_instance, NULL },
305 { 'p', specifier_prefix, NULL },
306 { 'i', specifier_string, u->instance },
314 return specifier_printf(format, table, u, ret);
317 int unit_full_printf(Unit *u, const char *format, char **ret) {
319 /* This is similar to unit_name_printf() but also supports
320 * unescaping. Also, adds a couple of additional codes:
322 * %f the the instance if set, otherwise the id
323 * %c cgroup path of unit
324 * %r where units in this slice are place in the cgroup tree
325 * %R the root of this systemd's instance tree
326 * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
327 * %U the UID of the configured user or running user
328 * %u the username of the configured user or running user
329 * %h the homedir of the configured user or running user
330 * %s the shell of the configured user or running user
331 * %m the machine ID of the running system
332 * %H the host name of the running system
333 * %b the boot ID of the running system
334 * %v `uname -r` of the running system
337 const Specifier table[] = {
338 { 'n', specifier_string, u->id },
339 { 'N', specifier_prefix_and_instance, NULL },
340 { 'p', specifier_prefix, NULL },
341 { 'P', specifier_prefix_unescaped, NULL },
342 { 'i', specifier_string, u->instance },
343 { 'I', specifier_instance_unescaped, NULL },
345 { 'f', specifier_filename, NULL },
346 { 'c', specifier_cgroup, NULL },
347 { 'r', specifier_cgroup_root, NULL },
348 { 'R', specifier_cgroup_root, NULL },
349 { 't', specifier_runtime, NULL },
350 { 'U', specifier_user_name, NULL },
351 { 'u', specifier_user_name, NULL },
352 { 'h', specifier_user_home, NULL },
353 { 's', specifier_user_shell, NULL },
355 { 'm', specifier_machine_id, NULL },
356 { 'H', specifier_host_name, NULL },
357 { 'b', specifier_boot_id, NULL },
358 { 'v', specifier_kernel_release, NULL },
366 return specifier_printf(format, table, u, ret);
369 int unit_full_printf_strv(Unit *u, char **l, char ***ret) {
374 /* Applies unit_full_printf to every entry in l */
383 for (i = l, j = r; *i; i++, j++) {
384 q = unit_full_printf(u, *i, j);
394 for (j--; j >= r; j--)