[systemd-commits] 4 commits - Makefile.am TODO man/systemd.unit.xml src/core

Lennart Poettering lennart at kemper.freedesktop.org
Tue Sep 18 02:55:20 PDT 2012


 Makefile.am              |    2 
 TODO                     |    9 -
 man/systemd.unit.xml     |   15 ++
 src/core/load-fragment.c |    1 
 src/core/mount.c         |    2 
 src/core/service.c       |    3 
 src/core/socket.c        |    3 
 src/core/swap.c          |    2 
 src/core/unit-printf.c   |  346 +++++++++++++++++++++++++++++++++++++++++++++++
 src/core/unit-printf.h   |   28 +++
 src/core/unit.c          |  266 ++----------------------------------
 src/core/unit.h          |   12 +
 12 files changed, 429 insertions(+), 260 deletions(-)

New commits:
commit 6569cae18ed640a4e9f52f73e2a3ec54b07d0406
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 11:53:47 2012 +0200

    unit-printf: add specifiers for the host name, machine id, boot id

diff --git a/TODO b/TODO
index 2a3cc77..f7da51c 100644
--- a/TODO
+++ b/TODO
@@ -62,8 +62,6 @@ Features:
 
 * journald: add kernel cmdline option to disable ratelimiting for debug purposes
 
-* Add a way to reference the machine/boot ID from ExecStart= and similar command lines
-
 * move PID 1 segfaults to /var/lib/systemd/coredump?
 
 * Document word splitting syntax for ExecStart= and friends
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index e0aadf4..5556968 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -273,6 +273,21 @@
                         <entry>User shell</entry>
                         <entry>This is the shell of the configured user of the unit, or (if none is set) the user running the systemd instance.</entry>
                       </row>
+                      <row>
+                        <entry><literal>%m</literal></entry>
+                        <entry>Machine ID</entry>
+                        <entry>The machine ID of the running system, formatted as string. See <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information.</entry>
+                      </row>
+                      <row>
+                        <entry><literal>%b</literal></entry>
+                        <entry>Boot ID</entry>
+                        <entry>The boot ID of the running system, formatted as string. See <citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry> for more information.</entry>
+                      </row>
+                      <row>
+                        <entry><literal>%H</literal></entry>
+                        <entry>Host name</entry>
+                        <entry>The host name of the running system.</entry>
+                      </row>
                     </tbody>
                   </tgroup>
                 </table>
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index 35da29a..308bbd6 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -124,6 +124,8 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
         int r;
         const char *username;
 
+        assert(u);
+
         c = unit_get_exec_context(u);
         if (!c)
                 return NULL;
