chiark / gitweb /
install: allow specifiers in WantedBy/RequiredBy/Alias
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 28 Jan 2013 04:11:31 +0000 (23:11 -0500)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 30 Jan 2013 00:01:41 +0000 (19:01 -0500)
This allows one templated unit to refer to another templated unit
at installation time.

Examples:

> grep WantedBy ~/.config/systemd/user/mpop@.timer
WantedBy=services@%i.target

> srv disable mpop@iit.timer
rm '/home/alxchk/.config/systemd/user/services@iit.target.wants/mpop@iit.timer'
> srv enable mpop@iit.timer
ln -s '/home/alxchk/.config/systemd/user/mpop@.timer' '/home/alxchk/.config/systemd/user/services@iit.target.wants/mpop@iit.timer'

Based-on-patch-by: Oleksii Shevchuk <alxchk@gmail.com>
Makefile.am
man/systemd.unit.xml
src/core/unit-printf.c
src/shared/install-printf.c [new file with mode: 0644]
src/shared/install-printf.h [new file with mode: 0644]
src/shared/install.c
src/shared/install.h

index 8d10144a945b1d2fe3da74a8d7235d6d8a85f043..c44ca0b76d53f8151e669ec4f8fa8dbf385ecba5 100644 (file)
@@ -901,6 +901,8 @@ noinst_LTLIBRARIES += \
 libsystemd_units_la_SOURCES = \
        src/shared/install.c \
        src/shared/install.h \
+       src/shared/install-printf.c \
+       src/shared/install-printf.h \
        src/shared/path-lookup.c \
        src/shared/path-lookup.h
 
@@ -1403,7 +1405,8 @@ test_strv_SOURCES = \
        src/test/test-strv.c
 
 test_strv_LDADD = \
-       libsystemd-shared.la
+       libsystemd-shared.la \
+       libsystemd-id128-internal.la
 
 test_install_SOURCES = \
        src/test/test-install.c
@@ -1415,7 +1418,8 @@ test_install_CFLAGS = \
 test_install_LDADD = \
        libsystemd-units.la \
        libsystemd-label.la \
-       libsystemd-shared.la
+       libsystemd-shared.la \
+       libsystemd-id128-internal.la
 
 test_watchdog_SOURCES = \
        src/test/test-watchdog.c
index c09b8aae725b6e91ceeb2f6b3eb007a214b78cd9..7c3a6c75f84cd6305949777a15e3b73bf26a7a6e 100644 (file)
                         </varlistentry>
                 </variablelist>
 
+                <para>The following specifiers are interpreted in the
+                Install section: %n, %N, %p, %i, %U, %u, %m, %H, %b.
+                For their meaning see the next section.
+                </para>
         </refsect1>
 
         <refsect1>
