summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTollef Fog Heen <tfheen@err.no>2011-09-23 19:27:55 +0200
committerTollef Fog Heen <tfheen@err.no>2011-09-23 19:27:55 +0200
commitbaf8bb13719693fbc4be438dd3c358f2f9d861cd (patch)
tree7deb946240ba261983a61e1b174db16f5d7a7411
parent055bf2bf621b62b6e07af358878c761488a2e6b5 (diff)
parent7c83341a593160e2b4739bdb8a1ad76b21bbdf9e (diff)
downloadsystemd-baf8bb13719693fbc4be438dd3c358f2f9d861cd.tar.gz
Merge commit 'v36'
-rw-r--r--Makefile.am29
-rw-r--r--TODO36
-rw-r--r--configure.ac2
-rw-r--r--man/sd-daemon.xml27
-rw-r--r--man/sd_booted.xml26
-rw-r--r--man/sd_is_fifo.xml20
-rw-r--r--man/sd_listen_fds.xml26
-rw-r--r--man/sd_notify.xml23
-rw-r--r--man/sd_readahead.xml26
-rw-r--r--man/systemd.path.xml6
-rw-r--r--man/systemd.unit.xml152
-rw-r--r--man/systemd.xml2
-rw-r--r--src/99-systemd.rules.in9
-rw-r--r--src/binfmt.c2
-rw-r--r--src/condition.c60
-rw-r--r--src/condition.h2
-rw-r--r--src/conf-parser.c2
-rw-r--r--src/dbus-common.c74
-rw-r--r--src/dbus-common.h4
-rw-r--r--src/dbus-manager.c2
-rw-r--r--src/detect-virt.c8
-rw-r--r--src/fsck.c134
-rw-r--r--src/getty-generator.c1
-rw-r--r--src/hostnamed.c27
-rw-r--r--src/install.c3
-rw-r--r--src/job.c5
-rw-r--r--src/kmsg-syslogd.c2
-rw-r--r--src/load-fragment-gperf.gperf.m42
-rw-r--r--src/load-fragment.c10
-rw-r--r--src/locale-setup.c1
-rw-r--r--src/localed.c25
-rw-r--r--src/loginctl.c53
-rw-r--r--src/logind-dbus.c4
-rw-r--r--src/logind.c7
-rw-r--r--src/main.c4
-rw-r--r--src/manager.c48
-rw-r--r--src/manager.h3
-rw-r--r--src/modules-load.c2
-rw-r--r--src/mount.c5
-rw-r--r--src/nspawn.c15
-rw-r--r--src/path.c2
-rw-r--r--src/quotacheck.c1
-rw-r--r--src/readahead-collect.c1
-rw-r--r--src/readahead-replay.c1
-rw-r--r--src/sd-login.c45
-rw-r--r--src/selinux-setup.c6
-rw-r--r--src/service.c78
-rw-r--r--src/shutdown.c1
-rw-r--r--src/socket.c8
-rw-r--r--src/stdout-syslog-bridge.c34
-rw-r--r--src/strv.c26
-rw-r--r--src/sysfs-show.c3
-rw-r--r--src/systemctl.c23
-rwxr-xr-xsrc/systemd-analyze16
-rw-r--r--src/timedated.c26
-rw-r--r--src/umount.c7
-rw-r--r--src/unit.c26
-rw-r--r--src/util.c272
-rw-r--r--src/util.h12
-rw-r--r--src/vconsole-setup.c1
-rw-r--r--src/virt.c314
-rw-r--r--src/virt.h38
-rw-r--r--units/console-shell.service.m42
-rw-r--r--units/dev-hugepages.mount2
-rw-r--r--units/dev-mqueue.mount2
-rw-r--r--units/emergency.service2
-rw-r--r--units/rescue.service.m48
-rw-r--r--units/sys-fs-fuse-connections.mount (renamed from units/dev-mqueue.automount)11
-rw-r--r--units/sys-kernel-config.mount (renamed from units/dev-hugepages.automount)11
-rw-r--r--units/sys-kernel-debug.automount15
-rw-r--r--units/sys-kernel-debug.mount2
-rw-r--r--units/sys-kernel-security.automount15
-rw-r--r--units/sys-kernel-security.mount2
-rw-r--r--units/systemd-readahead-collect.service.in1
-rw-r--r--units/systemd-readahead-replay.service.in1
-rw-r--r--units/var-lock.mount1
-rw-r--r--units/var-run.mount1
77 files changed, 1314 insertions, 592 deletions
diff --git a/Makefile.am b/Makefile.am
index e1d1186887..66a64fd4fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = po
LIBSYSTEMD_LOGIN_CURRENT=0
-LIBSYSTEMD_LOGIN_REVISION=4
+LIBSYSTEMD_LOGIN_REVISION=5
LIBSYSTEMD_LOGIN_AGE=0
LIBSYSTEMD_DAEMON_CURRENT=0
@@ -357,14 +357,12 @@ dist_systemunit_DATA = \
units/systemd-stdout-syslog-bridge.socket \
units/systemd-shutdownd.socket \
units/syslog.socket \
- units/dev-hugepages.automount \
units/dev-hugepages.mount \
- units/dev-mqueue.automount \
units/dev-mqueue.mount \
- units/sys-kernel-debug.automount \
+ units/sys-kernel-config.mount \
units/sys-kernel-debug.mount \
- units/sys-kernel-security.automount \
units/sys-kernel-security.mount \
+ units/sys-fs-fuse-connections.mount \
units/var-run.mount \
units/media.mount \
units/remount-rootfs.service \
@@ -615,6 +613,7 @@ noinst_LTLIBRARIES = \
libsystemd_basic_la_SOURCES = \
src/util.c \
+ src/virt.c \
src/label.c \
src/hashmap.c \
src/set.c \
@@ -1838,10 +1837,12 @@ endif
rm -f remote-fs.target && \
$(LN_S) $(systemunitdir)/remote-fs.target remote-fs.target )
( cd $(DESTDIR)$(systemunitdir)/sysinit.target.wants && \
- rm -f dev-hugepages.automount \
- dev-mqueue.automount \
- sys-kernel-debug.automount \
- sys-kernel-security.automount \
+ rm -f dev-hugepages.mount \
+ dev-mqueue.mount \
+ sys-kernel-config.mount \
+ sys-kernel-debug.mount \
+ sys-kernel-security.mount \
+ sys-fs-fuse-connections.mount \
systemd-vconsole-setup.service \
systemd-modules-load.service \
systemd-random-seed-load.service \
@@ -1850,10 +1851,12 @@ endif
systemd-ask-password-console.path \
systemd-kmsg-syslogd.service \
cryptsetup.target && \
- $(LN_S) ../dev-hugepages.automount dev-hugepages.automount && \
- $(LN_S) ../dev-mqueue.automount dev-mqueue.automount && \
- $(LN_S) ../sys-kernel-debug.automount sys-kernel-debug.automount && \
- $(LN_S) ../sys-kernel-security.automount sys-kernel-security.automount && \
+ $(LN_S) ../dev-hugepages.mount dev-hugepages.mount && \
+ $(LN_S) ../dev-mqueue.mount dev-mqueue.mount && \
+ $(LN_S) ../sys-kernel-config.mount sys-kernel-config.mount && \
+ $(LN_S) ../sys-kernel-debug.mount sys-kernel-debug.mount && \
+ $(LN_S) ../sys-kernel-security.mount sys-kernel-security.mount && \
+ $(LN_S) ../sys-fs-fuse-connections.mount sys-fs-fuse-connections.mount && \
$(LN_S) ../systemd-vconsole-setup.service systemd-vconsole-setup.service && \
$(LN_S) ../systemd-modules-load.service systemd-modules-load.service && \
$(LN_S) ../systemd-random-seed-load.service systemd-random-seed-load.service && \
diff --git a/TODO b/TODO
index 677e1c9f4f..98556378af 100644
--- a/TODO
+++ b/TODO
@@ -7,18 +7,31 @@ Bugfixes:
* make anaconda write timeout=0 for encrypted devices
-* fix broken Sockets=syslog-ng.socket packaging
-
-* logind: ensure ACLs are updated on login and logout
-
-* fix CUPS .path unit for globbing
-
* service: pid file reading after reload doesn't work, since we don't reset the pid variable
* make sure timeouts are applied to Type=oneshot services.
+* Dangling symlinks of .automount unit files in .wants/ directories, set up
+ automount points even when the original .automount file did not exist
+ anymore. Only the .mount unit was still around.
+
Features:
+* add an option to make mounts private/shareable and so on, enable this for root by default
+
+* internal restart counter for units (focus on auto-respawn)
+
+* finer-grained auto-respawn settings (rate-limit)
+
+* be able to specify a forced restart of service A where service B depends on, in case B
+ needs to be auto-respawned?
+
+* Something is wrong with symlink handling of "autovt@.service" in "systemctl list-unit-files"
+
+* introduce sd_log_open() to create a connection to the syslog bridge via sd-daemon.h
+
+* when a bus name of a service disappears from the bus make sure to queue further activation requests
+
* something like ConditionExec= or ExecStartPre= without failure state
* service restart retry configuration
@@ -47,8 +60,6 @@ Features:
* logind: non-local X11 server handling
-* logind: use sysfs path in device hash table instead of sysname, as soon as fb driver is fixed
-
* implement Register= switch in .socket units to enable registration
in Avahi, RPC and other socket registration services.
@@ -85,8 +96,6 @@ Features:
* GC unreferenced jobs (such as .device jobs)
-* avoid DefaultStandardOutput=syslog to have any effect on StandardInput=socket services
-
* cgroup_notify_empty(): recursively check groups up the tree, too
* when failing to start a service due to ratelimiting, try again later, if restart=always is set
@@ -100,13 +109,14 @@ Features:
- how to pass throw-away units to systemd, or dynamically change properties of existing units
- how to integrate cgconfig and suchlike with systemd
- security properties
+ - xinetd conversion
+ - details of instantiated @.service setups
* allow port=0 in .socket units
* move readahead files into /var, look for them with .path units
* teach dbus to activate all services it finds in /etc/systemd/services/org-*.service
-* figure out what happened to bluez patch
* support systemd.mask= on the kernel command line.
@@ -122,8 +132,6 @@ Features:
* maybe introduce ExecRestartPre=
-* Patch systemd-fsck to use -C and pass console fd to it
-
* configurable jitter for timer events
* timer events with system resume
@@ -143,6 +151,8 @@ Features:
* exec settings override
* writable cgroups dbus properties for live changes
+* read config fragments for all units from /lib/systemd/system/foobar.service.d/ to override/extend specific settings
+
* port over to LISTEN_FDS/LISTEN_PID:
- rpcbind (/var/run/rpcbind.sock!) HAVEPATCH
- cups HAVEPATCH
diff --git a/configure.ac b/configure.ac
index ca07456be6..18dc3fe36a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
AC_PREREQ(2.63)
-AC_INIT([systemd],[35],[systemd-devel@lists.freedesktop.org])
+AC_INIT([systemd],[36],[systemd-devel@lists.freedesktop.org])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml
index cbfe28f842..cd67d9992a 100644
--- a/man/sd-daemon.xml
+++ b/man/sd-daemon.xml
@@ -52,6 +52,11 @@
<funcsynopsis>
<funcsynopsisinfo>#include "sd-daemon.h"</funcsynopsisinfo>
</funcsynopsis>
+
+ <cmdsynopsis>
+ <command>pkg-config --cflags --libs libsystemd-daemon</command>
+ </cmdsynopsis>
+
</refsynopsisdiv>
<refsect1>
@@ -129,17 +134,20 @@
resp. <ulink url="http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.h"/></para>
<para>These APIs are implemented in the reference
- implementation's drop-in
- <filename>sd-daemon.c</filename> and
- <filename>sd-daemon.h</filename> files. It is
- recommended that applications consuming these APIs copy
- the implementation into their source tree, either
- verbatim or in excerpts. These interfaces are
- currently not available in a dynamic library.</para>
+ implementation's <filename>sd-daemon.c</filename> and
+ <filename>sd-daemon.h</filename> files. These
+ interfaces are available as shared library, which can
+ be compiled and linked to with the
+ <literal>libsystemd-daemon</literal>
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file. Alternatively, applications consuming these APIs
+ may copy the implementation into their source tree,
+ either verbatim or in excerpts.</para>
<para>The functions directly related to new-style
daemons become NOPs when -DDISABLE_SYSTEMD is set
- during compilation. In addition, if
+ during compilation and the reference implementation is
+ used as drop-in files. In addition, if
<filename>sd-daemon.c</filename> is compiled on
non-Linux systems they become NOPs.</para>
</refsect1>
@@ -156,7 +164,8 @@
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>fprintf</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/man/sd_booted.xml b/man/sd_booted.xml
index 841ee1d479..ebcde36b48 100644
--- a/man/sd_booted.xml
+++ b/man/sd_booted.xml
@@ -98,17 +98,23 @@
url="http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.h"/></para>
<para><function>sd_booted()</function> is implemented
- in the reference implementation's drop-in
+ in the reference implementation's
<filename>sd-daemon.c</filename> and
- <filename>sd-daemon.h</filename> files. It is
- recommended that applications consuming these APIs
- copy the implementation into their source tree. For
- more details about the reference implementation see
- <citerefentry><refentrytitle>sd_daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
-
- <para>If -DDISABLE_SYSTEMD is set during compilation
- this function will always return 0 and otherwise
- become a NOP.</para>
+ <filename>sd-daemon.h</filename> files. These
+ interfaces are available as shared library, which can
+ be compiled and linked to with the
+ <literal>libsystemd-daemon</literal>
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file. Alternatively, applications consuming these APIs
+ may copy the implementation into their source
+ tree. For more details about the reference
+ implementation see
+ <citerefentry><refentrytitle>sd_daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+
+ <para>If the reference implementation is used as
+ drop-in files and -DDISABLE_SYSTEMD is set during
+ compilation this function will always return 0 and
+ otherwise become a NOP.</para>
</refsect1>
<refsect1>
diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml
index 251f45ce0f..f6fafabc39 100644
--- a/man/sd_is_fifo.xml
+++ b/man/sd_is_fifo.xml
@@ -178,7 +178,7 @@
<filename>getsockname()</filename> to check the file
descriptor type and where it is bound to.</para>
- <para>For details about the algorithm check the
+ <para>For details about the algorithms check the
liberally licensed reference implementation sources:
<ulink url="http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.c"/>
resp. <ulink
@@ -186,13 +186,17 @@
<para><function>sd_is_fifo()</function> and the
related functions are implemented in the reference
- implementation's drop-in
- <filename>sd-daemon.c</filename> and
- <filename>sd-daemon.h</filename> files. It is
- recommended that applications consuming these APIs
- copy the implementation into their source tree. For
- more details about the reference implementation see
- <citerefentry><refentrytitle>sd_daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
+ implementation's <filename>sd-daemon.c</filename> and
+ <filename>sd-daemon.h</filename> files. These
+ interfaces are available as shared library, which can
+ be compiled and linked to with the
+ <literal>libsystemd-daemon</literal>
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file. Alternatively, applications consuming these APIs
+ may copy the implementation into their source
+ tree. For more details about the reference
+ implementation see
+ <citerefentry><refentrytitle>sd_daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
<para>These functions continue to work as described,
even if -DDISABLE_SYSTEMD is set during
diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml
index 128d859b97..3276aff63d 100644
--- a/man/sd_listen_fds.xml
+++ b/man/sd_listen_fds.xml
@@ -145,17 +145,23 @@
url="http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.h"/></para>
<para><function>sd_listen_fds()</function> is
- implemented in the reference implementation's drop-in
+ implemented in the reference implementation's
<filename>sd-daemon.c</filename> and
- <filename>sd-daemon.h</filename> files. It is
- recommended that applications consuming these APIs
- copy the implementation into their source tree. For
- more details about the reference implementation see
- <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
-
- <para>If -DDISABLE_SYSTEMD is set during compilation
- this function will always return 0 and otherwise
- become a NOP.</para>
+ <filename>sd-daemon.h</filename> files. These
+ interfaces are available as shared library, which can
+ be compiled and linked to with the
+ <literal>libsystemd-daemon</literal>
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file. Alternatively, applications consuming these APIs
+ may copy the implementation into their source
+ tree. For more details about the reference
+ implementation see
+ <citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+
+ <para>If the reference implementation is used as
+ drop-in files and -DDISABLE_SYSTEMD is set during
+ compilation this function will always return 0 and
+ otherwise become a NOP.</para>
</refsect1>
<refsect1>
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index c060bbad27..dd0ba935d6 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -206,7 +206,7 @@
datagram is accompanied by the process credentials of
the sending daemon, using SCM_CREDENTIALS.</para>
- <para>For details about the algorithm check the
+ <para>For details about the algorithms check the
liberally licensed reference implementation sources:
<ulink url="http://cgit.freedesktop.org/systemd/tree/src/sd-daemon.c"/>
resp. <ulink
@@ -214,17 +214,22 @@
<para><function>sd_notify()</function> and
<function>sd_notifyf()</function> are implemented in
- the reference implementation's drop-in
+ the reference implementation's
<filename>sd-daemon.c</filename> and
- <filename>sd-daemon.h</filename> files. It is
- recommended that applications consuming these APIs
- copy the implementation into their source tree. For
+ <filename>sd-daemon.h</filename> files. These
+ interfaces are available as shared library, which can
+ be compiled and linked to with the
+ <literal>libsystemd-daemon</literal>
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file. Alternatively, applications consuming these APIs
+ may copy the implementation into their source tree. For
more details about the reference implementation see
- <citerefentry><refentrytitle>sd_daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
+ <citerefentry><refentrytitle>sd_daemon</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
- <para>If -DDISABLE_SYSTEMD is set during compilation
- this function will always return 0 and otherwise
- become a NOP.</para>
+ <para>If the reference implementation is used as
+ drop-in files and -DDISABLE_SYSTEMD is set during
+ compilation these functions will always return 0 and
+ otherwise become a NOP.</para>
</refsect1>
<refsect1>
diff --git a/man/sd_readahead.xml b/man/sd_readahead.xml
index 004608dfba..88b135b7ec 100644
--- a/man/sd_readahead.xml
+++ b/man/sd_readahead.xml
@@ -134,17 +134,23 @@
url="http://cgit.freedesktop.org/systemd/tree/src/sd-readahead.h"/></para>
<para><function>sd_readahead()</function> is
- implemented in the reference implementation's drop-in
+ implemented in the reference implementation's
<filename>sd-readahead.c</filename> and
- <filename>sd-readahead.h</filename> files. It is
- recommended that applications consuming this API copy
- the implementation into their source tree. For more
- details about the reference implementation see
- <citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
-
- <para>If -DDISABLE_SYSTEMD is set during compilation
- this function will always return 0 and otherwise
- become a NOP.</para>
+ <filename>sd-readahead.h</filename> files. These
+ interfaces are available as shared library, which can
+ be compiled and linked to with the
+ <literal>libsystemd-daemon</literal>
+ <citerefentry><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file. Alternatively, applications consuming this API
+ may copy the implementation into their source
+ tree. For more details about the reference
+ implementation see
+ <citerefentry><refentrytitle>sd-readahead</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
+
+ <para>If the reference implementation is used as
+ drop-in files and -DDISABLE_SYSTEMD is set during
+ compilation this function will always return 0 and
+ otherwise become a NOP.</para>
</refsect1>
<refsect1>
diff --git a/man/systemd.path.xml b/man/systemd.path.xml
index f99931ab1e..10d8f73004 100644
--- a/man/systemd.path.xml
+++ b/man/systemd.path.xml
@@ -154,7 +154,11 @@
activated, then the configured unit is
immediately activated as
well. Something similar does not apply
- to <varname>PathChanged=</varname>.
+ to
+ <varname>PathChanged=</varname>. The
+ latter is not activated on simple
+ writes but only if files with were
+ opened for writing are closed.
</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index d38a001366..bf8de322dd 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -180,30 +180,86 @@
and no file by that name is found, systemd will look
for <filename>getty@.service</filename> and
instantiate a service from that configuration file if
- it is found. To refer to the instance string from
+ it is found.</para>
+
+ <para>To refer to the instance string from
within the configuration file you may use the special
<literal>%i</literal> specifier in many of the
- configuration options. Other specifiers that may be
- used are <literal>%n</literal>, <literal>%N</literal>,
- <literal>%p</literal>, <literal>%P</literal>,
- <literal>%I</literal>, <literal>%f</literal>,
- <literal>%c</literal>, <literal>%r</literal>,
- <literal>%R</literal> and <literal>%t</literal> for
- the full unit name, the unescaped unit name, the
- prefix name, the unescaped prefix name, the unescaped
- instance name, the unescaped filename, the control
- group path of the unit, the root control group path of
- systemd, and the parent directory of the root control
- cgroup path of systemd and the runtime socket dir,
- respectively. The unescaped filename is either the
- unescaped instance name (if set) with / prepended (if
- necessary), or the prefix name similarly prepended
- with /. The prefix name here refers to the string
- before the @, i.e. "getty" in the example above, where
- "tty3" is the instance name. The runtime socket
- directory is either <filename>/run</filename> (for the
- system manager) or <literal>$XDG_RUNTIME_DIR</literal>
- (for user managers).</para>
+ configuration options. Other specifiers exist, the
+ full list is:</para>
+
+ <table>
+ <title>Specifiers available in unit files</title>
+ <tgroup cols='3' align='left' colsep='1' rowsep='1'>
+ <colspec colname="spec" />
+ <colspec colname="mean" />
+ <colspec colname="detail" />
+ <thead>
+ <row>
+ <entry>Specifier</entry>
+ <entry>Meaning</entry>
+ <entry>Details</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>%n</literal></entry>
+ <entry>Full unit name</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%N</literal></entry>
+ <entry>Unescaped full unit name</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%p</literal></entry>
+ <entry>Prefix name</entry>
+ <entry>This refers to the string before the @, i.e. "getty" in the example above, where "tty3" is the instance name.</entry>
+ </row>
+ <row>
+ <entry><literal>%P</literal></entry>
+ <entry>Unescaped prefix name</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%i</literal></entry>
+ <entry>Instance name</entry>
+ <entry>This is the string between the @ character and the suffix.</entry>
+ </row>
+ <row>
+ <entry><literal>%I</literal></entry>
+ <entry>Unescaped instance name</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%f</literal></entry>
+ <entry>Unescaped file name</entry>
+ <entry>This is either the unescaped instance name (if set) with / prepended (if necessary), or the prefix name similarly prepended with /.</entry>
+ </row>
+ <row>
+ <entry><literal>%c</literal></entry>
+ <entry>Control group path of the unit</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%r</literal></entry>
+ <entry>Root control group path of systemd</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%R</literal></entry>
+ <entry>Parent directory of the root control group path of systemd</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><literal>%t</literal></entry>
+ <entry>Runtime socket dir</entry>
+ <entry>This is either /run (for the system manager) or $XDG_RUNTIME_DIR (for user managers).</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
<para>If a unit file is empty (i.e. has the file size
0) or is symlinked to <filename>/dev/null</filename>
@@ -609,6 +665,8 @@
<term><varname>ConditionPathExists=</varname></term>
<term><varname>ConditionPathExistsGlob=</varname></term>
<term><varname>ConditionPathIsDirectory=</varname></term>
+ <term><varname>ConditionPathIsSymbolicLink=</varname></term>
+ <term><varname>ConditionPathIsMountPoint=</varname></term>
<term><varname>ConditionDirectoryNotEmpty=</varname></term>
<term><varname>ConditionFileIsExecutable=</varname></term>
<term><varname>ConditionKernelCommandLine=</varname></term>
@@ -623,7 +681,7 @@
a file existence condition can be
checked before a unit is started. If
the specified absolute path name does
- not exist startup of a unit will not
+ not exist, startup of a unit will not
actually happen, however the unit is
still useful for ordering purposes in
this case. The condition is checked at
@@ -633,10 +691,11 @@
<varname>ConditionPathExists=</varname>
is prefixed with an exclamation mark
(!), the test is negated, and the unit
- only started if the path does not
- exist. <varname>ConditionPathExistsGlob=</varname>
- work in a similar way, but checks for
- the existance of at least one file or
+ is only started if the path does not
+ exist.
+ <varname>ConditionPathExistsGlob=</varname>
+ works in a similar way, but checks for
+ the existence of at least one file or
directory matching the specified
globbing
pattern. <varname>ConditionPathIsDirectory=</varname>
@@ -644,7 +703,17 @@
<varname>ConditionPathExists=</varname>
but verifies whether a certain path
exists and is a
- directory. <varname>ConditionFileIsExecutable=</varname>
+ directory. <varname>ConditionPathIsSymbolicLink=</varname>
+ is similar to
+ <varname>ConditionPathExists=</varname>
+ but verifies whether a certain path
+ exists and is a symbolic
+ link. <varname>ConditionPathIsMountPoint=</varname>
+ is similar to
+ <varname>ConditionPathExists=</varname>
+ but verifies whether a certain path
+ exists and is a mount
+ point. <varname>ConditionFileIsExecutable=</varname>
is similar to
<varname>ConditionPathExists=</varname>
but verifies whether a certain path
@@ -677,18 +746,28 @@
whether it is a specific
implementation. Takes either boolean
value to check if being executed in
- any virtual environment or one of the
+ any virtualized environment, or one of
+ <varname>vm</varname> and
+ <varname>container</varname> to test against
+ a specific type of virtualization
+ solution, or one of
<varname>qemu</varname>,
<varname>kvm</varname>,
<varname>vmware</varname>,
<varname>microsoft</varname>,
<varname>oracle</varname>,
<varname>xen</varname>,
- <varname>pidns</varname>,
- <varname>openvz</varname> to test
- against a specific implementation. The
- test may be negated by prepending an
- exclamation mark.
+ <varname>bochs</varname>,
+ <varname>chroot</varname>,
+ <varname>openvz</varname>,
+ <varname>lxc</varname>,
+ <varname>systemd-nspawn</varname>,
+ <varname>pidns</varname> to test
+ against a specific implementation. If
+ multiple virtualization technologies
+ are nested only the innermost is
+ considered. The test may be negated by
+ prepending an exclamation mark.
<varname>ConditionSecurity=</varname>
may be used to check whether the given
security module is enabled on the
@@ -717,7 +796,10 @@
prefix an argument with the pipe
symbol and an exclamation mark the
pipe symbol must be passed first, the
- exclamation second.</para></listitem>
+ exclamation second. Except for
+ <varname>ConditionPathIsSymbolicLink=</varname>,
+ all path checks follow
+ symlinks.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/man/systemd.xml b/man/systemd.xml
index a11c96e7f1..a8a6967446 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -259,7 +259,7 @@
services and sockets, i.e. controls
the default for
<option>StandardOutput=</option>
- resp. <option>StandardExecute=</option>
+ resp. <option>StandardError=</option>
(see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details). Takes one of
diff --git a/src/99-systemd.rules.in b/src/99-systemd.rules.in
index 884a614404..b2481aea9a 100644
--- a/src/99-systemd.rules.in
+++ b/src/99-systemd.rules.in
@@ -17,6 +17,7 @@ SUBSYSTEM=="block", KERNEL!="ram*|loop*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=
# Ignore encrypted devices with no identified superblock on it, since
# we are probably still calling mke2fs or mkswap on it.
+
SUBSYSTEM=="block", KERNEL!="ram*|loop*", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0"
# We need a hardware independent way to identify network devices. We
@@ -41,6 +42,14 @@ SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}="printer.target"
SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}="printer.target"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}="printer.target"
+# Apply sysctl variables to network devices (and only to those) as they appear.
+
SUBSYSTEM=="net", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/proc/sys/net/ipv4/conf/$name --prefix=/proc/sys/net/ipv4/neigh/$name --prefix=/proc/sys/net/ipv6/conf/$name --prefix=/proc/sys/net/ipv6/neigh/$name"
+# Asynchronously mount file systems implemented by these modules as
+# soon as they are loaded.
+
+SUBSYSTEM=="module", KERNEL=="fuse", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}="sys-fs-fuse-connections.mount"
+SUBSYSTEM=="module", KERNEL=="configfs", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}="sys-kernel-config.mount"
+
LABEL="systemd_end"
diff --git a/src/binfmt.c b/src/binfmt.c
index 552d8cc227..e8d6524391 100644
--- a/src/binfmt.c
+++ b/src/binfmt.c
@@ -33,7 +33,7 @@
#include "util.h"
static int delete_rule(const char *rule) {
- char *x, *fn, *e;
+ char *x, *fn = NULL, *e;
int r;
assert(rule[0]);
diff --git a/src/condition.c b/src/condition.c
index f9202f6850..e978656772 100644
--- a/src/condition.c
+++ b/src/condition.c
@@ -30,24 +30,28 @@
#include "util.h"
#include "condition.h"
+#include "virt.h"
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
Condition *c;
assert(type < _CONDITION_TYPE_MAX);
- if (!(c = new0(Condition, 1)))
+ c = new0(Condition, 1);
+ if (!c)
return NULL;
c->type = type;
c->trigger = trigger;
c->negate = negate;
- if (parameter)
- if (!(c->parameter = strdup(parameter))) {
+ if (parameter) {
+ c->parameter = strdup(parameter);
+ if (!c->parameter) {
free(c);
return NULL;
}
+ }
return c;
}
@@ -75,10 +79,11 @@ static bool test_kernel_command_line(const char *parameter) {
assert(parameter);
- if (detect_virtualization(NULL) > 0)
+ if (detect_container(NULL) > 0)
return false;
- if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
+ r = read_one_line_file("/proc/cmdline", &line);
+ if (r < 0) {
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
return false;
}
@@ -89,7 +94,8 @@ static bool test_kernel_command_line(const char *parameter) {
FOREACH_WORD_QUOTED(w, l, line, state) {
free(word);
- if (!(word = strndup(w, l)))
+ word = strndup(w, l);
+ if (!word)
break;
if (equal) {
@@ -113,24 +119,35 @@ static bool test_kernel_command_line(const char *parameter) {
}
static bool test_virtualization(const char *parameter) {
- int r, b;
+ int b;
+ Virtualization v;
const char *id;
assert(parameter);
- if ((r = detect_virtualization(&id)) < 0) {
- log_warning("Failed to detect virtualization, ignoring: %s", strerror(-r));
+ v = detect_virtualization(&id);
+ if (v < 0) {
+ log_warning("Failed to detect virtualization, ignoring: %s", strerror(-v));
return false;
}
+ /* First, compare with yes/no */
b = parse_boolean(parameter);
- if (r > 0 && b > 0)
+ if (v > 0 && b > 0)
+ return true;
+
+ if (v == 0 && b == 0)
return true;
- if (r == 0 && b == 0)
+ /* Then, compare categorization */
+ if (v == VIRTUALIZATION_VM && streq(parameter, "vm"))
return true;
+ if (v == VIRTUALIZATION_CONTAINER && streq(parameter, "container"))
+ return true;
+
+ /* Finally compare id */
return streq(parameter, id);
}
@@ -156,11 +173,22 @@ bool condition_test(Condition *c) {
case CONDITION_PATH_IS_DIRECTORY: {
struct stat st;
- if (lstat(c->parameter, &st) < 0)
- return !c->negate;
+ if (stat(c->parameter, &st) < 0)
+ return c->negate;
return S_ISDIR(st.st_mode) == !c->negate;
}
+ case CONDITION_PATH_IS_SYMBOLIC_LINK: {
+ struct stat st;
+
+ if (lstat(c->parameter, &st) < 0)
+ return c->negate;
+ return S_ISLNK(st.st_mode) == !c->negate;
+ }
+
+ case CONDITION_PATH_IS_MOUNT_POINT:
+ return (path_is_mount_point(c->parameter, true) > 0) == !c->negate;
+
case CONDITION_DIRECTORY_NOT_EMPTY: {
int k;
@@ -171,8 +199,8 @@ bool condition_test(Condition *c) {
case CONDITION_FILE_IS_EXECUTABLE: {
struct stat st;
- if (lstat(c->parameter, &st) < 0)
- return !c->negate;
+ if (stat(c->parameter, &st) < 0)
+ return c->negate;
return (S_ISREG(st.st_mode) && (st.st_mode & 0111)) == !c->negate;
}
@@ -247,6 +275,8 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
[CONDITION_PATH_EXISTS] = "ConditionPathExists",
[CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob",
[CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory",
+ [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink",
+ [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint",
[CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
[CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
[CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
diff --git a/src/condition.h b/src/condition.h
index 672996e836..dd65aa6054 100644
--- a/src/condition.h
+++ b/src/condition.h
@@ -30,6 +30,8 @@ typedef enum ConditionType {
CONDITION_PATH_EXISTS,
CONDITION_PATH_EXISTS_GLOB,
CONDITION_PATH_IS_DIRECTORY,
+ CONDITION_PATH_IS_SYMBOLIC_LINK,
+ CONDITION_PATH_IS_MOUNT_POINT,
CONDITION_DIRECTORY_NOT_EMPTY,
CONDITION_FILE_IS_EXECUTABLE,
CONDITION_KERNEL_COMMAND_LINE,
diff --git a/src/conf-parser.c b/src/conf-parser.c
index 3bb430e375..a71dcd0d8f 100644
--- a/src/conf-parser.c
+++ b/src/conf-parser.c
@@ -314,7 +314,7 @@ int config_parse(
continuation = c;
else {
continuation = strdup(l);
- if (!c) {
+ if (!continuation) {
r = -ENOMEM;
goto finish;
}
diff --git a/src/dbus-common.c b/src/dbus-common.c
index 43729f0372..40754e1e0d 100644
--- a/src/dbus-common.c
+++ b/src/dbus-common.c
@@ -971,3 +971,77 @@ int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
return 0;
}
+
+static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
+ DBusMessage *reply;
+ DBusConnection *bus = userdata;
+
+ assert_se(reply = dbus_pending_call_steal_reply(pending));
+ dbus_message_unref(reply);
+
+ dbus_connection_close(bus);
+}
+
+void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
+ DBusMessage *m = NULL;
+ DBusPendingCall *pending = NULL;
+
+ assert(bus);
+
+ /* We unregister the name here, but we continue to process
+ * requests, until we get the response for it, so that all
+ * requests are guaranteed to be processed. */
+
+ m = dbus_message_new_method_call(
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "ReleaseName");
+ if (!m)
+ goto oom;
+
+ if (!dbus_message_append_args(
+ m,
+ DBUS_TYPE_STRING,
+ &name,
+ DBUS_TYPE_INVALID))
+ goto oom;
+
+ if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
+ goto oom;
+
+ if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
+ goto oom;
+
+ dbus_message_unref(m);
+ dbus_pending_call_unref(pending);
+
+ return;
+
+oom:
+ log_error("Out of memory");
+
+ if (pending) {
+ dbus_pending_call_cancel(pending);
+ dbus_pending_call_unref(pending);
+ }
+
+ if (m)
+ dbus_message_unref(m);
+}
+
+DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
+ usec_t *remain_until = userdata;
+
+ assert(bus);
+ assert(m);
+ assert(remain_until);
+
+ /* Everytime we get a new message we reset out timeout */
+ *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
+
+ if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
+ dbus_connection_close(bus);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
diff --git a/src/dbus-common.h b/src/dbus-common.h
index aab65639c1..acd9208d66 100644
--- a/src/dbus-common.h
+++ b/src/dbus-common.h
@@ -167,4 +167,8 @@ int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, boo
int generic_print_property(const char *name, DBusMessageIter *iter, bool all);
+void bus_async_unregister_and_exit(DBusConnection *bus, const char *name);
+
+DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata);
+
#endif
diff --git a/src/dbus-manager.c b/src/dbus-manager.c
index 822189b103..7b68156abf 100644
--- a/src/dbus-manager.c
+++ b/src/dbus-manager.c
@@ -300,7 +300,7 @@ static int bus_manager_append_tainted(DBusMessageIter *i, const char *property,
free(p);
if (access("/proc/cgroups", F_OK) < 0)
- e = stpcpy(e, "cgroups-missing ");
+ stpcpy(e, "cgroups-missing ");
t = strstrip(buf);
diff --git a/src/detect-virt.c b/src/detect-virt.c
index 57f0176668..79cad5d8ab 100644
--- a/src/detect-virt.c
+++ b/src/detect-virt.c
@@ -25,16 +25,18 @@
#include <string.h>
#include "util.h"
+#include "virt.h"
int main(int argc, char *argv[]) {
- int r;
+ Virtualization r;
const char *id;
/* This is mostly intended to be used for scripts which want
* to detect whether we are being run in a virtualized
* environment or not */
- if ((r = detect_virtualization(&id)) < 0) {
+ r = detect_virtualization(&id);
+ if (r < 0) {
log_error("Failed to check for virtualization: %s", strerror(-r));
return EXIT_FAILURE;
}
@@ -42,5 +44,5 @@ int main(int argc, char *argv[]) {
if (r > 0)
puts(id);
- return r == 0;
+ return r > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/src/fsck.c b/src/fsck.c
index 5d9cf24f4d..c5088ad71c 100644
--- a/src/fsck.c
+++ b/src/fsck.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/file.h>
#include <libudev.h>
#include <dbus/dbus.h>
@@ -33,9 +34,11 @@
#include "dbus-common.h"
#include "special.h"
#include "bus-errors.h"
+#include "virt.h"
static bool arg_skip = false;
static bool arg_force = false;
+static bool arg_show_progress = false;
static void start_target(const char *target, bool isolate) {
DBusMessage *m = NULL, *reply = NULL;
@@ -142,10 +145,103 @@ static void test_files(void) {
if (access("/forcefsck", F_OK) >= 0)
arg_force = true;
+
+ if (access("/run/systemd/show-status", F_OK) >= 0 || plymouth_running())
+ arg_show_progress = true;
+}
+
+static double percent(int pass, unsigned long cur, unsigned long max) {
+ /* Values stolen from e2fsck */
+
+ static const int pass_table[] = {
+ 0, 70, 90, 92, 95, 100
+ };
+
+ if (pass <= 0)
+ return 0.0;
+
+ if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
+ return 100.0;
+
+ return (double) pass_table[pass-1] +
+ ((double) pass_table[pass] - (double) pass_table[pass-1]) *
+ (double) cur / (double) max;
+}
+
+static int process_progress(int fd) {
+ FILE *f, *console;
+ usec_t last = 0;
+ bool locked = false;
+ int clear = 0;
+
+ f = fdopen(fd, "r");
+ if (!f) {
+ close_nointr_nofail(fd);
+ return -errno;
+ }
+
+ console = fopen("/dev/console", "w");
+ if (!console) {
+ fclose(f);
+ return -ENOMEM;
+ }
+
+ while (!feof(f)) {
+ int pass, m;
+ unsigned long cur, max;
+ char *device;
+ double p;
+ usec_t t;
+
+ if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4)
+ break;
+
+ /* Only show one progress counter at max */
+ if (!locked) {
+ if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0) {
+ free(device);
+ continue;
+ }
+
+ locked = true;
+ }
+
+ /* Only update once every 50ms */
+ t = now(CLOCK_MONOTONIC);
+ if (last + 50 * USEC_PER_MSEC > t) {
+ free(device);
+ continue;
+ }
+
+ last = t;
+
+ p = percent(pass, cur, max);
+ fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
+ fflush(console);
+
+ free(device);
+
+ if (m > clear)
+ clear = m;
+ }
+
+ if (clear > 0) {
+ unsigned j;
+
+ fputc('\r', console);
+ for (j = 0; j < (unsigned) clear; j++)
+ fputc(' ', console);
+ fputc('\r', console);
+ fflush(console);
+ }
+
+ fclose(f);
+ fclose(console);
+ return 0;
}
int main(int argc, char *argv[]) {
- const char *cmdline[8];
+ const char *cmdline[9];
int i = 0, r = EXIT_FAILURE, q;
pid_t pid;
siginfo_t status;
@@ -153,13 +249,15 @@ int main(int argc, char *argv[]) {
struct udev_device *udev_device = NULL;
const char *device;
bool root_directory;
+ int progress_pipe[2] = { -1, -1 };
+ char dash_c[2+10+1];
if (argc > 2) {
log_error("This program expects one or no arguments.");
return EXIT_FAILURE;
}
- log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
+ log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
@@ -215,6 +313,12 @@ int main(int argc, char *argv[]) {
root_directory = true;
}
+ if (arg_show_progress)
+ if (pipe(progress_pipe) < 0) {
+ log_error("pipe(): %m");
+ goto finish;
+ }
+
cmdline[i++] = "/sbin/fsck";
cmdline[i++] = "-a";
cmdline[i++] = "-T";
@@ -226,19 +330,39 @@ int main(int argc, char *argv[]) {
if (arg_force)
cmdline[i++] = "-f";
+ if (progress_pipe[1] >= 0) {
+ snprintf(dash_c, sizeof(dash_c), "-C%i", progress_pipe[1]);
+ char_array_0(dash_c);
+ cmdline[i++] = dash_c;
+ }
+
cmdline[i++] = device;
cmdline[i++] = NULL;
- if ((pid = fork()) < 0) {
+ pid = fork();
+ if (pid < 0) {
log_error("fork(): %m");
goto finish;
} else if (pid == 0) {
/* Child */
+ if (progress_pipe[0] >= 0)
+ close_nointr_nofail(progress_pipe[0]);
execv(cmdline[0], (char**) cmdline);
_exit(8); /* Operational error */
}
- if ((q = wait_for_terminate(pid, &status)) < 0) {
+ if (progress_pipe[1] >= 0) {
+ close_nointr_nofail(progress_pipe[1]);
+ progress_pipe[1] = -1;
+ }
+
+ if (progress_pipe[0] >= 0) {
+ process_progress(progress_pipe[0]);
+ progress_pipe[0] = -1;
+ }
+
+ q = wait_for_terminate(pid, &status);
+ if (q < 0) {
log_error("waitid(): %s", strerror(-q));
goto finish;
}
@@ -276,5 +400,7 @@ finish:
if (udev)
udev_unref(udev);
+ close_pipe(progress_pipe);
+
return r;
}
diff --git a/src/getty-generator.c b/src/getty-generator.c
index d4beffaeff..6b5b254e6a 100644
--- a/src/getty-generator.c
+++ b/src/getty-generator.c
@@ -26,6 +26,7 @@
#include "log.h"
#include "util.h"
#include "unit-name.h"
+#include "virt.h"
const char *arg_dest = "/tmp";
diff --git a/src/hostnamed.c b/src/hostnamed.c
index e3b89a4c62..f3b2c94173 100644
--- a/src/hostnamed.c
+++ b/src/hostnamed.c
@@ -30,6 +30,8 @@
#include "strv.h"
#include "dbus-common.h"
#include "polkit.h"
+#include "def.h"
+#include "virt.h"
#define INTERFACE \
" <interface name=\"org.freedesktop.hostname1\">\n" \
@@ -85,6 +87,8 @@ static char *data[_PROP_MAX] = {
NULL
};
+static usec_t remain_until = 0;
+
static void free_data(void) {
int p;
@@ -230,7 +234,7 @@ static int write_data_other(void) {
assert(name[p]);
if (isempty(data[p])) {
- l = strv_env_unset(l, name[p]);
+ strv_env_unset(l, name[p]);
continue;
}
@@ -393,7 +397,7 @@ static DBusHandlerResult hostname_message_handler(
return bus_send_error_reply(connection, message, NULL, r);
}
- log_info("Changed static host name to '%s'", strempty(data[PROP_HOSTNAME]));
+ log_info("Changed static host name to '%s'", strempty(data[PROP_STATIC_HOSTNAME]));
changed = bus_properties_changed_new(
"/org/freedesktop/hostname1",
@@ -518,7 +522,10 @@ static int connect_bus(DBusConnection **_bus) {
goto fail;
}
- if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL)) {
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+
+ if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) ||
+ !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
log_error("Not enough memory");
r = -ENOMEM;
goto fail;
@@ -554,6 +561,7 @@ fail:
int main(int argc, char *argv[]) {
int r;
DBusConnection *bus = NULL;
+ bool exiting = false;
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
@@ -588,8 +596,17 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- while (dbus_connection_read_write_dispatch(bus, -1))
- ;
+ remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
+ for (;;) {
+
+ if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
+ break;
+
+ if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
+ exiting = true;
+ bus_async_unregister_and_exit(bus, "org.freedesktop.hostname1");
+ }
+ }
r = 0;
diff --git a/src/install.c b/src/install.c
index 7443973502..cfbd50ead9 100644
--- a/src/install.c
+++ b/src/install.c
@@ -479,7 +479,6 @@ static int find_symlinks_fd(
t = path_make_absolute(name, config_path);
if (!t) {
free(p);
- free(dest);
r = -ENOMEM;
break;
}
@@ -1905,7 +1904,7 @@ int unit_file_get_list(
} else if (r > 0) {
f->state = UNIT_FILE_DISABLED;
goto found;
- } else if (r == 0) {
+ } else {
f->state = UNIT_FILE_STATIC;
goto found;
}
diff --git a/src/job.c b/src/job.c
index 26e1a7ce99..5c0913b7d8 100644
--- a/src/job.c
+++ b/src/job.c
@@ -544,7 +544,9 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
j->type = JOB_START;
job_add_to_run_queue(j);
- return 0;
+
+ u = j->unit;
+ goto finish;
}
j->result = result;
@@ -613,6 +615,7 @@ int job_finish_and_invalidate(Job *j, JobResult result) {
unit_trigger_on_failure(u);
}
+finish:
/* Try to start the next jobs that can be started */
SET_FOREACH(other, u->meta.dependencies[UNIT_AFTER], i)
if (other->meta.job)
diff --git a/src/kmsg-syslogd.c b/src/kmsg-syslogd.c
index 83c2047a7a..0901a0e49b 100644
--- a/src/kmsg-syslogd.c
+++ b/src/kmsg-syslogd.c
@@ -379,7 +379,7 @@ static int process_event(Server *s, struct epoll_event *ev) {
return -errno;
}
- log_debug("Received SIG%s", strna(signal_to_string(sfsi.ssi_signo)));
+ log_debug("Received SIG%s", signal_to_string(sfsi.ssi_signo));
return 0;
} else {
diff --git a/src/load-fragment-gperf.gperf.m4 b/src/load-fragment-gperf.gperf.m4
index 08223c5c1b..7749b88dfb 100644
--- a/src/load-fragment-gperf.gperf.m4
+++ b/src/load-fragment-gperf.gperf.m4
@@ -112,6 +112,8 @@ Unit.JobTimeoutSec, config_parse_usec, 0,
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, 0
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, 0
Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, 0
+Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,0
+Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, 0
Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, 0
Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, 0
Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, 0
diff --git a/src/load-fragment.c b/src/load-fragment.c
index c8b4b5a9c6..12079c640f 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -554,6 +554,7 @@ int config_parse_exec(
if (!n[0]) {
log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
strv_free(n);
+ free(path);
return 0;
}
@@ -1545,10 +1546,12 @@ int config_parse_unit_condition_path(
assert(rvalue);
assert(data);
- if ((trigger = rvalue[0] == '|'))
+ trigger = rvalue[0] == '|';
+ if (trigger)
rvalue++;
- if ((negate = rvalue[0] == '!'))
+ negate = rvalue[0] == '!';
+ if (negate)
rvalue++;
if (!path_is_absolute(rvalue)) {
@@ -1556,7 +1559,8 @@ int config_parse_unit_condition_path(
return 0;
}
- if (!(c = condition_new(cond, rvalue, trigger, negate)))
+ c = condition_new(cond, rvalue, trigger, negate);
+ if (!c)
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
diff --git a/src/locale-setup.c b/src/locale-setup.c
index 41eb50bbba..340293619f 100644
--- a/src/locale-setup.c
+++ b/src/locale-setup.c
@@ -26,6 +26,7 @@
#include "locale-setup.h"
#include "util.h"
#include "macro.h"
+#include "virt.h"
enum {
/* We don't list LC_ALL here on purpose. People should be
diff --git a/src/localed.c b/src/localed.c
index d7dcc9e95b..fbb5a41d1a 100644
--- a/src/localed.c
+++ b/src/localed.c
@@ -29,6 +29,7 @@
#include "strv.h"
#include "dbus-common.h"
#include "polkit.h"
+#include "def.h"
#define INTERFACE \
" <interface name=\"org.freedesktop.locale1\">\n" \
@@ -108,6 +109,8 @@ static char *data[_PROP_MAX] = {
NULL
};
+static usec_t remain_until = 0;
+
static void free_data(void) {
int p;
@@ -212,6 +215,7 @@ static int write_data(void) {
}
if (strv_isempty(l)) {
+ strv_free(l);
if (unlink("/etc/locale.conf") < 0)
return errno == ENOENT ? 0 : -errno;
@@ -456,6 +460,8 @@ static DBusHandlerResult locale_message_handler(
}
}
+ strv_free(l);
+
for (p = 0; p < _PROP_MAX; p++) {
if (passed[p])
continue;
@@ -537,7 +543,10 @@ static int connect_bus(DBusConnection **_bus) {
goto fail;
}
- if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL)) {
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+
+ if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL) ||
+ !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
log_error("Not enough memory");
r = -ENOMEM;
goto fail;
@@ -573,6 +582,7 @@ fail:
int main(int argc, char *argv[]) {
int r;
DBusConnection *bus = NULL;
+ bool exiting = false;
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
@@ -604,8 +614,17 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- while (dbus_connection_read_write_dispatch(bus, -1))
- ;
+ remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
+ for (;;) {
+
+ if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
+ break;
+
+ if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
+ exiting = true;
+ bus_async_unregister_and_exit(bus, "org.freedesktop.locale1");
+ }
+ }
r = 0;
diff --git a/src/loginctl.c b/src/loginctl.c
index 53058d07a7..89762b66b0 100644
--- a/src/loginctl.c
+++ b/src/loginctl.c
@@ -64,6 +64,8 @@ static bool on_tty(void) {
}
static void pager_open_if_enabled(void) {
+
+ /* Cache result before we open the pager */
on_tty();
if (!arg_no_pager)
@@ -1061,10 +1063,9 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
uid_t uid;
uint32_t u;
- r = get_user_creds((const char**) (args+i), &uid, NULL, NULL);
- if (r < 0) {
+ ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL);
+ if (ret < 0) {
log_error("User %s unknown.", args[i]);
- r = -ENOENT;
goto finish;
}
@@ -1146,7 +1147,7 @@ finish:
}
static int activate(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1157,6 +1158,8 @@ static int activate(DBusConnection *bus, char **args, unsigned n) {
dbus_error_init(&error);
for (i = 1; i < n; i++) {
+ DBusMessage *reply;
+
m = dbus_message_new_method_call(
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1195,16 +1198,13 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
}
static int kill_session(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1218,6 +1218,8 @@ static int kill_session(DBusConnection *bus, char **args, unsigned n) {
arg_kill_who = "all";
for (i = 1; i < n; i++) {
+ DBusMessage *reply;
+
m = dbus_message_new_method_call(
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1255,16 +1257,13 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
}
static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1278,6 +1277,7 @@ static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
b = streq(args[0], "enable-linger");
for (i = 1; i < n; i++) {
+ DBusMessage *reply;
uint32_t u;
uid_t uid;
@@ -1327,16 +1327,13 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
}
static int terminate_user(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1349,6 +1346,7 @@ static int terminate_user(DBusConnection *bus, char **args, unsigned n) {
for (i = 1; i < n; i++) {
uint32_t u;
uid_t uid;
+ DBusMessage *reply;
m = dbus_message_new_method_call(
"org.freedesktop.login1",
@@ -1394,16 +1392,13 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
}
static int kill_user(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1417,6 +1412,7 @@ static int kill_user(DBusConnection *bus, char **args, unsigned n) {
arg_kill_who = "all";
for (i = 1; i < n; i++) {
+ DBusMessage *reply;
uid_t uid;
uint32_t u;
@@ -1465,16 +1461,13 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
}
static int attach(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1486,6 +1479,8 @@ static int attach(DBusConnection *bus, char **args, unsigned n) {
dbus_error_init(&error);
for (i = 2; i < n; i++) {
+ DBusMessage *reply;
+
m = dbus_message_new_method_call(
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1523,9 +1518,6 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
@@ -1581,7 +1573,7 @@ finish:
}
static int terminate_seat(DBusConnection *bus, char **args, unsigned n) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int ret = 0;
DBusError error;
unsigned i;
@@ -1592,6 +1584,8 @@ static int terminate_seat(DBusConnection *bus, char **args, unsigned n) {
dbus_error_init(&error);
for (i = 1; i < n; i++) {
+ DBusMessage *reply;
+
m = dbus_message_new_method_call(
"org.freedesktop.login1",
"/org/freedesktop/login1",
@@ -1627,9 +1621,6 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return ret;
diff --git a/src/logind-dbus.c b/src/logind-dbus.c
index b8f7d6718b..b33a096f3c 100644
--- a/src/logind-dbus.c
+++ b/src/logind-dbus.c
@@ -381,6 +381,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
session = hashmap_get(m->sessions, id);
if (session) {
+ free(id);
fifo_fd = session_create_fifo(session);
if (fifo_fd < 0) {
@@ -421,6 +422,9 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess
close_nointr_nofail(fifo_fd);
*_reply = reply;
+ strv_free(controllers);
+ strv_free(reset_controllers);
+
return 0;
}
diff --git a/src/logind.c b/src/logind.c
index 1aad48d2dc..4633a5ef29 100644
--- a/src/logind.c
+++ b/src/logind.c
@@ -413,6 +413,7 @@ static int manager_enumerate_users_from_cgroup(Manager *m) {
int r = 0;
char *name;
DIR *d;
+ int k;
r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d);
if (r < 0) {
@@ -423,9 +424,8 @@ static int manager_enumerate_users_from_cgroup(Manager *m) {
return r;
}
- while ((r = cg_read_subgroup(d, &name)) > 0) {
+ while ((k = cg_read_subgroup(d, &name)) > 0) {
User *user;
- int k;
k = manager_add_user_by_name(m, name, &user);
if (k < 0) {
@@ -446,6 +446,9 @@ static int manager_enumerate_users_from_cgroup(Manager *m) {
free(name);
}
+ if (r >= 0 && k < 0)
+ r = k;
+
closedir(d);
return r;
diff --git a/src/main.c b/src/main.c
index 7af060aa40..5c28a6c191 100644
--- a/src/main.c
+++ b/src/main.c
@@ -52,6 +52,7 @@
#include "build.h"
#include "strv.h"
#include "def.h"
+#include "virt.h"
static enum {
ACTION_RUN,
@@ -1364,7 +1365,6 @@ int main(int argc, char *argv[]) {
}
m->confirm_spawn = arg_confirm_spawn;
- m->show_status = arg_show_status;
#ifdef HAVE_SYSV_COMPAT
m->sysv_console = arg_sysv_console;
#endif
@@ -1379,6 +1379,8 @@ int main(int argc, char *argv[]) {
if (arg_default_controllers)
manager_set_default_controllers(m, arg_default_controllers);
+ manager_set_show_status(m, arg_show_status);
+
before_startup = now(CLOCK_MONOTONIC);
if ((r = manager_startup(m, serialization, fds)) < 0)
diff --git a/src/manager.c b/src/manager.c
index 163f69c22f..e626347dec 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -59,6 +59,7 @@
#include "bus-errors.h"
#include "exit-status.h"
#include "sd-daemon.h"
+#include "virt.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
@@ -2111,11 +2112,11 @@ static int manager_process_signal_fd(Manager *m) {
get_process_name(sfsi.ssi_pid, &p);
log_debug("Received SIG%s from PID %lu (%s).",
- strna(signal_to_string(sfsi.ssi_signo)),
+ signal_to_string(sfsi.ssi_signo),
(unsigned long) sfsi.ssi_pid, strna(p));
free(p);
} else
- log_debug("Received SIG%s.", strna(signal_to_string(sfsi.ssi_signo)));
+ log_debug("Received SIG%s.", signal_to_string(sfsi.ssi_signo));
switch (sfsi.ssi_signo) {
@@ -2233,8 +2234,9 @@ static int manager_process_signal_fd(Manager *m) {
if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
(int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
- manager_start_target(m, target_table[sfsi.ssi_signo - SIGRTMIN],
- (sfsi.ssi_signo == 1 || sfsi.ssi_signo == 2) ? JOB_ISOLATE : JOB_REPLACE);
+ int idx = (int) sfsi.ssi_signo - SIGRTMIN;
+ manager_start_target(m, target_table[idx],
+ (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE);
break;
}
@@ -2248,12 +2250,12 @@ static int manager_process_signal_fd(Manager *m) {
case 20:
log_debug("Enabling showing of status.");
- m->show_status = true;
+ manager_set_show_status(m, true);
break;
case 21:
log_debug("Disabling showing of status.");
- m->show_status = false;
+ manager_set_show_status(m, false);
break;
case 22:
@@ -2282,7 +2284,7 @@ static int manager_process_signal_fd(Manager *m) {
break;
default:
- log_warning("Got unhandled signal <%s>.", strna(signal_to_string(sfsi.ssi_signo)));
+ log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo));
}
}
}
@@ -2904,7 +2906,8 @@ bool manager_is_booting_or_shutting_down(Manager *m) {
return true;
/* Is there a job for the shutdown target? */
- if (((u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET))))
+ u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
+ if (u)
return !!u->meta.job;
return false;
@@ -3134,6 +3137,35 @@ void manager_recheck_syslog(Manager *m) {
log_open();
}
+void manager_set_show_status(Manager *m, bool b) {
+ assert(m);
+
+ if (m->running_as != MANAGER_SYSTEM)
+ return;
+
+ m->show_status = b;
+
+ if (b)
+ touch("/run/systemd/show-status");
+ else
+ unlink("/run/systemd/show-status");
+}
+
+bool manager_get_show_status(Manager *m) {
+ assert(m);
+
+ if (m->running_as != MANAGER_SYSTEM)
+ return false;
+
+ if (m->show_status)
+ return true;
+
+ /* If Plymouth is running make sure we show the status, so
+ * that there's something nice to see when people press Esc */
+
+ return plymouth_running();
+}
+
static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
[MANAGER_SYSTEM] = "system",
[MANAGER_USER] = "user"
diff --git a/src/manager.h b/src/manager.h
index 22730d2176..5deb5696b7 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -290,6 +290,9 @@ void manager_undo_generators(Manager *m);
void manager_recheck_syslog(Manager *m);
+void manager_set_show_status(Manager *m, bool b);
+bool manager_get_show_status(Manager *m);
+
const char *manager_running_as_to_string(ManagerRunningAs i);
ManagerRunningAs manager_running_as_from_string(const char *s);
diff --git a/src/modules-load.c b/src/modules-load.c
index 4b3b12109c..8dd98f73d8 100644
--- a/src/modules-load.c
+++ b/src/modules-load.c
@@ -77,7 +77,6 @@ int main(int argc, char *argv[]) {
continue;
log_error("Failed to open %s: %m", *fn);
- free(fn);
r = EXIT_FAILURE;
continue;
}
@@ -131,6 +130,7 @@ finish:
if (n_arguments > 3) {
arguments[n_arguments] = NULL;
+ strv_uniq(arguments);
execv("/sbin/modprobe", arguments);
log_error("Failed to execute /sbin/modprobe: %m");
diff --git a/src/mount.c b/src/mount.c
index 829c2cc13c..2fc799a6ed 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -320,7 +320,10 @@ static bool needs_quota(MountParameters *p) {
return false;
return mount_test_option(p->options, "usrquota") ||
- mount_test_option(p->options, "grpquota");
+ mount_test_option(p->options, "grpquota") ||
+ mount_test_option(p->options, "quota") ||
+ mount_test_option(p->options, "usrjquota") ||
+ mount_test_option(p->options, "grpjquota");
}
static int mount_add_fstab_links(Mount *m) {
diff --git a/src/nspawn.c b/src/nspawn.c
index 8c3cf6bfaa..8441c057b9 100644
--- a/src/nspawn.c
+++ b/src/nspawn.c
@@ -197,8 +197,10 @@ static int mount_all(const char *dest) {
/* Fix the timezone, if possible */
if (asprintf(&where, "%s/%s", dest, "/etc/localtime") >= 0) {
- mount("/etc/localtime", where, "bind", MS_BIND, NULL);
- mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
+
+ if (mount("/etc/localtime", where, "bind", MS_BIND, NULL) >= 0)
+ mount("/etc/localtime", where, "bind", MS_BIND|MS_REMOUNT|MS_RDONLY, NULL);
+
free(where);
}
@@ -725,6 +727,7 @@ int main(int argc, char *argv[]) {
gid_t gid = (gid_t) -1;
const char *envp[] = {
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "container=systemd-nspawn", /* LXC sets container=lxc, so follow the scheme here */
NULL, /* TERM */
NULL, /* HOME */
NULL, /* USER */
@@ -732,7 +735,7 @@ int main(int argc, char *argv[]) {
NULL
};
- envp[1] = strv_find_prefix(environ, "TERM=");
+ envp[2] = strv_find_prefix(environ, "TERM=");
close_nointr_nofail(master);
@@ -828,9 +831,9 @@ int main(int argc, char *argv[]) {
}
}
- if ((asprintf((char**)(envp + 2), "HOME=%s", home? home: "/root") < 0) ||
- (asprintf((char**)(envp + 3), "USER=%s", arg_user? arg_user : "root") < 0) ||
- (asprintf((char**)(envp + 4), "LOGNAME=%s", arg_user? arg_user : "root") < 0)) {
+ if ((asprintf((char**)(envp + 3), "HOME=%s", home? home: "/root") < 0) ||
+ (asprintf((char**)(envp + 4), "USER=%s", arg_user? arg_user : "root") < 0) ||
+ (asprintf((char**)(envp + 5), "LOGNAME=%s", arg_user? arg_user : "root") < 0)) {
log_error("Out of memory");
goto child_fail;
}
diff --git a/src/path.c b/src/path.c
index 1d4aa2174a..f15c9214ef 100644
--- a/src/path.c
+++ b/src/path.c
@@ -563,7 +563,7 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
assert(l > 0);
if (!(buf = malloc(l))) {
- log_error("Failed to allocate buffer: %s", strerror(-ENOMEM));
+ log_error("Failed to allocate buffer: %s", strerror(ENOMEM));
goto fail;
}
diff --git a/src/quotacheck.c b/src/quotacheck.c
index c475cecc91..98b59a090a 100644
--- a/src/quotacheck.c
+++ b/src/quotacheck.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include "util.h"
+#include "virt.h"
static bool arg_skip = false;
static bool arg_force = false;
diff --git a/src/readahead-collect.c b/src/readahead-collect.c
index df467f1a42..eac11e7e5c 100644
--- a/src/readahead-collect.c
+++ b/src/readahead-collect.c
@@ -49,6 +49,7 @@
#include "sd-daemon.h"
#include "ioprio.h"
#include "readahead-common.h"
+#include "virt.h"
/* fixme:
*
diff --git a/src/readahead-replay.c b/src/readahead-replay.c
index e97a0cfbbf..65011ac4be 100644
--- a/src/readahead-replay.c
+++ b/src/readahead-replay.c
@@ -41,6 +41,7 @@
#include "sd-daemon.h"
#include "ioprio.h"
#include "readahead-common.h"
+#include "virt.h"
static off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX;
diff --git a/src/sd-login.c b/src/sd-login.c
index 2489d78c60..a0a56c4952 100644
--- a/src/sd-login.c
+++ b/src/sd-login.c
@@ -481,33 +481,39 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui
if (uids && t) {
char *w, *state;
size_t l;
- unsigned i = 0;
FOREACH_WORD(w, l, t, state)
n++;
- b = new(uid_t, n);
- if (!b) {
- strv_free(a);
- return -ENOMEM;
- }
-
- FOREACH_WORD(w, l, t, state) {
- char *k;
+ if (n == 0)
+ b = NULL;
+ else {
+ unsigned i = 0;
- k = strndup(w, l);
- if (!k) {
- free(t);
- free(b);
+ b = new(uid_t, n);
+ if (!b) {
+ strv_free(a);
return -ENOMEM;
}
- r = parse_uid(k, b + i);
- free(k);
- if (r < 0)
- continue;
+ FOREACH_WORD(w, l, t, state) {
+ char *k;
+
+ k = strndup(w, l);
+ if (!k) {
+ free(t);
+ free(b);
+ strv_free(a);
+ return -ENOMEM;
+ }
- i++;
+ r = parse_uid(k, b + i);
+ free(k);
+ if (r < 0)
+ continue;
+
+ i++;
+ }
}
}
@@ -574,6 +580,9 @@ _public_ int sd_get_uids(uid_t **users) {
uid_t *l = NULL;
d = opendir("/run/systemd/users/");
+ if (!d)
+ return -errno;
+
for (;;) {
struct dirent buffer, *de;
int k;
diff --git a/src/selinux-setup.c b/src/selinux-setup.c
index 2abd99e6a2..a7e1fa4007 100644
--- a/src/selinux-setup.c
+++ b/src/selinux-setup.c
@@ -98,11 +98,13 @@ int selinux_setup(bool *loaded_policy) {
*loaded_policy = true;
} else {
+ log_open();
+
if (enforce > 0) {
- log_error("Failed to load SELinux policy.");
+ log_error("Failed to load SELinux policy. Freezing.");
return -EIO;
} else
- log_debug("Unable to load SELinux policy.");
+ log_debug("Unable to load SELinux policy. Ignoring.");
}
#endif
diff --git a/src/service.c b/src/service.c
index abd8f36bdd..c2053ce3ac 100644
--- a/src/service.c
+++ b/src/service.c
@@ -121,8 +121,6 @@ static void service_init(Unit *u) {
s->guess_main_pid = true;
exec_context_init(&s->exec_context);
- s->exec_context.std_output = u->meta.manager->default_std_output;
- s->exec_context.std_error = u->meta.manager->default_std_error;
RATELIMIT_INIT(s->ratelimit, 10*USEC_PER_SEC, 5);
@@ -783,19 +781,6 @@ static int service_load_sysv_path(Service *s, const char *path) {
free(short_description);
short_description = d;
- } else if (startswith_no_case(t, "X-Interactive:")) {
- int b;
-
- if ((b = parse_boolean(strstrip(t+14))) < 0) {
- log_warning("[%s:%u] Couldn't parse interactive flag. Ignoring.", path, line);
- continue;
- }
-
- if (b)
- s->exec_context.std_input = EXEC_INPUT_TTY;
- else
- s->exec_context.std_input = EXEC_INPUT_NULL;
-
} else if (state == LSB_DESCRIPTION) {
if (startswith(l, "#\t") || startswith(l, "# ")) {
@@ -845,9 +830,10 @@ static int service_load_sysv_path(Service *s, const char *path) {
s->type = SERVICE_FORKING;
s->remain_after_exit = !s->pid_file;
s->restart = SERVICE_RESTART_NO;
- s->exec_context.std_output =
- (s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY)
- ? EXEC_OUTPUT_TTY : s->meta.manager->default_std_output;
+
+ if (s->meta.manager->sysv_console)
+ s->exec_context.std_output = EXEC_OUTPUT_TTY;
+
s->exec_context.kill_mode = KILL_PROCESS;
/* We use the long description only if
@@ -1113,6 +1099,24 @@ static int service_add_default_dependencies(Service *s) {
return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
}
+static void service_fix_output(Service *s) {
+ assert(s);
+
+ /* If nothing has been explicitly configured, patch default
+ * output in. If input is socket/tty we avoid this however,
+ * since in that case we want output to default to the same
+ * place as we read input from. */
+
+ if (s->exec_context.std_error == EXEC_OUTPUT_INHERIT &&
+ s->exec_context.std_output == EXEC_OUTPUT_INHERIT &&
+ s->exec_context.std_input == EXEC_INPUT_NULL)
+ s->exec_context.std_error = s->meta.manager->default_std_error;
+
+ if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT &&
+ s->exec_context.std_input == EXEC_INPUT_NULL)
+ s->exec_context.std_output = s->meta.manager->default_std_output;
+}
+
static int service_load(Unit *u) {
int r;
Service *s = SERVICE(u);
@@ -1141,6 +1145,8 @@ static int service_load(Unit *u) {
/* This is a new unit? Then let's add in some extras */
if (u->meta.load_state == UNIT_LOADED) {
+ service_fix_output(s);
+
if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
return r;
@@ -1275,21 +1281,22 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
free(p2);
}
-static int service_load_pid_file(Service *s) {
+static int service_load_pid_file(Service *s, bool warn_if_missing) {
char *k;
int r;
pid_t pid;
assert(s);
- if (s->main_pid_known)
- return 0;
-
if (!s->pid_file)
- return 0;
+ return -ENOENT;
- if ((r = read_one_line_file(s->pid_file, &k)) < 0)
+ if ((r = read_one_line_file(s->pid_file, &k)) < 0) {
+ if (warn_if_missing)
+ log_warning("Failed to read PID file %s after %s. The service might be broken.",
+ s->pid_file, service_state_to_string(s->state));
return r;
+ }
r = parse_pid(k, &pid);
free(k);
@@ -1303,6 +1310,16 @@ static int service_load_pid_file(Service *s) {
return -ESRCH;
}
+ if (s->main_pid_known) {
+ if (pid == s->main_pid)
+ return 0;
+
+ log_debug("Main PID changing: %lu -> %lu",
+ (unsigned long) s->main_pid, (unsigned long) pid);
+ service_unwatch_main_pid(s);
+ s->main_pid_known = false;
+ }
+
if ((r = service_set_main_pid(s, pid)) < 0)
return r;
@@ -2588,6 +2605,11 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
success = is_clean_exit(code, status);
if (s->main_pid == pid) {
+ /* Forking services may occasionally move to a new PID.
+ * As long as they update the PID file before exiting the old
+ * PID, they're fine. */
+ if (service_load_pid_file(s, false) == 0)
+ return;
s->main_pid = 0;
exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status);
@@ -2718,7 +2740,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
* START_POST script */
if (success) {
- service_load_pid_file(s);
+ service_load_pid_file(s, !s->exec_command[SERVICE_EXEC_START_POST]);
service_search_main_pid(s);
service_enter_start_post(s);
@@ -2729,7 +2751,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
case SERVICE_START_POST:
if (success) {
- service_load_pid_file(s);
+ service_load_pid_file(s, true);
service_search_main_pid(s);
}
@@ -2739,7 +2761,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
case SERVICE_RELOAD:
if (success) {
- service_load_pid_file(s);
+ service_load_pid_file(s, true);
service_search_main_pid(s);
}
@@ -3093,7 +3115,7 @@ static int service_enumerate(Manager *m) {
free(fpath);
fpath = join(path, "/", de->d_name, NULL);
- if (!path) {
+ if (!fpath) {
r = -ENOMEM;
goto finish;
}
diff --git a/src/shutdown.c b/src/shutdown.c
index 1c6dc6597b..11213f9d59 100644
--- a/src/shutdown.c
+++ b/src/shutdown.c
@@ -41,6 +41,7 @@
#include "log.h"
#include "umount.h"
#include "util.h"
+#include "virt.h"
#define TIMEOUT_USEC (5 * USEC_PER_SEC)
#define FINALIZE_ATTEMPTS 50
diff --git a/src/socket.c b/src/socket.c
index 572e622011..7ddf326a22 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -844,7 +844,7 @@ static int mq_address_create(
fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr);
umask(old_mask);
- if (fd < 0 && errno != EEXIST) {
+ if (fd < 0) {
r = -errno;
goto fail;
}
@@ -1962,6 +1962,12 @@ int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
if (p->fd >= 0)
rn_fds++;
+ if (rn_fds <= 0) {
+ *fds = NULL;
+ *n_fds = 0;
+ return 0;
+ }
+
if (!(rfds = new(int, rn_fds)))
return -ENOMEM;
diff --git a/src/stdout-syslog-bridge.c b/src/stdout-syslog-bridge.c
index 48a301f6a7..9a0408819e 100644
--- a/src/stdout-syslog-bridge.c
+++ b/src/stdout-syslog-bridge.c
@@ -88,7 +88,7 @@ struct Stream {
bool prefix:1;
bool tee_console:1;
- char buffer[LINE_MAX];
+ char buffer[LINE_MAX+1];
size_t length;
LIST_FIELDS(Stream, stream);
@@ -111,9 +111,9 @@ static int stream_log(Stream *s, char *p, usec_t ts) {
if (*p == 0)
return 0;
- /* Patch in LOG_USER facility if necessary */
+ /* Patch in configured facility if necessary */
if ((priority & LOG_FACMASK) == 0)
- priority = LOG_USER | LOG_PRI(priority);
+ priority = (s->priority & LOG_FACMASK) | priority;
/*
* The format glibc uses to talk to the syslog daemon is:
@@ -321,16 +321,25 @@ static int stream_scan(Stream *s, usec_t ts) {
p = s->buffer;
remaining = s->length;
for (;;) {
- char *newline;
-
- if (!(newline = memchr(p, '\n', remaining)))
- break;
+ char *end;
+ size_t skip;
+
+ end = memchr(p, '\n', remaining);
+ if (!end) {
+ if (remaining >= LINE_MAX) {
+ end = p + LINE_MAX;
+ skip = LINE_MAX;
+ } else
+ break;
+ } else
+ skip = end - p + 1;
- *newline = 0;
+ *end = 0;
- if ((r = stream_line(s, p, ts)) >= 0) {
- remaining -= newline-p+1;
- p = newline+1;
+ r = stream_line(s, p, ts);
+ if (r >= 0) {
+ remaining -= skip;
+ p += skip;
}
}
@@ -347,7 +356,8 @@ static int stream_process(Stream *s, usec_t ts) {
int r;
assert(s);
- if ((l = read(s->fd, s->buffer+s->length, LINE_MAX-s->length)) < 0) {
+ l = read(s->fd, s->buffer+s->length, LINE_MAX-s->length);
+ if (l < 0) {
if (errno == EAGAIN)
return 0;
diff --git a/src/strv.c b/src/strv.c
index 92851b2233..bb309d9f92 100644
--- a/src/strv.c
+++ b/src/strv.c
@@ -67,7 +67,8 @@ void strv_free(char **l) {
char **strv_copy(char **l) {
char **r, **k;
- if (!(k = r = new(char*, strv_length(l)+1)))
+ k = r = new(char*, strv_length(l)+1);
+ if (!k)
return NULL;
if (l)
@@ -198,15 +199,23 @@ char **strv_merge_concat(char **a, char **b, const char *suffix) {
if (!b)
return strv_copy(a);
- if (!(r = new(char*, strv_length(a)+strv_length(b)+1)))
+ r = new(char*, strv_length(a) + strv_length(b) + 1);
+ if (!r)
return NULL;
- for (k = r; *a; k++, a++)
- if (!(*k = strdup(*a)))
- goto fail;
- for (; *b; k++, b++)
- if (!(*k = strappend(*b, suffix)))
+ k = r;
+ if (a)
+ for (; *a; k++, a++) {
+ *k = strdup(*a);
+ if (!*k)
+ goto fail;
+ }
+
+ for (; *b; k++, b++) {
+ *k = strappend(*b, suffix);
+ if (!*k)
goto fail;
+ }
*k = NULL;
return r;
@@ -317,7 +326,8 @@ char **strv_append(char **l, const char *s) {
if (!s)
return strv_copy(l);
- if (!(r = new(char*, strv_length(l)+2)))
+ r = new(char*, strv_length(l)+2);
+ if (!r)
return NULL;
for (k = r; *l; k++, l++)
diff --git a/src/sysfs-show.c b/src/sysfs-show.c
index ab866a4707..b8b356d77b 100644
--- a/src/sysfs-show.c
+++ b/src/sysfs-show.c
@@ -165,6 +165,9 @@ int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) {
else
r = udev_enumerate_add_match_tag(e, "seat");
+ if (r < 0)
+ goto finish;
+
r = udev_enumerate_scan_devices(e);
if (r < 0)
goto finish;
diff --git a/src/systemctl.c b/src/systemctl.c
index 7caeb6dd91..2bf2b697e2 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -137,6 +137,8 @@ static bool on_tty(void) {
}
static void pager_open_if_enabled(void) {
+
+ /* Cache result before we open the pager */
on_tty();
if (arg_no_pager)
@@ -608,6 +610,7 @@ static int list_unit_files(DBusConnection *bus, char **args) {
r = unit_file_get_list(arg_scope, arg_root, h);
if (r < 0) {
+ unit_file_list_free(h);
log_error("Failed to get unit file list: %s", strerror(-r));
return r;
}
@@ -1054,7 +1057,7 @@ finish:
}
static int load_unit(DBusConnection *bus, char **args) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
DBusError error;
int r;
char **name;
@@ -1065,6 +1068,7 @@ static int load_unit(DBusConnection *bus, char **args) {
assert(args);
STRV_FOREACH(name, args+1) {
+ DBusMessage *reply;
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
@@ -1102,9 +1106,6 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return r;
@@ -1794,7 +1795,7 @@ finish:
}
static int kill_unit(DBusConnection *bus, char **args) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int r = 0;
DBusError error;
char **name;
@@ -1811,6 +1812,7 @@ static int kill_unit(DBusConnection *bus, char **args) {
arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
STRV_FOREACH(name, args+1) {
+ DBusMessage *reply;
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
@@ -1850,9 +1852,6 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return r;
@@ -2155,8 +2154,6 @@ static void print_status_info(UnitStatusInfo *i) {
printf(")%s\n", off);
- on = off = NULL;
-
if (i->main_pid == p->pid &&
i->start_timestamp == p->start_timestamp &&
i->exit_timestamp == p->start_timestamp)
@@ -3230,7 +3227,7 @@ finish:
}
static int reset_failed(DBusConnection *bus, char **args) {
- DBusMessage *m = NULL, *reply = NULL;
+ DBusMessage *m = NULL;
int r;
DBusError error;
char **name;
@@ -3242,6 +3239,7 @@ static int reset_failed(DBusConnection *bus, char **args) {
return daemon_reload(bus, args);
STRV_FOREACH(name, args+1) {
+ DBusMessage *reply;
if (!(m = dbus_message_new_method_call(
"org.freedesktop.systemd1",
@@ -3278,9 +3276,6 @@ finish:
if (m)
dbus_message_unref(m);
- if (reply)
- dbus_message_unref(reply);
-
dbus_error_free(&error);
return r;
diff --git a/src/systemd-analyze b/src/systemd-analyze
index ae7dcfbd8a..ac6404099e 100755
--- a/src/systemd-analyze
+++ b/src/systemd-analyze
@@ -147,7 +147,7 @@ elif sys.argv[1] == 'plot':
context.set_line_width(1)
context.set_source_rgb(0.7, 0.7, 0.7)
- for x in range(0, (finish_time - start_time)/10000, 100):
+ for x in range(0, max((finish_time - start_time)/10000,110), 100):
context.move_to(x, 0)
context.line_to(x, height-border*2)
@@ -163,7 +163,7 @@ elif sys.argv[1] == 'plot':
banner = "Running on %s (%s %s) %s" % (os.uname()[1], os.uname()[2], os.uname()[3], os.uname()[4])
draw_text(context, 0, -15, banner, hcenter = 0, vcenter = 1)
- for x in range(0, (finish_time - start_time)/10000, 100):
+ for x in range(0, max((finish_time - start_time)/10000,110), 100):
draw_text(context, x, -5, "%lus" % (x/100), vcenter = 0, hcenter = 0)
y = 0
@@ -221,6 +221,18 @@ elif sys.argv[1] == 'plot':
draw_text(context, 0, height-border*2, "Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating", hcenter = 0, vcenter = -1)
+ if initrd_time > 0:
+ draw_text(context, 0, height-border*2 + bar_height, "Startup finished in %lums (kernel) + %lums (initrd) + %lums (userspace) = %lums" % ( \
+ initrd_time/1000, \
+ (start_time - initrd_time)/1000, \
+ (finish_time - start_time)/1000, \
+ finish_time/1000), hcenter = 0, vcenter = -1)
+ else:
+ draw_text(context, 0, height-border*2 + bar_height, "Startup finished in %lums (kernel) + %lums (userspace) = %lums" % ( \
+ start_time/1000, \
+ (finish_time - start_time)/1000, \
+ finish_time/1000), hcenter = 0, vcenter = -1)
+
surface.finish()
elif sys.argv[1] in ("help", "--help", "-h"):
help()
diff --git a/src/timedated.c b/src/timedated.c
index 734538882f..f6fe2d83b6 100644
--- a/src/timedated.c
+++ b/src/timedated.c
@@ -29,6 +29,7 @@
#include "strv.h"
#include "dbus-common.h"
#include "polkit.h"
+#include "def.h"
#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n"
#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n"
@@ -69,7 +70,7 @@
#define INTERFACES_LIST \
BUS_GENERIC_INTERFACES_LIST \
- "org.freedesktop.locale1\0"
+ "org.freedesktop.timedate1\0"
const char timedate_interface[] _introspect_("timedate1") = INTERFACE;
@@ -77,6 +78,8 @@ static char *zone = NULL;
static bool local_rtc = false;
static int use_ntp = -1;
+static usec_t remain_until = 0;
+
static void free_data(void) {
free(zone);
zone = NULL;
@@ -243,7 +246,7 @@ static int write_data_local_rtc(void) {
p++;
e = strchr(p, '\n');
- if (!p) {
+ if (!e) {
free(s);
return -EIO;
}
@@ -788,7 +791,10 @@ static int connect_bus(DBusConnection **_bus) {
goto fail;
}
- if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL)) {
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+
+ if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL) ||
+ !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
log_error("Not enough memory");
r = -ENOMEM;
goto fail;
@@ -824,6 +830,7 @@ fail:
int main(int argc, char *argv[]) {
int r;
DBusConnection *bus = NULL;
+ bool exiting = false;
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
@@ -861,8 +868,17 @@ int main(int argc, char *argv[]) {
goto finish;
}
- while (dbus_connection_read_write_dispatch(bus, -1))
- ;
+ remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
+ for (;;) {
+
+ if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
+ break;
+
+ if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
+ exiting = true;
+ bus_async_unregister_and_exit(bus, "org.freedesktop.hostname1");
+ }
+ }
r = 0;
diff --git a/src/umount.c b/src/umount.c
index 67be42ea33..4e036d82a3 100644
--- a/src/umount.c
+++ b/src/umount.c
@@ -565,10 +565,13 @@ int umount_all(bool *changed) {
/* retry umount, until nothing can be umounted anymore */
do {
umount_changed = false;
- r = mount_points_list_umount(&mp_list_head, &umount_changed, false);
+
+ mount_points_list_umount(&mp_list_head, &umount_changed, false);
if (umount_changed)
*changed = true;
- } while(umount_changed);
+
+ } while (umount_changed);
+
/* umount one more time with logging enabled */
r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
if (r <= 0)
diff --git a/src/unit.c b/src/unit.c
index 031e61993d..903a8e4da4 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -774,7 +774,7 @@ int unit_add_default_target_dependency(Unit *u, Unit *target) {
/* If either side wants no automatic dependencies, then let's
* skip this */
if (!u->meta.default_dependencies ||
- target->meta.default_dependencies)
+ !target->meta.default_dependencies)
return 0;
/* Don't create loops */
@@ -888,16 +888,20 @@ int unit_start(Unit *u) {
if (u->meta.load_state != UNIT_LOADED)
return -EINVAL;
- /* If this is already (being) started, then this will
- * succeed. Note that this will even succeed if this unit is
- * not startable by the user. This is relied on to detect when
- * we need to wait for units and when waiting is finished. */
+ /* If this is already started, then this will succeed. Note
+ * that this will even succeed if this unit is not startable
+ * by the user. This is relied on to detect when we need to
+ * wait for units and when waiting is finished. */
state = unit_active_state(u);
if (UNIT_IS_ACTIVE_OR_RELOADING(state))
return -EALREADY;
- /* If the conditions failed, don't do anything at all */
- if (!unit_condition_test(u)) {
+ /* If the conditions failed, don't do anything at all. If we
+ * already are activating this call might still be useful to
+ * speed up activation in case there is some hold-off time,
+ * but we don't want to recheck the condition in that case. */
+ if (state != UNIT_ACTIVATING &&
+ !unit_condition_test(u)) {
log_debug("Starting of %s requested but condition failed. Ignoring.", u->meta.id);
return -EALREADY;
}
@@ -2431,13 +2435,7 @@ void unit_status_printf(Unit *u, const char *format, ...) {
if (!UNIT_VTABLE(u)->show_status)
return;
- if (u->meta.manager->running_as != MANAGER_SYSTEM)
- return;
-
- /* If Plymouth is running make sure we show the status, so
- * that there's something nice to see when people press Esc */
-
- if (!u->meta.manager->show_status && !plymouth_running())
+ if (!manager_get_show_status(u->meta.manager))
return;
if (!manager_is_booting_or_shutting_down(u->meta.manager))
diff --git a/src/util.c b/src/util.c
index 6033aa05b2..425a732344 100644
--- a/src/util.c
+++ b/src/util.c
@@ -782,13 +782,7 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
}
}
- if (buf)
- buf[l] = 0;
- else if (!(buf = calloc(1, 1))) {
- r = -errno;
- goto finish;
- }
-
+ buf[l] = 0;
*contents = buf;
buf = NULL;
@@ -4273,224 +4267,6 @@ const char *default_term_for_tty(const char *tty) {
return term;
}
-/* Returns a short identifier for the various VM implementations */
-int detect_vm(const char **id) {
-
-#if defined(__i386__) || defined(__x86_64__)
-
- /* Both CPUID and DMI are x86 specific interfaces... */
-
- static const char *const dmi_vendors[] = {
- "/sys/class/dmi/id/sys_vendor",
- "/sys/class/dmi/id/board_vendor",
- "/sys/class/dmi/id/bios_vendor"
- };
-
- static const char dmi_vendor_table[] =
- "QEMU\0" "qemu\0"
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMware\0" "vmware\0"
- "VMW\0" "vmware\0"
- "Microsoft Corporation\0" "microsoft\0"
- "innotek GmbH\0" "oracle\0"
- "Xen\0" "xen\0"
- "Bochs\0" "bochs\0";
-
- static const char cpuid_vendor_table[] =
- "XenVMMXenVMM\0" "xen\0"
- "KVMKVMKVM\0" "kvm\0"
- /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
- "VMwareVMware\0" "vmware\0"
- /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
- "Microsoft Hv\0" "microsoft\0";
-
- uint32_t eax, ecx;
- union {
- uint32_t sig32[3];
- char text[13];
- } sig;
- unsigned i;
- const char *j, *k;
- bool hypervisor;
-
- /* http://lwn.net/Articles/301888/ */
- zero(sig);
-
-#if defined (__i386__)
-#define REG_a "eax"
-#define REG_b "ebx"
-#elif defined (__amd64__)
-#define REG_a "rax"
-#define REG_b "rbx"
-#endif
-
- /* First detect whether there is a hypervisor */
- eax = 1;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=c" (ecx)
- : "0" (eax)
- );
-
- hypervisor = !!(ecx & 0x80000000U);
-
- if (hypervisor) {
-
- /* There is a hypervisor, see what it is */
- eax = 0x40000000U;
- __asm__ __volatile__ (
- /* ebx/rbx is being used for PIC! */
- " push %%"REG_b" \n\t"
- " cpuid \n\t"
- " mov %%ebx, %1 \n\t"
- " pop %%"REG_b" \n\t"
-
- : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
- : "0" (eax)
- );
-
- NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
- if (streq(sig.text, j)) {
-
- if (id)
- *id = k;
-
- return 1;
- }
- }
-
- for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
- char *s;
- int r;
- const char *found = NULL;
-
- if ((r = read_one_line_file(dmi_vendors[i], &s)) < 0) {
- if (r != -ENOENT)
- return r;
-
- continue;
- }
-
- NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
- if (startswith(s, j))
- found = k;
- free(s);
-
- if (found) {
- if (id)
- *id = found;
-
- return 1;
- }
- }
-
- if (hypervisor) {
- if (id)
- *id = "other";
-
- return 1;
- }
-
-#endif
- return 0;
-}
-
-int detect_container(const char **id) {
- FILE *f;
-
- /* Unfortunately many of these operations require root access
- * in one way or another */
-
- if (geteuid() != 0)
- return -EPERM;
-
- if (running_in_chroot() > 0) {
-
- if (id)
- *id = "chroot";
-
- return 1;
- }
-
- /* /proc/vz exists in container and outside of the container,
- * /proc/bc only outside of the container. */
- if (access("/proc/vz", F_OK) >= 0 &&
- access("/proc/bc", F_OK) < 0) {
-
- if (id)
- *id = "openvz";
-
- return 1;
- }
-
- if ((f = fopen("/proc/self/cgroup", "re"))) {
-
- for (;;) {
- char line[LINE_MAX], *p;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- if (!(p = strchr(strstrip(line), ':')))
- continue;
-
- if (strncmp(p, ":ns:", 4))
- continue;
-
- if (!streq(p, ":ns:/")) {
- fclose(f);
-
- if (id)
- *id = "pidns";
-
- return 1;
- }
- }
-
- fclose(f);
- }
-
- return 0;
-}
-
-/* Returns a short identifier for the various VM/container implementations */
-int detect_virtualization(const char **id) {
- static __thread const char *cached_id = NULL;
- const char *_id;
- int r;
-
- if (_likely_(cached_id)) {
-
- if (cached_id == (const char*) -1)
- return 0;
-
- if (id)
- *id = cached_id;
-
- return 1;
- }
-
- if ((r = detect_container(&_id)) != 0)
- goto finish;
-
- r = detect_vm(&_id);
-
-finish:
- if (r > 0) {
- cached_id = _id;
-
- if (id)
- *id = _id;
- } else if (r == 0)
- cached_id = (const char*) -1;
-
- return r;
-}
-
bool dirent_is_file(struct dirent *de) {
assert(de);
@@ -5529,6 +5305,9 @@ int get_files_in_directory(const char *path, char ***list) {
* number */
d = opendir(path);
+ if (!d)
+ return -errno;
+
for (;;) {
struct dirent buffer, *de;
int k;
@@ -5629,6 +5408,8 @@ char *join(const char *x, ...) {
p = stpcpy(p, t);
}
+
+ va_end(ap);
} else
r[0] = 0;
@@ -5815,7 +5596,7 @@ static const char* const ip_tos_table[] = {
DEFINE_STRING_TABLE_LOOKUP(ip_tos, int);
-static const char *const signal_table[] = {
+static const char *const __signal_table[] = {
[SIGHUP] = "HUP",
[SIGINT] = "INT",
[SIGQUIT] = "QUIT",
@@ -5851,7 +5632,44 @@ static const char *const signal_table[] = {
[SIGSYS] = "SYS"
};
-DEFINE_STRING_TABLE_LOOKUP(signal, int);
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int);
+
+const char *signal_to_string(int signo) {
+ static __thread char buf[12];
+ const char *name;
+
+ name = __signal_to_string(signo);
+ if (name)
+ return name;
+
+ if (signo >= SIGRTMIN && signo <= SIGRTMAX)
+ snprintf(buf, sizeof(buf) - 1, "RTMIN+%d", signo - SIGRTMIN);
+ else
+ snprintf(buf, sizeof(buf) - 1, "%d", signo);
+ char_array_0(buf);
+ return buf;
+}
+
+int signal_from_string(const char *s) {
+ int signo;
+ int offset = 0;
+ unsigned u;
+
+ signo =__signal_from_string(s);
+ if (signo > 0)
+ return signo;
+
+ if (startswith(s, "RTMIN+")) {
+ s += 6;
+ offset = SIGRTMIN;
+ }
+ if (safe_atou(s, &u) >= 0) {
+ signo = (int) u + offset;
+ if (signo > 0 && signo < _NSIG)
+ return signo;
+ }
+ return -1;
+}
bool kexec_loaded(void) {
bool loaded = false;
diff --git a/src/util.h b/src/util.h
index 3e1f46d826..ba0800dc07 100644
--- a/src/util.h
+++ b/src/util.h
@@ -288,13 +288,13 @@ int make_null_stdio(void);
unsigned long long random_ull(void);
-#define DEFINE_STRING_TABLE_LOOKUP(name,type) \
- const char *name##_to_string(type i) { \
+#define __DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
+ scope const char *name##_to_string(type i) { \
if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \
return NULL; \
return name##_table[i]; \
} \
- type name##_from_string(const char *s) { \
+ scope type name##_from_string(const char *s) { \
type i; \
unsigned u = 0; \
assert(s); \
@@ -309,6 +309,8 @@ unsigned long long random_ull(void);
} \
struct __useless_struct_to_allow_trailing_semicolon__
+#define DEFINE_STRING_TABLE_LOOKUP(name,type) __DEFINE_STRING_TABLE_LOOKUP(name,type,)
+#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) __DEFINE_STRING_TABLE_LOOKUP(name,type,static)
int fd_nonblock(int fd, bool nonblock);
int fd_cloexec(int fd, bool cloexec);
@@ -404,10 +406,6 @@ bool tty_is_vc(const char *tty);
int vtnr_from_tty(const char *tty);
const char *default_term_for_tty(const char *tty);
-int detect_vm(const char **id);
-int detect_container(const char **id);
-int detect_virtualization(const char **id);
-
void execute_directory(const char *directory, DIR *_d, char *argv[]);
int kill_and_sigcont(pid_t pid, int sig);
diff --git a/src/vconsole-setup.c b/src/vconsole-setup.c
index 4347a2078f..8a89358a2d 100644
--- a/src/vconsole-setup.c
+++ b/src/vconsole-setup.c
@@ -39,6 +39,7 @@
#include "util.h"
#include "log.h"
#include "macro.h"
+#include "virt.h"
static bool is_vconsole(int fd) {
unsigned char data[1];
diff --git a/src/virt.c b/src/virt.c
new file mode 100644
index 0000000000..380fabded2
--- /dev/null
+++ b/src/virt.c
@@ -0,0 +1,314 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "util.h"
+#include "virt.h"
+
+/* Returns a short identifier for the various VM implementations */
+int detect_vm(const char **id) {
+
+#if defined(__i386__) || defined(__x86_64__)
+
+ /* Both CPUID and DMI are x86 specific interfaces... */
+
+ static const char *const dmi_vendors[] = {
+ "/sys/class/dmi/id/sys_vendor",
+ "/sys/class/dmi/id/board_vendor",
+ "/sys/class/dmi/id/bios_vendor"
+ };
+
+ static const char dmi_vendor_table[] =
+ "QEMU\0" "qemu\0"
+ /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+ "VMware\0" "vmware\0"
+ "VMW\0" "vmware\0"
+ "Microsoft Corporation\0" "microsoft\0"
+ "innotek GmbH\0" "oracle\0"
+ "Xen\0" "xen\0"
+ "Bochs\0" "bochs\0";
+
+ static const char cpuid_vendor_table[] =
+ "XenVMMXenVMM\0" "xen\0"
+ "KVMKVMKVM\0" "kvm\0"
+ /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
+ "VMwareVMware\0" "vmware\0"
+ /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
+ "Microsoft Hv\0" "microsoft\0";
+
+ uint32_t eax, ecx;
+ union {
+ uint32_t sig32[3];
+ char text[13];
+ } sig;
+ unsigned i;
+ const char *j, *k;
+ bool hypervisor;
+
+ /* http://lwn.net/Articles/301888/ */
+ zero(sig);
+
+#if defined (__i386__)
+#define REG_a "eax"
+#define REG_b "ebx"
+#elif defined (__amd64__)
+#define REG_a "rax"
+#define REG_b "rbx"
+#endif
+
+ /* First detect whether there is a hypervisor */
+ eax = 1;
+ __asm__ __volatile__ (
+ /* ebx/rbx is being used for PIC! */
+ " push %%"REG_b" \n\t"
+ " cpuid \n\t"
+ " pop %%"REG_b" \n\t"
+
+ : "=a" (eax), "=c" (ecx)
+ : "0" (eax)
+ );
+
+ hypervisor = !!(ecx & 0x80000000U);
+
+ if (hypervisor) {
+
+ /* There is a hypervisor, see what it is */
+ eax = 0x40000000U;
+ __asm__ __volatile__ (
+ /* ebx/rbx is being used for PIC! */
+ " push %%"REG_b" \n\t"
+ " cpuid \n\t"
+ " mov %%ebx, %1 \n\t"
+ " pop %%"REG_b" \n\t"
+
+ : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
+ : "0" (eax)
+ );
+
+ NULSTR_FOREACH_PAIR(j, k, cpuid_vendor_table)
+ if (streq(sig.text, j)) {
+
+ if (id)
+ *id = k;
+
+ return 1;
+ }
+ }
+
+ for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
+ char *s;
+ int r;
+ const char *found = NULL;
+
+ if ((r = read_one_line_file(dmi_vendors[i], &s)) < 0) {
+ if (r != -ENOENT)
+ return r;
+
+ continue;
+ }
+
+ NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
+ if (startswith(s, j))
+ found = k;
+ free(s);
+
+ if (found) {
+ if (id)
+ *id = found;
+
+ return 1;
+ }
+ }
+
+ if (hypervisor) {
+ if (id)
+ *id = "other";
+
+ return 1;
+ }
+
+#endif
+ return 0;
+}
+
+int detect_container(const char **id) {
+ FILE *f;
+
+ /* Unfortunately many of these operations require root access
+ * in one way or another */
+
+ if (geteuid() != 0)
+ return -EPERM;
+
+ if (running_in_chroot() > 0) {
+
+ if (id)
+ *id = "chroot";
+
+ return 1;
+ }
+
+ /* /proc/vz exists in container and outside of the container,
+ * /proc/bc only outside of the container. */
+ if (access("/proc/vz", F_OK) >= 0 &&
+ access("/proc/bc", F_OK) < 0) {
+
+ if (id)
+ *id = "openvz";
+
+ return 1;
+ }
+
+ f = fopen("/proc/1/environ", "re");
+ if (f) {
+ bool done = false;
+
+ do {
+ char line[LINE_MAX];
+ unsigned i;
+
+ for (i = 0; i < sizeof(line)-1; i++) {
+ int c;
+
+ c = getc(f);
+ if (_unlikely_(c == EOF)) {
+ done = true;
+ break;
+ } else if (c == 0)
+ break;
+
+ line[i] = c;
+ }
+ line[i] = 0;
+
+ if (streq(line, "container=lxc")) {
+ fclose(f);
+
+ if (id)
+ *id = "lxc";
+ return 1;
+
+ } else if (streq(line, "container=systemd-nspawn")) {
+ fclose(f);
+
+ if (id)
+ *id = "systemd-nspawn";
+ return 1;
+
+ } else if (startswith(line, "container=")) {
+ fclose(f);
+
+ if (id)
+ *id = "other";
+ return 1;
+ }
+
+ } while (!done);
+
+ fclose(f);
+ }
+
+ f = fopen("/proc/self/cgroup", "re");
+ if (f) {
+
+ for (;;) {
+ char line[LINE_MAX], *p;
+
+ if (!fgets(line, sizeof(line), f))
+ break;
+
+ p = strchr(strstrip(line), ':');
+ if (!p)
+ continue;
+
+ if (strncmp(p, ":ns:", 4))
+ continue;
+
+ if (!streq(p, ":ns:/")) {
+ fclose(f);
+
+ if (id)
+ *id = "pidns";
+
+ return 1;
+ }
+ }
+
+ fclose(f);
+ }
+
+ return 0;
+}
+
+/* Returns a short identifier for the various VM/container implementations */
+Virtualization detect_virtualization(const char **id) {
+
+ static __thread Virtualization cached_virt = _VIRTUALIZATION_INVALID;
+ static __thread const char *cached_id = NULL;
+
+ const char *_id;
+ int r;
+ Virtualization v;
+
+ if (_likely_(cached_virt >= 0)) {
+
+ if (id && cached_virt > 0)
+ *id = cached_id;
+
+ return cached_virt;
+ }
+
+ r = detect_container(&_id);
+ if (r < 0) {
+ v = r;
+ goto finish;
+ } else if (r > 0) {
+ v = VIRTUALIZATION_CONTAINER;
+ goto finish;
+ }
+
+ r = detect_vm(&_id);
+ if (r < 0) {
+ v = r;
+ goto finish;
+ } else if (r > 0) {
+ v = VIRTUALIZATION_VM;
+ goto finish;
+ }
+
+ v = VIRTUALIZATION_NONE;
+
+finish:
+ if (v > 0) {
+ cached_id = _id;
+
+ if (id)
+ *id = _id;
+ }
+
+ if (v >= 0)
+ cached_virt = v;
+
+ return v;
+}
diff --git a/src/virt.h b/src/virt.h
new file mode 100644
index 0000000000..f55c9a68fd
--- /dev/null
+++ b/src/virt.h
@@ -0,0 +1,38 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foovirthfoo
+#define foovirthfoo
+
+/***
+ This file is part of systemd.
+
+ Copyright 2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+int detect_vm(const char **id);
+int detect_container(const char **id);
+
+typedef enum Virtualization {
+ VIRTUALIZATION_NONE = 0,
+ VIRTUALIZATION_VM,
+ VIRTUALIZATION_CONTAINER,
+ _VIRTUALIZATION_MAX,
+ _VIRTUALIZATION_INVALID = -1
+} Virtualization;
+
+Virtualization detect_virtualization(const char **id);
+
+#endif
diff --git a/units/console-shell.service.m4 b/units/console-shell.service.m4
index cce2d5a5a4..a4a9108b32 100644
--- a/units/console-shell.service.m4
+++ b/units/console-shell.service.m4
@@ -31,6 +31,8 @@ WorkingDirectory=/root
ExecStart=-/sbin/sulogin
ExecStopPost=-/bin/systemctl poweroff
StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
KillMode=process
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
diff --git a/units/dev-hugepages.mount b/units/dev-hugepages.mount
index e6014e54a0..72a522e69c 100644
--- a/units/dev-hugepages.mount
+++ b/units/dev-hugepages.mount
@@ -8,6 +8,8 @@
[Unit]
Description=Huge Pages File System
DefaultDependencies=no
+Before=sysinit.target
+ConditionPathExists=/sys/kernel/mm/hugepages
[Mount]
What=hugetlbfs
diff --git a/units/dev-mqueue.mount b/units/dev-mqueue.mount
index 8519df5aca..cffdaf773f 100644
--- a/units/dev-mqueue.mount
+++ b/units/dev-mqueue.mount
@@ -8,6 +8,8 @@
[Unit]
Description=POSIX Message Queue File System
DefaultDependencies=no
+Before=sysinit.target
+ConditionPathExists=/proc/sys/fs/mqueue
[Mount]
What=mqueue
diff --git a/units/emergency.service b/units/emergency.service
index eff5261868..4847f4f0c6 100644
--- a/units/emergency.service
+++ b/units/emergency.service
@@ -21,6 +21,8 @@ ExecStartPre=-/bin/echo 'Welcome to emergency mode. Use "systemctl default" or ^
ExecStart=-/sbin/sulogin
ExecStopPost=/bin/systemctl --fail --no-block default
StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
KillMode=process
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
diff --git a/units/rescue.service.m4 b/units/rescue.service.m4
index d2fd582e86..19b30d89f9 100644
--- a/units/rescue.service.m4
+++ b/units/rescue.service.m4
@@ -11,7 +11,7 @@
Description=Rescue Shell
DefaultDependencies=no
Conflicts=shutdown.target
-After=basic.target
+After=basic.target plymouth-start.service
Before=shutdown.target
[Service]
@@ -25,12 +25,14 @@ ExecStart=-/bin/bash -c "exec ${SINGLE}"',
m4_ifdef(`TARGET_MANDRIVA',
`EnvironmentFile=/etc/sysconfig/init
ExecStart=-/bin/bash -c "exec ${SINGLE}"',
-`ExecStart=-/sbin/sulogin'
m4_ifdef(`TARGET_MEEGO',
`EnvironmentFile=/etc/sysconfig/init
-ExecStart=-/bin/bash -c "exec ${SINGLE}"',)))
+ExecStart=-/bin/bash -c "exec ${SINGLE}"',
+`ExecStart=-/sbin/sulogin')))
ExecStopPost=-/bin/systemctl --fail --no-block default
StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
KillMode=process
# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
diff --git a/units/dev-mqueue.automount b/units/sys-fs-fuse-connections.mount
index 1061597571..037471537b 100644
--- a/units/dev-mqueue.automount
+++ b/units/sys-fs-fuse-connections.mount
@@ -6,10 +6,13 @@
# (at your option) any later version.
[Unit]
-Description=POSIX Message Queue File System Automount Point
+Description=FUSE Control File System
DefaultDependencies=no
+ConditionPathExists=/sys/fs/fuse/connections
+After=systemd-modules-load.service
Before=sysinit.target
-ConditionPathExists=/proc/sys/fs/mqueue
-[Automount]
-Where=/dev/mqueue
+[Mount]
+What=fusectl
+Where=/sys/fs/fuse/connections
+Type=fusectl
diff --git a/units/dev-hugepages.automount b/units/sys-kernel-config.mount
index 6e03df3560..d6862bf6bd 100644
--- a/units/dev-hugepages.automount
+++ b/units/sys-kernel-config.mount
@@ -6,10 +6,13 @@
# (at your option) any later version.
[Unit]
-Description=Huge Pages File System Automount Point
+Description=Configuration File System
DefaultDependencies=no
+ConditionPathExists=/sys/kernel/config
+After=systemd-modules-load.service
Before=sysinit.target
-ConditionPathExists=/sys/kernel/mm/hugepages
-[Automount]
-Where=/dev/hugepages
+[Mount]
+What=configfs
+Where=/sys/kernel/config
+Type=configfs
diff --git a/units/sys-kernel-debug.automount b/units/sys-kernel-debug.automount
deleted file mode 100644
index 2f2de9829f..0000000000
--- a/units/sys-kernel-debug.automount
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-[Unit]
-Description=Debug File System Automount Point
-DefaultDependencies=no
-Before=sysinit.target
-ConditionPathExists=/sys/kernel/debug
-
-[Automount]
-Where=/sys/kernel/debug
diff --git a/units/sys-kernel-debug.mount b/units/sys-kernel-debug.mount
index 53d107260b..d9fca1ff3d 100644
--- a/units/sys-kernel-debug.mount
+++ b/units/sys-kernel-debug.mount
@@ -8,6 +8,8 @@
[Unit]
Description=Debug File System
DefaultDependencies=no
+ConditionPathExists=/sys/kernel/debug
+Before=sysinit.target
[Mount]
What=debugfs
diff --git a/units/sys-kernel-security.automount b/units/sys-kernel-security.automount
deleted file mode 100644
index b7b16e19aa..0000000000
--- a/units/sys-kernel-security.automount
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-[Unit]
-Description=Security File System Automount Point
-DefaultDependencies=no
-Before=sysinit.target
-ConditionPathExists=/sys/kernel/security
-
-[Automount]
-Where=/sys/kernel/security
diff --git a/units/sys-kernel-security.mount b/units/sys-kernel-security.mount
index 770207f004..80cd7617d4 100644
--- a/units/sys-kernel-security.mount
+++ b/units/sys-kernel-security.mount
@@ -8,6 +8,8 @@
[Unit]
Description=Security File System
DefaultDependencies=no
+ConditionPathExists=/sys/kernel/security
+Before=sysinit.target
[Mount]
What=securityfs
diff --git a/units/systemd-readahead-collect.service.in b/units/systemd-readahead-collect.service.in
index 1a66f9fa6f..56ba54f0b3 100644
--- a/units/systemd-readahead-collect.service.in
+++ b/units/systemd-readahead-collect.service.in
@@ -16,6 +16,7 @@ Before=sysinit.target shutdown.target
Type=notify
ExecStart=@rootlibexecdir@/systemd-readahead-collect
RemainAfterExit=yes
+StandardOutput=null
[Install]
WantedBy=default.target
diff --git a/units/systemd-readahead-replay.service.in b/units/systemd-readahead-replay.service.in
index 5cc6defd9b..7c82e408e2 100644
--- a/units/systemd-readahead-replay.service.in
+++ b/units/systemd-readahead-replay.service.in
@@ -16,6 +16,7 @@ ConditionPathExists=/.readahead
Type=notify
ExecStart=@rootlibexecdir@/systemd-readahead-replay
RemainAfterExit=yes
+StandardOutput=null
[Install]
WantedBy=default.target
diff --git a/units/var-lock.mount b/units/var-lock.mount
index 80e1bab261..07277adac3 100644
--- a/units/var-lock.mount
+++ b/units/var-lock.mount
@@ -10,6 +10,7 @@ Description=Lock Directory
Before=local-fs.target
# skip mounting if the directory does not exist or is a symlink
ConditionPathIsDirectory=/var/lock
+ConditionPathIsSymbolicLink=!/var/lock
[Mount]
What=/run/lock
diff --git a/units/var-run.mount b/units/var-run.mount
index c513dfecd2..ab4da424c9 100644
--- a/units/var-run.mount
+++ b/units/var-run.mount
@@ -10,6 +10,7 @@ Description=Runtime Directory
Before=local-fs.target
# skip mounting if the directory does not exist or is a symlink
ConditionPathIsDirectory=/var/run
+ConditionPathIsSymbolicLink=!/var/run
[Mount]
What=/run