summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile-man.am7
-rw-r--r--coccinelle/free_and_replace.cocci15
-rw-r--r--coccinelle/mfree_return.cocci6
-rw-r--r--hwdb/70-pointingstick.hwdb4
-rw-r--r--man/journal-remote.conf.xml13
-rw-r--r--man/journal-upload.conf.xml113
-rw-r--r--man/sd-journal.xml15
-rw-r--r--man/sd_bus_creds_get_pid.xml2
-rw-r--r--man/sd_journal_add_match.xml3
-rw-r--r--man/sd_journal_enumerate_fields.xml3
-rw-r--r--man/sd_journal_get_catalog.xml4
-rw-r--r--man/sd_journal_get_cursor.xml3
-rw-r--r--man/sd_journal_get_cutoff_realtime_usec.xml3
-rw-r--r--man/sd_journal_get_usage.xml3
-rw-r--r--man/sd_journal_has_runtime_files.xml12
-rw-r--r--man/sd_journal_next.xml3
-rw-r--r--man/sd_journal_open.xml3
-rw-r--r--man/sd_journal_print.xml7
-rw-r--r--man/sd_journal_query_unique.xml3
-rw-r--r--man/sd_journal_seek_head.xml3
-rw-r--r--man/sd_journal_stream_fd.xml4
-rw-r--r--man/systemd.exec.xml50
-rw-r--r--man/systemd.resource-control.xml18
-rw-r--r--man/systemd.unit.xml6
-rw-r--r--shell-completion/zsh/_systemctl.in14
-rw-r--r--src/basic/alloc-util.h8
-rw-r--r--src/basic/bitmap.c6
-rw-r--r--src/basic/env-util.c3
-rw-r--r--src/basic/fs-util.c8
-rw-r--r--src/basic/path-util.c4
-rw-r--r--src/basic/prioq.c4
-rw-r--r--src/basic/replace-var.c3
-rw-r--r--src/basic/strbuf.c3
-rw-r--r--src/basic/string-util.c6
-rw-r--r--src/basic/strv.c9
-rw-r--r--src/basic/terminal-util.h53
-rw-r--r--src/boot/bootctl.c5
-rw-r--r--src/core/dbus-execute.c86
-rw-r--r--src/core/dynamic-user.c4
-rw-r--r--src/core/execute.c90
-rw-r--r--src/core/execute.h5
-rw-r--r--src/core/load-fragment-gperf.gperf.m46
-rw-r--r--src/core/load-fragment.c114
-rw-r--r--src/core/load-fragment.h2
-rw-r--r--src/core/manager.c3
-rw-r--r--src/core/mount.c14
-rw-r--r--src/core/service.c4
-rw-r--r--src/core/timer.c2
-rw-r--r--src/core/transaction.c6
-rw-r--r--src/core/unit.c46
-rw-r--r--src/cryptsetup/cryptsetup-generator.c9
-rw-r--r--src/import/curl-util.c4
-rw-r--r--src/import/export-raw.c4
-rw-r--r--src/import/export-tar.c4
-rw-r--r--src/import/import-raw.c4
-rw-r--r--src/import/import-tar.c4
-rw-r--r--src/import/importd.c6
-rw-r--r--src/import/pull-job.c4
-rw-r--r--src/import/pull-raw.c4
-rw-r--r--src/import/pull-tar.c4
-rw-r--r--src/journal-remote/journal-remote-write.c10
-rw-r--r--src/journal-remote/journal-upload.c4
-rw-r--r--src/journal/journal-file.c3
-rw-r--r--src/journal/mmap-cache.c6
-rw-r--r--src/journal/sd-journal.c9
-rw-r--r--src/libsystemd-network/ndisc-router.c3
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c4
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c4
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c4
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c4
-rw-r--r--src/libsystemd-network/sd-dhcp6-lease.c4
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c4
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c4
-rw-r--r--src/libsystemd-network/sd-lldp.c4
-rw-r--r--src/libsystemd-network/sd-ndisc.c4
-rw-r--r--src/libsystemd/sd-bus/bus-slot.c4
-rw-r--r--src/libsystemd/sd-bus/bus-track.c8
-rw-r--r--src/libudev/libudev-list.c14
-rw-r--r--src/libudev/libudev-monitor.c3
-rw-r--r--src/login/loginctl.c90
-rw-r--r--src/login/logind-button.c9
-rw-r--r--src/login/logind-device.c9
-rw-r--r--src/login/logind-inhibit.c9
-rw-r--r--src/login/logind-seat.c9
-rw-r--r--src/login/logind-session.c12
-rw-r--r--src/machine/machine.c4
-rw-r--r--src/machine/operation.c3
-rw-r--r--src/network/networkd-netdev-tunnel.c8
-rw-r--r--src/network/networkd-wait-online-link.c3
-rw-r--r--src/nspawn/nspawn-settings.c4
-rw-r--r--src/resolve/resolved-dns-query.c8
-rw-r--r--src/resolve/resolved-dns-rr.c10
-rw-r--r--src/resolve/resolved-dns-scope.c4
-rw-r--r--src/resolve/resolved-dns-search-domain.c4
-rw-r--r--src/resolve/resolved-dns-server.c3
-rw-r--r--src/resolve/resolved-dns-stream.c4
-rw-r--r--src/resolve/resolved-dns-transaction.c3
-rw-r--r--src/resolve/resolved-link.c6
-rw-r--r--src/resolve/resolved-manager.c4
-rw-r--r--src/shared/install.c23
-rw-r--r--src/shared/machine-image.c3
-rw-r--r--src/shared/ptyfwd.c3
-rw-r--r--src/systemctl/systemctl.c106
-rw-r--r--src/test/test-calendarspec.c25
-rw-r--r--src/timesync/timesyncd-server.c7
-rw-r--r--src/udev/udev-ctrl.c3
-rw-r--r--src/udev/udev-rules.c3
107 files changed, 890 insertions, 447 deletions
diff --git a/Makefile-man.am b/Makefile-man.am
index a900b8d25a..013e0d7967 100644
--- a/Makefile-man.am
+++ b/Makefile-man.am
@@ -2272,19 +2272,25 @@ endif
if HAVE_MICROHTTPD
MANPAGES += \
man/journal-remote.conf.5 \
+ man/journal-upload.conf.5 \
man/systemd-journal-gatewayd.service.8 \
man/systemd-journal-remote.8 \
man/systemd-journal-upload.8
MANPAGES_ALIAS += \
man/journal-remote.conf.d.5 \
+ man/journal-upload.conf.d.5 \
man/systemd-journal-gatewayd.8 \
man/systemd-journal-gatewayd.socket.8
man/journal-remote.conf.d.5: man/journal-remote.conf.5
+man/journal-upload.conf.d.5: man/journal-upload.conf.5
man/systemd-journal-gatewayd.8: man/systemd-journal-gatewayd.service.8
man/systemd-journal-gatewayd.socket.8: man/systemd-journal-gatewayd.service.8
man/journal-remote.conf.d.html: man/journal-remote.conf.html
$(html-alias)
+man/journal-upload.conf.d.html: man/journal-upload.conf.html
+ $(html-alias)
+
man/systemd-journal-gatewayd.html: man/systemd-journal-gatewayd.service.html
$(html-alias)
@@ -2607,6 +2613,7 @@ EXTRA_DIST += \
man/hostnamectl.xml \
man/hwdb.xml \
man/journal-remote.conf.xml \
+ man/journal-upload.conf.xml \
man/journalctl.xml \
man/journald.conf.xml \
man/kernel-command-line.xml \
diff --git a/coccinelle/free_and_replace.cocci b/coccinelle/free_and_replace.cocci
new file mode 100644
index 0000000000..9dcdbf4d42
--- /dev/null
+++ b/coccinelle/free_and_replace.cocci
@@ -0,0 +1,15 @@
+@@
+expression p, q;
+@@
+- free(p);
+- p = q;
+- q = NULL;
+- return 0;
++ return free_and_replace(p, q);
+@@
+expression p, q;
+@@
+- free(p);
+- p = q;
+- q = NULL;
++ free_and_replace(p, q);
diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci
new file mode 100644
index 0000000000..8119fe07f2
--- /dev/null
+++ b/coccinelle/mfree_return.cocci
@@ -0,0 +1,6 @@
+@@
+expression p;
+@@
+- free(p);
+- return NULL;
++ return mfree(p);
diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb
index 2b30896dff..e18ef28290 100644
--- a/hwdb/70-pointingstick.hwdb
+++ b/hwdb/70-pointingstick.hwdb
@@ -87,6 +87,10 @@ evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr*
evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr*
POINTINGSTICK_CONST_ACCEL=1.5
+# Latitude E7470
+evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*:pvr*
+ POINTINGSTICK_CONST_ACCEL=0.6
+
#########################################
# Lenovo
#########################################
diff --git a/man/journal-remote.conf.xml b/man/journal-remote.conf.xml
index 2d345963d9..f7ac8c46e0 100644
--- a/man/journal-remote.conf.xml
+++ b/man/journal-remote.conf.xml
@@ -45,22 +45,21 @@
<refnamediv>
<refname>journal-remote.conf</refname>
<refname>journal-remote.conf.d</refname>
- <refpurpose>Journal remote service configuration files</refpurpose>
+ <refpurpose>Configuration files for the service accepting remote journal uploads</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/systemd/journal-remote.conf</filename></para>
- <para><filename>/etc/systemd/journald.conf.d/*.conf</filename></para>
- <para><filename>/run/systemd/journald.conf.d/*.conf</filename></para>
- <para><filename>/usr/lib/systemd/journald.conf.d/*.conf</filename></para>
+ <para><filename>/etc/systemd/journal-remote.conf.d/*.conf</filename></para>
+ <para><filename>/run/systemd/journal-remote.conf.d/*.conf</filename></para>
+ <para><filename>/usr/lib/systemd/journal-remote.conf.d/*.conf</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
- <para>These files configure various parameters of the systemd-remote-journal
- application,
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ <para>These files configure various parameters of
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
</refsect1>
<xi:include href="standard-conf.xml" xpointer="main-conf" />
diff --git a/man/journal-upload.conf.xml b/man/journal-upload.conf.xml
new file mode 100644
index 0000000000..e3be62dfd1
--- /dev/null
+++ b/man/journal-upload.conf.xml
@@ -0,0 +1,113 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2016 Zbigniew Jędrzejewski-Szmek
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="journal-upload.conf" conditional='HAVE_MICROHTTPD'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <refentryinfo>
+ <title>journal-upload.conf</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Monkey with a keyboard</contrib>
+ <firstname>Zbigniew</firstname>
+ <surname>Jędrzejewski-Szmek</surname>
+ <email>zbyszek@in.waw.pl</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>journal-upload.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>journal-upload.conf</refname>
+ <refname>journal-upload.conf.d</refname>
+ <refpurpose>Configuration files for the journal upload service</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <para><filename>/etc/systemd/journal-upload.conf</filename></para>
+ <para><filename>/etc/systemd/journal-upload.conf.d/*.conf</filename></para>
+ <para><filename>/run/systemd/journal-upload.conf.d/*.conf</filename></para>
+ <para><filename>/usr/lib/systemd/journal-upload.conf.d/*.conf</filename></para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para>These files configure various parameters of
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <xi:include href="standard-conf.xml" xpointer="main-conf" />
+
+ <refsect1>
+ <title>Options</title>
+
+ <para>All options are configured in the <literal>[Upload]</literal> section:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><varname>URL=</varname></term>
+
+ <listitem><para>The URL to upload the journal entries to. See the description
+ of <varname>--url=</varname> option in
+ <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ for the description of possible values.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ServerKeyFile=</varname></term>
+
+ <listitem><para>SSL key in PEM format.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ServerCertificateFile=</varname></term>
+
+ <listitem><para>SSL CA certificate in PEM format.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>TrustedCertificateFile=</varname></term>
+
+ <listitem><para>SSL CA certificate.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/man/sd-journal.xml b/man/sd-journal.xml
index 936a83acf7..0f4b3e8eea 100644
--- a/man/sd-journal.xml
+++ b/man/sd-journal.xml
@@ -98,6 +98,21 @@
tool.</para>
</refsect1>
+ <refsect1>
+ <title>Thread safety</title>
+
+ <para>Functions that operate on the <structname>sd_journal</structname> object are thread
+ agnostic — given <structname>sd_journal</structname> pointer may only be used from one thread at
+ a time, but multiple threads may use multiple such objects safely. Other functions —
+ those that are used to send entries to the journal, like
+ <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and similar, or those that are used to retrieve global information like
+ <citerefentry><refentrytitle>sd_journal_stream_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>sd_journal_get_catalog_for_message_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ — are thread-safe and may be called from multiple threads in parallel.</para>
+ </refsect1>
+
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml
index 4c05835568..9e68d5e8c7 100644
--- a/man/sd_bus_creds_get_pid.xml
+++ b/man/sd_bus_creds_get_pid.xml
@@ -366,7 +366,7 @@
-ENXIO is returned.</para>
<para><function>sd_bus_creds_get_cgroup()</function> will retrieve
- the cgroup path. See <ulink
+ the control group path. See <ulink
url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>.
</para>
diff --git a/man/sd_journal_add_match.xml b/man/sd_journal_add_match.xml
index 98415d53fd..7c64329aed 100644
--- a/man/sd_journal_add_match.xml
+++ b/man/sd_journal_add_match.xml
@@ -168,6 +168,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_add_match()</function>,
<function>sd_journal_add_disjunction()</function>,
<function>sd_journal_add_conjunction()</function> and
diff --git a/man/sd_journal_enumerate_fields.xml b/man/sd_journal_enumerate_fields.xml
index fa5884106b..bc2c21ed4b 100644
--- a/man/sd_journal_enumerate_fields.xml
+++ b/man/sd_journal_enumerate_fields.xml
@@ -110,6 +110,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function>
interfaces are available as a shared library, which can be compiled and linked to with the
<constant>libsystemd</constant> <citerefentry
diff --git a/man/sd_journal_get_catalog.xml b/man/sd_journal_get_catalog.xml
index c19eb11b20..35ec46f63e 100644
--- a/man/sd_journal_get_catalog.xml
+++ b/man/sd_journal_get_catalog.xml
@@ -112,6 +112,10 @@
<refsect1>
<title>Notes</title>
+ <para>Function <function>sd_journal_get_catalog()</function> is thread-agnostic and only a
+ single thread may operate on a given <structname>sd_journal</structname> object. Function
+ <function>sd_journal_get_catalog_for_message_id() is thread-safe.</function></para>
+
<para>The <function>sd_journal_get_catalog()</function> and
<function>sd_journal_get_catalog_for_message_id()</function>
interfaces are available as a shared library, which can be
diff --git a/man/sd_journal_get_cursor.xml b/man/sd_journal_get_cursor.xml
index a400d8b1b5..b7aa05f8b2 100644
--- a/man/sd_journal_get_cursor.xml
+++ b/man/sd_journal_get_cursor.xml
@@ -122,6 +122,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_get_cursor()</function> and
<function>sd_journal_test_cursor()</function> interfaces are
available as a shared library, which can be compiled and linked to
diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml
index 23e7cc65e8..0950e11b44 100644
--- a/man/sd_journal_get_cutoff_realtime_usec.xml
+++ b/man/sd_journal_get_cutoff_realtime_usec.xml
@@ -120,6 +120,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The
<function>sd_journal_get_cutoff_realtime_usec()</function> and
<function>sd_journal_get_cutoff_monotonic_usec()</function>
diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml
index 72c804d834..06b0ff534d 100644
--- a/man/sd_journal_get_usage.xml
+++ b/man/sd_journal_get_usage.xml
@@ -80,6 +80,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_get_usage()</function> interface is
available as a shared library, which can be compiled and linked to
with the
diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml
index 237e649206..3f6d56ca77 100644
--- a/man/sd_journal_has_runtime_files.xml
+++ b/man/sd_journal_has_runtime_files.xml
@@ -86,6 +86,18 @@
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
+ <para>Functions listed here are available as a shared library, which can be compiled and linked
+ to with the <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file.</para>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
diff --git a/man/sd_journal_next.xml b/man/sd_journal_next.xml
index 115fe26661..7c385de260 100644
--- a/man/sd_journal_next.xml
+++ b/man/sd_journal_next.xml
@@ -146,6 +146,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_next()</function>,
<function>sd_journal_previous()</function>,
<function>sd_journal_next_skip()</function> and
diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml
index 74e67023b5..25b3048f2e 100644
--- a/man/sd_journal_open.xml
+++ b/man/sd_journal_open.xml
@@ -208,6 +208,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_open()</function>,
<function>sd_journal_open_directory()</function> and
<function>sd_journal_close()</function> interfaces are available
diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml
index 76542527fc..2d8dd635aa 100644
--- a/man/sd_journal_print.xml
+++ b/man/sd_journal_print.xml
@@ -201,9 +201,10 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
</refsect1>
<refsect1>
- <title>Async signal safety</title>
- <para><function>sd_journal_sendv()</function> is "async signal
- safe" in the meaning of
+ <title>Thread safety</title>
+ <para>All functions listed here are thread-safe and may be called in parallel from multiple threads.</para>
+
+ <para><function>sd_journal_sendv()</function> is "async signal safe" in the meaning of
<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml
index dbff55c105..d7a41a039c 100644
--- a/man/sd_journal_query_unique.xml
+++ b/man/sd_journal_query_unique.xml
@@ -150,6 +150,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_query_unique()</function>,
<function>sd_journal_enumerate_unique()</function> and
<function>sd_journal_restart_unique()</function> interfaces are
diff --git a/man/sd_journal_seek_head.xml b/man/sd_journal_seek_head.xml
index d74c2d5bbc..985073496c 100644
--- a/man/sd_journal_seek_head.xml
+++ b/man/sd_journal_seek_head.xml
@@ -144,6 +144,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_seek_head()</function>,
<function>sd_journal_seek_tail()</function>,
<function>sd_journal_seek_monotonic_usec()</function>,
diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml
index 2ea7731b48..226298ae1b 100644
--- a/man/sd_journal_stream_fd.xml
+++ b/man/sd_journal_stream_fd.xml
@@ -104,6 +104,10 @@
<refsect1>
<title>Notes</title>
+ <para>Function <function>sd_journal_stream_fd()</function> is thread-safe and may be be called
+ from multiple threads. All calls will return the same file descriptor, although temporarily
+ multiple file descriptors may be open.</para>
+
<para>The <function>sd_journal_stream_fd()</function> interface is
available as a shared library, which can be compiled and linked to
with the
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 71dc86ec2f..7453aa7bee 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -74,6 +74,10 @@
execution specific configuration options are configured in the
[Service], [Socket], [Mount], or [Swap] sections, depending on the
unit type.</para>
+
+ <para>In addition, options which control resources through Linux Control Groups (cgroups) are listed in
+ <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ Those options complement options listed here.</para>
</refsect1>
<refsect1>
@@ -405,8 +409,9 @@
<option>null</option>,
<option>tty</option>,
<option>tty-force</option>,
- <option>tty-fail</option> or
- <option>socket</option>.</para>
+ <option>tty-fail</option>,
+ <option>socket</option> or
+ <option>fd</option>.</para>
<para>If <option>null</option> is selected, standard input
will be connected to <filename>/dev/null</filename>, i.e. all
@@ -444,6 +449,20 @@
<citerefentry project='freebsd'><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
daemon.</para>
+ <para>The <option>fd</option> option connects
+ the input stream to a single file descriptor provided by a socket unit.
+ A custom named file descriptor can be specified as part of this option,
+ after a <literal>:</literal> (e.g. <literal>fd:<replaceable>foobar</replaceable></literal>).
+ If no name is specified, <literal>stdin</literal> is assumed
+ (i.e. <literal>fd</literal> is equivalent to <literal>fd:stdin</literal>).
+ At least one socket unit defining such name must be explicitly provided via the
+ <varname>Sockets=</varname> option, and file descriptor name may differ
+ from the name of its containing socket unit.
+ If multiple matches are found, the first one will be used.
+ See <varname>FileDescriptorName=</varname> in
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more details about named descriptors and ordering.</para>
+
<para>This setting defaults to
<option>null</option>.</para></listitem>
</varlistentry>
@@ -460,8 +479,9 @@
<option>kmsg</option>,
<option>journal+console</option>,
<option>syslog+console</option>,
- <option>kmsg+console</option> or
- <option>socket</option>.</para>
+ <option>kmsg+console</option>,
+ <option>socket</option> or
+ <option>fd</option>.</para>
<para><option>inherit</option> duplicates the file descriptor
of standard input for standard output.</para>
@@ -510,6 +530,20 @@
similar to the same option of
<varname>StandardInput=</varname>.</para>
+ <para>The <option>fd</option> option connects
+ the output stream to a single file descriptor provided by a socket unit.
+ A custom named file descriptor can be specified as part of this option,
+ after a <literal>:</literal> (e.g. <literal>fd:<replaceable>foobar</replaceable></literal>).
+ If no name is specified, <literal>stdout</literal> is assumed
+ (i.e. <literal>fd</literal> is equivalent to <literal>fd:stdout</literal>).
+ At least one socket unit defining such name must be explicitly provided via the
+ <varname>Sockets=</varname> option, and file descriptor name may differ
+ from the name of its containing socket unit.
+ If multiple matches are found, the first one will be used.
+ See <varname>FileDescriptorName=</varname> in
+ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ for more details about named descriptors and ordering.</para>
+
<para>If the standard output (or error output, see below) of a unit is connected to the journal, syslog or the
kernel log buffer, the unit will implicitly gain a dependency of type <varname>After=</varname> on
<filename>systemd-journald.socket</filename> (also see the automatic dependencies section above).</para>
@@ -527,9 +561,13 @@
<listitem><para>Controls where file descriptor 2 (STDERR) of
the executed processes is connected to. The available options
are identical to those of <varname>StandardOutput=</varname>,
- with one exception: if set to <option>inherit</option> the
+ with some exceptions: if set to <option>inherit</option> the
file descriptor used for standard output is duplicated for
- standard error. This setting defaults to the value set with
+ standard error, while <option>fd</option> operates on the error
+ stream and will look by default for a descriptor named
+ <literal>stderr</literal>.</para>
+
+ <para>This setting defaults to the value set with
<option>DefaultStandardError=</option> in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
which defaults to <option>inherit</option>. Note that setting
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index 10aefbe0c5..02878b28a0 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -60,12 +60,10 @@
<refsect1>
<title>Description</title>
- <para>Unit configuration files for services, slices, scopes,
- sockets, mount points, and swap devices share a subset of
- configuration options for resource control of spawned
- processes. Internally, this relies on the Control Groups
- kernel concept for organizing processes in a hierarchical tree of
- named groups for the purpose of resource management.</para>
+ <para>Unit configuration files for services, slices, scopes, sockets, mount points, and swap devices share a subset
+ of configuration options for resource control of spawned processes. Internally, this relies on the Linux Control
+ Groups (cgroups) kernel concept for organizing processes in a hierarchical tree of named groups for the purpose of
+ resource management.</para>
<para>This man page lists the configuration options shared by
those six unit types. See
@@ -83,6 +81,11 @@
[Slice], [Scope], [Service], [Socket], [Mount], or [Swap]
sections, depending on the unit type.</para>
+ <para>In addition, options which control resources available to programs
+ <emphasis>executed</emphasis> by systemd are listed in
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ Those options complement options listed here.</para>
+
<para>See the <ulink
url="http://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/">New
Control Group Interfaces</ulink> for an introduction on how to make
@@ -111,7 +114,7 @@
<term><option>CPU</option></term>
<listitem>
<para>Due to the lack of consensus in the kernel community, the CPU controller support on the unified
- cgroup hierarchy requires out-of-tree kernel patches. See <ulink
+ control group hierarchy requires out-of-tree kernel patches. See <ulink
url="https://git.kernel.org/cgit/linux/kernel/git/tj/cgroup.git/tree/Documentation/cgroup-v2-cpu.txt?h=cgroup-v2-cpu">cgroup-v2-cpu.txt</ulink>.</para>
<para><varname>CPUWeight=</varname> and <varname>StartupCPUWeight=</varname> replace
@@ -751,6 +754,7 @@
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
The documentation for control groups and specific controllers in the Linux kernel:
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 79bdb2cd38..04efee2891 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -203,9 +203,7 @@
<filename>/run/systemd/system</filename> directories. Drop-in files in <filename>/etc</filename>
take precedence over those in <filename>/run</filename> which in turn take precedence over those
in <filename>/usr/lib</filename>. Drop-in files under any of these directories take precedence
- over unit files wherever located. (Of course, since <filename>/run</filename> is temporary and
- <filename>/usr/lib</filename> is for vendors, it is unlikely drop-ins should be used in either
- of those places.)</para>
+ over unit files wherever located.</para>
<!-- Note that we do not document .include here, as we consider it mostly obsolete, and want
people to use .d/ drop-ins instead. -->
@@ -1254,7 +1252,7 @@
<row>
<entry><literal>%r</literal></entry>
<entry>Control group path of the slice the unit is placed in</entry>
- <entry>This usually maps to the parent cgroup path of <literal>%c</literal>.</entry>
+ <entry>This usually maps to the parent control group path of <literal>%c</literal>.</entry>
</row>
<row>
<entry><literal>%R</literal></entry>
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index b525286932..03a1c930b0 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -123,15 +123,11 @@ _systemctl_really_all_units()
}
_filter_units_by_property() {
- local property=$1 value=$2 ; shift ; shift
- local -a units ; units=($*)
- local props
- for props in ${(ps:\n\n:)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do
- props=(${(f)props})
- if [[ "${props[2]}" = "$property=$value" ]]; then
- echo -E - " ${props[1]#Id=}"
- fi
- done
+ local property=$1 value=$2; shift 2
+ local -a units; units=("${(q-)@}")
+ local -A props
+ props=(${(f)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property=\"Id,$property\" -- ${units} 2>/dev/null")"})
+ echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}"
}
_systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ }
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
index ceeee519b7..a44dd473c1 100644
--- a/src/basic/alloc-util.h
+++ b/src/basic/alloc-util.h
@@ -43,6 +43,14 @@ static inline void *mfree(void *memory) {
return NULL;
}
+#define free_and_replace(a, b) \
+ ({ \
+ free(a); \
+ (a) = (b); \
+ (b) = NULL; \
+ 0; \
+ })
+
void* memdup(const void *p, size_t l) _alloc_(2);
static inline void freep(void *p) {
diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c
index f4b12fc261..f6212e6151 100644
--- a/src/basic/bitmap.c
+++ b/src/basic/bitmap.c
@@ -58,10 +58,8 @@ Bitmap *bitmap_copy(Bitmap *b) {
return NULL;
ret->bitmaps = newdup(uint64_t, b->bitmaps, b->n_bitmaps);
- if (!ret->bitmaps) {
- free(ret);
- return NULL;
- }
+ if (!ret->bitmaps)
+ return mfree(ret);
ret->n_bitmaps = ret->bitmaps_allocated = b->n_bitmaps;
return ret;
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
index 7f5fddb700..b74290d6fd 100644
--- a/src/basic/env-util.c
+++ b/src/basic/env-util.c
@@ -544,8 +544,7 @@ char *replace_env(const char *format, char **env) {
return k;
fail:
- free(r);
- return NULL;
+ return mfree(r);
}
char **replace_env_argv(char **argv, char **env) {
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index 86d9ad7e36..48952a1c26 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -678,9 +678,7 @@ int chase_symlinks(const char *path, const char *_root, char **ret) {
!path_startswith(parent, root))
return -EINVAL;
- free(done);
- done = parent;
- parent = NULL;
+ free_and_replace(done, parent);
fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
if (fd_parent < 0)
@@ -724,9 +722,7 @@ int chase_symlinks(const char *path, const char *_root, char **ret) {
if (fd < 0)
return -errno;
- free(buffer);
- buffer = destination;
- destination = NULL;
+ free_and_replace(buffer, destination);
todo = buffer;
free(done);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index a76963aa9f..0f5b20cf05 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -288,9 +288,7 @@ char **path_strv_resolve(char **l, const char *prefix) {
} else {
/* canonicalized path goes outside of
* prefix, keep the original path instead */
- free(u);
- u = orig;
- orig = NULL;
+ free_and_replace(u, orig);
}
} else
free(t);
diff --git a/src/basic/prioq.c b/src/basic/prioq.c
index d2ec516d29..4570b8e4ba 100644
--- a/src/basic/prioq.c
+++ b/src/basic/prioq.c
@@ -62,9 +62,7 @@ Prioq* prioq_free(Prioq *q) {
return NULL;
free(q->items);
- free(q);
-
- return NULL;
+ return mfree(q);
}
int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) {
diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c
index 6a204b9ec3..0d21423a9c 100644
--- a/src/basic/replace-var.c
+++ b/src/basic/replace-var.c
@@ -107,6 +107,5 @@ char *replace_var(const char *text, char *(*lookup)(const char *variable, void*u
return r;
oom:
- free(r);
- return NULL;
+ return mfree(r);
}
diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c
index 4bef87d3c2..00aaf9e621 100644
--- a/src/basic/strbuf.c
+++ b/src/basic/strbuf.c
@@ -62,8 +62,7 @@ struct strbuf *strbuf_new(void) {
err:
free(str->buf);
free(str->root);
- free(str);
- return NULL;
+ return mfree(str);
}
static void strbuf_node_cleanup(struct strbuf_node *node) {
diff --git a/src/basic/string-util.c b/src/basic/string-util.c
index dc7de5dab8..6b06e643c9 100644
--- a/src/basic/string-util.c
+++ b/src/basic/string-util.c
@@ -610,8 +610,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
return r;
oom:
- free(r);
- return NULL;
+ return mfree(r);
}
char *strip_tab_ansi(char **ibuf, size_t *_isz) {
@@ -682,8 +681,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
if (ferror(f)) {
fclose(f);
- free(obuf);
- return NULL;
+ return mfree(obuf);
}
fclose(f);
diff --git a/src/basic/strv.c b/src/basic/strv.c
index 34e464d253..0eec868eed 100644
--- a/src/basic/strv.c
+++ b/src/basic/strv.c
@@ -87,8 +87,7 @@ void strv_clear(char **l) {
char **strv_free(char **l) {
strv_clear(l);
- free(l);
- return NULL;
+ return mfree(l);
}
char **strv_free_erase(char **l) {
@@ -426,8 +425,7 @@ char *strv_join_quoted(char **l) {
return buf;
oom:
- free(buf);
- return NULL;
+ return mfree(buf);
}
int strv_push(char ***l, char *value) {
@@ -869,8 +867,7 @@ char ***strv_free_free(char ***l) {
for (i = l; *i; i++)
strv_free(*i);
- free(l);
- return NULL;
+ return mfree(l);
}
char **strv_skip(char **l, size_t n) {
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index 169ab772ff..b862bfaf05 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -36,6 +36,10 @@
#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m"
#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
+#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
+#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
+#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m"
+#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
#define ANSI_NORMAL "\x1B[0m"
#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
@@ -83,37 +87,24 @@ bool on_tty(void);
bool terminal_is_dumb(void);
bool colors_enabled(void);
-static inline const char *ansi_underline(void) {
- return colors_enabled() ? ANSI_UNDERLINE : "";
-}
-
-static inline const char *ansi_highlight(void) {
- return colors_enabled() ? ANSI_HIGHLIGHT : "";
-}
-
-static inline const char *ansi_highlight_underline(void) {
- return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : "";
-}
-
-static inline const char *ansi_highlight_red(void) {
- return colors_enabled() ? ANSI_HIGHLIGHT_RED : "";
-}
-
-static inline const char *ansi_highlight_green(void) {
- return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : "";
-}
-
-static inline const char *ansi_highlight_yellow(void) {
- return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : "";
-}
-
-static inline const char *ansi_highlight_blue(void) {
- return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : "";
-}
-
-static inline const char *ansi_normal(void) {
- return colors_enabled() ? ANSI_NORMAL : "";
-}
+#define DEFINE_ANSI_FUNC(name, NAME) \
+ static inline const char *ansi_##name(void) { \
+ return colors_enabled() ? ANSI_##NAME : ""; \
+ } \
+ struct __useless_struct_to_allow_trailing_semicolon__
+
+DEFINE_ANSI_FUNC(underline, UNDERLINE);
+DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
+DEFINE_ANSI_FUNC(highlight_underline, HIGHLIGHT_UNDERLINE);
+DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
+DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
+DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW);
+DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(highlight_red_underline, HIGHLIGHT_RED_UNDERLINE);
+DEFINE_ANSI_FUNC(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE);
+DEFINE_ANSI_FUNC(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE);
+DEFINE_ANSI_FUNC(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE);
+DEFINE_ANSI_FUNC(normal, NORMAL);
int get_ctty_devnr(pid_t pid, dev_t *d);
int get_ctty(pid_t, dev_t *_devnr, char **r);
diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c
index ee6d7eb864..dc11b0d9db 100644
--- a/src/boot/bootctl.c
+++ b/src/boot/bootctl.c
@@ -621,7 +621,8 @@ static const char *efi_subdirs[] = {
"EFI/systemd",
"EFI/BOOT",
"loader",
- "loader/entries"
+ "loader/entries",
+ NULL
};
static int create_dirs(const char *esp_path) {
@@ -917,7 +918,7 @@ static int remove_binaries(const char *esp_path) {
if (q < 0 && r == 0)
r = q;
- for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) {
+ for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
q = rmdir_one(esp_path, efi_subdirs[i-1]);
if (q < 0 && r == 0)
r = q;
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index b8720d7d3d..1a7f770db1 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -627,6 +627,53 @@ static int property_get_syslog_facility(
return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
}
+static int property_get_input_fdname(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+ const char *name;
+
+ assert(bus);
+ assert(c);
+ assert(property);
+ assert(reply);
+
+ name = exec_context_fdname(c, STDIN_FILENO);
+
+ return sd_bus_message_append(reply, "s", name);
+}
+
+static int property_get_output_fdname(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ ExecContext *c = userdata;
+ const char *name = NULL;
+
+ assert(bus);
+ assert(c);
+ assert(property);
+ assert(reply);
+
+ if (c->std_output == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardOutputFileDescriptorName"))
+ name = exec_context_fdname(c, STDOUT_FILENO);
+ else if (c->std_error == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardErrorFileDescriptorName"))
+ name = exec_context_fdname(c, STDERR_FILENO);
+
+ return sd_bus_message_append(reply, "s", name);
+}
+
const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -677,8 +724,11 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_input_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1030,7 +1080,6 @@ int bus_exec_context_set_transient_property(
return 1;
-
} else if (streq(name, "StandardOutput")) {
const char *s;
ExecOutput p;
@@ -1072,6 +1121,41 @@ int bus_exec_context_set_transient_property(
return 1;
} else if (STR_IN_SET(name,
+ "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) {
+ const char *s;
+
+ r = sd_bus_message_read(message, "s", &s);
+ if (r < 0)
+ return r;
+
+ if (!fdname_is_valid(s))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
+
+ if (mode != UNIT_CHECK) {
+ if (streq(name, "StandardInputFileDescriptorName")) {
+ c->std_input = EXEC_INPUT_NAMED_FD;
+ r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], s);
+ if (r < 0)
+ return r;
+ unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", s);
+ } else if (streq(name, "StandardOutputFileDescriptorName")) {
+ c->std_output = EXEC_OUTPUT_NAMED_FD;
+ r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], s);
+ if (r < 0)
+ return r;
+ unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", s);
+ } else if (streq(name, "StandardErrorFileDescriptorName")) {
+ c->std_error = EXEC_OUTPUT_NAMED_FD;
+ r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s);
+ if (r < 0)
+ return r;
+ unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", s);
+ }
+ }
+
+ return 1;
+
+ } else if (STR_IN_SET(name,
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
"NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c
index 1043da3eb7..e1846e1adb 100644
--- a/src/core/dynamic-user.c
+++ b/src/core/dynamic-user.c
@@ -42,9 +42,7 @@ static DynamicUser* dynamic_user_free(DynamicUser *d) {
(void) hashmap_remove(d->manager->dynamic_users, d->name);
safe_close_pair(d->storage_socket);
- free(d);
-
- return NULL;
+ return mfree(d);
}
static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) {
diff --git a/src/core/execute.c b/src/core/execute.c
index 869522704a..1b7b4a928d 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -411,7 +411,8 @@ static int fixup_output(ExecOutput std_output, int socket_fd) {
static int setup_input(
const ExecContext *context,
const ExecParameters *params,
- int socket_fd) {
+ int socket_fd,
+ int named_iofds[3]) {
ExecInput i;
@@ -461,6 +462,10 @@ static int setup_input(
case EXEC_INPUT_SOCKET:
return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
+ case EXEC_INPUT_NAMED_FD:
+ (void) fd_nonblock(named_iofds[STDIN_FILENO], false);
+ return dup2(named_iofds[STDIN_FILENO], STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
+
default:
assert_not_reached("Unknown input type");
}
@@ -472,6 +477,7 @@ static int setup_output(
const ExecParameters *params,
int fileno,
int socket_fd,
+ int named_iofds[3],
const char *ident,
uid_t uid,
gid_t gid,
@@ -523,7 +529,7 @@ static int setup_output(
return fileno;
/* Duplicate from stdout if possible */
- if (e == o || e == EXEC_OUTPUT_INHERIT)
+ if ((e == o && e != EXEC_OUTPUT_NAMED_FD) || e == EXEC_OUTPUT_INHERIT)
return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
o = e;
@@ -585,6 +591,10 @@ static int setup_output(
assert(socket_fd >= 0);
return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
+ case EXEC_OUTPUT_NAMED_FD:
+ (void) fd_nonblock(named_iofds[fileno], false);
+ return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno;
+
default:
assert_not_reached("Unknown error type");
}
@@ -2157,6 +2167,7 @@ static int exec_child(
DynamicCreds *dcreds,
char **argv,
int socket_fd,
+ int named_iofds[3],
int *fds, unsigned n_fds,
char **files_env,
int user_lookup_fd,
@@ -2298,19 +2309,19 @@ static int exec_child(
if (socket_fd >= 0)
(void) fd_nonblock(socket_fd, false);
- r = setup_input(context, params, socket_fd);
+ r = setup_input(context, params, socket_fd, named_iofds);
if (r < 0) {
*exit_status = EXIT_STDIN;
return r;
}
- r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
+ r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
if (r < 0) {
*exit_status = EXIT_STDOUT;
return r;
}
- r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
+ r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino);
if (r < 0) {
*exit_status = EXIT_STDERR;
return r;
@@ -2829,6 +2840,7 @@ int exec_spawn(Unit *unit,
int *fds = NULL; unsigned n_fds = 0;
_cleanup_free_ char *line = NULL;
int socket_fd, r;
+ int named_iofds[3] = { -1, -1, -1 };
char **argv;
pid_t pid;
@@ -2855,6 +2867,10 @@ int exec_spawn(Unit *unit,
n_fds = params->n_fds;
}
+ r = exec_context_named_iofds(unit, context, params, named_iofds);
+ if (r < 0)
+ return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m");
+
r = exec_context_load_environment(unit, context, &files_env);
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
@@ -2884,6 +2900,7 @@ int exec_spawn(Unit *unit,
dcreds,
argv,
socket_fd,
+ named_iofds,
fds, n_fds,
files_env,
unit->manager->user_lookup_fds[1],
@@ -2946,6 +2963,9 @@ void exec_context_done(ExecContext *c) {
for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
c->rlimit[l] = mfree(c->rlimit[l]);
+ for (l = 0; l < 3; l++)
+ c->stdio_fdname[l] = mfree(c->stdio_fdname[l]);
+
c->working_directory = mfree(c->working_directory);
c->root_directory = mfree(c->root_directory);
c->tty_path = mfree(c->tty_path);
@@ -3044,6 +3064,56 @@ static void invalid_env(const char *p, void *userdata) {
log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path);
}
+const char* exec_context_fdname(const ExecContext *c, int fd_index) {
+ assert(c);
+
+ switch (fd_index) {
+ case STDIN_FILENO:
+ if (c->std_input != EXEC_INPUT_NAMED_FD)
+ return NULL;
+ return c->stdio_fdname[STDIN_FILENO] ?: "stdin";
+ case STDOUT_FILENO:
+ if (c->std_output != EXEC_OUTPUT_NAMED_FD)
+ return NULL;
+ return c->stdio_fdname[STDOUT_FILENO] ?: "stdout";
+ case STDERR_FILENO:
+ if (c->std_error != EXEC_OUTPUT_NAMED_FD)
+ return NULL;
+ return c->stdio_fdname[STDERR_FILENO] ?: "stderr";
+ default:
+ return NULL;
+ }
+}
+
+int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) {
+ unsigned i, targets;
+ const char *stdio_fdname[3];
+
+ assert(c);
+ assert(p);
+
+ targets = (c->std_input == EXEC_INPUT_NAMED_FD) +
+ (c->std_output == EXEC_OUTPUT_NAMED_FD) +
+ (c->std_error == EXEC_OUTPUT_NAMED_FD);
+
+ for (i = 0; i < 3; i++)
+ stdio_fdname[i] = exec_context_fdname(c, i);
+
+ for (i = 0; i < p->n_fds && targets > 0; i++)
+ if (named_iofds[STDIN_FILENO] < 0 && c->std_input == EXEC_INPUT_NAMED_FD && stdio_fdname[STDIN_FILENO] && streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) {
+ named_iofds[STDIN_FILENO] = p->fds[i];
+ targets--;
+ } else if (named_iofds[STDOUT_FILENO] < 0 && c->std_output == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDOUT_FILENO] && streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) {
+ named_iofds[STDOUT_FILENO] = p->fds[i];
+ targets--;
+ } else if (named_iofds[STDERR_FILENO] < 0 && c->std_error == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDERR_FILENO] && streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) {
+ named_iofds[STDERR_FILENO] = p->fds[i];
+ targets--;
+ }
+
+ return (targets == 0 ? 0 : -ENOENT);
+}
+
int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) {
char **i, **r = NULL;
@@ -3740,9 +3810,7 @@ ExecRuntime *exec_runtime_unref(ExecRuntime *r) {
free(r->tmp_dir);
free(r->var_tmp_dir);
safe_close_pair(r->netns_storage_socket);
- free(r);
-
- return NULL;
+ return mfree(r);
}
int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) {
@@ -3898,7 +3966,8 @@ static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
[EXEC_INPUT_TTY] = "tty",
[EXEC_INPUT_TTY_FORCE] = "tty-force",
[EXEC_INPUT_TTY_FAIL] = "tty-fail",
- [EXEC_INPUT_SOCKET] = "socket"
+ [EXEC_INPUT_SOCKET] = "socket",
+ [EXEC_INPUT_NAMED_FD] = "fd",
};
DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
@@ -3913,7 +3982,8 @@ static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
[EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
[EXEC_OUTPUT_JOURNAL] = "journal",
[EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
- [EXEC_OUTPUT_SOCKET] = "socket"
+ [EXEC_OUTPUT_SOCKET] = "socket",
+ [EXEC_OUTPUT_NAMED_FD] = "fd",
};
DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
diff --git a/src/core/execute.h b/src/core/execute.h
index 1de439c3ad..c7d0f7761e 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -50,6 +50,7 @@ typedef enum ExecInput {
EXEC_INPUT_TTY_FORCE,
EXEC_INPUT_TTY_FAIL,
EXEC_INPUT_SOCKET,
+ EXEC_INPUT_NAMED_FD,
_EXEC_INPUT_MAX,
_EXEC_INPUT_INVALID = -1
} ExecInput;
@@ -65,6 +66,7 @@ typedef enum ExecOutput {
EXEC_OUTPUT_JOURNAL,
EXEC_OUTPUT_JOURNAL_AND_CONSOLE,
EXEC_OUTPUT_SOCKET,
+ EXEC_OUTPUT_NAMED_FD,
_EXEC_OUTPUT_MAX,
_EXEC_OUTPUT_INVALID = -1
} ExecOutput;
@@ -120,6 +122,7 @@ struct ExecContext {
ExecInput std_input;
ExecOutput std_output;
ExecOutput std_error;
+ char *stdio_fdname[3];
nsec_t timer_slack_nsec;
@@ -284,6 +287,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix);
int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_root);
int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l);
+int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]);
+const char* exec_context_fdname(const ExecContext *c, int fd_index);
bool exec_context_may_touch_console(ExecContext *c);
bool exec_context_maintains_privileges(ExecContext *c);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index a700d853cc..08c88b6b53 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -35,9 +35,9 @@ $1.Environment, config_parse_environ, 0,
$1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files)
$1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment)
$1.DynamicUser, config_parse_bool, 0, offsetof($1, exec_context.dynamic_user)
-$1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input)
-$1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output)
-$1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error)
+$1.StandardInput, config_parse_exec_input, 0, offsetof($1, exec_context)
+$1.StandardOutput, config_parse_exec_output, 0, offsetof($1, exec_context)
+$1.StandardError, config_parse_exec_output, 0, offsetof($1, exec_context)
$1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path)
$1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset)
$1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 06c156a623..a69f60097d 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -776,8 +776,104 @@ int config_parse_socket_bindtodevice(
return 0;
}
-DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input literal specifier");
+DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output literal specifier");
+
+int config_parse_exec_input(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ ExecContext *c = data;
+ const char *name;
+ int r;
+
+ assert(data);
+ assert(filename);
+ assert(line);
+ assert(rvalue);
+
+ name = startswith(rvalue, "fd:");
+ if (name) {
+ /* Strip prefix and validate fd name */
+ if (!fdname_is_valid(name)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", name);
+ return 0;
+ }
+ c->std_input = EXEC_INPUT_NAMED_FD;
+ r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], name);
+ if (r < 0)
+ log_oom();
+ return r;
+ } else {
+ ExecInput ei = exec_input_from_string(rvalue);
+ if (ei == _EXEC_INPUT_INVALID)
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue);
+ else
+ c->std_input = ei;
+ return 0;
+ }
+}
+
+int config_parse_exec_output(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ ExecContext *c = data;
+ ExecOutput eo;
+ const char *name;
+ int r;
+
+ assert(data);
+ assert(filename);
+ assert(line);
+ assert(lvalue);
+ assert(rvalue);
+
+ name = startswith(rvalue, "fd:");
+ if (name) {
+ /* Strip prefix and validate fd name */
+ if (!fdname_is_valid(name)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", name);
+ return 0;
+ }
+ eo = EXEC_OUTPUT_NAMED_FD;
+ } else {
+ eo = exec_output_from_string(rvalue);
+ if (eo == _EXEC_OUTPUT_INVALID) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue);
+ return 0;
+ }
+ }
+
+ if (streq(lvalue, "StandardOutput")) {
+ c->std_output = eo;
+ r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], name);
+ if (r < 0)
+ log_oom();
+ return r;
+ } else if (streq(lvalue, "StandardError")) {
+ c->std_error = eo;
+ r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], name);
+ if (r < 0)
+ log_oom();
+ return r;
+ } else {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output property, ignoring: %s", lvalue);
+ return 0;
+ }
+}
int config_parse_exec_io_class(const char *unit,
const char *filename,
@@ -1591,11 +1687,7 @@ int config_parse_fdname(
return 0;
}
- free(s->fdname);
- s->fdname = p;
- p = NULL;
-
- return 0;
+ return free_and_replace(s->fdname, p);
}
int config_parse_service_sockets(
@@ -2052,9 +2144,7 @@ int config_parse_working_directory(
return 0;
}
- free(c->working_directory);
- c->working_directory = k;
- k = NULL;
+ free_and_replace(c->working_directory, k);
c->working_directory_home = false;
}
@@ -4189,8 +4279,8 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_exec_cpu_affinity, "CPUAFFINITY" },
{ config_parse_mode, "MODE" },
{ config_parse_unit_env_file, "FILE" },
- { config_parse_output, "OUTPUT" },
- { config_parse_input, "INPUT" },
+ { config_parse_exec_output, "OUTPUT" },
+ { config_parse_exec_input, "INPUT" },
{ config_parse_log_facility, "FACILITY" },
{ config_parse_log_level, "LEVEL" },
{ config_parse_exec_secure_bits, "SECUREBITS" },
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index 8b688740cf..6d1fe55bcd 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -45,7 +45,9 @@ int config_parse_service_timeout(const char *unit, const char *filename, unsigne
int config_parse_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_service_restart(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_socket_bindtodevice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_exec_output(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_output(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_exec_input(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_input(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_io_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_exec_io_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/core/manager.c b/src/core/manager.c
index 3569249788..50aae0d1ba 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1119,8 +1119,7 @@ Manager* manager_free(Manager *m) {
hashmap_free(m->uid_refs);
hashmap_free(m->gid_refs);
- free(m);
- return NULL;
+ return mfree(m);
}
void manager_enumerate(Manager *m) {
diff --git a/src/core/mount.c b/src/core/mount.c
index 15619dffe3..da480001e1 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1484,17 +1484,9 @@ static int mount_setup_unit(
MOUNT(u)->from_proc_self_mountinfo = true;
- free(p->what);
- p->what = w;
- w = NULL;
-
- free(p->options);
- p->options = o;
- o = NULL;
-
- free(p->fstype);
- p->fstype = f;
- f = NULL;
+ free_and_replace(p->what, w);
+ free_and_replace(p->options, o);
+ free_and_replace(p->fstype, f);
if (load_extras) {
r = mount_add_extras(MOUNT(u));
diff --git a/src/core/service.c b/src/core/service.c
index 63045ede55..c949de9cbe 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3088,9 +3088,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
if (!streq_ptr(s->status_text, t)) {
- free(s->status_text);
- s->status_text = t;
- t = NULL;
+ free_and_replace(s->status_text, t);
notify_dbus = true;
}
diff --git a/src/core/timer.c b/src/core/timer.c
index 9538059c13..2469a517ea 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -261,6 +261,8 @@ static void timer_set_state(Timer *t, TimerState state) {
if (state != TIMER_WAITING) {
t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
+ t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
+ t->next_elapse_realtime = USEC_INFINITY;
}
if (state != old_state)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 8370b864fb..e22e3b30c2 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -1085,10 +1085,8 @@ Transaction *transaction_new(bool irreversible) {
return NULL;
tr->jobs = hashmap_new(NULL);
- if (!tr->jobs) {
- free(tr);
- return NULL;
- }
+ if (!tr->jobs)
+ return mfree(tr);
tr->irreversible = irreversible;
diff --git a/src/core/unit.c b/src/core/unit.c
index 67668bdc48..2fa397bd41 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -88,10 +88,8 @@ Unit *unit_new(Manager *m, size_t size) {
return NULL;
u->names = set_new(&string_hash_ops);
- if (!u->names) {
- free(u);
- return NULL;
- }
+ if (!u->names)
+ return mfree(u);
u->manager = m;
u->type = _UNIT_TYPE_INVALID;
@@ -860,18 +858,14 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) {
return r;
}
- if (c->std_output != EXEC_OUTPUT_KMSG &&
- c->std_output != EXEC_OUTPUT_SYSLOG &&
- c->std_output != EXEC_OUTPUT_JOURNAL &&
- c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
- c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE &&
- c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
- c->std_error != EXEC_OUTPUT_KMSG &&
- c->std_error != EXEC_OUTPUT_SYSLOG &&
- c->std_error != EXEC_OUTPUT_JOURNAL &&
- c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE &&
- c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE &&
- c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE)
+ if (!IN_SET(c->std_output,
+ EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE,
+ EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE,
+ EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE) &&
+ !IN_SET(c->std_error,
+ EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE,
+ EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE,
+ EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE))
return 0;
/* If syslog or kernel logging is requested, make sure our own
@@ -3055,7 +3049,7 @@ int unit_coldplug(Unit *u) {
return r;
}
-static bool fragment_mtime_newer(const char *path, usec_t mtime) {
+static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) {
struct stat st;
if (!path)
@@ -3065,12 +3059,12 @@ static bool fragment_mtime_newer(const char *path, usec_t mtime) {
/* What, cannot access this anymore? */
return true;
- if (mtime > 0)
+ if (path_masked)
+ /* For masked files check if they are still so */
+ return !null_or_empty(&st);
+ else
/* For non-empty files check the mtime */
return timespec_load(&st.st_mtim) > mtime;
- else if (!null_or_empty(&st))
- /* For masked files check if they are still so */
- return true;
return false;
}
@@ -3081,18 +3075,22 @@ bool unit_need_daemon_reload(Unit *u) {
assert(u);
- if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime))
+ /* For unit files, we allow masking… */
+ if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime,
+ u->load_state == UNIT_MASKED))
return true;
- if (fragment_mtime_newer(u->source_path, u->source_mtime))
+ /* Source paths should not be masked… */
+ if (fragment_mtime_newer(u->source_path, u->source_mtime, false))
return true;
(void) unit_find_dropin_paths(u, &t);
if (!strv_equal(u->dropin_paths, t))
return true;
+ /* … any drop-ins that are masked are simply omitted from the list. */
STRV_FOREACH(path, u->dropin_paths)
- if (fragment_mtime_newer(*path, u->dropin_mtime))
+ if (fragment_mtime_newer(*path, u->dropin_mtime, false))
return true;
return false;
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 8ac5ab730a..de0a3b6f9c 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -264,16 +264,13 @@ static crypto_device *get_crypto_device(const char *uuid) {
d->keyfile = d->options = d->name = NULL;
d->uuid = strdup(uuid);
- if (!d->uuid) {
- free(d);
- return NULL;
- }
+ if (!d->uuid)
+ return mfree(d);
r = hashmap_put(arg_disks, d->uuid, d);
if (r < 0) {
free(d->uuid);
- free(d);
- return NULL;
+ return mfree(d);
}
}
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index 6990c47f48..734e1560e6 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -235,9 +235,7 @@ CurlGlue *curl_glue_unref(CurlGlue *g) {
sd_event_source_unref(g->timer);
sd_event_unref(g->event);
- free(g);
-
- return NULL;
+ return mfree(g);
}
int curl_glue_new(CurlGlue **glue, sd_event *event) {
diff --git a/src/import/export-raw.c b/src/import/export-raw.c
index 6136b677dd..a3dbce1954 100644
--- a/src/import/export-raw.c
+++ b/src/import/export-raw.c
@@ -87,9 +87,7 @@ RawExport *raw_export_unref(RawExport *e) {
free(e->buffer);
free(e->path);
- free(e);
-
- return NULL;
+ return mfree(e);
}
int raw_export_new(
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index d79c27f2d0..3bb6027431 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -91,9 +91,7 @@ TarExport *tar_export_unref(TarExport *e) {
free(e->buffer);
free(e->path);
- free(e);
-
- return NULL;
+ return mfree(e);
}
int tar_export_new(
diff --git a/src/import/import-raw.c b/src/import/import-raw.c
index fd6b9f7703..29f3f896e5 100644
--- a/src/import/import-raw.c
+++ b/src/import/import-raw.c
@@ -100,9 +100,7 @@ RawImport* raw_import_unref(RawImport *i) {
free(i->final_path);
free(i->image_root);
free(i->local);
- free(i);
-
- return NULL;
+ return mfree(i);
}
int raw_import_new(
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 8b81324fde..22f9b8c5ea 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -107,9 +107,7 @@ TarImport* tar_import_unref(TarImport *i) {
free(i->final_path);
free(i->image_root);
free(i->local);
- free(i);
-
- return NULL;
+ return mfree(i);
}
int tar_import_new(
diff --git a/src/import/importd.c b/src/import/importd.c
index 28b4302cb3..9d31a956a5 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -141,8 +141,7 @@ static Transfer *transfer_unref(Transfer *t) {
safe_close(t->stdin_fd);
safe_close(t->stdout_fd);
- free(t);
- return NULL;
+ return mfree(t);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref);
@@ -548,8 +547,7 @@ static Manager *manager_unref(Manager *m) {
m->bus = sd_bus_flush_close_unref(m->bus);
sd_event_unref(m->event);
- free(m);
- return NULL;
+ return mfree(m);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index 6bcf35ef4e..e550df2c57 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -50,9 +50,7 @@ PullJob* pull_job_unref(PullJob *j) {
free(j->payload);
free(j->checksum);
- free(j);
-
- return NULL;
+ return mfree(j);
}
static void pull_job_finish(PullJob *j, int ret) {
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 8993402821..0cf410a5d9 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -110,9 +110,7 @@ RawPull* raw_pull_unref(RawPull *i) {
free(i->settings_path);
free(i->image_root);
free(i->local);
- free(i);
-
- return NULL;
+ return mfree(i);
}
int raw_pull_new(
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index 8c61c46f73..68e2397b02 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -114,9 +114,7 @@ TarPull* tar_pull_unref(TarPull *i) {
free(i->settings_path);
free(i->image_root);
free(i->local);
- free(i);
-
- return NULL;
+ return mfree(i);
}
int tar_pull_new(
diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c
index 7bba52566e..8729372aa3 100644
--- a/src/journal-remote/journal-remote-write.c
+++ b/src/journal-remote/journal-remote-write.c
@@ -75,10 +75,8 @@ Writer* writer_new(RemoteServer *server) {
memset(&w->metrics, 0xFF, sizeof(w->metrics));
w->mmap = mmap_cache_new();
- if (!w->mmap) {
- free(w);
- return NULL;
- }
+ if (!w->mmap)
+ return mfree(w);
w->n_ref = 1;
w->server = server;
@@ -103,9 +101,7 @@ Writer* writer_free(Writer *w) {
if (w->mmap)
mmap_cache_unref(w->mmap);
- free(w);
-
- return NULL;
+ return mfree(w);
}
Writer* writer_unref(Writer *w) {
diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c
index c0f967ab94..61190ff83c 100644
--- a/src/journal-remote/journal-upload.c
+++ b/src/journal-remote/journal-upload.c
@@ -527,9 +527,7 @@ static int perform_upload(Uploader *u) {
log_debug("Upload finished successfully with code %ld: %s",
status, strna(u->answer));
- free(u->last_cursor);
- u->last_cursor = u->current_cursor;
- u->current_cursor = NULL;
+ free_and_replace(u->last_cursor, u->current_cursor);
return update_cursor_state(u);
}
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 49199b269f..d3e0214731 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -394,8 +394,7 @@ JournalFile* journal_file_close(JournalFile *f) {
gcry_md_close(f->hmac);
#endif
- free(f);
- return NULL;
+ return mfree(f);
}
void journal_file_close_set(Set *s) {
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 293d27053a..d91247b524 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -325,10 +325,8 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
f->fd = fd;
r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
- if (r < 0) {
- free(f);
- return NULL;
- }
+ if (r < 0)
+ return mfree(f);
return f;
}
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 98c8a47afe..f2f8546086 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -387,7 +387,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) {
}
static char *match_make_string(Match *m) {
- char *p, *r;
+ char *p = NULL, *r;
Match *i;
bool enclose = false;
@@ -397,15 +397,12 @@ static char *match_make_string(Match *m) {
if (m->type == MATCH_DISCRETE)
return strndup(m->data, m->size);
- p = NULL;
LIST_FOREACH(matches, i, m->matches) {
char *t, *k;
t = match_make_string(i);
- if (!t) {
- free(p);
- return NULL;
- }
+ if (!t)
+ return mfree(p);
if (p) {
k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c
index d9950b638c..41ff2b353a 100644
--- a/src/libsystemd-network/ndisc-router.c
+++ b/src/libsystemd-network/ndisc-router.c
@@ -49,8 +49,7 @@ _public_ sd_ndisc_router* sd_ndisc_router_unref(sd_ndisc_router *rt) {
if (rt->n_ref > 0)
return NULL;
- free(rt);
- return NULL;
+ return mfree(rt);
}
sd_ndisc_router *ndisc_router_new(size_t raw_size) {
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 179e5950bd..5ccb23922c 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1873,9 +1873,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
- free(client);
-
- return NULL;
+ return mfree(client);
}
int sd_dhcp_client_new(sd_dhcp_client **ret) {
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index ef50ed17a1..8387b185c0 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -282,9 +282,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
free(lease->static_route);
free(lease->client_id);
free(lease->vendor_specific);
- free(lease);
-
- return NULL;
+ return mfree(lease);
}
static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 11ee2e252e..f16314a37f 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -178,9 +178,7 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
hashmap_free(server->leases_by_client_id);
free(server->bound_leases);
- free(server);
-
- return NULL;
+ return mfree(server);
}
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 463fde401c..e81215f7d7 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -1300,9 +1300,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
sd_dhcp6_client_detach_event(client);
free(client->req_opts);
- free(client);
-
- return NULL;
+ return mfree(client);
}
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c
index 5c10a6326a..ab59977a3f 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -389,9 +389,7 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
free(lease->ntp);
lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
- free(lease);
-
- return NULL;
+ return mfree(lease);
}
int dhcp6_lease_new(sd_dhcp6_lease **ret) {
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index 662885840f..4dd343c101 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -135,9 +135,7 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) {
ipv4acd_reset(acd);
sd_ipv4acd_detach_event(acd);
- free(acd);
-
- return NULL;
+ return mfree(acd);
}
int sd_ipv4acd_new(sd_ipv4acd **ret) {
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index 5603a533a5..13209261f9 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -90,9 +90,7 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
return NULL;
sd_ipv4acd_unref(ll->acd);
- free(ll);
-
- return NULL;
+ return mfree(ll);
}
int sd_ipv4ll_new(sd_ipv4ll **ret) {
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index 0bd1e66aa0..0702241506 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -374,9 +374,7 @@ _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
hashmap_free(lldp->neighbor_by_id);
prioq_free(lldp->neighbor_by_expiry);
- free(lldp);
-
- return NULL;
+ return mfree(lldp);
}
_public_ int sd_lldp_new(sd_lldp **ret) {
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 07b0d7f704..1d3be9b862 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -148,9 +148,7 @@ _public_ sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) {
ndisc_reset(nd);
sd_ndisc_detach_event(nd);
- free(nd);
-
- return NULL;
+ return mfree(nd);
}
_public_ int sd_ndisc_new(sd_ndisc **ret) {
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
index 8e9074c7df..33590c31ac 100644
--- a/src/libsystemd/sd-bus/bus-slot.c
+++ b/src/libsystemd/sd-bus/bus-slot.c
@@ -212,9 +212,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
bus_slot_disconnect(slot);
free(slot->description);
- free(slot);
-
- return NULL;
+ return mfree(slot);
}
_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 00e93a215f..4acaf24793 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -74,9 +74,7 @@ static struct track_item* track_item_free(struct track_item *i) {
sd_bus_slot_unref(i->slot);
free(i->name);
- free(i);
-
- return NULL;
+ return mfree(i);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free);
@@ -206,9 +204,7 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
bus_track_remove_from_queue(track);
hashmap_free(track->names);
sd_bus_unref(track->bus);
- free(track);
-
- return NULL;
+ return mfree(track);
}
static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c
index da496ed456..0d51322a15 100644
--- a/src/libudev/libudev-list.c
+++ b/src/libudev/libudev-list.c
@@ -166,17 +166,16 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *
entry = new0(struct udev_list_entry, 1);
if (entry == NULL)
return NULL;
+
entry->name = strdup(name);
- if (entry->name == NULL) {
- free(entry);
- return NULL;
- }
+ if (entry->name == NULL)
+ return mfree(entry);
+
if (value != NULL) {
entry->value = strdup(value);
if (entry->value == NULL) {
free(entry->name);
- free(entry);
- return NULL;
+ return mfree(entry);
}
}
@@ -193,8 +192,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *
if (entries == NULL) {
free(entry->name);
free(entry->value);
- free(entry);
- return NULL;
+ return mfree(entry);
}
list->entries = entries;
list->entries_max += add;
diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c
index 1f9d16c450..a1f2b33ad5 100644
--- a/src/libudev/libudev-monitor.c
+++ b/src/libudev/libudev-monitor.c
@@ -207,8 +207,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c
udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT);
if (udev_monitor->sock < 0) {
log_debug_errno(errno, "error getting socket: %m");
- free(udev_monitor);
- return NULL;
+ return mfree(udev_monitor);
}
} else {
udev_monitor->bound = true;
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 0fc33cf541..4c618ed19e 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -83,6 +83,34 @@ static OutputFlags get_output_flags(void) {
colors_enabled() * OUTPUT_COLOR;
}
+static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ int r;
+ char *ans;
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "GetSession",
+ error, &reply,
+ "s", session_id);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(reply, "o", &ans);
+ if (r < 0)
+ return r;
+
+ ans = strdup(ans);
+ if (!ans)
+ return -ENOMEM;
+
+ *path = ans;
+ return 0;
+}
+
static int list_sessions(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -115,10 +143,38 @@ static int list_sessions(int argc, char *argv[], void *userdata) {
return bus_log_parse_error(r);
if (arg_legend)
- printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT");
+ printf("%10s %10s %-16s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT", "TTY");
while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) {
- printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat);
+ _cleanup_(sd_bus_error_free) sd_bus_error error2 = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply2 = NULL;
+ _cleanup_free_ char *path = NULL;
+ const char *tty = NULL;
+
+ r = get_session_path(bus, id, &error2, &path);
+ if (r < 0)
+ log_warning("Failed to get session path: %s", bus_error_message(&error, r));
+ else {
+ r = sd_bus_get_property(
+ bus,
+ "org.freedesktop.login1",
+ path,
+ "org.freedesktop.login1.Session",
+ "TTY",
+ &error2,
+ &reply2,
+ "s");
+ if (r < 0)
+ log_warning("Failed to get TTY for session %s: %s",
+ id, bus_error_message(&error2, r));
+ else {
+ r = sd_bus_message_read(reply2, "s", &tty);
+ if (r < 0)
+ return bus_log_parse_error(r);
+ }
+ }
+
+ printf("%10s %10"PRIu32" %-16s %-16s %-16s\n", id, uid, user, seat, strna(tty));
k++;
}
if (r < 0)
@@ -165,7 +221,7 @@ static int list_users(int argc, char *argv[], void *userdata) {
printf("%10s %-16s\n", "UID", "USER");
while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) {
- printf("%10u %-16s\n", (unsigned) uid, user);
+ printf("%10"PRIu32" %-16s\n", uid, user);
k++;
}
if (r < 0)
@@ -462,9 +518,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
printf("%s - ", strna(i.id));
if (i.name)
- printf("%s (%u)\n", i.name, (unsigned) i.uid);
+ printf("%s (%"PRIu32")\n", i.name, i.uid);
else
- printf("%u\n", (unsigned) i.uid);
+ printf("%"PRIu32"\n", i.uid);
s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
@@ -477,7 +533,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
if (i.leader > 0) {
_cleanup_free_ char *t = NULL;
- printf("\t Leader: %u", (unsigned) i.leader);
+ printf("\t Leader: %"PRIu32, i.leader);
get_process_comm(i.leader, &t);
if (t)
@@ -589,9 +645,9 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
*new_line = true;
if (i.name)
- printf("%s (%u)\n", i.name, (unsigned) i.uid);
+ printf("%s (%"PRIu32")\n", i.name, i.uid);
else
- printf("%u\n", (unsigned) i.uid);
+ printf("%"PRIu32"\n", i.uid);
s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
@@ -887,26 +943,14 @@ static int show_session(int argc, char *argv[], void *userdata) {
for (i = 1; i < argc; i++) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL;
- const char *path = NULL;
+ _cleanup_free_ char *path = NULL;
- r = sd_bus_call_method(
- bus,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "GetSession",
- &error, &reply,
- "s", argv[i]);
+ r = get_session_path(bus, argv[1], &error, &path);
if (r < 0) {
- log_error("Failed to get session: %s", bus_error_message(&error, r));
+ log_error("Failed to get session path: %s", bus_error_message(&error, r));
return r;
}
- r = sd_bus_message_read(reply, "o", &path);
- if (r < 0)
- return bus_log_parse_error(r);
-
if (properties)
r = show_properties(bus, path, &new_line);
else
diff --git a/src/login/logind-button.c b/src/login/logind-button.c
index baa6b7113c..90fb93bbaf 100644
--- a/src/login/logind-button.c
+++ b/src/login/logind-button.c
@@ -43,15 +43,12 @@ Button* button_new(Manager *m, const char *name) {
return NULL;
b->name = strdup(name);
- if (!b->name) {
- free(b);
- return NULL;
- }
+ if (!b->name)
+ return mfree(b);
if (hashmap_put(m->buttons, b->name, b) < 0) {
free(b->name);
- free(b);
- return NULL;
+ return mfree(b);
}
b->manager = m;
diff --git a/src/login/logind-device.c b/src/login/logind-device.c
index eb5edd1cd5..6537fa04bf 100644
--- a/src/login/logind-device.c
+++ b/src/login/logind-device.c
@@ -34,15 +34,12 @@ Device* device_new(Manager *m, const char *sysfs, bool master) {
return NULL;
d->sysfs = strdup(sysfs);
- if (!d->sysfs) {
- free(d);
- return NULL;
- }
+ if (!d->sysfs)
+ return mfree(d);
if (hashmap_put(m->devices, d->sysfs, d) < 0) {
free(d->sysfs);
- free(d);
- return NULL;
+ return mfree(d);
}
d->manager = m;
diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c
index 6c78e0dddc..c93b24009b 100644
--- a/src/login/logind-inhibit.c
+++ b/src/login/logind-inhibit.c
@@ -45,17 +45,14 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) {
return NULL;
i->state_file = strappend("/run/systemd/inhibit/", id);
- if (!i->state_file) {
- free(i);
- return NULL;
- }
+ if (!i->state_file)
+ return mfree(i);
i->id = basename(i->state_file);
if (hashmap_put(m->inhibitors, i->id, i) < 0) {
free(i->state_file);
- free(i);
- return NULL;
+ return mfree(i);
}
i->manager = m;
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index b5192320e4..ecc7bd2e5b 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -48,18 +48,15 @@ Seat *seat_new(Manager *m, const char *id) {
return NULL;
s->state_file = strappend("/run/systemd/seats/", id);
- if (!s->state_file) {
- free(s);
- return NULL;
- }
+ if (!s->state_file)
+ return mfree(s);
s->id = basename(s->state_file);
s->manager = m;
if (hashmap_put(m->seats, s->id, s) < 0) {
free(s->state_file);
- free(s);
- return NULL;
+ return mfree(s);
}
return s;
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index ba1bcc2630..cbf035f706 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -62,16 +62,13 @@ Session* session_new(Manager *m, const char *id) {
return NULL;
s->state_file = strappend("/run/systemd/sessions/", id);
- if (!s->state_file) {
- free(s);
- return NULL;
- }
+ if (!s->state_file)
+ return mfree(s);
s->devices = hashmap_new(&devt_hash_ops);
if (!s->devices) {
free(s->state_file);
- free(s);
- return NULL;
+ return mfree(s);
}
s->id = basename(s->state_file);
@@ -79,8 +76,7 @@ Session* session_new(Manager *m, const char *id) {
if (hashmap_put(m->sessions, s->id, s) < 0) {
hashmap_free(s->devices);
free(s->state_file);
- free(s);
- return NULL;
+ return mfree(s);
}
s->manager = m;
diff --git a/src/machine/machine.c b/src/machine/machine.c
index dd046d6563..a02b9d7575 100644
--- a/src/machine/machine.c
+++ b/src/machine/machine.c
@@ -80,9 +80,7 @@ Machine* machine_new(Manager *manager, MachineClass class, const char *name) {
fail:
free(m->state_file);
free(m->name);
- free(m);
-
- return NULL;
+ return mfree(m);
}
void machine_free(Machine *m) {
diff --git a/src/machine/operation.c b/src/machine/operation.c
index 2bf93cb493..c966d0d21c 100644
--- a/src/machine/operation.c
+++ b/src/machine/operation.c
@@ -147,6 +147,5 @@ Operation *operation_free(Operation *o) {
if (o->machine)
LIST_REMOVE(operations_by_machine, o->machine->operations, o);
- free(o);
- return NULL;
+ return mfree(o);
}
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 77a4734df8..9138ee4511 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -201,12 +201,18 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
}
static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) {
- Tunnel *t = VTI(netdev);
uint32_t ikey, okey;
+ Tunnel *t;
int r;
assert(link);
assert(m);
+
+ if (netdev->kind == NETDEV_KIND_VTI)
+ t = VTI(netdev);
+ else
+ t = VTI6(netdev);
+
assert(t);
if (t->key != 0)
diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c
index 5727422e3d..e63ba07e90 100644
--- a/src/network/networkd-wait-online-link.c
+++ b/src/network/networkd-wait-online-link.c
@@ -77,8 +77,7 @@ Link *link_free(Link *l) {
}
free(l->ifname);
- free(l);
- return NULL;
+ return mfree(l);
}
int link_update_rtnl(Link *l, sd_netlink_message *m) {
diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c
index 5f1522cfb6..09c8f070ba 100644
--- a/src/nspawn/nspawn-settings.c
+++ b/src/nspawn/nspawn-settings.c
@@ -101,9 +101,7 @@ Settings* settings_free(Settings *s) {
expose_port_free_all(s->expose_ports);
custom_mount_free_all(s->custom_mounts, s->n_custom_mounts);
- free(s);
-
- return NULL;
+ return mfree(s);
}
bool settings_private_network(Settings *s) {
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index 53be18efc6..e03db4d003 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -83,9 +83,7 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
if (c->scope)
LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c);
- free(c);
-
- return NULL;
+ return mfree(c);
}
static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
@@ -421,9 +419,7 @@ DnsQuery *dns_query_free(DnsQuery *q) {
q->manager->n_dns_queries--;
}
- free(q);
-
- return NULL;
+ return mfree(q);
}
int dns_query_new(
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 5687588a7d..87e4abec6e 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -73,10 +73,8 @@ DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const D
return dns_resource_key_ref((DnsResourceKey*) key);
k = dns_resource_key_new_consume(key->class, key->type, destination);
- if (!k) {
- free(destination);
- return NULL;
- }
+ if (!k)
+ return mfree(destination);
return k;
}
@@ -513,9 +511,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
}
free(rr->to_string);
- free(rr);
-
- return NULL;
+ return mfree(rr);
}
int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 03811ac8e7..8dbc7f623b 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -128,9 +128,7 @@ DnsScope* dns_scope_free(DnsScope *s) {
dns_zone_flush(&s->zone);
LIST_REMOVE(scopes, s->manager->dns_scopes, s);
- free(s);
-
- return NULL;
+ return mfree(s);
}
DnsServer *dns_scope_get_dns_server(DnsScope *s) {
diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c
index 732471027b..1386e6a17b 100644
--- a/src/resolve/resolved-dns-search-domain.c
+++ b/src/resolve/resolved-dns-search-domain.c
@@ -104,9 +104,7 @@ DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) {
return NULL;
free(d->name);
- free(d);
-
- return NULL;
+ return mfree(d);
}
void dns_search_domain_unlink(DnsSearchDomain *d) {
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 97cc8c0e09..7282848e35 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -139,8 +139,7 @@ DnsServer* dns_server_unref(DnsServer *s) {
return NULL;
free(s->server_string);
- free(s);
- return NULL;
+ return mfree(s);
}
void dns_server_unlink(DnsServer *s) {
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index dd0e0b90e3..878bae47dc 100644
--- a/src/resolve/resolved-dns-stream.c
+++ b/src/resolve/resolved-dns-stream.c
@@ -343,9 +343,7 @@ DnsStream *dns_stream_unref(DnsStream *s) {
dns_packet_unref(s->write_packet);
dns_packet_unref(s->read_packet);
- free(s);
-
- return NULL;
+ return mfree(s);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref);
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index d455b6b1fa..2fce44ec8b 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -134,8 +134,7 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
dns_answer_unref(t->validated_keys);
dns_resource_key_unref(t->key);
- free(t);
- return NULL;
+ return mfree(t);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index ea4a007139..13e1f91192 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -101,8 +101,7 @@ Link *link_free(Link *l) {
free(l->state_file);
- free(l);
- return NULL;
+ return mfree(l);
}
void link_allocate_scopes(Link *l) {
@@ -698,8 +697,7 @@ LinkAddress *link_address_free(LinkAddress *a) {
dns_resource_record_unref(a->llmnr_address_rr);
dns_resource_record_unref(a->llmnr_ptr_rr);
- free(a);
- return NULL;
+ return mfree(a);
}
void link_address_add_rrs(LinkAddress *a, bool force_remove) {
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 40f08e8044..0954641c20 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -630,9 +630,7 @@ Manager *manager_free(Manager *m) {
dns_trust_anchor_flush(&m->trust_anchor);
manager_etc_hosts_flush(m);
- free(m);
-
- return NULL;
+ return mfree(m);
}
int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
diff --git a/src/shared/install.c b/src/shared/install.c
index f44f80560a..d33a658d0a 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -214,8 +214,8 @@ static int path_is_config(const LookupPaths *p, const char *path) {
assert(p);
assert(path);
- /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern
- * configuration from transient or generated units */
+ /* Note that we do *not* have generic checks for /etc or /run in place, since with
+ * them we couldn't discern configuration from transient or generated units */
parent = dirname_malloc(path);
if (!parent)
@@ -232,8 +232,8 @@ static int path_is_runtime(const LookupPaths *p, const char *path) {
assert(p);
assert(path);
- /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime
- * directories, as safety net. */
+ /* Everything in /run is considered runtime. On top of that we also add
+ * explicit checks for the various runtime directories, as safety net. */
rpath = skip_root(p, path);
if (rpath && path_startswith(rpath, "/run"))
@@ -1097,7 +1097,7 @@ static int config_parse_default_instance(
UnitFileInstallInfo *i = data;
const char *name;
- char *printed;
+ _cleanup_free_ char *printed = NULL;
int r;
assert(filename);
@@ -1117,15 +1117,10 @@ static int config_parse_default_instance(
if (r < 0)
return r;
- if (!unit_instance_is_valid(printed)) {
- free(printed);
+ if (!unit_instance_is_valid(printed))
return -EINVAL;
- }
-
- free(i->default_instance);
- i->default_instance = printed;
- return 0;
+ return free_and_replace(i->default_instance, printed);
}
static int unit_file_load(
@@ -1371,9 +1366,7 @@ static int install_info_follow(
if (!streq(basename(i->symlink_target), i->name))
return -EXDEV;
- free(i->path);
- i->path = i->symlink_target;
- i->symlink_target = NULL;
+ free_and_replace(i->path, i->symlink_target);
i->type = _UNIT_FILE_TYPE_INVALID;
return unit_file_load_or_readlink(c, i, i->path, root_dir, flags);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 529d89ee2a..060f8d50c7 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -62,8 +62,7 @@ Image *image_unref(Image *i) {
free(i->name);
free(i->path);
- free(i);
- return NULL;
+ return mfree(i);
}
static char **image_settings_path(Image *image) {
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c
index 24055e772b..293c6673fc 100644
--- a/src/shared/ptyfwd.c
+++ b/src/shared/ptyfwd.c
@@ -463,8 +463,7 @@ int pty_forward_new(
PTYForward *pty_forward_free(PTYForward *f) {
pty_forward_disconnect(f);
- free(f);
- return NULL;
+ return mfree(f);
}
int pty_forward_get_last_char(PTYForward *f, char *ch) {
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 7ed60dbe87..129706d15f 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -362,22 +362,24 @@ static int compare_unit_info(const void *a, const void *b) {
return strcasecmp(u->id, v->id);
}
+static const char* unit_type_suffix(const char *name) {
+ const char *dot;
+
+ dot = strrchr(name, '.');
+ if (!dot)
+ return "";
+
+ return dot + 1;
+}
+
static bool output_show_unit(const UnitInfo *u, char **patterns) {
assert(u);
if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
return false;
- if (arg_types) {
- const char *dot;
-
- dot = strrchr(u->id, '.');
- if (!dot)
- return false;
-
- if (!strv_find(arg_types, dot+1))
- return false;
- }
+ if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
+ return false;
if (arg_all)
return true;
@@ -403,10 +405,10 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) {
}
static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
- unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
+ unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len;
const UnitInfo *u;
unsigned n_shown = 0;
- int job_count = 0;
+ int job_count = 0, desc_len;
max_id_len = strlen("UNIT");
load_len = strlen("LOAD");
@@ -464,18 +466,20 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
for (u = unit_infos; u < unit_infos + c; u++) {
_cleanup_free_ char *e = NULL, *j = NULL;
+ const char *on_underline = "", *off_underline = "";
const char *on_loaded = "", *off_loaded = "";
const char *on_active = "", *off_active = "";
const char *on_circle = "", *off_circle = "";
const char *id;
- bool circle = false;
+ bool circle = false, underline = false;
if (!n_shown && !arg_no_legend) {
if (circle_len > 0)
fputs(" ", stdout);
- printf("%-*s %-*s %-*s %-*s ",
+ printf("%s%-*s %-*s %-*s %-*s ",
+ ansi_underline(),
id_len, "UNIT",
load_len, "LOAD",
active_len, "ACTIVE",
@@ -484,23 +488,33 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
if (job_count)
printf("%-*s ", job_len, "JOB");
- if (!arg_full && arg_no_pager)
- printf("%.*s\n", desc_len, "DESCRIPTION");
- else
- printf("%s\n", "DESCRIPTION");
+ printf("%.*s%s\n",
+ !arg_full && arg_no_pager ? desc_len : -1,
+ "DESCRIPTION",
+ ansi_normal());
}
n_shown++;
+ if (u + 1 < unit_infos + c &&
+ !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
+ on_underline = ansi_underline();
+ off_underline = ansi_normal();
+ underline = true;
+ }
+
if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
- on_loaded = ansi_highlight_red();
on_circle = ansi_highlight_yellow();
- off_loaded = off_circle = ansi_normal();
+ off_circle = ansi_normal();
circle = true;
+ on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ off_loaded = on_underline;
} else if (streq(u->active_state, "failed") && !arg_plain) {
- on_circle = on_active = ansi_highlight_red();
- off_circle = off_active = ansi_normal();
+ on_circle = ansi_highlight_red();
+ off_circle = ansi_normal();
circle = true;
+ on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ off_active = on_underline;
}
if (u->machine) {
@@ -523,17 +537,18 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
if (circle_len > 0)
printf("%s%s%s ", on_circle, circle ? special_glyph(BLACK_CIRCLE) : " ", off_circle);
- printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
+ printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
+ on_underline,
on_active, id_len, id, off_active,
on_loaded, load_len, u->load_state, off_loaded,
on_active, active_len, u->active_state,
sub_len, u->sub_state, off_active,
job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
- if (desc_len > 0)
- printf("%.*s\n", desc_len, u->description);
- else
- printf("%s\n", u->description);
+ printf("%.*s%s\n",
+ desc_len > 0 ? desc_len : -1,
+ u->description,
+ off_underline);
}
if (!arg_no_legend) {
@@ -1395,35 +1410,46 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
id_cols = max_id_len;
if (!arg_no_legend && c > 0)
- printf("%-*s %-*s\n",
+ printf("%s%-*s %-*s%s\n",
+ ansi_underline(),
id_cols, "UNIT FILE",
- state_cols, "STATE");
+ state_cols, "STATE",
+ ansi_normal());
for (u = units; u < units + c; u++) {
_cleanup_free_ char *e = NULL;
- const char *on, *off;
+ const char *on, *off, *on_underline = "", *off_underline = "";
const char *id;
+ bool underline = false;
+
+ if (u + 1 < units + c &&
+ !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) {
+ on_underline = ansi_underline();
+ off_underline = ansi_normal();
+ underline = true;
+ }
if (IN_SET(u->state,
UNIT_FILE_MASKED,
UNIT_FILE_MASKED_RUNTIME,
UNIT_FILE_DISABLED,
- UNIT_FILE_BAD)) {
- on = ansi_highlight_red();
- off = ansi_normal();
- } else if (u->state == UNIT_FILE_ENABLED) {
- on = ansi_highlight_green();
- off = ansi_normal();
- } else
- on = off = "";
+ UNIT_FILE_BAD))
+ on = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
+ else if (u->state == UNIT_FILE_ENABLED)
+ on = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
+ else
+ on = on_underline;
+ off = off_underline;
id = basename(u->path);
e = arg_full ? NULL : ellipsize(id, id_cols, 33);
- printf("%-*s %s%-*s%s\n",
+ printf("%s%-*s %s%-*s%s%s\n",
+ on_underline,
id_cols, e ? e : id,
- on, state_cols, unit_file_state_to_string(u->state), off);
+ on, state_cols, unit_file_state_to_string(u->state), off,
+ off_underline);
}
if (!arg_no_legend)
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 57d9da4855..752ad0aca8 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -73,7 +73,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_
u = after;
r = calendar_spec_next_usec(c, after, &u);
- printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof(buf), u));
+ printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u));
if (expect != (usec_t)-1)
assert_se(r >= 0 && u == expect);
else
@@ -109,6 +109,28 @@ static void test_timestamp(void) {
assert_se(y == x);
}
+static void test_hourly_bug_4031(void) {
+ CalendarSpec *c;
+ usec_t n, u, w;
+ char buf[FORMAT_TIMESTAMP_MAX], zaf[FORMAT_TIMESTAMP_MAX];
+ int r;
+
+ assert_se(calendar_spec_from_string("hourly", &c) >= 0);
+ n = now(CLOCK_REALTIME);
+ assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0);
+
+ printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n);
+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u);
+
+ assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0);
+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w);
+
+ assert_se(n < u);
+ assert_se(u <= n + USEC_PER_HOUR);
+ assert_se(u < w);
+ assert_se(w <= u + USEC_PER_HOUR);
+}
+
int main(int argc, char* argv[]) {
CalendarSpec *c;
@@ -177,6 +199,7 @@ int main(int argc, char* argv[]) {
assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0);
test_timestamp();
+ test_hourly_bug_4031();
return 0;
}
diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c
index 6bda86fe6e..57a7bf2c25 100644
--- a/src/timesync/timesyncd-server.c
+++ b/src/timesync/timesyncd-server.c
@@ -61,8 +61,7 @@ ServerAddress* server_address_free(ServerAddress *a) {
manager_set_server_address(a->name->manager, NULL);
}
- free(a);
- return NULL;
+ return mfree(a);
}
int server_name_new(
@@ -137,9 +136,7 @@ ServerName *server_name_free(ServerName *n) {
log_debug("Removed server %s.", n->string);
free(n->string);
- free(n);
-
- return NULL;
+ return mfree(n);
}
void server_name_flush_addresses(ServerName *n) {
diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c
index f68a09d7a8..7717ac7924 100644
--- a/src/udev/udev-ctrl.c
+++ b/src/udev/udev-ctrl.c
@@ -211,8 +211,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) {
err:
if (conn->sock >= 0)
close(conn->sock);
- free(conn);
- return NULL;
+ return mfree(conn);
}
struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) {
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c
index 26fa52cf6c..7619c8371b 100644
--- a/src/udev/udev-rules.c
+++ b/src/udev/udev-rules.c
@@ -1583,8 +1583,7 @@ struct udev_rules *udev_rules_unref(struct udev_rules *rules) {
strbuf_cleanup(rules->strbuf);
free(rules->uids);
free(rules->gids);
- free(rules);
- return NULL;
+ return mfree(rules);
}
bool udev_rules_check_timestamp(struct udev_rules *rules) {