index 7430beb3da1598ddaf1faca3f3d5a951d6db4236..7415824cdfc1a0cfc7be6811bac96a38b110fbf3 100644 (file)
@@ -250,12 +250,13 @@ char *unit_full_printf(Unit *u, const char *format) {
          * %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 UID 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
          * %m the machine ID of the running system
-         * %b the boot ID of the running system
          * %H the host name of the running system
+         * %b the boot ID of the running system
          */
 
         const Specifier table[] = {
@@ -282,7 +283,6 @@ char *unit_full_printf(Unit *u, const char *format) {
                 { 0, NULL, NULL }
         };
 
-        assert(u);
         assert(format);
 
         return specifier_printf(format, table, u);
diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c
new file mode 100644 (file)
index 0000000..85aebc4
--- /dev/null
@@ -0,0 +1,95 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+  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 <assert.h>
+#include <stdlib.h>
+
+#include "specifier.h"
+#include "unit-name.h"
+#include "install-printf.h"
+
+static char *specifier_prefix_and_instance(char specifier, void *data, void *userdata) {
+        InstallInfo *i = userdata;
+        assert(i);
+
+        return unit_name_to_prefix_and_instance(i->name);
+}
+
+static char *specifier_prefix(char specifier, void *data, void *userdata) {
+        InstallInfo *i = userdata;
+        assert(i);
+
+        return unit_name_to_prefix(i->name);
+}
+
+static char *specifier_instance(char specifier, void *data, void *userdata) {
+        InstallInfo *i = userdata;
+        char *instance;
+        int r;
+
+        assert(i);
+
+        r = unit_name_to_instance(i->name, &instance);
+        if (r < 0)
+                return NULL;
+        if (instance != NULL)
+                return instance;
+        else
+                return strdup("");
+}
+
+char *install_full_printf(InstallInfo *i, const char *format) {
+
+        /* This is similar to unit_full_printf() but does not support
+         * anything path-related.
+         *
+         * %n: the full id of the unit                 (foo@bar.waldo)
+         * %N: the id of the unit without the suffix   (foo@bar)
+         * %p: the prefix                              (foo)
+         * %i: the instance                            (bar)
+
+         * %U the UID of the configured user or running user
+         * %u the username of the configured user or running user
+         * %m the machine ID of the running system
+         * %H the host name of the running system
+         * %b the boot ID of the running system
+         */
+
+        const Specifier table[] = {
+                { 'n', specifier_string,              i->name },
+                { 'N', specifier_prefix_and_instance, NULL },
+                { 'p', specifier_prefix,              NULL },
+                { 'i', specifier_instance,            NULL },
+
+//                { 'U', specifier_user_name,           NULL },
+//                { 'u', specifier_user_name,           NULL },
+
+                { 'm', specifier_machine_id,          NULL },
+                { 'H', specifier_host_name,           NULL },
+                { 'b', specifier_boot_id,             NULL },
+                { 0, NULL, NULL }
+        };
+
+        assert(i);
+        assert(format);
+
+        return specifier_printf(format, table, i);
+}
diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h
new file mode 100644 (file)
index 0000000..46f5294
--- /dev/null
@@ -0,0 +1,25 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Zbigniew Jędrzejewski-Szmek
+
+  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/>.
+***/
+
+#pragma once
+
+#include "install.h"
+char *install_full_printf(InstallInfo *i, const char *format);
index 24905e1af637b3fef03b5f68b8df25e49e9f22f8..7fb352cffff26e4510240faf012d50a1e9002153 100644 (file)
 #include "install.h"
 #include "conf-parser.h"
 #include "conf-files.h"
-
-typedef struct {
-        char *name;
-        char *path;
-
-        char **aliases;
-        char **wanted_by;
-        char **required_by;
-} InstallInfo;
+#include "specifier.h"
+#include "install-printf.h"
 
 typedef struct {
         Hashmap *will_install;
@@ -1177,16 +1170,17 @@ static int install_info_symlink_alias(
         assert(config_path);
 
         STRV_FOREACH(s, i->aliases) {
-                char *alias_path;
+                char _cleanup_free_ *alias_path = NULL, *dst = NULL;
 
-                alias_path = path_make_absolute(*s, config_path);
+                dst = install_full_printf(i, *s);
+                if (!dst)
+                        return -ENOMEM;
 
+                alias_path = path_make_absolute(dst, config_path);
                 if (!alias_path)
                         return -ENOMEM;
 
                 q = create_symlink(i->path, alias_path, force, changes, n_changes);
-                free(alias_path);
-
                 if (r == 0)
                         r = q;
         }
@@ -1208,18 +1202,21 @@ static int install_info_symlink_wants(
         assert(config_path);
 
         STRV_FOREACH(s, i->wanted_by) {
-                char *path;
+                char _cleanup_free_ *path = NULL, *dst = NULL;
 
-                if (!unit_name_is_valid(*s, true)) {
+                dst = install_full_printf(i, *s);
+                if (!dst)
+                        return -ENOMEM;
+
+                if (!unit_name_is_valid(dst, true)) {
                         r = -EINVAL;
                         continue;
                 }
 
-                if (asprintf(&path, "%s/%s.wants/%s", config_path, *s, i->name) < 0)
+                if (asprintf(&path, "%s/%s.wants/%s", config_path, dst, i->name) < 0)
                         return -ENOMEM;
 
                 q = create_symlink(i->path, path, force, changes, n_changes);
-                free(path);
 
                 if (r == 0)
                         r = q;
@@ -1242,18 +1239,21 @@ static int install_info_symlink_requires(
         assert(config_path);
 
         STRV_FOREACH(s, i->required_by) {
-                char *path;
+                char _cleanup_free_ *path = NULL, *dst = NULL;
 
-                if (!unit_name_is_valid(*s, true)) {
+                dst = install_full_printf(i, *s);
+                if (!dst)
+                        return -ENOMEM;
+
+                if (!unit_name_is_valid(dst, true)) {
                         r = -EINVAL;
                         continue;
                 }
 
-                if (asprintf(&path, "%s/%s.requires/%s", config_path, *s, i->name) < 0)
+                if (asprintf(&path, "%s/%s.requires/%s", config_path, dst, i->name) < 0)
                         return -ENOMEM;
 
                 q = create_symlink(i->path, path, force, changes, n_changes);
-                free(path);
 
                 if (r == 0)
                         r = q;
index 55249914b13bc8aa240039eaadbc28e8cf5a3306..5a351254bb3e21a6172eca232748c240cd95a84b 100644 (file)
@@ -63,6 +63,15 @@ typedef struct UnitFileList {
         UnitFileState state;
 } UnitFileList;
 
+typedef struct {
+        char *name;
+        char *path;
+
+        char **aliases;
+        char **wanted_by;
+        char **required_by;
+} InstallInfo;
+
 int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
 int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);