diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index fbbfd4f514..5cb83afa57 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -2152,16 +2152,17 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
LogExtraFields=
- Configures additional log metadata fields to include in all log records generated by processes
- associated with this unit. This setting takes one or more journal field assignments in the format
- FIELD=VALUE separated by whitespace. See
- systemd.journal-fields7 for
- details on the journal field concept. Even though the underlying journal implementation permits binary field
- values, this setting accepts only valid UTF-8 values. To include space characters in a journal field value,
- enclose the assignment in double quotes ("). The usual specifiers are expanded in all assignments (see
- below). Note that this setting is not only useful for attaching additional metadata to log records of a unit,
- but given that all fields and values are indexed may also be used to implement cross-unit log record
- matching. Assign an empty string to reset the list.
+ Configures additional log metadata fields to include in all log records generated by
+ processes associated with this unit. This setting takes one or more journal field assignments in the
+ format FIELD=VALUE separated by whitespace. See
+ systemd.journal-fields7
+ for details on the journal field concept. Even though the underlying journal implementation permits
+ binary field values, this setting accepts only valid UTF-8 values. To include space characters in a
+ journal field value, enclose the assignment in double quotes (").
+ The usual specifiers are expanded in all assignments (see below). Note that this setting is not only
+ useful for attaching additional metadata to log records of a unit, but given that all fields and
+ values are indexed may also be used to implement cross-unit log record matching. Assign an empty
+ string to reset the list.
@@ -2355,10 +2356,16 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
$PATH
- Colon-separated list of directories to use
- when launching executables. systemd uses a fixed value of
- /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin.
-
+ Colon-separated list of directories to use when launching
+ executables. systemd uses a fixed value of
+ /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
+ in the system manager. When compiled for systems with "unmerged /usr" (/bin is
+ not a symlink to /usr/bin),
+ :/sbin:/bin is appended. In case of the
+ the user manager, each bin/ and sbin/ pair is switched, so
+ that programs from /usr/bin have higher priority than programs from
+ /usr/sbin, etc. It is recommended to not rely on this in any way, and have only
+ one program with a given name in $PATH.
diff --git a/src/basic/path-util.h b/src/basic/path-util.h
index 1f46cd65c9..71fb7041a3 100644
--- a/src/basic/path-util.h
+++ b/src/basic/path-util.h
@@ -11,30 +11,38 @@
#include "time-util.h"
#define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin"
+#define PATH_SPLIT_BIN_SBIN(x) x "bin:" x "sbin"
#define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
#define PATH_NORMAL_SBIN_BIN(x) x "bin"
+#define PATH_NORMAL_BIN_SBIN(x) x "bin"
#define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0"
#if HAVE_SPLIT_BIN
# define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x)
+# define PATH_BIN_SBIN(x) PATH_SPLIT_BIN_SBIN(x)
# define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x)
#else
# define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x)
+# define PATH_BIN_SBIN(x) PATH_NORMAL_BIN_SBIN(x)
# define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x)
#endif
#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
+#define DEFAULT_USER_PATH_NORMAL PATH_BIN_SBIN("/usr/local/") ":" PATH_BIN_SBIN("/usr/")
#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
+#define DEFAULT_USER_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_BIN_SBIN("/")
#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
#define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/")
#if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
+# define DEFAULT_USER_PATH DEFAULT_USER_PATH_SPLIT_USR
# define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
#else
# define DEFAULT_PATH DEFAULT_PATH_NORMAL
+# define DEFAULT_USER_PATH DEFAULT_USER_PATH_NORMAL
# define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
#endif
diff --git a/src/core/manager.c b/src/core/manager.c
index 00bf6f70bc..d9114bb0c5 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -603,6 +603,8 @@ static char** sanitize_environment(char **l) {
}
int manager_default_environment(Manager *m) {
+ int r;
+
assert(m);
m->transient_environment = strv_free(m->transient_environment);
@@ -616,16 +618,29 @@ int manager_default_environment(Manager *m) {
* /proc/self/environ valid; it is used for tagging
* the init process inside containers. */
m->transient_environment = strv_new("PATH=" DEFAULT_PATH);
+ if (!m->transient_environment)
+ return log_oom();
/* Import locale variables LC_*= from configuration */
(void) locale_setup(&m->transient_environment);
- } else
- /* The user manager passes its own environment
- * along to its children. */
- m->transient_environment = strv_copy(environ);
+ } else {
+ _cleanup_free_ char *k = NULL;
- if (!m->transient_environment)
- return log_oom();
+ /* The user manager passes its own environment
+ * along to its children, except for $PATH. */
+ m->transient_environment = strv_copy(environ);
+ if (!m->transient_environment)
+ return log_oom();
+
+ k = strdup("PATH=" DEFAULT_USER_PATH);
+ if (!k)
+ return log_oom();
+
+ r = strv_env_replace(&m->transient_environment, k);
+ if (r < 0)
+ return log_oom();
+ TAKE_PTR(k);
+ }
sanitize_environment(m->transient_environment);