]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
manager: read ~/.config/systemd/user.conf in user mode
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 19 Feb 2021 09:56:04 +0000 (10:56 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 22 Feb 2021 09:03:07 +0000 (10:03 +0100)
This changes the paths we read user manager config from in two ways:

- split-usr-root paths are dropped. The user manager is a poster boy for
  non-early-boot, so reading dropins only from /usr is appropriate.

- we look at ~/.config/systemd/user.conf. Users should be allowed to override
  their own config.

As user managers become more and more used, it becomes more important for users
to customize their own daemon. By reading from ~/.config, this is possible
without privileges.

man/systemd-system.conf.xml
src/core/main.c

index 075666ac6b0814190846f104e5268235ef326887..0811e1909e94dd9caa202077b2f31fe40167308d 100644 (file)
@@ -31,7 +31,9 @@
     <filename>/etc/systemd/system.conf.d/*.conf</filename>,
     <filename>/run/systemd/system.conf.d/*.conf</filename>,
     <filename>/usr/lib/systemd/system.conf.d/*.conf</filename></para>
-    <para><filename>/etc/systemd/user.conf</filename>,
+
+    <para><filename>~/.config/systemd/user.conf</filename>,
+    <filename>/etc/systemd/user.conf</filename>,
     <filename>/etc/systemd/user.conf.d/*.conf</filename>,
     <filename>/run/systemd/user.conf.d/*.conf</filename>,
     <filename>/usr/lib/systemd/user.conf.d/*.conf</filename></para>
   <refsect1>
     <title>Description</title>
 
-    <para>When run as a system instance, systemd interprets the
-    configuration file <filename>system.conf</filename> and the files
-    in <filename>system.conf.d</filename> directories; when run as a
-    user instance, systemd interprets the configuration file
-    <filename>user.conf</filename> and the files in
-    <filename>user.conf.d</filename> directories. These configuration
-    files contain a few settings controlling basic manager
-    operations. See
-    <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry>
-    for a general description of the syntax.</para>
+    <para>When run as a system instance, <command>systemd</command> interprets the configuration file
+    <filename>system.conf</filename> and the files in <filename>system.conf.d</filename> directories; when
+    run as a user instance, it interprets the configuration file <filename>user.conf</filename> (either in
+    the home directory of the user, or if not found, under <filename>/etc/systemd/</filename>) and the files
+    in <filename>user.conf.d</filename> directories. These configuration files contain a few settings
+    controlling basic manager operations.</para>
+
+    <para>See
+    <citerefentry><refentrytitle>systemd.syntax</refentrytitle><manvolnum>7</manvolnum></citerefentry> for a
+    general description of the syntax.</para>
   </refsect1>
 
   <xi:include href="standard-conf.xml" xpointer="main-conf" />
index f29449d691c9d8f3a74c9d0ed6a486515b7aee1f..2237925209a2e32032998d393ae82fc0039a3c75 100644 (file)
@@ -163,6 +163,36 @@ static char **saved_env = NULL;
 static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
                                const struct rlimit *saved_rlimit_memlock);
 
+static int manager_find_user_config_paths(char ***ret_files, char ***ret_dirs) {
+        _cleanup_free_ char *base = NULL;
+        _cleanup_strv_free_ char **files = NULL, **dirs = NULL;
+        int r;
+
+        r = xdg_user_config_dir(&base, "/systemd");
+        if (r < 0)
+                return r;
+
+        r = strv_extendf(&files, "%s/user.conf", base);
+        if (r < 0)
+                return r;
+
+        r = strv_extend(&files, PKGSYSCONFDIR "/user.conf");
+        if (r < 0)
+                return r;
+
+        r = strv_consume(&dirs, TAKE_PTR(base));
+        if (r < 0)
+                return r;
+
+        r = strv_extend_strv(&dirs, CONF_PATHS_STRV("systemd"), false);
+        if (r < 0)
+                return r;
+
+        *ret_files = TAKE_PTR(files);
+        *ret_dirs = TAKE_PTR(dirs);
+        return 0;
+}
+
 _noreturn_ static void freeze_or_exit_or_reboot(void) {
 
         /* If we are running in a container, let's prefer exiting, after all we can propagate an exit code to
@@ -668,26 +698,34 @@ static int parse_config_file(void) {
                 {}
         };
 
-        const char *fn, *conf_dirs_nulstr;
+        _cleanup_strv_free_ char **_free_files = NULL, **_free_dirs = NULL;
 
-        fn = arg_system ?
-                PKGSYSCONFDIR "/system.conf" :
-                PKGSYSCONFDIR "/user.conf";
+        const char *const *files, *const *dirs, *suffix;
+        int r;
 
-        conf_dirs_nulstr = arg_system ?
-                CONF_PATHS_NULSTR("systemd/system.conf.d") :
-                CONF_PATHS_NULSTR("systemd/user.conf.d");
+        if (arg_system) {
+                files = STRV_MAKE_CONST(PKGSYSCONFDIR "/system.conf");
+                dirs = (const char* const*) CONF_PATHS_STRV("systemd");
+                suffix = "system.conf.d";
+        } else {
+                r = manager_find_user_config_paths(&_free_files, &_free_dirs);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to determine config file paths: %m");
+                files = (const char* const*) _free_files;
+                dirs = (const char* const*) _free_dirs;
+                suffix = "user.conf.d";
+        }
 
-        (void) config_parse_many_nulstr(
-                        fn, conf_dirs_nulstr,
+        (void) config_parse_many(
+                        files, dirs, suffix,
                         "Manager\0",
                         config_item_table_lookup, items,
                         CONFIG_PARSE_WARN,
                         NULL,
                         NULL);
 
-        /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY
-         * like everywhere else. */
+        /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we use
+         * USEC_INFINITY like everywhere else. */
         if (arg_default_timeout_start_usec <= 0)
                 arg_default_timeout_start_usec = USEC_INFINITY;
         if (arg_default_timeout_stop_usec <= 0)