@@ -147,6 +149,8 @@ static char *specifier_user_home(char specifier, void *data, void *userdata) {
         int r;
         const char *username, *home;
 
+        assert(u);
+
         c = unit_get_exec_context(u);
         if (!c)
                 return NULL;
@@ -176,6 +180,8 @@ static char *specifier_user_shell(char specifier, void *data, void *userdata) {
         int r;
         const char *username, *shell;
 
+        assert(u);
+
         c = unit_get_exec_context(u);
         if (!c)
                 return NULL;
@@ -199,6 +205,42 @@ static char *specifier_user_shell(char specifier, void *data, void *userdata) {
         return strdup(shell);
 }
 
+static char *specifier_machine_id(char specifier, void *data, void *userdata) {
+        sd_id128_t id;
+        char *buf;
+        int r;
+
+        r = sd_id128_get_machine(&id);
+        if (r < 0)
+                return NULL;
+
+        buf = new(char, 33);
+        if (!buf)
+                return NULL;
+
+        return sd_id128_to_string(id, buf);
+}
+
+static char *specifier_boot_id(char specifier, void *data, void *userdata) {
+        sd_id128_t id;
+        char *buf;
+        int r;
+
+        r = sd_id128_get_boot(&id);
+        if (r < 0)
+                return NULL;
+
+        buf = new(char, 33);
+        if (!buf)
+                return NULL;
+
+        return sd_id128_to_string(id, buf);
+}
+
+static char *specifier_host_name(char specifier, void *data, void *userdata) {
+        return gethostname_malloc();
+}
+
 char *unit_name_printf(Unit *u, const char* format) {
 
         /*
@@ -238,6 +280,9 @@ char *unit_full_printf(Unit *u, const char *format) {
          * %u the username of the configured user or running user
          * %h the homedir of the configured user or running user
          * %s the shell of the configured user or running user
+         * %m the machine ID of the running system
+         * %b the boot ID of the running system
+         * %H the host name of the running system
          */
 
         const Specifier table[] = {
@@ -256,6 +301,10 @@ char *unit_full_printf(Unit *u, const char *format) {
                 { 'u', specifier_user_name,           NULL },
                 { 'h', specifier_user_home,           NULL },
                 { 's', specifier_user_shell,          NULL },
+
+                { 'm', specifier_machine_id,          NULL },
+                { 'H', specifier_host_name,           NULL },
+                { 'b', specifier_boot_id,             NULL },
                 { 0, NULL, NULL }
         };
 

commit 3ef63c317481c2b3f1fe39e1b0f130aac3544522
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 11:40:01 2012 +0200

    unit-printf: before resolving exec context specifiers check whether the object actually has an exec context

diff --git a/src/core/mount.c b/src/core/mount.c
index fc981c7..92e2f73 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1797,6 +1797,8 @@ DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
 
 const UnitVTable mount_vtable = {
         .object_size = sizeof(Mount),
+        .exec_context_offset = offsetof(Mount, exec_context),
+
         .sections =
                 "Unit\0"
                 "Mount\0"
diff --git a/src/core/service.c b/src/core/service.c
index 1e3e875..39e1ab5 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3837,6 +3837,8 @@ DEFINE_STRING_TABLE_LOOKUP(start_limit_action, StartLimitAction);
 
 const UnitVTable service_vtable = {
         .object_size = sizeof(Service),
+        .exec_context_offset = offsetof(Service, exec_context),
+
         .sections =
                 "Unit\0"
                 "Service\0"
diff --git a/src/core/socket.c b/src/core/socket.c
index 63e6ed2..3614045 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2196,6 +2196,8 @@ DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
 
 const UnitVTable socket_vtable = {
         .object_size = sizeof(Socket),
+        .exec_context_offset = offsetof(Socket, exec_context),
+
         .sections =
                 "Unit\0"
                 "Socket\0"
diff --git a/src/core/swap.c b/src/core/swap.c
index 8ba6055..d5bf153 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -1355,6 +1355,8 @@ DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
 
 const UnitVTable swap_vtable = {
         .object_size = sizeof(Swap),
+        .exec_context_offset = offsetof(Swap, exec_context),
+
         .sections =
                 "Unit\0"
                 "Swap\0"
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
index cd49206..35da29a 100644
--- a/src/core/unit-printf.c
+++ b/src/core/unit-printf.c
@@ -119,16 +119,21 @@ static char *specifier_runtime(char specifier, void *data, void *userdata) {
 }
 
 static char *specifier_user_name(char specifier, void *data, void *userdata) {
-        Service *s = userdata;
+        Unit *u = userdata;
+        ExecContext *c;
         int r;
         const char *username;
 
+        c = unit_get_exec_context(u);
+        if (!c)
+                return NULL;
+
         /* get USER env from our own env if set */
-        if (!s->exec_context.user)
+        if (!c->user)
                 return getusername_malloc();
 
         /* fish username from passwd */
-        username = s->exec_context.user;
+        username = c->user;
         r = get_user_creds(&username, NULL, NULL, NULL, NULL);
         if (r < 0)
                 return NULL;
@@ -137,12 +142,17 @@ static char *specifier_user_name(char specifier, void *data, void *userdata) {
 }
 
 static char *specifier_user_home(char specifier, void *data, void *userdata) {
-        Service *s = userdata;
+        Unit *u = userdata;
+        ExecContext *c;
         int r;
         const char *username, *home;
 
+        c = unit_get_exec_context(u);
+        if (!c)
+                return NULL;
+
         /* return HOME if set, otherwise from passwd */
-        if (!s->exec_context.user) {
+        if (!c->user) {
                 char *h;
 
                 r = get_home_dir(&h);
@@ -152,7 +162,7 @@ static char *specifier_user_home(char specifier, void *data, void *userdata) {
                 return h;
         }
 
-        username = s->exec_context.user;
+        username = c->user;
         r = get_user_creds(&username, NULL, NULL, &home, NULL);
         if (r < 0)
                return NULL;
@@ -161,12 +171,17 @@ static char *specifier_user_home(char specifier, void *data, void *userdata) {
 }
 
 static char *specifier_user_shell(char specifier, void *data, void *userdata) {
-        Service *s = userdata;
+        Unit *u = userdata;
+        ExecContext *c;
         int r;
         const char *username, *shell;
 
+        c = unit_get_exec_context(u);
+        if (!c)
+                return NULL;
+
         /* return HOME if set, otherwise from passwd */
-        if (!s->exec_context.user) {
+        if (!c->user) {
                 char *sh;
 
                 r = get_shell(&sh);
@@ -176,7 +191,7 @@ static char *specifier_user_shell(char specifier, void *data, void *userdata) {
                 return sh;
         }
 
-        username = s->exec_context.user;
+        username = c->user;
         r = get_user_creds(&username, NULL, NULL, NULL, &shell);
         if (r < 0)
                 return strdup("/bin/sh");
diff --git a/src/core/unit.c b/src/core/unit.c
index 4eea5b5..1e33936 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2684,6 +2684,17 @@ int unit_exec_context_defaults(Unit *u, ExecContext *c) {
         return 0;
 }
 
+ExecContext *unit_get_exec_context(Unit *u) {
+        size_t offset;
+        assert(u);
+
+        offset = UNIT_VTABLE(u)->exec_context_offset;
+        if (offset <= 0)
+                return NULL;
+
+        return (ExecContext*) ((uint8_t*) u + offset);
+}
+
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
         [UNIT_RELOADING] = "reloading",
diff --git a/src/core/unit.h b/src/core/unit.h
index da715dc..bf961c2 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -266,6 +266,10 @@ struct UnitVTable {
         /* How much memory does an object of this unit type need */
         size_t object_size;
 
+        /* If greater than 0, the offset into the object where
+         * ExecContext is found, if the unit type has that */
+        size_t exec_context_offset;
+
         /* Config file sections this unit type understands, separated
          * by NUL chars */
         const char *sections;
@@ -538,6 +542,8 @@ int unit_add_mount_links(Unit *u);
 
 int unit_exec_context_defaults(Unit *u, ExecContext *c);
 
+ExecContext *unit_get_exec_context(Unit *u);
+
 const char *unit_active_state_to_string(UnitActiveState i);
 UnitActiveState unit_active_state_from_string(const char *s);
 

commit 41f9172f427bdbb8221c64029f78364b8dd4e527
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 11:27:56 2012 +0200

    unit: split unit_printf() and friends into its own .c file

diff --git a/Makefile.am b/Makefile.am
index c7aff78..5da132c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -909,6 +909,8 @@ noinst_LTLIBRARIES += \
 libsystemd_core_la_SOURCES = \
 	src/core/unit.c \
 	src/core/unit.h \
+	src/core/unit-printf.c \
+	src/core/unit-printf.h \
 	src/core/job.c \
 	src/core/job.h \
 	src/core/manager.c \
diff --git a/TODO b/TODO
index 8addd6e..2a3cc77 100644
--- a/TODO
+++ b/TODO
@@ -30,7 +30,8 @@ F18:
 
 Features:
 
-* instantiated target units
+* instantiated [Install] for target units
+  https://bugs.freedesktop.org/show_bug.cgi?id=54377
 
 * support *static* (/run) hibernate inhibitors. All rpm -i actions should completely prevent any
   sort of hibernate action until the next reboot. If the kernel or any other base tool is replaced
@@ -40,10 +41,12 @@ Features:
 * move debug shell to tty6 and make sure this doesn't break the gettys on tty6
 
 * move cryptsetup key caching into kernel keyctl?
+  https://bugs.freedesktop.org/show_bug.cgi?id=54982
 
 * make nspawn work without terminal
 
 * hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
+  https://bugs.freedesktop.org/show_bug.cgi?id=54712
 
 * after deserializing sockets in socket.c we should reapply sockopts and things
 
@@ -55,8 +58,6 @@ Features:
 
 * http://lists.freedesktop.org/archives/systemd-devel/2012-September/006502.html
 
-* don't use writev() in tmpfiles for sake of compat with sysfs?
-
 * come up with a nice way to write queue/read_ahead_kb for a block device without interfering with readahead
 
 * journald: add kernel cmdline option to disable ratelimiting for debug purposes
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 1f3da70..0d5d841 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -42,6 +42,7 @@
 #include "securebits.h"
 #include "missing.h"
 #include "unit-name.h"
+#include "unit-printf.h"
 #include "bus-errors.h"
 #include "utf8.h"
 #include "path-util.h"
diff --git a/src/core/service.c b/src/core/service.c
index 5f7ddfa..1e3e875 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -33,6 +33,7 @@
 #include "log.h"
 #include "strv.h"
 #include "unit-name.h"
+#include "unit-printf.h"
 #include "dbus-service.h"
 #include "special.h"
 #include "bus-errors.h"
diff --git a/src/core/socket.c b/src/core/socket.c
index f346030..63e6ed2 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -39,6 +39,7 @@
 #include "mkdir.h"
 #include "path-util.h"
 #include "unit-name.h"
+#include "unit-printf.h"
 #include "dbus-socket.h"
 #include "missing.h"
 #include "special.h"
diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c
new file mode 100644
index 0000000..cd49206
--- /dev/null
+++ b/src/core/unit-printf.c
@@ -0,0 +1,282 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "systemd/sd-id128.h"
+#include "unit.h"
+#include "specifier.h"
+#include "path-util.h"
+#include "strv.h"
+#include "unit-name.h"
+#include "unit-printf.h"
+
+static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        assert(u);
+
+        return unit_name_to_prefix_and_instance(u->id);
+}
+
+static char *specifier_prefix(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        assert(u);
+
+        return unit_name_to_prefix(u->id);
+}
+
+static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        char *p, *r;
+
+        assert(u);
+
+        p = unit_name_to_prefix(u->id);
+        if (!p)
+                return NULL;
+
+        r = unit_name_unescape(p);
+        free(p);
+
+        return r;
+}
+
+static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        assert(u);
+
+        if (u->instance)
+                return unit_name_unescape(u->instance);
+
+        return strdup("");
+}
+
+static char *specifier_filename(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        assert(u);
+
+        if (u->instance)
+                return unit_name_path_unescape(u->instance);
+
+        return unit_name_to_path(u->id);
+}
+
+static char *specifier_cgroup(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        assert(u);
+
+        return unit_default_cgroup_path(u);
+}
+
+static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        char *p;
+        assert(u);
+
+        if (specifier == 'r')
+                return strdup(u->manager->cgroup_hierarchy);
+
+        if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
+                return strdup("");
+
+        if (streq(p, "/")) {
+                free(p);
+                return strdup("");
+        }
+
+        return p;
+}
+
+static char *specifier_runtime(char specifier, void *data, void *userdata) {
+        Unit *u = userdata;
+        assert(u);
+
+        if (u->manager->running_as == MANAGER_USER) {
+                const char *e;
+
+                e = getenv("XDG_RUNTIME_DIR");
+                if (e)
+                        return strdup(e);
+        }
+
+        return strdup("/run");
+}
+
+static char *specifier_user_name(char specifier, void *data, void *userdata) {
+        Service *s = userdata;
+        int r;
+        const char *username;
+
+        /* get USER env from our own env if set */
+        if (!s->exec_context.user)
+                return getusername_malloc();
+
+        /* fish username from passwd */
+        username = s->exec_context.user;
+        r = get_user_creds(&username, NULL, NULL, NULL, NULL);
+        if (r < 0)
+                return NULL;
+
+        return strdup(username);
+}
+
+static char *specifier_user_home(char specifier, void *data, void *userdata) {
+        Service *s = userdata;
+        int r;
+        const char *username, *home;
+
+        /* return HOME if set, otherwise from passwd */
+        if (!s->exec_context.user) {
+                char *h;
+
+                r = get_home_dir(&h);
+                if (r < 0)
+                        return NULL;
+
+                return h;
+        }
+
+        username = s->exec_context.user;
+        r = get_user_creds(&username, NULL, NULL, &home, NULL);
+        if (r < 0)
+               return NULL;
+
+        return strdup(home);
+}
+
+static char *specifier_user_shell(char specifier, void *data, void *userdata) {
+        Service *s = userdata;
+        int r;
+        const char *username, *shell;
+
+        /* return HOME if set, otherwise from passwd */
+        if (!s->exec_context.user) {
+                char *sh;
+
+                r = get_shell(&sh);
+                if (r < 0)
+                        return strdup("/bin/sh");
+
+                return sh;
+        }
+
+        username = s->exec_context.user;
+        r = get_user_creds(&username, NULL, NULL, NULL, &shell);
+        if (r < 0)
+                return strdup("/bin/sh");
+
+        return strdup(shell);
+}
+
+char *unit_name_printf(Unit *u, const char* format) {
+
+        /*
+         * This will use the passed string as format string and
+         * replace the following specifiers:
+         *
+         * %n: the full id of the unit                 (foo at bar.waldo)
+         * %N: the id of the unit without the suffix   (foo at bar)
+         * %p: the prefix                              (foo)
+         * %i: the instance                            (bar)
+         */
+
+        const Specifier table[] = {
+                { 'n', specifier_string,              u->id },
+                { 'N', specifier_prefix_and_instance, NULL },
+                { 'p', specifier_prefix,              NULL },
+                { 'i', specifier_string,              u->instance },
+                { 0, NULL, NULL }
+        };
+
+        assert(u);
+        assert(format);
+
+        return specifier_printf(format, table, u);
+}
+
+char *unit_full_printf(Unit *u, const char *format) {
+
+        /* This is similar to unit_name_printf() but also supports
+         * unescaping. Also, adds a couple of additional codes:
+         *
+         * %f the the instance if set, otherwise the id
+         * %c cgroup path of unit
+         * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
+         * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
+         * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
+         * %u the username of the configured user or running user
+         * %h the homedir of the configured user or running user
+         * %s the shell of the configured user or running user
+         */
+
+        const Specifier table[] = {
+                { 'n', specifier_string,              u->id },
+                { 'N', specifier_prefix_and_instance, NULL },
+                { 'p', specifier_prefix,              NULL },
+                { 'P', specifier_prefix_unescaped,    NULL },
+                { 'i', specifier_string,              u->instance },
+                { 'I', specifier_instance_unescaped,  NULL },
+
+                { 'f', specifier_filename,            NULL },
+                { 'c', specifier_cgroup,              NULL },
+                { 'r', specifier_cgroup_root,         NULL },
+                { 'R', specifier_cgroup_root,         NULL },
+                { 't', specifier_runtime,             NULL },
+                { 'u', specifier_user_name,           NULL },
+                { 'h', specifier_user_home,           NULL },
+                { 's', specifier_user_shell,          NULL },
+                { 0, NULL, NULL }
+        };
+
+        assert(u);
+        assert(format);
+
+        return specifier_printf(format, table, u);
+}
+
+char **unit_full_printf_strv(Unit *u, char **l) {
+        size_t n;
+        char **r, **i, **j;
+
+        /* Applies unit_full_printf to every entry in l */
+
+        assert(u);
+
+        n = strv_length(l);
+        r = new(char*, n+1);
+        if (!r)
+                return NULL;
+
+        for (i = l, j = r; *i; i++, j++) {
+                *j = unit_full_printf(u, *i);
+                if (!*j)
+                        goto fail;
+        }
+
+        *j = NULL;
+        return r;
+
+fail:
+        for (j--; j >= r; j--)
+                free(*j);
+
+        free(r);
+
+        return NULL;
+}
diff --git a/src/core/unit-printf.h b/src/core/unit-printf.h
new file mode 100644
index 0000000..d2f4ccd
--- /dev/null
+++ b/src/core/unit-printf.h
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "unit.h"
+
+char *unit_name_printf(Unit *u, const char* text);
+char *unit_full_printf(Unit *u, const char *text);
+char **unit_full_printf_strv(Unit *u, char **l);
diff --git a/src/core/unit.c b/src/core/unit.c
index 6554401..4eea5b5 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -40,7 +40,6 @@
 #include "load-dropin.h"
 #include "log.h"
 #include "unit-name.h"
-#include "specifier.h"
 #include "dbus-unit.h"
 #include "special.h"
 #include "cgroup-util.h"
@@ -1965,7 +1964,7 @@ int unit_add_cgroup(Unit *u, CGroupBonding *b) {
         return 0;
 }
 
-static char *default_cgroup_path(Unit *u) {
+char *unit_default_cgroup_path(Unit *u) {
         char *p;
 
         assert(u);
@@ -1998,7 +1997,7 @@ int unit_add_cgroup_from_text(Unit *u, const char *name) {
                 return r;
 
         if (!path) {
-                path = default_cgroup_path(u);
+                path = unit_default_cgroup_path(u);
                 ours = true;
         }
 
@@ -2060,7 +2059,8 @@ static int unit_add_one_default_cgroup(Unit *u, const char *controller) {
         if (!(b->controller = strdup(controller)))
                 goto fail;
 
-        if (!(b->path = default_cgroup_path(u)))
+        b->path = unit_default_cgroup_path(u);
+        if (!b->path)
                 goto fail;
 
         b->ours = true;
@@ -2217,256 +2217,6 @@ int unit_get_related_unit(Unit *u, const char *type, Unit **_found) {
         return 0;
 }
 
-static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        assert(u);
-
-        return unit_name_to_prefix_and_instance(u->id);
-}
-
-static char *specifier_prefix(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        assert(u);
-
-        return unit_name_to_prefix(u->id);
-}
-
-static char *specifier_prefix_unescaped(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        char *p, *r;
-
-        assert(u);
-
-        if (!(p = unit_name_to_prefix(u->id)))
-                return NULL;
-
-        r = unit_name_unescape(p);
-        free(p);
-
-        return r;
-}
-
-static char *specifier_instance_unescaped(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        assert(u);
-
-        if (u->instance)
-                return unit_name_unescape(u->instance);
-
-        return strdup("");
-}
-
-static char *specifier_filename(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        assert(u);
-
-        if (u->instance)
-                return unit_name_path_unescape(u->instance);
-
-        return unit_name_to_path(u->id);
-}
-
-static char *specifier_cgroup(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        assert(u);
-
-        return default_cgroup_path(u);
-}
-
-static char *specifier_cgroup_root(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        char *p;
-        assert(u);
-
-        if (specifier == 'r')
-                return strdup(u->manager->cgroup_hierarchy);
-
-        if (path_get_parent(u->manager->cgroup_hierarchy, &p) < 0)
-                return strdup("");
-
-        if (streq(p, "/")) {
-                free(p);
-                return strdup("");
-        }
-
-        return p;
-}
-
-static char *specifier_runtime(char specifier, void *data, void *userdata) {
-        Unit *u = userdata;
-        assert(u);
-
-        if (u->manager->running_as == MANAGER_USER) {
-                const char *e;
-
-                e = getenv("XDG_RUNTIME_DIR");
-                if (e)
-                        return strdup(e);
-        }
-
-        return strdup("/run");
-}
-
-static char *specifier_user_name(char specifier, void *data, void *userdata) {
-        Service *s = userdata;
-        int r;
-        const char *username;
-
-        /* get USER env from our own env if set */
-        if (!s->exec_context.user)
-                return getusername_malloc();
-
-        /* fish username from passwd */
-        username = s->exec_context.user;
-        r = get_user_creds(&username, NULL, NULL, NULL, NULL);
-        if (r < 0)
-                return NULL;
-
-        return strdup(username);
-}
-
-static char *specifier_user_home(char specifier, void *data, void *userdata) {
-        Service *s = userdata;
-        int r;
-        const char *username, *home;
-
-        /* return HOME if set, otherwise from passwd */
-        if (!s->exec_context.user) {
-                char *h;
-
-                r = get_home_dir(&h);
-                if (r < 0)
-                        return NULL;
-
-                return h;
-        }
-
-        username = s->exec_context.user;
-        r = get_user_creds(&username, NULL, NULL, &home, NULL);
-        if (r < 0)
-               return NULL;
-
-        return strdup(home);
-}
-
-static char *specifier_user_shell(char specifier, void *data, void *userdata) {
-        Service *s = userdata;
-        int r;
-        const char *username, *shell;
-
-        /* return HOME if set, otherwise from passwd */
-        if (!s->exec_context.user) {
-                char *sh;
-
-                r = get_shell(&sh);
-                if (r < 0)
-                        return strdup("/bin/sh");
-
-                return sh;
-        }
-
-        username = s->exec_context.user;
-        r = get_user_creds(&username, NULL, NULL, NULL, &shell);
-        if (r < 0)
-                return strdup("/bin/sh");
-
-        return strdup(shell);
-}
-
-char *unit_name_printf(Unit *u, const char* format) {
-
-        /*
-         * This will use the passed string as format string and
-         * replace the following specifiers:
-         *
-         * %n: the full id of the unit                 (foo at bar.waldo)
-         * %N: the id of the unit without the suffix   (foo at bar)
-         * %p: the prefix                              (foo)
-         * %i: the instance                            (bar)
-         */
-
-        const Specifier table[] = {
-                { 'n', specifier_string,              u->id },
-                { 'N', specifier_prefix_and_instance, NULL },
-                { 'p', specifier_prefix,              NULL },
-                { 'i', specifier_string,              u->instance },
-                { 0, NULL, NULL }
-        };
-
-        assert(u);
-        assert(format);
-
-        return specifier_printf(format, table, u);
-}
-
-char *unit_full_printf(Unit *u, const char *format) {
-
-        /* This is similar to unit_name_printf() but also supports
-         * unescaping. Also, adds a couple of additional codes:
-         *
-         * %f the the instance if set, otherwise the id
-         * %c cgroup path of unit
-         * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
-         * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
-         * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
-         * %u the username of the configured user or running user
-         * %h the homedir of the configured user or running user
-         * %s the shell of the configured user or running user
-         */
-
-        const Specifier table[] = {
-                { 'n', specifier_string,              u->id },
-                { 'N', specifier_prefix_and_instance, NULL },
-                { 'p', specifier_prefix,              NULL },
-                { 'P', specifier_prefix_unescaped,    NULL },
-                { 'i', specifier_string,              u->instance },
-                { 'I', specifier_instance_unescaped,  NULL },
-
-                { 'f', specifier_filename,            NULL },
-                { 'c', specifier_cgroup,              NULL },
-                { 'r', specifier_cgroup_root,         NULL },
-                { 'R', specifier_cgroup_root,         NULL },
-                { 't', specifier_runtime,             NULL },
-                { 'u', specifier_user_name,           NULL },
-                { 'h', specifier_user_home,           NULL },
-                { 's', specifier_user_shell,          NULL },
-                { 0, NULL, NULL }
-        };
-
-        assert(u);
-        assert(format);
-
-        return specifier_printf(format, table, u);
-}
-
-char **unit_full_printf_strv(Unit *u, char **l) {
-        size_t n;
-        char **r, **i, **j;
-
-        /* Applies unit_full_printf to every entry in l */
-
-        assert(u);
-
-        n = strv_length(l);
-        if (!(r = new(char*, n+1)))
-                return NULL;
-
-        for (i = l, j = r; *i; i++, j++)
-                if (!(*j = unit_full_printf(u, *i)))
-                        goto fail;
-
-        *j = NULL;
-        return r;
-
-fail:
-        for (j--; j >= r; j--)
-                free(*j);
-
-        free(r);
-
-        return NULL;
-}
-
 int unit_watch_bus_name(Unit *u, const char *name) {
         assert(u);
         assert(name);
diff --git a/src/core/unit.h b/src/core/unit.h
index 5b4dda4..da715dc 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -495,10 +495,6 @@ char *unit_dbus_path(Unit *u);
 int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
 int unit_get_related_unit(Unit *u, const char *type, Unit **_found);
 
-char *unit_name_printf(Unit *u, const char* text);
-char *unit_full_printf(Unit *u, const char *text);
-char **unit_full_printf_strv(Unit *u, char **l);
-
 bool unit_can_serialize(Unit *u);
 int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
 void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_attr_(4,5);
@@ -522,6 +518,8 @@ bool unit_pending_active(Unit *u);
 
 int unit_add_default_target_dependency(Unit *u, Unit *target);
 
+char *unit_default_cgroup_path(Unit *u);
+
 int unit_following_set(Unit *u, Set **s);
 
 void unit_trigger_on_failure(Unit *u);

commit 99006251161aee07b6a099e3186b4360be66eeaa
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Sep 18 11:18:37 2012 +0200

    unit: fix %f resolving

diff --git a/src/core/unit.c b/src/core/unit.c
index be0d654..6554401 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2263,7 +2263,7 @@ static char *specifier_filename(char specifier, void *data, void *userdata) {
         if (u->instance)
                 return unit_name_path_unescape(u->instance);
 
-        return unit_name_to_path(u->instance);
+        return unit_name_to_path(u->id);
 }
 
 static char *specifier_cgroup(char specifier, void *data, void *userdata) {
@@ -2404,12 +2404,14 @@ char *unit_full_printf(Unit *u, const char *format) {
         /* This is similar to unit_name_printf() but also supports
          * unescaping. Also, adds a couple of additional codes:
          *
+         * %f the the instance if set, otherwise the id
          * %c cgroup path of unit
          * %r root cgroup path of this systemd instance (e.g. "/user/lennart/shared/systemd-4711")
          * %R parent of root cgroup path (e.g. "/usr/lennart/shared")
          * %t the runtime directory to place sockets in (e.g. "/run" or $XDG_RUNTIME_DIR)
-         * %u the username of the configured User or running user
-         * %h the homedir of the configured User or running user
+         * %u the username of the configured user or running user
+         * %h the homedir of the configured user or running user
+         * %s the shell of the configured user or running user
          */
 
         const Specifier table[] = {
@@ -2419,6 +2421,7 @@ char *unit_full_printf(Unit *u, const char *format) {
                 { 'P', specifier_prefix_unescaped,    NULL },
                 { 'i', specifier_string,              u->instance },
                 { 'I', specifier_instance_unescaped,  NULL },
+
                 { 'f', specifier_filename,            NULL },
                 { 'c', specifier_cgroup,              NULL },
                 { 'r', specifier_cgroup_root,         NULL },



More information about the systemd-commits mailing list