diff options
143 files changed, 2617 insertions, 2543 deletions
diff --git a/.gitignore b/.gitignore index 605d109dfa..6149b01c6c 100644 --- a/.gitignore +++ b/.gitignore @@ -96,7 +96,6 @@ /systemd-kmsg-syslogd /systemd-localed /systemd-logind -/systemd-machine-id-commit /systemd-machine-id-setup /systemd-machined /systemd-modules-load diff --git a/Makefile-man.am b/Makefile-man.am index 7dd014116f..49586fe04c 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -102,7 +102,6 @@ MANPAGES += \ man/systemd-inhibit.1 \ man/systemd-initctl.service.8 \ man/systemd-journald.service.8 \ - man/systemd-machine-id-commit.1 \ man/systemd-machine-id-commit.service.8 \ man/systemd-machine-id-setup.1 \ man/systemd-notify.1 \ @@ -2351,7 +2350,6 @@ EXTRA_DIST += \ man/systemd-localed.service.xml \ man/systemd-logind.service.xml \ man/systemd-machine-id-commit.service.xml \ - man/systemd-machine-id-commit.xml \ man/systemd-machine-id-setup.xml \ man/systemd-machined.service.xml \ man/systemd-modules-load.service.xml \ diff --git a/Makefile.am b/Makefile.am index e9ad72333b..6ddc0b74f3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -397,7 +397,6 @@ rootlibexec_PROGRAMS = \ systemd-remount-fs \ systemd-reply-password \ systemd-fsck \ - systemd-machine-id-commit \ systemd-ac-power \ systemd-sysctl \ systemd-sleep \ @@ -2331,6 +2330,9 @@ systemd_machine_id_setup_SOURCES = \ systemd_machine_id_setup_LDADD = \ libshared.la +SYSINIT_TARGET_WANTS += \ + systemd-machine-id-commit.service + # ------------------------------------------------------------------------------ systemd_sysctl_SOURCES = \ src/sysctl/sysctl.c @@ -2353,18 +2355,6 @@ systemd_fsck_LDADD = \ libshared.la # ------------------------------------------------------------------------------ -systemd_machine_id_commit_SOURCES = \ - src/machine-id-commit/machine-id-commit.c \ - src/core/machine-id-setup.c \ - src/core/machine-id-setup.h - -systemd_machine_id_commit_LDADD = \ - libshared.la - -SYSINIT_TARGET_WANTS += \ - systemd-machine-id-commit.service - -# ------------------------------------------------------------------------------ systemd_ac_power_SOURCES = \ src/ac-power/ac-power.c @@ -17,7 +17,7 @@ CHANGES WITH 227: It allows accounting the number of tasks in a cgroup and enforcing limits on it. This adds two new setting TasksAccounting= and TasksMax= to each unit, as well as a - gloabl option DefaultTasksAccounting=. + global option DefaultTasksAccounting=. * Support for the "net_cls" cgroup controller has been added. It allows assigning a net class ID to each task in the cgroup, @@ -27,10 +27,39 @@ CHANGES WITH 227: sockets. This adds a new config directive called NetClass= to CGroup - enabled units. Allowed values are positive numbers for fix + enabled units. Allowed values are positive numbers for fixed assignments and "auto" for picking a free value automatically. + * 'systemctl is-system-running' now returns 'offline' if the + system is not booted with systemd. This command can now be + used as a substitute for 'systemd-notify --booted'. + + * Watchdog timeouts have been increased to 3 minutes for all + in-tree service files. Apparently, disk IO issues are more + frequent than we hoped, and user reported >1 minute waiting + for disk IO. + + * 'machine-id-commit' functionality has been merged into + 'machine-id-setup --commit'. The separate binary has been + removed. + + * The WorkingDirectory= directive in unit files may now be + set to the special value '~'. In this case, the working + directory is set to the home directory of the user configured + in User=. + + * A new systemd.crash_reboot=1 kernel command line option has + been added that triggers a reboot after crashing. This can + also be set through CrashReboot= in systemd.conf. + + * The CrashChVT= configuration file setting is renamed to + CrashChangeVT=, following our usual logic of not abbreviating + unnecessarily. The old directive is still supported for compat + reasons. Also, this directive now takes an integer value + between 1 and 63, or a boolean value. The formerly supported + '-1' value for disabling stays around for compat reasons. + * The PrivateTmp, PrivateDevices, PrivateNetwork, NoNewPrivileges, TTYPath, WorkingDirectory and RootDirectory properties can now be set for transient units. @@ -26,13 +26,8 @@ External: Features: -* add "requires=" deps on slices from services, not just "wants=" - * add a concept of RemainAfterExit= to scope units -* add sd_booted() check into "systemctl is-system-running", and return - a new state "foreign" or so if we are not running on systemd. - * add journal vacuum by max number of files * add a new command "systemctl revert" or so, that removes all dropin diff --git a/coccinelle/strempty.cocci b/coccinelle/strempty.cocci new file mode 100644 index 0000000000..e3bd0a1f56 --- /dev/null +++ b/coccinelle/strempty.cocci @@ -0,0 +1,10 @@ +@@ +expression s; +@@ +- s ?: "" ++ strempty(s) +@@ +expression s; +@@ +- s ? s : "" ++ strempty(s) diff --git a/man/journalctl.xml b/man/journalctl.xml index ca933645a9..305f1b9412 100644 --- a/man/journalctl.xml +++ b/man/journalctl.xml @@ -767,6 +767,12 @@ complete.</para></listitem> </varlistentry> + <varlistentry> + <term><option>--rotate</option></term> + + <listitem><para>Asks the Journal daemon to rotate journal files. + </para></listitem> + </varlistentry> <xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="version" /> <xi:include href="standard-options.xml" xpointer="no-pager" /> diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml index eb73727027..2f81746b5e 100644 --- a/man/kernel-command-line.xml +++ b/man/kernel-command-line.xml @@ -79,8 +79,9 @@ <term><varname>systemd.unit=</varname></term> <term><varname>rd.systemd.unit=</varname></term> <term><varname>systemd.dump_core=</varname></term> - <term><varname>systemd.crash_shell=</varname></term> <term><varname>systemd.crash_chvt=</varname></term> + <term><varname>systemd.crash_shell=</varname></term> + <term><varname>systemd.crash_reboot=</varname></term> <term><varname>systemd.confirm_spawn=</varname></term> <term><varname>systemd.show_status=</varname></term> <term><varname>systemd.log_target=</varname></term> diff --git a/man/machine-id.xml b/man/machine-id.xml index 92d67a3869..db72c2a01c 100644 --- a/man/machine-id.xml +++ b/man/machine-id.xml @@ -63,7 +63,7 @@ <para>The machine ID is usually generated from a random source during system installation and stays constant for all subsequent boots. Optionally, for stateless systems, it is generated during - runtime at boot if it is found to be empty.</para> + runtime at early boot if it is found to be empty.</para> <para>The machine ID does not change based on user configuration or when hardware is replaced.</para> @@ -119,7 +119,7 @@ id[8] = (id[8] & 0x3F) | 0x80;</programlisting> <filename>/etc/machine-id</filename> originates in the <filename>/var/lib/dbus/machine-id</filename> file introduced by D-Bus. In fact, this latter file might be a symlink to - <varname>/etc/machine-id</varname>.</para> + <filename>/etc/machine-id</filename>.</para> </refsect1> <refsect1> diff --git a/man/systemctl.xml b/man/systemctl.xml index e8cd47339c..36edc204b7 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -1124,9 +1124,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <tgroup cols='3'> <thead> <row> - <entry>Printed string</entry> - <entry>Meaning</entry> - <entry>Return value</entry> + <entry>Name</entry> + <entry>Description</entry> + <entry>Exit Code</entry> </row> </thead> <tbody> @@ -1141,7 +1141,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <row> <entry><literal>linked</literal></entry> <entry morerows='1'>Made available through a symlink to the unit file (permanently or just in <filename>/run</filename>).</entry> - <entry morerows='1'>1</entry> + <entry morerows='1'>> 0</entry> </row> <row> <entry><literal>linked-runtime</literal></entry> @@ -1149,7 +1149,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <row> <entry><literal>masked</literal></entry> <entry morerows='1'>Disabled entirely (permanently or just in <filename>/run</filename>).</entry> - <entry morerows='1'>1</entry> + <entry morerows='1'>> 0</entry> </row> <row> <entry><literal>masked-runtime</literal></entry> @@ -1167,7 +1167,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <row> <entry><literal>disabled</literal></entry> <entry>Unit file is not enabled.</entry> - <entry>1</entry> + <entry>> 0</entry> </row> </tbody> </tgroup> @@ -1478,22 +1478,25 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <listitem> <para>Checks whether the system is operational. This - returns success when the system is fully up and running, - meaning not in startup, shutdown or maintenance - mode. Failure is returned otherwise. In addition, the + returns success (exit code 0) when the system is fully up + and running, specifically not in startup, shutdown or + maintenance mode, and with no failed services. Failure is + returned otherwise (exit code non-zero). In addition, the current state is printed in a short string to standard output, see table below. Use <option>--quiet</option> to suppress this output.</para> <table> - <title>Manager Operational States</title> - <tgroup cols='2'> - <colspec colname='name' /> - <colspec colname='description' /> + <title><command>is-system-running</command> output</title> + <tgroup cols='3'> + <colspec colname='name'/> + <colspec colname='description'/> + <colspec colname='exit-code'/> <thead> <row> <entry>Name</entry> <entry>Description</entry> + <entry>Exit Code</entry> </row> </thead> <tbody> @@ -1503,32 +1506,53 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service <filename>basic.target</filename> is reached or the <varname>maintenance</varname> state entered. </para></entry> + <entry>> 0</entry> </row> <row> <entry><varname>starting</varname></entry> <entry><para>Late bootup, before the job queue becomes idle for the first time, or one of the rescue targets are reached.</para></entry> + <entry>> 0</entry> </row> <row> <entry><varname>running</varname></entry> <entry><para>The system is fully operational.</para></entry> + <entry>0</entry> </row> <row> <entry><varname>degraded</varname></entry> <entry><para>The system is operational but one or more units failed.</para></entry> + <entry>> 0</entry> </row> <row> <entry><varname>maintenance</varname></entry> <entry><para>The rescue or emergency target is active.</para></entry> + <entry>> 0</entry> </row> <row> <entry><varname>stopping</varname></entry> <entry><para>The manager is shutting down.</para></entry> + <entry>> 0</entry> + </row> + <row> + <entry><varname>offline</varname></entry> + <entry><para>The manager is not + running. Specifically, this is the operational + state if an incompatible program is running as + system manager (PID 1).</para></entry> + <entry>> 0</entry> + </row> + <row> + <entry><varname>unknown</varname></entry> + <entry><para>The operational state could not be + determined, due to lack of resources or another + error cause.</para></entry> + <entry>> 0</entry> </row> </tbody> </tgroup> diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml index 198315052f..58e6fd1780 100644 --- a/man/systemd-analyze.xml +++ b/man/systemd-analyze.xml @@ -168,6 +168,13 @@ <option>--log-level=</option> described in <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para> + <para><command>systemd-analyze set-log-target + <replaceable>TARGET</replaceable></command> changes the current log + target of the <command>systemd</command> daemon to + <replaceable>TARGET</replaceable> (accepts the same values as + <option>--log-target=</option> described in + <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para> + <para><command>systemd-analyze verify</command> will load unit files and print warnings if any errors are detected. Files specified on the command line will be loaded, but also any other diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml index dae6ee6042..bd0082712e 100644 --- a/man/systemd-journald.service.xml +++ b/man/systemd-journald.service.xml @@ -99,7 +99,10 @@ reboot. To make the data persistent, it is sufficient to create <filename>/var/log/journal/</filename> where <filename>systemd-journald</filename> will then store the - data.</para> + data:</para> + + <programlisting>mkdir -p /var/log/journal +systemd-tmpfiles --create --prefix /var/log/journal</programlisting> <para><filename>systemd-journald</filename> will forward all received log messages to the diff --git a/man/systemd-machine-id-commit.service.xml b/man/systemd-machine-id-commit.service.xml index 7c8fc0874e..10f36b3008 100644 --- a/man/systemd-machine-id-commit.service.xml +++ b/man/systemd-machine-id-commit.service.xml @@ -42,55 +42,50 @@ <refnamediv> <refname>systemd-machine-id-commit.service</refname> - <refpurpose>Commit transient machine-id to disk</refpurpose> + <refpurpose>Commit a transient machine-id to disk</refpurpose> </refnamediv> <refsynopsisdiv> <para><filename>systemd-machine-id-commit.service</filename></para> - <para><filename>/usr/lib/systemd/systemd-machine-id-commit</filename></para> </refsynopsisdiv> <refsect1> <title>Description</title> - <para><filename>systemd-machine-id-commit.service</filename> is a - service responsible for committing any transient - <filename>/etc/machine-id</filename> file to a writable file + <para><filename>systemd-machine-id-commit.service</filename> is an + early-boot service responsible for committing transient + <filename>/etc/machine-id</filename> files to a writable disk file system. See <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> - for more information about this file.</para> - - <para>This service is started shortly after - <filename>local-fs.target</filename> if - <filename>/etc/machine-id</filename> is an independent mount point - (probably a tmpfs one) and /etc is writable. - <command>systemd-machine-id-commit</command> will then write - current machine ID to disk and unmount the transient + for more information about machine IDs.</para> + + <para>This service is started after + <filename>local-fs.target</filename> in case + <filename>/etc/machine-id</filename> is a mount point of its own + (usually from a memory file system such as + <literal>tmpfs</literal>) and /etc is writable. The service will + invoke <command>systemd-machine-id-setup --commit</command>, which + writes the current transient machine ID to disk and unmount the <filename>/etc/machine-id</filename> file in a race-free manner to - ensure that file is always valid for other processes.</para> - - <para>Note that the traditional way to initialize the machine ID - in <filename>/etc/machine-id</filename> is to use - <command>systemd-machine-id-setup</command> by system installer - tools. You can also use - <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> - to initialize the machine ID on mounted (but not booted) system - images. The main use case for that service is - <filename>/etc/machine-id</filename> being an empty file at boot - and initrd chaining to systemd giving it a read only file system - that will be turned read-write later during the boot - process.</para> - - <para>There is no consequence if that service fails other than a - newer machine-id will be generated during next system boot. - </para> + ensure that file is always valid and accessible for other + processes. See + <citerefentry><refentrytitle>systemd-machine-id-setup</refentrytitle><manvolnum>1</manvolnum></citerefentry> + for details.</para> + + <para>The main use case of this service are systems where + <filename>/etc/machine-id</filename> is read-only and initially + not initialized. In this case the system manager will generate a + transient machine ID file on a memory file system, and mount it + over <filename>/etc/machine-id</filename>, during the early boot + phase. This service is then invoked in a later boot phase, as soon + as <filename>/etc</filename> has been remounted writable and the + ID may thus be committed to disk to make it permanent.</para> </refsect1> <refsect1> <title>See Also</title> <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>systemd-machine-id-commit</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-machine-id-setup</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> diff --git a/man/systemd-machine-id-commit.xml b/man/systemd-machine-id-commit.xml deleted file mode 100644 index d216aa0745..0000000000 --- a/man/systemd-machine-id-commit.xml +++ /dev/null @@ -1,123 +0,0 @@ -<?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 2014 Didier Roche - - 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="systemd-machine-id-commit" - xmlns:xi="http://www.w3.org/2001/XInclude"> - - <refentryinfo> - <title>systemd-machine-id-commit</title> - <productname>systemd</productname> - - <authorgroup> - <author> - <contrib>Developer</contrib> - <firstname>Didier</firstname> - <surname>Roche</surname> - <email>didrocks@ubuntu.com</email> - </author> - </authorgroup> - </refentryinfo> - - <refmeta> - <refentrytitle>systemd-machine-id-commit</refentrytitle> - <manvolnum>1</manvolnum> - </refmeta> - - <refnamediv> - <refname>systemd-machine-id-commit</refname> - <refpurpose>Commit transient machine ID to /etc/machine-id</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis> - <command>systemd-machine-id-commit</command> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1> - <title>Description</title> - - <para><command>systemd-machine-id-commit</command> may be used to - write on disk any transient machine ID mounted as a temporary file - system in <filename>/etc/machine-id</filename> at boot time. See - <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> - for more information about this file.</para> - - <para>This tool will execute no operation if - <filename>/etc/machine-id</filename> doesn't contain any valid - machine ID, isn't mounted as an independent temporary file system, - or <filename>/etc</filename> is read-only. If those conditions are - met, it will then write current machine ID to disk and unmount the - transient <filename>/etc/machine-id</filename> file in a race-free - manner to ensure that this file is always valid for other - processes.</para> - - <para>Note that the traditional way to initialize the machine ID - in <filename>/etc/machine-id</filename> is to use - <command>systemd-machine-id-setup</command> by system installer - tools. You can also use - <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> - to initialize the machine ID on mounted (but not booted) system - images.</para> - </refsect1> - - <refsect1> - <title>Options</title> - - <para>The following options are understood:</para> - - <variablelist> - <varlistentry> - <term><option>--root=<replaceable>root</replaceable></option></term> - <listitem><para>Takes a directory path - as an argument. All paths will be - prefixed with the given alternate - <replaceable>root</replaceable> path, - including config search paths. - </para></listitem> - </varlistentry> - <xi:include href="standard-options.xml" xpointer="help" /> - <xi:include href="standard-options.xml" xpointer="version" /> - </variablelist> - - </refsect1> - - <refsect1> - <title>Exit status</title> - - <para>On success, 0 is returned, a non-zero failure code - otherwise.</para> - </refsect1> - - <refsect1> - <title>See Also</title> - <para> - <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>systemd-machine-id-commit.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, - <citerefentry><refentrytitle>systemd-machine-id-setup</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>, - <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> - </para> - </refsect1> - -</refentry> diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml index 182717f524..efcf408332 100644 --- a/man/systemd-machine-id-setup.xml +++ b/man/systemd-machine-id-setup.xml @@ -1,4 +1,4 @@ -<?xml version='1.0'?> <!--*-nxml-*--> +<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*--> <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> @@ -35,6 +35,12 @@ <surname>Poettering</surname> <email>lennart@poettering.net</email> </author> + <author> + <contrib>Developer</contrib> + <firstname>Didier</firstname> + <surname>Roche</surname> + <email>didrocks@ubuntu.com</email> + </author> </authorgroup> </refentryinfo> @@ -59,30 +65,43 @@ <para><command>systemd-machine-id-setup</command> may be used by system installer tools to initialize the machine ID stored in - <filename>/etc/machine-id</filename> at install time with a - randomly generated ID. See + <filename>/etc/machine-id</filename> at install time, with a + provisioned or randomly generated ID. See <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more information about this file.</para> - <para>This tool will execute no operation if - <filename>/etc/machine-id</filename> is already - initialized.</para> - - <para>If a valid D-Bus machine ID is already configured for the - system, the D-Bus machine ID is copied and used to initialize the - machine ID in <filename>/etc/machine-id</filename>.</para> - - <para>If run inside a KVM virtual machine and a UUID is passed via - the <option>-uuid</option> option, this UUID is used to initialize - the machine ID instead of a randomly generated one. The caller - must ensure that the UUID passed is sufficiently unique and is - different for every booted instanced of the VM.</para> - - <para>Similar, if run inside a Linux container environment and a - UUID is set for the container this is used to initialize the - machine ID. For details see the documentation of the <ulink - url="http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface">Container - Interface</ulink>.</para> + <para>If the tool is invoked without the <option>--commit</option> + switch <filename>/etc/machine-id</filename> is initialized with a + valid, new machined ID if it is missing or empty. The new machine + ID will be acquired in the following fashion:</para> + + <orderedlist> + <listitem><para>If a valid D-Bus machine ID is already + configured for the system, the D-Bus machine ID is copied and + used to initialize the machine ID in + <filename>/etc/machine-id</filename>.</para></listitem> + + <listitem><para>If run inside a KVM virtual machine and a UUID + is was configured (via the <option>-uuid</option> + option), this UUID is used to initialize the machine ID. The + caller must ensure that the UUID passed is sufficiently unique + and is different for every booted instance of the + VM.</para></listitem> + + <listitem><para>Similar, if run inside a Linux container + environment and a UUID is configured for the container this is + used to initialize the machine ID. For details see the + documentation of the <ulink + url="http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface">Container + Interface</ulink>.</para></listitem> + + <listitem><para>Otherwise a new ID is randomly + generated.</para></listitem> + </orderedlist> + + <para>The <option>--commit</option> switch may be used to commit a + transient machined ID to disk, making it persistent. For details, + see below.</para> <para>Use <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> @@ -97,13 +116,41 @@ <para>The following options are understood:</para> <variablelist> + <varlistentry> <term><option>--root=<replaceable>root</replaceable></option></term> - <listitem><para>Takes a directory path as an argument. All - paths will be prefixed with the given alternate - <replaceable>root</replaceable> path, including config search - paths. </para></listitem> + <listitem><para>Takes a directory path as argument. All paths + operated will be prefixed with the given alternate + <replaceable>root</replaceable> path, including the path for + <filename>/etc/machine-id</filename> itself.</para></listitem> </varlistentry> + + <varlistentry> + <term><option>--commit</option></term> + <listitem><para>Commit a transient machine ID to disk. This + command may be used to convert a transient machine ID into a + persistent one. A transient machine ID file is one that was + bind mounted from a memory file system (usually + <literal>tmpfs</literal>) to + <filename>/etc/machine-id</filename> during the early phase of + the boot process. This may happen because + <filename>/etc</filename> is initially read-only and was + missing a valid machine ID file at that point.</para> + + <para>This command will execute no operation if + <filename>/etc/machine-id</filename> is not mounted from a + memory file system, or if <filename>/etc</filename> is + read-only. The command will write the current transient + machine ID to disk and unmount the + <filename>/etc/machine-id</filename> mount point in a + race-free manner to ensure that this file is always valid and + accessible for other processes.</para> + + <para>This command is primarily used by the + <citerefentry><refentrytitle>systemd-machine-id-commit.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> + early-boot service.</para></listitem> + </varlistentry> + <xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="version" /> </variablelist> @@ -122,6 +169,7 @@ <para> <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd-machine-id-commit.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry project='dbus'><refentrytitle>dbus-uuidgen</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> </para> diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml index 06d5ae5319..71d501f435 100644 --- a/man/systemd-notify.xml +++ b/man/systemd-notify.xml @@ -124,7 +124,12 @@ systemd, non-zero otherwise. If this option is passed, no message is sent. This option is hence unrelated to the other options. For details about the semantics of this option, see - <citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem> + <citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>. An + alternative way to check for this state is to call + <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> + with the <command>is-system-running</command> command. It will + return <literal>offline</literal> if the system was not booted + with systemd. </para></listitem> </varlistentry> <xi:include href="standard-options.xml" xpointer="help" /> @@ -156,12 +161,12 @@ mkfifo /tmp/waldo systemd-notify --ready --status="Waiting for data..." while : ; do - read a < /tmp/waldo - systemd-notify --status="Processing $a" + read a < /tmp/waldo + systemd-notify --status="Processing $a" - # Do something with $a ... + # Do something with $a ... - systemd-notify --status="Waiting for data..." + systemd-notify --status="Waiting for data..." done</programlisting> </example> </refsect1> diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml index a4ba0959ea..56db9ff17e 100644 --- a/man/systemd-system.conf.xml +++ b/man/systemd-system.conf.xml @@ -90,9 +90,10 @@ <term><varname>LogColor=</varname></term> <term><varname>LogLocation=</varname></term> <term><varname>DumpCore=yes</varname></term> + <term><varname>CrashChangeVT=no</varname></term> <term><varname>CrashShell=no</varname></term> + <term><varname>CrashReboot=no</varname></term> <term><varname>ShowStatus=yes</varname></term> - <term><varname>CrashChVT=1</varname></term> <term><varname>DefaultStandardOutput=journal</varname></term> <term><varname>DefaultStandardError=inherit</varname></term> diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 7633948645..d3f56fee40 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -84,22 +84,27 @@ <varlistentry> <term><varname>WorkingDirectory=</varname></term> - <listitem><para>Takes an absolute directory path. Sets the - working directory for executed processes. If not set, defaults - to the root directory when systemd is running as a system - instance and the respective user's home directory if run as - user.</para></listitem> + <listitem><para>Takes an absolute directory path, or the + special value <literal>~</literal>. Sets the working directory + for executed processes. If set to <literal>~</literal> the + home directory of the user specified in + <varname>User=</varname> is used. If not set, defaults to the + root directory when systemd is running as a system instance + and the respective user's home directory if run as user. If + the setting is prefixed with the <literal>-</literal> + character, a missing working directory is not considered + fatal.</para></listitem> </varlistentry> <varlistentry> <term><varname>RootDirectory=</varname></term> <listitem><para>Takes an absolute directory path. Sets the - root directory for executed processes, with the - <citerefentry project='man-pages'><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry> + root directory for executed processes, with the <citerefentry + project='man-pages'><refentrytitle>chroot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call. If this is used, it must be ensured that the - process and all its auxiliary files are available in the - <function>chroot()</function> jail.</para></listitem> + process binary and all its auxiliary files are available in + the <function>chroot()</function> jail.</para></listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 642d95a029..eeb98198ab 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -287,7 +287,7 @@ below (see section "Command Lines" below). </para> - <para>When <varname>Type</varname> is not + <para>When <varname>Type=</varname> is not <option>oneshot</option>, only one command may and must be given. When <varname>Type=oneshot</varname> is used, zero or more commands may be specified. This can be specified by @@ -421,7 +421,7 @@ <varname>ExecStop=</varname> defined, or where the service exited unexpectedly. This argument takes multiple command lines, following the same scheme as described for - <varname>ExecStart</varname>. Use of these settings is + <varname>ExecStart=</varname>. Use of these settings is optional. Specifier and environment variable substitution is supported.</para></listitem> </varlistentry> @@ -486,7 +486,7 @@ "keep-alive ping"). If the time between two such calls is larger than the configured time, then the service is placed in a failed state and it will be terminated with - <varname>SIGABRT</varname>. By setting + <constant>SIGABRT</constant>. By setting <varname>Restart=</varname> to <option>on-failure</option> or <option>always</option>, the service will be automatically restarted. The time configured here will be passed to the @@ -905,12 +905,15 @@ <varlistentry> <term><varname>USBFunctionDescriptors=</varname></term> - <listitem><para>Configure the location of file containing - FunctionFS descriptors. This is is used only when socket with - <varname>ListenUSBFunction</varname> line want to activate this service. Content of - this file is writen to ep0 file after it is opened. This is required - for socket activation using <varname>ListenUSBFunction</varname> - (i.e. for passing all ffs endpoints to service).</para></listitem> + <listitem><para>Configure the location of the file containing + <ulink url="https://www.kernel.org/doc/Documentation/usb/functionfs.txt">functionfs</ulink> + descriptors. This is is used only when a socket with + <varname>ListenUSBFunction=</varname> configured wants to + activate this service. Content of this file is writen to + <filename>ep0</filename> file after it is opened. This is + required for socket activation using + <varname>ListenUSBFunction=</varname> (i.e. for passing all + functionfs endpoints to the service).</para></listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml index 7f884aa1be..bb75b69cea 100644 --- a/man/systemd.socket.xml +++ b/man/systemd.socket.xml @@ -262,13 +262,17 @@ <varlistentry> <term><varname>ListenUSBFunction=</varname></term> - <listitem><para>Specifies a functionfs endpoint location - to listen on. This expects an absolute file system path as + <listitem><para>Specifies a + <ulink url="https://www.kernel.org/doc/Documentation/usb/functionfs.txt">functionfs</ulink> + endpoint location to + listen on. This expects an absolute file system path as the argument. Behavior otherwise is very similar to the <varname>ListenFIFO=</varname> directive above. Use this to - open functionfs endpoint ep0. When using this option, activated - service has to have <varname>USBFunctionDescriptors</varname> - and <varname>USBFunctionStrings</varname> options set.</para></listitem> + open functionfs endpoint <filename>ep0</filename>. When using + this option, activated service has to have the + <varname>USBFunctionDescriptors=</varname> and + <varname>USBFunctionStrings=</varname> options set. + </para></listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.special.xml b/man/systemd.special.xml index 6e0dff9b47..78bad4d814 100644 --- a/man/systemd.special.xml +++ b/man/systemd.special.xml @@ -215,20 +215,19 @@ <term><filename>exit.target</filename></term> <listitem> <para>A special service unit for shutting down the system or - user service manager. It also works in containers and is - equivalent to <filename>poweroff.target</filename> on - non-container systems.</para> + user service manager. It is equivalent to + <filename>poweroff.target</filename> on non-container + systems, and also works in containers.</para> - <para>Applications wanting to terminate the user service - manager should start this unit. If systemd receives + <para>systemd will start this unit when it receives a + request to shut down over D-Bus or a <constant>SIGTERM</constant> or <constant>SIGINT</constant> - when running as user service daemon, it will start this - unit.</para> + signal when running as user service daemon.</para> - <para>Normally, this pulls in + <para>Normally, this (indirectly) pulls in <filename>shutdown.target</filename> which in turn should be - conflicted by all units that want to be shut down on user - service manager exit.</para> + conflicted by all units that want to be scheduled for + shutdown when the service manager starts to exit.</para> </listitem> </varlistentry> <varlistentry> diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 015deab4bb..8985b6b940 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -1055,8 +1055,11 @@ <literal>auto</literal> (for dynamic allocation). Network traffic of all processes inside the unit will have the network class ID assigned by the kernel. Also see - <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> - .</para></listitem> + the kernel docs for + <ulink url="https://www.kernel.org/doc/Documentation/cgroups/net_cls.txt">net_cls controller</ulink> + and + <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + </para></listitem> </varlistentry> </variablelist> diff --git a/man/systemd.xml b/man/systemd.xml index 479f55de76..9e927c3204 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -1,4 +1,4 @@ -<?xml version='1.0'?> <!--*-nxml-*--> +<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*--> <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> @@ -131,17 +131,48 @@ <varlistentry> <term><option>--dump-core</option></term> - <listitem><para>Dump core on crash. This switch has no effect - when run as user instance.</para></listitem> + <listitem><para>Enable core dumping on crash. This switch has + no effect when running as user instance. This setting may also + be enabled during boot on the kernel command line via the + <varname>systemd.dump_core=</varname> option, see + below.</para></listitem> </varlistentry> + + <varlistentry> + <term><option>--crash-vt=</option><replaceable>VT</replaceable></term> + + <listitem><para>Switch to a specific virtual console (VT) on + crash. Takes a positive integer in the range 1..63, or a + boolean argument. If an integer is passed, selects which VT to + switch to. If <constant>yes</constant>, the VT kernel messages + are written to is selected. If <constant>no</constant>, no VT + switch is attempted. This switch has no effect when running as + user instance. This setting may also be enabled during boot, + on the kernel command line via the + <varname>systemd.crash_vt=</varname> option, see + below.</para></listitem> + </varlistentry> + <varlistentry> <term><option>--crash-shell</option></term> - <listitem><para>Run shell on - crash. This switch has no effect when - run as user - instance.</para></listitem> + <listitem><para>Run a shell on crash. This switch has no + effect when running as user instance. This setting may also be + enabled during boot, on the kernel command line via the + <varname>systemd.crash_shell=</varname> option, see + below.</para></listitem> </varlistentry> + + <varlistentry> + <term><option>--crash-reboot</option></term> + + <listitem><para>Automatically reboot the system on crash. This + switch has no effect when running as user instance. This + setting may also be enabled during boot, on the kernel command + line via the <varname>systemd.crash_reboot=</varname> option, + see below.</para></listitem> + </varlistentry> + <varlistentry> <term><option>--confirm-spawn</option></term> @@ -854,50 +885,67 @@ <term><varname>systemd.dump_core=</varname></term> <listitem><para>Takes a boolean argument. If - <option>true</option>, systemd dumps core when it crashes. - Otherwise, no core dump is created. Defaults to - <option>true</option>.</para></listitem> + <option>yes</option>, the systemd manager (PID 1) dumps core + when it crashes. Otherwise, no core dump is created. Defaults + to <option>yes</option>.</para></listitem> + </varlistentry> + + <varlistentry> + <term><varname>systemd.crash_chvt=</varname></term> + + <listitem><para>Takes a positive integer, or a boolean + argument. If a positive integer (in the range 1..63) is + specified the system manager (PID 1) will activate the specified + virtual terminal (VT) when it crashes. Defaults to + <constant>no</constant>, meaning that no such switch is + attempted. If set to <constant>yes</constant> the VT the + kernel messages are written to is selected.</para></listitem> </varlistentry> <varlistentry> <term><varname>systemd.crash_shell=</varname></term> <listitem><para>Takes a boolean argument. If - <option>true</option>, systemd spawns a shell when it crashes. - Otherwise, no shell is spawned. Defaults to - <option>false</option>, for security reasons, as the shell is - not protected by any password + <option>yes</option>, the system manager (PID 1) spawns a + shell when it crashes, after a 10s delay. Otherwise, no shell + is spawned. Defaults to <option>no</option>, for security + reasons, as the shell is not protected by password authentication.</para></listitem> </varlistentry> <varlistentry> - <term><varname>systemd.crash_chvt=</varname></term> + <term><varname>systemd.crash_reboot=</varname></term> - <listitem><para>Takes an integer argument. If positive systemd - activates the specified virtual terminal when it crashes. - Defaults to <constant>-1</constant>.</para></listitem> + <listitem><para>Takes a boolean argument. If + <option>yes</option>, the system manager (PID 1) will reboot + the machine automatically when it crashes, after a 10s delay. + Otherwise, the system will hang indefinitely. Defaults to + <option>no</option>, in order to avoid a reboot loop. If + combined with <varname>systemd.crash_shell=</varname>, it is + first attempted to invoke a shell, and if this is not + successful the system is rebooted.</para></listitem> </varlistentry> <varlistentry> <term><varname>systemd.confirm_spawn=</varname></term> <listitem><para>Takes a boolean argument. If - <option>true</option>, asks for confirmation when spawning - processes. Defaults to - <option>false</option>.</para></listitem> + <option>yes</option>, the system manager (PID 1) asks for + confirmation when spawning processes. Defaults to + <option>no</option>.</para></listitem> </varlistentry> <varlistentry> <term><varname>systemd.show_status=</varname></term> <listitem><para>Takes a boolean argument or the constant - <constant>auto</constant>. If <option>true</option>, shows - terse service status updates on the console during bootup. - <constant>auto</constant> behaves like <option>false</option> - until a service fails or there is a significant delay in boot. - Defaults to <option>true</option>, unless - <option>quiet</option> is passed as kernel command line option - in which case it defaults to + <constant>auto</constant>. If <option>yes</option>, the + systemd manager (PID 1) shows terse service status updates on + the console during bootup. <constant>auto</constant> behaves + like <option>false</option> until a service fails or there is + a significant delay in boot. Defaults to + <option>yes</option>, unless <option>quiet</option> is passed + as kernel command line option in which case it defaults to <constant>auto</constant>.</para></listitem> </varlistentry> diff --git a/man/timedatectl.xml b/man/timedatectl.xml index 9a86c4126a..c439bc56ed 100644 --- a/man/timedatectl.xml +++ b/man/timedatectl.xml @@ -178,7 +178,7 @@ protected by a different access policy.</para> <para>Note that even if time synchronization is turned off - with this command another, unrelated system service might + with this command, another unrelated system service might still synchronize the clock with the network. Also note that strictly speaking <filename>systemd-timesyncd.service</filename> does more than diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl index bb2bb25deb..056cdbce70 100644 --- a/shell-completion/bash/journalctl +++ b/shell-completion/bash/journalctl @@ -47,7 +47,7 @@ _journalctl() { --version --list-catalog --update-catalog --list-boots --show-cursor --dmesg -k --pager-end -e -r --reverse --utc -x --catalog --no-full --force --dump-catalog - --flush' + --flush --rotate' [ARG]='-b --boot --this-boot -D --directory --file -F --field -o --output -u --unit --user-unit -p --priority --vacuum-size --vacuum-time' diff --git a/src/activate/activate.c b/src/activate/activate.c index 5318829442..2dfc4a0bc4 100644 --- a/src/activate/activate.c +++ b/src/activate/activate.c @@ -19,21 +19,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> +#include <getopt.h> #include <sys/epoll.h> #include <sys/prctl.h> #include <sys/socket.h> #include <sys/wait.h> -#include <getopt.h> +#include <unistd.h> #include "systemd/sd-daemon.h" -#include "socket-util.h" -#include "build.h" #include "log.h" -#include "strv.h" #include "macro.h" #include "signal-util.h" +#include "socket-util.h" +#include "strv.h" static char** arg_listen = NULL; static bool arg_accept = false; @@ -314,9 +313,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0 /* done */; + return version(); case 'l': { int r = strv_extend(&arg_listen, optarg); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 3657ef50f1..f05f1e5581 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -20,25 +20,25 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> -#include <stdlib.h> #include <getopt.h> #include <locale.h> +#include <stdio.h> +#include <stdlib.h> #include "sd-bus.h" -#include "bus-util.h" + +#include "analyze-verify.h" #include "bus-error.h" -#include "log.h" -#include "build.h" -#include "util.h" -#include "strxcpyx.h" -#include "strv.h" -#include "unit-name.h" -#include "special.h" +#include "bus-util.h" #include "hashmap.h" +#include "log.h" #include "pager.h" -#include "analyze-verify.h" +#include "special.h" +#include "strv.h" +#include "strxcpyx.h" #include "terminal-util.h" +#include "unit-name.h" +#include "util.h" #define SCALE_X (0.1 / 1000.0) /* pixels per us */ #define SCALE_Y (20.0) @@ -1217,10 +1217,8 @@ static int dump(sd_bus *bus, char **args) { &error, &reply, ""); - if (r < 0) { - log_error("Failed issue method call: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed issue method call: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &text); if (r < 0) @@ -1251,11 +1249,36 @@ static int set_log_level(sd_bus *bus, char **args) { &error, "s", args[0]); - if (r < 0) { - log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); - return -EIO; + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + + return 0; +} + +static int set_log_target(sd_bus *bus, char **args) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(args); + + if (strv_length(args) != 1) { + log_error("This command expects one argument only."); + return -E2BIG; } + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogTarget", + &error, + "s", + args[0]); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + return 0; } @@ -1285,7 +1308,8 @@ static void help(void) { " critical-chain Print a tree of the time critical chain of units\n" " plot Output SVG graphic showing service initialization\n" " dot Output dependency graph in dot(1) format\n" - " set-log-level LEVEL Set logging threshold for systemd\n" + " set-log-level LEVEL Set logging threshold for manager\n" + " set-log-target TARGET Set logging target for manager\n" " dump Output state serialization of service manager\n" " verify FILE... Check unit files for correctness\n" , program_invocation_short_name); @@ -1339,9 +1363,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_USER: arg_user = true; @@ -1434,7 +1456,7 @@ int main(int argc, char *argv[]) { else { _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; - r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus); + r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; @@ -1454,6 +1476,8 @@ int main(int argc, char *argv[]) { r = dump(bus, argv+optind+1); else if (streq(argv[optind], "set-log-level")) r = set_log_level(bus, argv+optind+1); + else if (streq(argv[optind], "set-log-target")) + r = set_log_target(bus, argv+optind+1); else log_error("Unknown operation '%s'.", argv[optind]); } diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 4a9105f421..13a85e1158 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -775,15 +775,19 @@ int executable_is_script(const char *path, char **interpreter) { /** * Retrieve one field from a file like /proc/self/status. pattern - * should start with '\n' and end with a ':'. Whitespace and zeros - * after the ':' will be skipped. field must be freed afterwards. + * should not include whitespace or the delimiter (':'). pattern matches only + * the beginning of a line. Whitespace before ':' is skipped. Whitespace and + * zeros after the ':' will be skipped. field must be freed afterwards. + * terminator specifies the terminating characters of the field value (not + * included in the value). */ -int get_status_field(const char *filename, const char *pattern, char **field) { +int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) { _cleanup_free_ char *status = NULL; char *t, *f; size_t len; int r; + assert(terminator); assert(filename); assert(pattern); assert(field); @@ -792,11 +796,31 @@ int get_status_field(const char *filename, const char *pattern, char **field) { if (r < 0) return r; - t = strstr(status, pattern); - if (!t) - return -ENOENT; + t = status; + + do { + bool pattern_ok; + + do { + t = strstr(t, pattern); + if (!t) + return -ENOENT; + + /* Check that pattern occurs in beginning of line. */ + pattern_ok = (t == status || t[-1] == '\n'); + + t += strlen(pattern); + + } while (!pattern_ok); + + t += strspn(t, " \t"); + if (!*t) + return -ENOENT; + + } while (*t != ':'); + + t++; - t += strlen(pattern); if (*t) { t += strspn(t, " \t"); @@ -812,7 +836,7 @@ int get_status_field(const char *filename, const char *pattern, char **field) { t --; } - len = strcspn(t, WHITESPACE); + len = strcspn(t, terminator); f = strndup(t, len); if (!f) diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 2e8148ff24..4998d4d042 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -48,4 +48,4 @@ int write_env_file(const char *fname, char **l); int executable_is_script(const char *path, char **interpreter); -int get_status_field(const char *filename, const char *pattern, char **field); +int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field); diff --git a/src/basic/log.c b/src/basic/log.c index 38f42b3a6e..e6d7d15182 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -922,7 +922,7 @@ int log_set_max_level_from_string(const char *e) { t = log_level_from_string(e); if (t < 0) - return t; + return -EINVAL; log_set_max_level(t); return 0; diff --git a/src/basic/prioq.c b/src/basic/prioq.c index b89888be0e..d55b348c22 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -19,6 +19,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +/* + * Priority Queue + * The prioq object implements a priority queue. That is, it orders objects by + * their priority and allows O(1) access to the object with the highest + * priority. Insertion and removal are Θ(log n). Optionally, the caller can + * provide a pointer to an index which will be kept up-to-date by the prioq. + * + * The underlying algorithm used in this implementation is a Heap. + */ + #include "util.h" #include "prioq.h" @@ -101,7 +111,7 @@ static unsigned shuffle_up(Prioq *q, unsigned idx) { k = (idx-1)/2; - if (q->compare_func(q->items[k].data, q->items[idx].data) < 0) + if (q->compare_func(q->items[k].data, q->items[idx].data) <= 0) break; swap(q, idx, k); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index cff2d2a034..d8a94a4572 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -215,7 +215,7 @@ int get_process_capeff(pid_t pid, char **capeff) { p = procfs_file_alloca(pid, "status"); - r = get_status_field(p, "\nCapEff:", capeff); + r = get_proc_field(p, "CapEff", WHITESPACE, capeff); if (r == -ENOENT) return -ESRCH; diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c index a39a0f775a..747e6f4dbb 100644 --- a/src/basic/selinux-util.c +++ b/src/basic/selinux-util.c @@ -295,14 +295,20 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char * return r; } -void mac_selinux_free(char *label) { +char* mac_selinux_free(char *label) { #ifdef HAVE_SELINUX + if (!label) + return NULL; + if (!mac_selinux_use()) - return; + return NULL; + freecon((security_context_t) label); #endif + + return NULL; } int mac_selinux_create_file_prepare(const char *path, mode_t mode) { diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h index 8467185291..2afcaec183 100644 --- a/src/basic/selinux-util.h +++ b/src/basic/selinux-util.h @@ -24,6 +24,8 @@ #include <sys/socket.h> #include <stdbool.h> +#include "macro.h" + bool mac_selinux_use(void); void mac_selinux_retest(void); @@ -36,7 +38,7 @@ int mac_selinux_apply(const char *path, const char *label); int mac_selinux_get_create_label_from_exe(const char *exe, char **label); int mac_selinux_get_our_label(char **label); int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label); -void mac_selinux_free(char *label); +char* mac_selinux_free(char *label); int mac_selinux_create_file_prepare(const char *path, mode_t mode); void mac_selinux_create_file_clear(void); @@ -45,3 +47,5 @@ int mac_selinux_create_socket_prepare(const char *label); void mac_selinux_create_socket_clear(void); int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); + +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, mac_selinux_free); diff --git a/src/basic/strv.c b/src/basic/strv.c index b9aef64b15..9524e80a6f 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -720,3 +720,28 @@ bool strv_fnmatch(char* const* patterns, const char *s, int flags) { return false; } + +char ***strv_free_free(char ***l) { + char ***i; + + if (!l) + return NULL; + + for (i = l; *i; i++) + strv_free(*i); + + free(l); + return NULL; +} + +char **strv_skip(char **l, size_t n) { + + while (n > 0) { + if (strv_isempty(l)) + return l; + + l++, n--; + } + + return l; +} diff --git a/src/basic/strv.h b/src/basic/strv.h index f07da8cdf3..4c4b6526de 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -154,3 +154,7 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i return strv_isempty(patterns) || strv_fnmatch(patterns, s, flags); } + +char ***strv_free_free(char ***l); + +char **strv_skip(char **l, size_t n); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index dd3d525854..287e0dfa13 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -48,7 +48,7 @@ int chvt(int vt) { if (fd < 0) return -errno; - if (vt < 0) { + if (vt <= 0) { int tiocl[2] = { TIOCL_GETKMSGREDIRECT, 0 diff --git a/src/basic/util.c b/src/basic/util.c index bc61ec0115..2bad33be1b 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -72,6 +72,7 @@ * otherwise conflicts with sys/mount.h. Yay, Linux is great! */ #include <linux/fs.h> +#include "build.h" #include "def.h" #include "device-nodes.h" #include "env-util.h" @@ -6201,15 +6202,6 @@ int ptsname_malloc(int fd, char **ret) { int openpt_in_namespace(pid_t pid, int flags) { _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; _cleanup_close_pair_ int pair[2] = { -1, -1 }; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int))]; - } control = {}; - struct msghdr mh = { - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg; siginfo_t si; pid_t child; int r; @@ -6243,15 +6235,7 @@ int openpt_in_namespace(pid_t pid, int flags) { if (unlockpt(master) < 0) _exit(EXIT_FAILURE); - cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), &master, sizeof(int)); - - mh.msg_controllen = cmsg->cmsg_len; - - if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0) + if (send_one_fd(pair[1], master, 0) < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); @@ -6265,26 +6249,7 @@ int openpt_in_namespace(pid_t pid, int flags) { if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) return -EIO; - if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0) - return -errno; - - CMSG_FOREACH(cmsg, &mh) - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - int *fds; - unsigned n_fds; - - fds = (int*) CMSG_DATA(cmsg); - n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); - - if (n_fds != 1) { - close_many(fds, n_fds); - return -EIO; - } - - return fds[0]; - } - - return -EIO; + return receive_one_fd(pair[0], 0); } ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) { @@ -6884,7 +6849,7 @@ int fgetxattr_malloc(int fd, const char *name, char **value) { } } -int send_one_fd(int transport_fd, int fd) { +int send_one_fd(int transport_fd, int fd, int flags) { union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; @@ -6894,7 +6859,6 @@ int send_one_fd(int transport_fd, int fd) { .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg; - ssize_t k; assert(transport_fd >= 0); assert(fd >= 0); @@ -6906,14 +6870,13 @@ int send_one_fd(int transport_fd, int fd) { memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); mh.msg_controllen = CMSG_SPACE(sizeof(int)); - k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL); - if (k < 0) + if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0) return -errno; return 0; } -int receive_one_fd(int transport_fd) { +int receive_one_fd(int transport_fd, int flags) { union { struct cmsghdr cmsghdr; uint8_t buf[CMSG_SPACE(sizeof(int))]; @@ -6922,33 +6885,45 @@ int receive_one_fd(int transport_fd) { .msg_control = &control, .msg_controllen = sizeof(control), }; - struct cmsghdr *cmsg; - ssize_t k; + struct cmsghdr *cmsg, *found = NULL; assert(transport_fd >= 0); /* - * Receive a single FD via @transport_fd. We don't care for the - * transport-type, but the caller must assure that no other CMSG types - * than SCM_RIGHTS is enabled. We also retrieve a single FD at most, so - * for packet-based transports, the caller must ensure to send only a - * single FD per packet. - * This is best used in combination with send_one_fd(). + * Receive a single FD via @transport_fd. We don't care for + * the transport-type. We retrieve a single FD at most, so for + * packet-based transports, the caller must ensure to send + * only a single FD per packet. This is best used in + * combination with send_one_fd(). */ - k = recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC); - if (k < 0) + if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0) return -errno; - cmsg = CMSG_FIRSTHDR(&mh); - if (!cmsg || CMSG_NXTHDR(&mh, cmsg) || - cmsg->cmsg_level != SOL_SOCKET || - cmsg->cmsg_type != SCM_RIGHTS || - cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || - *(const int *)CMSG_DATA(cmsg) < 0) { + CMSG_FOREACH(cmsg, &mh) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS && + cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + assert(!found); + found = cmsg; + break; + } + } + + if (!found) { cmsg_close_all(&mh); return -EIO; } - return *(const int *)CMSG_DATA(cmsg); + return *(int*) CMSG_DATA(found); +} + +void nop_signal_handler(int sig) { + /* nothing here */ +} + +int version(void) { + puts(PACKAGE_STRING "\n" + SYSTEMD_FEATURES); + return 0; } diff --git a/src/basic/util.h b/src/basic/util.h index 56d9f037bf..afd906477a 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -942,5 +942,9 @@ int reset_uid_gid(void); int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink); int fgetxattr_malloc(int fd, const char *name, char **value); -int send_one_fd(int transport_fd, int fd); -int receive_one_fd(int transport_fd); +int send_one_fd(int transport_fd, int fd, int flags); +int receive_one_fd(int transport_fd, int flags); + +void nop_signal_handler(int sig); + +int version(void); diff --git a/src/basic/virt.c b/src/basic/virt.c index 1fc6c1baba..70543177b6 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -240,7 +240,7 @@ static int detect_vm_zvm(void) { _cleanup_free_ char *t = NULL; int r; - r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t); + r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t); if (r == -ENOENT) return VIRTUALIZATION_NONE; if (r < 0) diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index 1e216f52bd..ddb5c88806 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -19,20 +19,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <errno.h> -#include <string.h> -#include <stdio.h> -#include <limits.h> #include <getopt.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "conf-files.h" +#include "fileio.h" #include "log.h" #include "strv.h" #include "util.h" -#include "conf-files.h" -#include "fileio.h" -#include "build.h" static const char conf_file_dirs[] = CONF_DIRS_NULSTR("binfmt"); @@ -143,9 +142,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case '?': return -EINVAL; diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index ac1711b318..f991e30cfa 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -20,28 +20,27 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> -#include <getopt.h> -#include <stdlib.h> #include <assert.h> -#include <sys/statfs.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/mman.h> -#include <dirent.h> +#include <blkid/blkid.h> #include <ctype.h> -#include <limits.h> +#include <dirent.h> +#include <errno.h> #include <ftw.h> +#include <getopt.h> +#include <limits.h> #include <stdbool.h> -#include <blkid/blkid.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/statfs.h> +#include <unistd.h> +#include "blkid-util.h" #include "efivars.h" -#include "build.h" -#include "util.h" #include "rm-rf.h" -#include "blkid-util.h" +#include "util.h" static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) { struct statfs sfs; @@ -967,8 +966,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - printf(VERSION "\n"); - return 0; + return version(); case ARG_PATH: arg_path = optarg; diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c index c66f12e3a6..db5fc863b0 100644 --- a/src/bootchart/svg.c +++ b/src/bootchart/svg.c @@ -30,6 +30,7 @@ #include <sys/utsname.h> #include <fcntl.h> +#include "architecture.h" #include "util.h" #include "fileio.h" #include "macro.h" @@ -147,7 +148,7 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start, _cleanup_free_ char *model = NULL; _cleanup_free_ char *buf = NULL; char date[256] = "Unknown"; - char *cpu; + const char *cpu; char *c; time_t t; int r; @@ -188,20 +189,11 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start, assert_se(r > 0); /* CPU type */ - r = read_full_file("/proc/cpuinfo", &buf, NULL); + r = get_proc_field("/proc/cpuinfo", PROC_CPUINFO_MODEL, "\n", &buf); if (r < 0) - return log_error_errno(r, "Unable to read cpuinfo: %m"); - - cpu = strstr(buf, "model name"); - if (!cpu) { - log_error("Unable to read module name from cpuinfo.\n"); - return -ENOENT; - } - - cpu += 13; - c = strchr(cpu, '\n'); - if (c) - *c = '\0'; + cpu = "Unknown"; + else + cpu = buf; fprintf(of, "<text class=\"t1\" x=\"0\" y=\"30\">Bootchart for %s - %s</text>\n", uts.nodename, date); diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 3cc3b33ae7..2bc265d9b4 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -22,26 +22,26 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/socket.h> -#include <unistd.h> -#include <string.h> #include <errno.h> -#include <sys/prctl.h> -#include <stddef.h> #include <getopt.h> #include <pthread.h> +#include <stddef.h> +#include <string.h> +#include <sys/prctl.h> +#include <sys/socket.h> +#include <unistd.h> -#include "log.h" -#include "util.h" #include "sd-daemon.h" + #include "bus-internal.h" -#include "build.h" -#include "strv.h" -#include "def.h" -#include "capability.h" #include "bus-xml-policy.h" -#include "proxy.h" +#include "capability.h" +#include "def.h" #include "formats-util.h" +#include "log.h" +#include "proxy.h" +#include "strv.h" +#include "util.h" static char *arg_address = NULL; static char **arg_configuration = NULL; @@ -215,9 +215,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_ADDRESS: r = free_and_strdup(&arg_address, optarg); diff --git a/src/bus-proxyd/stdio-bridge.c b/src/bus-proxyd/stdio-bridge.c index f275f6705f..168fc9ead0 100644 --- a/src/bus-proxyd/stdio-bridge.c +++ b/src/bus-proxyd/stdio-bridge.c @@ -21,23 +21,23 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> -#include <string.h> #include <errno.h> -#include <stddef.h> #include <getopt.h> +#include <stddef.h> +#include <string.h> +#include <unistd.h> -#include "log.h" -#include "util.h" #include "sd-daemon.h" #include "sd-bus.h" + #include "bus-internal.h" #include "bus-util.h" -#include "build.h" -#include "strv.h" #include "def.h" -#include "proxy.h" #include "formats-util.h" +#include "log.h" +#include "proxy.h" +#include "strv.h" +#include "util.h" static char *arg_address = NULL; static char *arg_command_line_buffer = NULL; @@ -86,9 +86,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_ADDRESS: { char *a; diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index ec4215f741..41c539a1bc 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -19,25 +19,25 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> -#include <unistd.h> #include <errno.h> #include <getopt.h> +#include <stdio.h> #include <string.h> +#include <unistd.h> + +#include "sd-bus.h" +#include "bus-error.h" +#include "bus-util.h" #include "cgroup-show.h" #include "cgroup-util.h" +#include "fileio.h" #include "log.h" -#include "path-util.h" -#include "util.h" -#include "pager.h" -#include "build.h" #include "output-mode.h" -#include "fileio.h" -#include "sd-bus.h" -#include "bus-util.h" -#include "bus-error.h" +#include "pager.h" +#include "path-util.h" #include "unit-name.h" +#include "util.h" static bool arg_no_pager = false; static bool arg_kernel_threads = false; @@ -89,9 +89,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_PAGER: arg_no_pager = true; @@ -147,7 +145,7 @@ static int get_cgroup_root(char **ret) { if (!path) return log_oom(); - r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); if (r < 0) return log_error_errno(r, "Failed to create bus connection: %m"); diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c index 612bc8fdec..b79519dd09 100644 --- a/src/cgroups-agent/cgroups-agent.c +++ b/src/cgroups-agent/cgroups-agent.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { * this to avoid an activation loop when we start dbus when we * are called when the dbus service is shut down. */ - r = bus_open_system_systemd(&bus); + r = bus_connect_system_systemd(&bus); if (r < 0) { /* If we couldn't connect we assume this was triggered * while systemd got restarted/transitioned from diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c index 9cf13cf57d..ad9cd2532f 100644 --- a/src/cgtop/cgtop.c +++ b/src/cgtop/cgtop.c @@ -19,27 +19,27 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> #include <alloca.h> +#include <errno.h> #include <getopt.h> #include <signal.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> -#include "path-util.h" -#include "terminal-util.h" -#include "process-util.h" -#include "util.h" -#include "hashmap.h" -#include "cgroup-util.h" -#include "build.h" -#include "fileio.h" #include "sd-bus.h" -#include "bus-util.h" + #include "bus-error.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "path-util.h" +#include "process-util.h" +#include "terminal-util.h" #include "unit-name.h" +#include "util.h" typedef struct Group { char *path; @@ -696,9 +696,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_CPU_TYPE: if (optarg) { @@ -863,7 +861,7 @@ static int get_cgroup_root(char **ret) { if (!path) return log_oom(); - r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); if (r < 0) return log_error_errno(r, "Failed to create bus connection: %m"); diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 868c8cc05a..adf613d328 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -595,6 +595,33 @@ static int property_get_address_families( return sd_bus_message_close_container(reply); } +static int property_get_working_directory( + 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 *wd; + + assert(bus); + assert(reply); + assert(c); + + if (c->working_directory_home) + wd = "~"; + else + wd = c->working_directory; + + if (c->working_directory_missing_ok) + wd = strjoina("!", wd); + + return sd_bus_message_append(reply, "s", wd); +} + 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), @@ -616,7 +643,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST), @@ -847,8 +874,7 @@ int bus_exec_context_set_transient_property( return 1; - } else if (STR_IN_SET(name, - "TTYPath", "WorkingDirectory", "RootDirectory")) { + } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) { const char *s; r = sd_bus_message_read(message, "s", &s); @@ -859,24 +885,51 @@ int bus_exec_context_set_transient_property( return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name); if (mode != UNIT_CHECK) { - char *t; + if (streq(name, "TTYPath")) + r = free_and_strdup(&c->tty_path, s); + else { + assert(streq(name, "RootDirectory")); + r = free_and_strdup(&c->root_directory, s); + } + if (r < 0) + return r; - t = strdup(s); - if (!t) - return -ENOMEM; + unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s); + } - if (streq(name, "TTYPath")) { - free(c->tty_path); - c->tty_path = t; - } else if (streq(name, "WorkingDirectory")) { - free(c->working_directory); - c->working_directory = t; - } else if (streq(name, "RootDirectory")) { - free(c->root_directory); - c->root_directory = t; + return 1; + + } else if (streq(name, "WorkingDirectory")) { + const char *s; + bool missing_ok; + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (s[0] == '-') { + missing_ok = true; + s++; + } else + missing_ok = false; + + if (!streq(s, "~") && !path_is_absolute(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'"); + + if (mode != UNIT_CHECK) { + if (streq(s, "~")) { + c->working_directory = mfree(c->working_directory); + c->working_directory_home = true; + } else { + r = free_and_strdup(&c->working_directory, s); + if (r < 0) + return r; + + c->working_directory_home = false; } - unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s); + c->working_directory_missing_ok = missing_ok; + unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s); } return 1; diff --git a/src/core/execute.c b/src/core/execute.c index 7796c07fcf..137a176c18 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1325,7 +1325,7 @@ static int exec_child( _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL; _cleanup_free_ char *mac_selinux_context_net = NULL; - const char *username = NULL, *home = NULL, *shell = NULL; + const char *username = NULL, *home = NULL, *shell = NULL, *wd; unsigned n_dont_close = 0; int dont_close[n_fds + 4]; uid_t uid = UID_INVALID; @@ -1698,6 +1698,13 @@ static int exec_child( } } + if (context->working_directory_home) + wd = home; + else if (context->working_directory) + wd = context->working_directory; + else + wd = "/"; + if (params->apply_chroot) { if (!needs_mount_namespace && context->root_directory) if (chroot(context->root_directory) < 0) { @@ -1705,21 +1712,15 @@ static int exec_child( return -errno; } - if (chdir(context->working_directory ?: "/") < 0 && + if (chdir(wd) < 0 && !context->working_directory_missing_ok) { *exit_status = EXIT_CHDIR; return -errno; } } else { - _cleanup_free_ char *d = NULL; - - if (asprintf(&d, "%s/%s", - context->root_directory ?: "", - context->working_directory ?: "") < 0) { - *exit_status = EXIT_MEMORY; - return -ENOMEM; - } + const char *d; + d = strjoina(strempty(context->root_directory), "/", strempty(wd)); if (chdir(d) < 0 && !context->working_directory_missing_ok) { *exit_status = EXIT_CHDIR; diff --git a/src/core/execute.h b/src/core/execute.h index a750246a89..2c93044748 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -103,6 +103,7 @@ struct ExecContext { struct rlimit *rlimit[_RLIMIT_MAX]; char *working_directory, *root_directory; bool working_directory_missing_ok; + bool working_directory_home; mode_t umask; int oom_score_adjust; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index fd293d8287..27159aa4c7 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -17,7 +17,7 @@ struct ConfigPerfItem; %% m4_dnl Define the context options only once m4_define(`EXEC_CONTEXT_CONFIG_ITEMS', -`$1.WorkingDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.working_directory) +`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context) $1.RootDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.root_directory) $1.User, config_parse_unit_string_printf, 0, offsetof($1, exec_context.user) $1.Group, config_parse_unit_string_printf, 0, offsetof($1, exec_context.group) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index a13f42b5e0..7045c31f2e 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -20,44 +20,42 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <linux/oom.h> #include <errno.h> -#include <string.h> #include <fcntl.h> -#include <sched.h> #include <linux/fs.h> -#include <sys/stat.h> +#include <linux/oom.h> +#include <sched.h> +#include <string.h> #include <sys/resource.h> - +#include <sys/stat.h> #ifdef HAVE_SECCOMP #include <seccomp.h> #endif -#include "unit.h" -#include "strv.h" +#include "af-list.h" +#include "bus-error.h" +#include "bus-internal.h" +#include "bus-util.h" +#include "cap-list.h" +#include "cgroup.h" #include "conf-parser.h" -#include "load-fragment.h" -#include "log.h" +#include "env-util.h" +#include "errno-list.h" #include "ioprio.h" -#include "securebits.h" +#include "log.h" #include "missing.h" -#include "unit-name.h" -#include "unit-printf.h" -#include "utf8.h" #include "path-util.h" -#include "env-util.h" -#include "cgroup.h" -#include "bus-util.h" -#include "bus-error.h" -#include "errno-list.h" -#include "af-list.h" -#include "cap-list.h" -#include "signal-util.h" -#include "bus-internal.h" - #ifdef HAVE_SECCOMP #include "seccomp-util.h" #endif +#include "securebits.h" +#include "signal-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit-printf.h" +#include "unit.h" +#include "utf8.h" +#include "load-fragment.h" int config_parse_warn_compat( const char *unit, @@ -195,16 +193,17 @@ int config_parse_unit_strv_printf(const char *unit, k ? k : rvalue, data, userdata); } -int config_parse_unit_path_printf(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_unit_path_printf( + 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) { _cleanup_free_ char *k = NULL; Unit *u = userdata; @@ -1846,6 +1845,70 @@ int config_parse_bus_endpoint_policy( return bus_endpoint_add_policy(c->bus_endpoint, name, access); } +int config_parse_working_directory( + 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; + Unit *u = userdata; + bool missing_ok; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(c); + assert(u); + + if (rvalue[0] == '-') { + missing_ok = true; + rvalue++; + } else + missing_ok = false; + + if (streq(rvalue, "~")) { + c->working_directory_home = true; + c->working_directory = mfree(c->working_directory); + } else { + _cleanup_free_ char *k = NULL; + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s', ignoring: %m", rvalue); + return 0; + } + + path_kill_slashes(k); + + if (!utf8_is_valid(k)) { + log_invalid_utf8(unit, LOG_ERR, filename, line, 0, rvalue); + return 0; + } + + if (!path_is_absolute(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Working directory path '%s' is not absolute, ignoring.", rvalue); + return 0; + } + + free(c->working_directory); + c->working_directory = k; + k = NULL; + + c->working_directory_home = false; + } + + c->working_directory_missing_ok = missing_ok; + return 0; +} + int config_parse_unit_env_file(const char *unit, const char *filename, unsigned line, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 5d0a09249f..6ee7c71bc4 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -106,6 +106,7 @@ int config_parse_protect_home(const char* unit, const char *filename, unsigned l int config_parse_protect_system(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_bus_name(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_utmp_mode(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_working_directory(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); /* gperf prototypes */ const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length); diff --git a/src/core/main.c b/src/core/main.c index bc72a2b00b..bac2043281 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -19,63 +19,63 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> #include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> +#include <fcntl.h> #include <getopt.h> #include <signal.h> -#include <fcntl.h> -#include <sys/prctl.h> +#include <stdio.h> +#include <string.h> #include <sys/mount.h> - -#ifdef HAVE_VALGRIND_VALGRIND_H -#include <valgrind/valgrind.h> -#endif +#include <sys/prctl.h> +#include <sys/reboot.h> +#include <sys/stat.h> +#include <unistd.h> #ifdef HAVE_SECCOMP #include <seccomp.h> #endif +#ifdef HAVE_VALGRIND_VALGRIND_H +#include <valgrind/valgrind.h> +#endif #include "sd-daemon.h" #include "sd-bus.h" -#include "log.h" -#include "fdset.h" -#include "special.h" -#include "conf-parser.h" -#include "missing.h" -#include "pager.h" -#include "build.h" -#include "strv.h" -#include "def.h" -#include "virt.h" + #include "architecture.h" -#include "watchdog.h" -#include "switch-root.h" +#include "build.h" +#include "bus-error.h" +#include "bus-util.h" #include "capability.h" -#include "killall.h" -#include "env-util.h" #include "clock-util.h" +#include "conf-parser.h" +#include "dbus-manager.h" +#include "def.h" +#include "env-util.h" +#include "fdset.h" #include "fileio.h" -#include "bus-error.h" -#include "bus-util.h" -#include "selinux-util.h" #include "formats-util.h" -#include "process-util.h" -#include "terminal-util.h" -#include "signal-util.h" -#include "manager.h" -#include "dbus-manager.h" +#include "hostname-setup.h" +#include "ima-setup.h" +#include "killall.h" +#include "kmod-setup.h" #include "load-fragment.h" - -#include "mount-setup.h" +#include "log.h" #include "loopback-setup.h" -#include "hostname-setup.h" #include "machine-id-setup.h" +#include "manager.h" +#include "missing.h" +#include "mount-setup.h" +#include "pager.h" +#include "process-util.h" #include "selinux-setup.h" -#include "ima-setup.h" +#include "selinux-util.h" +#include "signal-util.h" #include "smack-setup.h" -#include "kmod-setup.h" +#include "special.h" +#include "strv.h" +#include "switch-root.h" +#include "terminal-util.h" +#include "virt.h" +#include "watchdog.h" static enum { ACTION_RUN, @@ -88,8 +88,9 @@ static enum { static char *arg_default_unit = NULL; static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID; static bool arg_dump_core = true; -static bool arg_crash_shell = false; static int arg_crash_chvt = -1; +static bool arg_crash_shell = false; +static bool arg_crash_reboot = false; static bool arg_confirm_spawn = false; static ShowStatus arg_show_status = _SHOW_STATUS_UNSET; static bool arg_switched_root = false; @@ -116,8 +117,6 @@ static bool arg_default_blockio_accounting = false; static bool arg_default_memory_accounting = false; static bool arg_default_tasks_accounting = false; -static void nop_handler(int sig) {} - static void pager_open_if_enabled(void) { if (arg_no_pager <= 0) @@ -126,49 +125,65 @@ static void pager_open_if_enabled(void) { pager_open(false); } +noreturn static void freeze_or_reboot(void) { + + if (arg_crash_reboot) { + log_notice("Rebooting in 10s..."); + (void) sleep(10); + + log_notice("Rebooting now..."); + (void) reboot(RB_AUTOBOOT); + log_emergency_errno(errno, "Failed to reboot: %m"); + } + + log_emergency("Freezing execution."); + freeze(); +} + noreturn static void crash(int sig) { if (getpid() != 1) /* Pass this on immediately, if this is not PID 1 */ - raise(sig); + (void) raise(sig); else if (!arg_dump_core) log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig)); else { struct sigaction sa = { - .sa_handler = nop_handler, + .sa_handler = nop_signal_handler, .sa_flags = SA_NOCLDSTOP|SA_RESTART, }; pid_t pid; /* We want to wait for the core process, hence let's enable SIGCHLD */ - sigaction(SIGCHLD, &sa, NULL); + (void) sigaction(SIGCHLD, &sa, NULL); pid = raw_clone(SIGCHLD, NULL); if (pid < 0) log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig)); - else if (pid == 0) { - struct rlimit rl = {}; + struct rlimit rl = { + .rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY, + }; /* Enable default signal handler for core dump */ - zero(sa); - sa.sa_handler = SIG_DFL; - sigaction(sig, &sa, NULL); + sa = (struct sigaction) { + .sa_handler = SIG_DFL, + }; + (void) sigaction(sig, &sa, NULL); /* Don't limit the core dump size */ - rl.rlim_cur = RLIM_INFINITY; - rl.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CORE, &rl); + (void) setrlimit(RLIMIT_CORE, &rl); /* Just to be sure... */ (void) chdir("/"); /* Raise the signal again */ pid = raw_getpid(); - kill(pid, sig); /* raise() would kill the parent */ + (void) kill(pid, sig); /* raise() would kill the parent */ assert_not_reached("We shouldn't be here..."); - _exit(1); + _exit(EXIT_FAILURE); } else { siginfo_t status; int r; @@ -190,8 +205,8 @@ noreturn static void crash(int sig) { } } - if (arg_crash_chvt) - chvt(arg_crash_chvt); + if (arg_crash_chvt >= 0) + (void) chvt(arg_crash_chvt); if (arg_crash_shell) { struct sigaction sa = { @@ -200,27 +215,30 @@ noreturn static void crash(int sig) { }; pid_t pid; - log_info("Executing crash shell in 10s..."); - sleep(10); + log_notice("Executing crash shell in 10s..."); + (void) sleep(10); /* Let the kernel reap children for us */ - assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); + (void) sigaction(SIGCHLD, &sa, NULL); pid = raw_clone(SIGCHLD, NULL); if (pid < 0) log_emergency_errno(errno, "Failed to fork off crash shell: %m"); else if (pid == 0) { - make_console_stdio(); - execle("/bin/sh", "/bin/sh", NULL, environ); + (void) setsid(); + (void) make_console_stdio(); + (void) execle("/bin/sh", "/bin/sh", NULL, environ); log_emergency_errno(errno, "execle() failed: %m"); - _exit(1); - } else - log_info("Successfully spawned crash shell as PID "PID_FMT".", pid); + freeze_or_reboot(); + _exit(EXIT_FAILURE); + } else { + log_info("Spawned crash shell as PID "PID_FMT".", pid); + freeze(); + } } - log_emergency("Freezing execution."); - freeze(); + freeze_or_reboot(); } static void install_crash_handler(void) { @@ -254,17 +272,20 @@ static int console_setup(void) { return 0; } -static int set_default_unit(const char *u) { - char *c; +static int parse_crash_chvt(const char *value) { + int b; - assert(u); + if (safe_atoi(value, &arg_crash_chvt) >= 0) + return 0; - c = strdup(u); - if (!c) - return -ENOMEM; + b = parse_boolean(value); + if (b < 0) + return b; - free(arg_default_unit); - arg_default_unit = c; + if (b > 0) + arg_crash_chvt = 0; /* switch to where kmsg goes */ + else + arg_crash_chvt = -1; /* turn off switching */ return 0; } @@ -292,12 +313,12 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { if (streq(key, "systemd.unit") && value) { if (!in_initrd()) - return set_default_unit(value); + return free_and_strdup(&arg_default_unit, value); } else if (streq(key, "rd.systemd.unit") && value) { if (in_initrd()) - return set_default_unit(value); + return free_and_strdup(&arg_default_unit, value); } else if (streq(key, "systemd.dump_core") && value) { @@ -307,6 +328,11 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { else arg_dump_core = r; + } else if (streq(key, "systemd.crash_chvt") && value) { + + if (parse_crash_chvt(value) < 0) + log_warning("Failed to parse crash chvt switch %s. Ignoring.", value); + } else if (streq(key, "systemd.crash_shell") && value) { r = parse_boolean(value); @@ -315,12 +341,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { else arg_crash_shell = r; - } else if (streq(key, "systemd.crash_chvt") && value) { + } else if (streq(key, "systemd.crash_reboot") && value) { - if (safe_atoi(value, &r) < 0) - log_warning("Failed to parse crash chvt switch %s. Ignoring.", value); + r = parse_boolean(value); + if (r < 0) + log_warning("Failed to parse crash reboot switch %s. Ignoring.", value); else - arg_crash_chvt = r; + arg_crash_reboot = r; } else if (streq(key, "systemd.confirm_spawn") && value) { @@ -384,7 +411,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { /* SysV compatibility */ for (i = 0; i < ELEMENTSOF(rlmap); i += 2) if (streq(key, rlmap[i])) - return set_default_unit(rlmap[i+1]); + return free_and_strdup(&arg_default_unit, rlmap[i+1]); } return 0; @@ -410,9 +437,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { \ r = func(rvalue); \ if (r < 0) \ - log_syntax(unit, LOG_ERR, filename, line, -r, \ - "Invalid " descr "'%s': %s", \ - rvalue, strerror(-r)); \ + log_syntax(unit, LOG_ERR, filename, line, r, \ + "Invalid " descr "'%s': %m", \ + rvalue); \ \ return 0; \ } @@ -478,21 +505,32 @@ static int config_parse_show_status( return 0; } -static void strv_free_free(char ***l) { - char ***i; +static int config_parse_crash_chvt( + 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) { - if (!l) - return; + int r; - for (i = l; *i; i++) - strv_free(*i); + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); - free(l); -} + r = parse_crash_chvt(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue); + return 0; + } -static void free_join_controllers(void) { - strv_free_free(arg_join_controllers); - arg_join_controllers = NULL; + return 0; } static int config_parse_join_controllers(const char *unit, @@ -513,7 +551,7 @@ static int config_parse_join_controllers(const char *unit, assert(lvalue); assert(rvalue); - free_join_controllers(); + arg_join_controllers = strv_free_free(arg_join_controllers); for (;;) { _cleanup_free_ char *word = NULL; @@ -530,7 +568,7 @@ static int config_parse_join_controllers(const char *unit, l = strv_split(word, ","); if (!l) - log_oom(); + return log_oom(); strv_uniq(l); if (strv_length(l) <= 1) { @@ -605,9 +643,11 @@ static int parse_config_file(void) { { "Manager", "LogColor", config_parse_color, 0, NULL }, { "Manager", "LogLocation", config_parse_location, 0, NULL }, { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core }, + { "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, NULL }, + { "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, NULL }, { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell }, + { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot }, { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, - { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt }, { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL }, { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, @@ -695,7 +735,9 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION, ARG_DUMP_CONFIGURATION_ITEMS, ARG_DUMP_CORE, + ARG_CRASH_CHVT, ARG_CRASH_SHELL, + ARG_CRASH_REBOOT, ARG_CONFIRM_SPAWN, ARG_SHOW_STATUS, ARG_DESERIALIZE, @@ -718,7 +760,9 @@ static int parse_argv(int argc, char *argv[]) { { "version", no_argument, NULL, ARG_VERSION }, { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, { "dump-core", optional_argument, NULL, ARG_DUMP_CORE }, + { "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT }, { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL }, + { "crash-reboot", optional_argument, NULL, ARG_CRASH_REBOOT }, { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN }, { "show-status", optional_argument, NULL, ARG_SHOW_STATUS }, { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, @@ -803,7 +847,7 @@ static int parse_argv(int argc, char *argv[]) { case ARG_UNIT: - r = set_default_unit(optarg); + r = free_and_strdup(&arg_default_unit, optarg); if (r < 0) return log_error_errno(r, "Failed to set default unit %s: %m", optarg); @@ -836,21 +880,42 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_DUMP_CORE: - r = optarg ? parse_boolean(optarg) : 1; - if (r < 0) { - log_error("Failed to parse dump core boolean %s.", optarg); - return r; + if (!optarg) + arg_dump_core = true; + else { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse dump core boolean: %s", optarg); + arg_dump_core = r; } - arg_dump_core = r; + break; + + case ARG_CRASH_CHVT: + r = parse_crash_chvt(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse crash virtual terminal index: %s", optarg); break; case ARG_CRASH_SHELL: - r = optarg ? parse_boolean(optarg) : 1; - if (r < 0) { - log_error("Failed to parse crash shell boolean %s.", optarg); - return r; + if (!optarg) + arg_crash_shell = true; + else { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse crash shell boolean: %s", optarg); + arg_crash_shell = r; + } + break; + + case ARG_CRASH_REBOOT: + if (!optarg) + arg_crash_reboot = true; + else { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse crash shell boolean: %s", optarg); + arg_crash_reboot = r; } - arg_crash_shell = r; break; case ARG_CONFIRM_SPAWN: @@ -880,17 +945,16 @@ static int parse_argv(int argc, char *argv[]) { r = safe_atoi(optarg, &fd); if (r < 0 || fd < 0) { log_error("Failed to parse deserialize option %s.", optarg); - return r < 0 ? r : -EINVAL; + return -EINVAL; } - fd_cloexec(fd, true); + (void) fd_cloexec(fd, true); f = fdopen(fd, "r"); if (!f) return log_error_errno(errno, "Failed to open serialization fd: %m"); safe_fclose(arg_serialization); - arg_serialization = f; break; @@ -950,14 +1014,16 @@ static int help(void) { " --unit=UNIT Set default unit\n" " --system Run a system instance, even if PID != 1\n" " --user Run a user instance\n" - " --dump-core[=0|1] Dump core on crash\n" - " --crash-shell[=0|1] Run shell on crash\n" - " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n" - " --show-status[=0|1] Show status updates on the console during bootup\n" + " --dump-core[=BOOL] Dump core on crash\n" + " --crash-vt=NR Change to specified VT on crash\n" + " --crash-reboot[=BOOL] Reboot on crash\n" + " --crash-shell[=BOOL] Run shell on crash\n" + " --confirm-spawn[=BOOL] Ask for confirmation when spawning processes\n" + " --show-status[=BOOL] Show status updates on the console during bootup\n" " --log-target=TARGET Set log target (console, journal, kmsg, journal-or-kmsg, null)\n" " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n" - " --log-color[=0|1] Highlight important log messages\n" - " --log-location[=0|1] Include code location in log messages\n" + " --log-color[=BOOL] Highlight important log messages\n" + " --log-location[=BOOL] Include code location in log messages\n" " --default-standard-output= Set default standard output for services\n" " --default-standard-error= Set default standard error output for services\n", program_invocation_short_name); @@ -965,16 +1031,9 @@ static int help(void) { return 0; } -static int version(void) { - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - - return 0; -} - static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching_root) { - FILE *f = NULL; - FDSet *fds = NULL; + _cleanup_fdset_free_ FDSet *fds = NULL; + _cleanup_fclose_ FILE *f = NULL; int r; assert(m); @@ -982,56 +1041,39 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching assert(_fds); r = manager_open_serialization(m, &f); - if (r < 0) { - log_error_errno(r, "Failed to create serialization file: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to create serialization file: %m"); /* Make sure nothing is really destructed when we shut down */ m->n_reloading ++; bus_manager_send_reloading(m, true); fds = fdset_new(); - if (!fds) { - r = -ENOMEM; - log_error_errno(r, "Failed to allocate fd set: %m"); - goto fail; - } + if (!fds) + return log_oom(); r = manager_serialize(m, f, fds, switching_root); - if (r < 0) { - log_error_errno(r, "Failed to serialize state: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to serialize state: %m"); - if (fseeko(f, 0, SEEK_SET) < 0) { - log_error_errno(errno, "Failed to rewind serialization fd: %m"); - goto fail; - } + if (fseeko(f, 0, SEEK_SET) == (off_t) -1) + return log_error_errno(errno, "Failed to rewind serialization fd: %m"); r = fd_cloexec(fileno(f), false); - if (r < 0) { - log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m"); r = fdset_cloexec(fds, false); - if (r < 0) { - log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); - goto fail; - } + if (r < 0) + return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); *_f = f; *_fds = fds; - return 0; - -fail: - fdset_free(fds); - - safe_fclose(f); + f = NULL; + fds = NULL; - return r; + return 0; } static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { @@ -1090,7 +1132,7 @@ static void test_mtab(void) { log_error("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. " "This is not supported anymore. " "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output."); - freeze(); + freeze_or_reboot(); } static void test_usr(void) { @@ -1116,15 +1158,19 @@ static int initialize_join_controllers(void) { return -ENOMEM; arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL); - arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL); - arg_join_controllers[2] = NULL; + if (!arg_join_controllers[0]) + goto oom; - if (!arg_join_controllers[0] || !arg_join_controllers[1]) { - free_join_controllers(); - return -ENOMEM; - } + arg_join_controllers[1] = strv_new("net_cls", "net_prio", NULL); + if (!arg_join_controllers[1]) + goto oom; + arg_join_controllers[2] = NULL; return 0; + +oom: + arg_join_controllers = strv_free_free(arg_join_controllers); + return -ENOMEM; } static int enforce_syscall_archs(Set *archs) { @@ -1222,7 +1268,6 @@ int main(int argc, char *argv[]) { char *switch_root_dir = NULL, *switch_root_init = NULL; struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0); const char *error_message = NULL; - uint8_t shutdown_exit_code = 0; #ifdef HAVE_SYSV_COMPAT if (getpid() != 1 && strstr(program_invocation_short_name, "init")) { @@ -1369,7 +1414,7 @@ int main(int argc, char *argv[]) { } /* Initialize default unit */ - r = set_default_unit(SPECIAL_DEFAULT_TARGET); + r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET); if (r < 0) { log_emergency_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET); error_message = "Failed to set default unit"; @@ -1646,8 +1691,7 @@ int main(int argc, char *argv[]) { /* This will close all file descriptors that were opened, but * not claimed by any unit. */ - fdset_free(fds); - fds = NULL; + fds = fdset_free(fds); arg_serialization = safe_fclose(arg_serialization); @@ -1775,8 +1819,9 @@ int main(int argc, char *argv[]) { goto finish; case MANAGER_EXIT: + retval = m->return_value; + if (m->running_as == MANAGER_USER) { - retval = EXIT_SUCCESS; log_debug("Exit."); goto finish; } @@ -1809,21 +1854,17 @@ int main(int argc, char *argv[]) { finish: pager_close(); - if (m) { + if (m) arg_shutdown_watchdog = m->shutdown_watchdog; - shutdown_exit_code = m->return_value; - } + m = manager_free(m); for (j = 0; j < ELEMENTSOF(arg_default_rlimit); j++) arg_default_rlimit[j] = mfree(arg_default_rlimit[j]); arg_default_unit = mfree(arg_default_unit); - - free_join_controllers(); - + arg_join_controllers = strv_free_free(arg_join_controllers); arg_default_environment = strv_free(arg_default_environment); - arg_syscall_archs = set_free(arg_syscall_archs); mac_selinux_finish(); @@ -1841,7 +1882,7 @@ finish: * that the new systemd can pass the kernel default to * its child processes */ if (saved_rlimit_nofile.rlim_cur > 0) - setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile); + (void) setrlimit(RLIMIT_NOFILE, &saved_rlimit_nofile); if (switch_root_dir) { /* Kill all remaining processes from the @@ -1883,10 +1924,10 @@ finish: /* do not pass along the environment we inherit from the kernel or initrd */ if (switch_root_dir) - clearenv(); + (void) clearenv(); assert(i <= args_size); - execv(args[0], (char* const*) args); + (void) execv(args[0], (char* const*) args); } /* Try the fallback, if there is any, without any @@ -1896,14 +1937,10 @@ finish: * but let's hope that doesn't matter.) */ arg_serialization = safe_fclose(arg_serialization); - - if (fds) { - fdset_free(fds); - fds = NULL; - } + fds = fdset_free(fds); /* Reopen the console */ - make_console_stdio(); + (void) make_console_stdio(); for (j = 1, i = 1; j < (unsigned) argc; j++) args[i++] = argv[j]; @@ -1917,30 +1954,26 @@ finish: if (switch_root_init) { args[0] = switch_root_init; - execv(args[0], (char* const*) args); + (void) execv(args[0], (char* const*) args); log_warning_errno(errno, "Failed to execute configured init, trying fallback: %m"); } args[0] = "/sbin/init"; - execv(args[0], (char* const*) args); + (void) execv(args[0], (char* const*) args); if (errno == ENOENT) { log_warning("No /sbin/init, trying fallback"); args[0] = "/bin/sh"; args[1] = NULL; - execv(args[0], (char* const*) args); + (void) execv(args[0], (char* const*) args); log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m"); } else log_warning_errno(errno, "Failed to execute /sbin/init, giving up: %m"); } arg_serialization = safe_fclose(arg_serialization); - - if (fds) { - fdset_free(fds); - fds = NULL; - } + fds = fdset_free(fds); #ifdef HAVE_VALGRIND_VALGRIND_H /* If we are PID 1 and running under valgrind, then let's exit @@ -1969,6 +2002,7 @@ finish: xsprintf(log_level, "%d", log_get_max_level()); switch (log_get_target()) { + case LOG_TARGET_KMSG: case LOG_TARGET_JOURNAL_OR_KMSG: case LOG_TARGET_SYSLOG_OR_KMSG: @@ -1994,7 +2028,7 @@ finish: if (streq(shutdown_verb, "exit")) { command_line[pos++] = "--exit-code"; command_line[pos++] = exit_code; - xsprintf(exit_code, "%d", shutdown_exit_code); + xsprintf(exit_code, "%d", retval); } assert(pos < ELEMENTSOF(command_line)); @@ -2010,7 +2044,7 @@ finish: /* Tell the binary how often to ping, ignore failure */ if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, arg_shutdown_watchdog) > 0) - strv_push(&env_block, e); + (void) strv_push(&env_block, e); } else watchdog_close(true); @@ -2030,7 +2064,7 @@ finish: manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL, "%s, freezing.", error_message); - freeze(); + freeze_or_reboot(); } return retval; diff --git a/src/core/manager.c b/src/core/manager.c index 9bfe867ea0..9de9691a47 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -19,19 +19,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <dirent.h> #include <errno.h> -#include <string.h> +#include <fcntl.h> +#include <linux/kd.h> #include <signal.h> -#include <sys/wait.h> -#include <unistd.h> -#include <sys/inotify.h> +#include <string.h> #include <sys/epoll.h> -#include <sys/reboot.h> +#include <sys/inotify.h> #include <sys/ioctl.h> -#include <linux/kd.h> -#include <fcntl.h> -#include <dirent.h> +#include <sys/reboot.h> #include <sys/timerfd.h> +#include <sys/wait.h> +#include <unistd.h> #ifdef HAVE_AUDIT #include <libaudit.h> @@ -40,40 +40,40 @@ #include "sd-daemon.h" #include "sd-messages.h" +#include "audit-fd.h" +#include "boot-timestamps.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-kernel.h" +#include "bus-util.h" +#include "dbus-job.h" +#include "dbus-manager.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "env-util.h" +#include "exit-status.h" #include "hashmap.h" -#include "macro.h" -#include "strv.h" +#include "locale-setup.h" #include "log.h" -#include "util.h" +#include "macro.h" +#include "missing.h" #include "mkdir.h" +#include "path-lookup.h" +#include "path-util.h" +#include "process-util.h" #include "ratelimit.h" -#include "locale-setup.h" -#include "unit-name.h" -#include "missing.h" #include "rm-rf.h" -#include "path-lookup.h" +#include "signal-util.h" #include "special.h" -#include "exit-status.h" +#include "strv.h" +#include "terminal-util.h" +#include "time-util.h" +#include "transaction.h" +#include "unit-name.h" +#include "util.h" #include "virt.h" #include "watchdog.h" -#include "path-util.h" -#include "audit-fd.h" -#include "boot-timestamps.h" -#include "env-util.h" -#include "bus-common-errors.h" -#include "bus-error.h" -#include "bus-util.h" -#include "bus-kernel.h" -#include "time-util.h" -#include "process-util.h" -#include "terminal-util.h" -#include "signal-util.h" -#include "dbus.h" -#include "dbus-unit.h" -#include "dbus-job.h" -#include "dbus-manager.h" #include "manager.h" -#include "transaction.h" /* Initial delay and the interval for printing status messages about running jobs */ #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) diff --git a/src/core/manager.h b/src/core/manager.h index cc0e5e3361..fad10aaacf 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -27,8 +27,8 @@ #include "sd-bus.h" #include "sd-event.h" -#include "fdset.h" #include "cgroup-util.h" +#include "fdset.h" #include "hashmap.h" #include "list.h" #include "ratelimit.h" @@ -69,11 +69,11 @@ typedef enum StatusType { STATUS_TYPE_EMERGENCY, } StatusType; +#include "execute.h" #include "job.h" #include "path-lookup.h" -#include "execute.h" -#include "unit-name.h" #include "show-status.h" +#include "unit-name.h" struct Manager { /* Note that the set of units we know of is allowed to be diff --git a/src/core/namespace.c b/src/core/namespace.c index eb88574f8f..2b8b707df5 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -643,16 +643,7 @@ int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) { int setup_netns(int netns_storage_socket[2]) { _cleanup_close_ int netns = -1; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int))]; - } control = {}; - struct msghdr mh = { - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg; - int r; + int r, q; assert(netns_storage_socket); assert(netns_storage_socket[0] >= 0); @@ -669,12 +660,8 @@ int setup_netns(int netns_storage_socket[2]) { if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0) return -errno; - if (recvmsg(netns_storage_socket[0], &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) < 0) { - if (errno != EAGAIN) { - r = -errno; - goto fail; - } - + netns = receive_one_fd(netns_storage_socket[0], MSG_DONTWAIT); + if (netns == -EAGAIN) { /* Nothing stored yet, so let's create a new namespace */ if (unshare(CLONE_NEWNET) < 0) { @@ -691,15 +678,13 @@ int setup_netns(int netns_storage_socket[2]) { } r = 1; - } else { - /* Yay, found something, so let's join the namespace */ - CMSG_FOREACH(cmsg, &mh) - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int))); - netns = *(int*) CMSG_DATA(cmsg); - } + } else if (netns < 0) { + r = netns; + goto fail; + } else { + /* Yay, found something, so let's join the namespace */ if (setns(netns, CLONE_NEWNET) < 0) { r = -errno; goto fail; @@ -708,21 +693,14 @@ int setup_netns(int netns_storage_socket[2]) { r = 0; } - cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), &netns, sizeof(int)); - mh.msg_controllen = cmsg->cmsg_len; - - if (sendmsg(netns_storage_socket[1], &mh, MSG_DONTWAIT|MSG_NOSIGNAL) < 0) { - r = -errno; + q = send_one_fd(netns_storage_socket[1], netns, MSG_DONTWAIT); + if (q < 0) { + r = q; goto fail; } fail: lockf(netns_storage_socket[0], F_ULOCK, 0); - return r; } diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c index e5b457643b..ff1ea23528 100644 --- a/src/core/selinux-setup.c +++ b/src/core/selinux-setup.c @@ -78,14 +78,14 @@ int mac_selinux_setup(bool *loaded_policy) { before_load = now(CLOCK_MONOTONIC); r = selinux_init_load_policy(&enforce); if (r == 0) { + _cleanup_(mac_selinux_freep) char *label = NULL; char timespan[FORMAT_TIMESPAN_MAX]; - char *label; mac_selinux_retest(); /* Transition to the new context */ r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label); - if (r < 0 || label == NULL) { + if (r < 0 || !label) { log_open(); log_error("Failed to compute init label, ignoring."); } else { @@ -94,8 +94,6 @@ int mac_selinux_setup(bool *loaded_policy) { log_open(); if (r < 0) log_error("Failed to transition into init label '%s', ignoring.", label); - - mac_selinux_free(label); } after_load = now(CLOCK_MONOTONIC); diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 5296efce1d..27c581d9c1 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -430,6 +430,5 @@ int main(int argc, char *argv[]) { error: log_emergency_errno(r, "Critical error while doing system shutdown: %m"); - freeze(); } diff --git a/src/core/socket.c b/src/core/socket.c index 69cca2fcdf..d242b10758 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -19,38 +19,39 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/stat.h> -#include <unistd.h> +#include <arpa/inet.h> #include <errno.h> #include <fcntl.h> -#include <sys/epoll.h> -#include <signal.h> -#include <arpa/inet.h> -#include <netinet/tcp.h> #include <mqueue.h> +#include <netinet/tcp.h> +#include <signal.h> +#include <sys/epoll.h> +#include <sys/stat.h> +#include <unistd.h> #include "sd-event.h" + +#include "bus-error.h" +#include "bus-util.h" +#include "copy.h" +#include "dbus-socket.h" +#include "def.h" +#include "exit-status.h" +#include "formats-util.h" +#include "label.h" #include "log.h" -#include "strv.h" +#include "missing.h" #include "mkdir.h" #include "path-util.h" -#include "unit-name.h" -#include "unit-printf.h" -#include "missing.h" -#include "special.h" -#include "label.h" -#include "exit-status.h" -#include "def.h" -#include "smack-util.h" -#include "bus-util.h" -#include "bus-error.h" #include "selinux-util.h" -#include "dbus-socket.h" -#include "unit.h" -#include "formats-util.h" #include "signal-util.h" +#include "smack-util.h" #include "socket.h" -#include "copy.h" +#include "special.h" +#include "strv.h" +#include "unit-name.h" +#include "unit-printf.h" +#include "unit.h" static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = UNIT_INACTIVE, @@ -955,50 +956,48 @@ static void socket_apply_fifo_options(Socket *s, int fd) { if (s->pipe_size > 0) if (fcntl(fd, F_SETPIPE_SZ, s->pipe_size) < 0) - log_unit_warning_errno(UNIT(s), errno, "F_SETPIPE_SZ: %m"); + log_unit_warning_errno(UNIT(s), errno, "Setting pipe size failed, ignoring: %m"); if (s->smack) { r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, s->smack); if (r < 0) - log_unit_error_errno(UNIT(s), r, "mac_smack_apply_fd: %m"); + log_unit_error_errno(UNIT(s), r, "SMACK relabelling failed, ignoring: %m"); } } static int fifo_address_create( const char *path, mode_t directory_mode, - mode_t socket_mode, - int *_fd) { + mode_t socket_mode) { - int fd = -1, r = 0; - struct stat st; + _cleanup_close_ int fd = -1; mode_t old_mask; + struct stat st; + int r; assert(path); - assert(_fd); mkdir_parents_label(path, directory_mode); r = mac_selinux_create_file_prepare(path, S_IFIFO); if (r < 0) - goto fail; + return r; /* Enforce the right access mode for the fifo */ old_mask = umask(~ socket_mode); /* Include the original umask in our mask */ - umask(~socket_mode | old_mask); + (void) umask(~socket_mode | old_mask); r = mkfifo(path, socket_mode); - umask(old_mask); + (void) umask(old_mask); if (r < 0 && errno != EEXIST) { r = -errno; goto fail; } - fd = open(path, - O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW); + fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW); if (fd < 0) { r = -errno; goto fail; @@ -1015,13 +1014,14 @@ static int fifo_address_create( (st.st_mode & 0777) != (socket_mode & ~old_mask) || st.st_uid != getuid() || st.st_gid != getgid()) { - r = -EEXIST; goto fail; } - *_fd = fd; - return 0; + r = fd; + fd = -1; + + return r; fail: mac_selinux_create_file_clear(); @@ -1030,51 +1030,36 @@ fail: return r; } -static int special_address_create( - const char *path, - int *_fd) { - - int fd = -1, r = 0; +static int special_address_create(const char *path) { + _cleanup_close_ int fd = -1; struct stat st; + int r; assert(path); - assert(_fd); fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW); - if (fd < 0) { - r = -errno; - goto fail; - } + if (fd < 0) + return -errno; - if (fstat(fd, &st) < 0) { - r = -errno; - goto fail; - } + if (fstat(fd, &st) < 0) + return -errno; /* Check whether this is a /proc, /sys or /dev file or char device */ - if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) { - r = -EEXIST; - goto fail; - } - - *_fd = fd; - return 0; + if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) + return -EEXIST; -fail: - safe_close(fd); + r = fd; + fd = -1; return r; } -static int ffs_address_create( - const char *path, - int *_fd) { - +static int usbffs_address_create(const char *path) { _cleanup_close_ int fd = -1; struct stat st; + int r; assert(path); - assert(_fd); fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW); if (fd < 0) @@ -1087,32 +1072,32 @@ static int ffs_address_create( if (!S_ISREG(st.st_mode)) return -EEXIST; - *_fd = fd; + r = fd; fd = -1; - return 0; + return r; } static int mq_address_create( const char *path, mode_t mq_mode, long maxmsg, - long msgsize, - int *_fd) { + long msgsize) { - int fd = -1, r = 0; + _cleanup_close_ int fd = -1; struct stat st; mode_t old_mask; struct mq_attr _attr, *attr = NULL; + int r; assert(path); - assert(_fd); if (maxmsg > 0 && msgsize > 0) { - zero(_attr); - _attr.mq_flags = O_NONBLOCK; - _attr.mq_maxmsg = maxmsg; - _attr.mq_msgsize = msgsize; + _attr = (struct mq_attr) { + .mq_flags = O_NONBLOCK, + .mq_maxmsg = maxmsg, + .mq_msgsize = msgsize, + }; attr = &_attr; } @@ -1120,33 +1105,24 @@ static int mq_address_create( old_mask = umask(~ mq_mode); /* Include the original umask in our mask */ - umask(~mq_mode | old_mask); + (void) umask(~mq_mode | old_mask); fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr); - umask(old_mask); + (void) umask(old_mask); - if (fd < 0) { - r = -errno; - goto fail; - } + if (fd < 0) + return -errno; - if (fstat(fd, &st) < 0) { - r = -errno; - goto fail; - } + if (fstat(fd, &st) < 0) + return -errno; if ((st.st_mode & 0777) != (mq_mode & ~old_mask) || st.st_uid != getuid() || - st.st_gid != getgid()) { - - r = -EEXIST; - goto fail; - } + st.st_gid != getgid()) + return -EEXIST; - *_fd = fd; - return 0; + r = fd; + fd = -1; -fail: - safe_close(fd); return r; } @@ -1166,8 +1142,7 @@ static int socket_symlink(Socket *s) { return 0; } -static int ffs_write_descs(int fd, Unit *u) { - Service *s = SERVICE(u); +static int usbffs_write_descs(int fd, Service *s) { int r; if (!s->usb_function_descriptors || !s->usb_function_strings) @@ -1175,27 +1150,25 @@ static int ffs_write_descs(int fd, Unit *u) { r = copy_file_fd(s->usb_function_descriptors, fd, false); if (r < 0) - return 0; - - r = copy_file_fd(s->usb_function_strings, fd, false); + return r; - return r; + return copy_file_fd(s->usb_function_strings, fd, false); } -static int select_ep(const struct dirent *d) { +static int usbffs_select_ep(const struct dirent *d) { return d->d_name[0] != '.' && !streq(d->d_name, "ep0"); } -static int ffs_dispatch_eps(SocketPort *p) { +static int usbffs_dispatch_eps(SocketPort *p) { _cleanup_free_ struct dirent **ent = NULL; - int r, i, n, k; _cleanup_free_ char *path = NULL; + int r, i, n, k; r = path_get_parent(p->path, &path); if (r < 0) return r; - r = scandir(path, &ent, select_ep, alphasort); + r = scandir(path, &ent, usbffs_select_ep, alphasort); if (r < 0) return -errno; @@ -1216,10 +1189,12 @@ static int ffs_dispatch_eps(SocketPort *p) { path_kill_slashes(ep); - r = ffs_address_create(ep, &p->auxiliary_fds[k]); + r = usbffs_address_create(ep); if (r < 0) goto fail; + p->auxiliary_fds[k] = r; + ++k; free(ent[i]); } @@ -1227,9 +1202,7 @@ static int ffs_dispatch_eps(SocketPort *p) { return r; fail: - while (k) - safe_close(p->auxiliary_fds[--k]); - + close_many(p->auxiliary_fds, k); p->auxiliary_fds = mfree(p->auxiliary_fds); p->n_auxiliary_fds = 0; @@ -1237,10 +1210,10 @@ fail: } static int socket_open_fds(Socket *s) { + _cleanup_(mac_selinux_freep) char *label = NULL; + bool know_label = false; SocketPort *p; int r; - char *label = NULL; - bool know_label = false; assert(s); @@ -1249,7 +1222,9 @@ static int socket_open_fds(Socket *s) { if (p->fd >= 0) continue; - if (p->type == SOCKET_SOCKET) { + switch (p->type) { + + case SOCKET_SOCKET: if (!know_label) { /* Figure out label, if we don't it know @@ -1300,64 +1275,72 @@ static int socket_open_fds(Socket *s) { p->fd = r; socket_apply_socket_options(s, p->fd); socket_symlink(s); + break; - } else if (p->type == SOCKET_SPECIAL) { + case SOCKET_SPECIAL: - r = special_address_create( - p->path, - &p->fd); - if (r < 0) + p->fd = special_address_create(p->path); + if (p->fd < 0) { + r = p->fd; goto rollback; + } + break; - } else if (p->type == SOCKET_FIFO) { + case SOCKET_FIFO: - r = fifo_address_create( + p->fd = fifo_address_create( p->path, s->directory_mode, - s->socket_mode, - &p->fd); - if (r < 0) + s->socket_mode); + if (p->fd < 0) { + r = p->fd; goto rollback; + } socket_apply_fifo_options(s, p->fd); socket_symlink(s); + break; - } else if (p->type == SOCKET_MQUEUE) { + case SOCKET_MQUEUE: - r = mq_address_create( + p->fd = mq_address_create( p->path, s->socket_mode, s->mq_maxmsg, - s->mq_msgsize, - &p->fd); - if (r < 0) + s->mq_msgsize); + if (p->fd < 0) { + r = p->fd; goto rollback; - } else if (p->type == SOCKET_USB_FUNCTION) { + } + break; - r = ffs_address_create( - p->path, - &p->fd); - if (r < 0) + case SOCKET_USB_FUNCTION: + + p->fd = usbffs_address_create(p->path); + if (p->fd < 0) { + r = p->fd; goto rollback; + } - r = ffs_write_descs(p->fd, s->service.unit); + r = usbffs_write_descs(p->fd, SERVICE(UNIT_DEREF(s->service))); if (r < 0) goto rollback; - r = ffs_dispatch_eps(p); + r = usbffs_dispatch_eps(p); if (r < 0) goto rollback; - } else + + break; + + default: assert_not_reached("Unknown port type"); + } } - mac_selinux_free(label); return 0; rollback: socket_close_fds(s); - mac_selinux_free(label); - return r; } diff --git a/src/core/system.conf b/src/core/system.conf index 231609033b..c30c595413 100644 --- a/src/core/system.conf +++ b/src/core/system.conf @@ -17,9 +17,10 @@ #LogColor=yes #LogLocation=no #DumpCore=yes -#CrashShell=no #ShowStatus=yes -#CrashChVT=1 +#CrashChangeVT=no +#CrashShell=no +#CrashReboot=no #CPUAffinity=1 2 #JoinControllers=cpu,cpuacct net_cls,net_prio #RuntimeWatchdogSec=0 diff --git a/src/core/unit.c b/src/core/unit.c index 9cc48a8982..33c0317ce0 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1129,12 +1129,12 @@ static int unit_add_slice_dependencies(Unit *u) { return 0; if (UNIT_ISSET(u->slice)) - return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true); + return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice), true); - if (streq(u->id, SPECIAL_ROOT_SLICE)) + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) return 0; - return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true); + return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE, NULL, true); } static int unit_add_mount_dependencies(Unit *u) { diff --git a/src/delta/delta.c b/src/delta/delta.c index 990130d00b..4edafc7cdf 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -21,21 +21,20 @@ ***/ #include <errno.h> -#include <string.h> -#include <unistd.h> #include <getopt.h> +#include <string.h> #include <sys/prctl.h> +#include <unistd.h> #include "hashmap.h" -#include "util.h" -#include "path-util.h" #include "log.h" #include "pager.h" -#include "build.h" -#include "strv.h" +#include "path-util.h" #include "process-util.h" -#include "terminal-util.h" #include "signal-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" static const char prefixes[] = "/etc\0" @@ -544,9 +543,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_PAGER: arg_no_pager = true; diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c index 97ae569ca5..dcf4e9749e 100644 --- a/src/detect-virt/detect-virt.c +++ b/src/detect-virt/detect-virt.c @@ -19,14 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <errno.h> #include <getopt.h> +#include <stdbool.h> +#include <stdlib.h> #include "util.h" #include "virt.h" -#include "build.h" static bool arg_quiet = false; static enum { @@ -75,9 +74,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'q': arg_quiet = true; @@ -99,8 +96,7 @@ static int parse_argv(int argc, char *argv[]) { } if (optind < argc) { - log_error("%s takes no arguments.", - program_invocation_short_name); + log_error("%s takes no arguments.", program_invocation_short_name); return -EINVAL; } @@ -108,7 +104,7 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { - int retval = EXIT_SUCCESS, r; + int r; /* This is mostly intended to be used for scripts which want * to detect whether we are being run in a virtualized @@ -126,7 +122,7 @@ int main(int argc, char *argv[]) { case ONLY_VM: r = detect_vm(); if (r < 0) { - log_error_errno(r, "Failed to check for vm: %m"); + log_error_errno(r, "Failed to check for VM: %m"); return EXIT_FAILURE; } @@ -155,7 +151,5 @@ int main(int argc, char *argv[]) { if (!arg_quiet) puts(virtualization_to_string(r)); - retval = r != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE; - - return retval; + return r != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/escape/escape.c b/src/escape/escape.c index 341453398d..a4bfeb5df5 100644 --- a/src/escape/escape.c +++ b/src/escape/escape.c @@ -19,14 +19,13 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <getopt.h> #include <stdio.h> #include <stdlib.h> -#include <getopt.h> #include "log.h" -#include "unit-name.h" -#include "build.h" #include "strv.h" +#include "unit-name.h" static enum { ACTION_ESCAPE, @@ -83,9 +82,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_SUFFIX: diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index e2a1c00a75..4f0c669ca1 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -19,24 +19,22 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ - #include <fcntl.h> -#include <unistd.h> #include <getopt.h> #include <shadow.h> +#include <unistd.h> -#include "strv.h" -#include "fileio.h" +#include "ask-password-api.h" #include "copy.h" -#include "build.h" +#include "fileio.h" +#include "hostname-util.h" +#include "locale-util.h" #include "mkdir.h" -#include "time-util.h" #include "path-util.h" #include "random-util.h" -#include "locale-util.h" -#include "ask-password-api.h" +#include "strv.h" #include "terminal-util.h" -#include "hostname-util.h" +#include "time-util.h" static char *arg_root = NULL; static char *arg_locale = NULL; /* $LANG */ @@ -704,9 +702,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_ROOT: free(arg_root); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index bd3051f30d..30c846f01d 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -60,14 +60,14 @@ static bool arg_force = false; static bool arg_show_progress = false; static const char *arg_repair = "-a"; -static void start_target(const char *target) { +static void start_target(const char *target, const char *mode) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; int r; assert(target); - r = bus_open_system_systemd(&bus); + r = bus_connect_system_systemd(&bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); return; @@ -83,7 +83,7 @@ static void start_target(const char *target) { "StartUnitReplace", &error, NULL, - "sss", "basic.target", target, "replace"); + "sss", "basic.target", target, mode); /* Don't print a warning if we aren't called during startup */ if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB)) @@ -463,10 +463,10 @@ int main(int argc, char *argv[]) { if (status.si_code == CLD_EXITED && (status.si_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory) /* System should be rebooted. */ - start_target(SPECIAL_REBOOT_TARGET); + start_target(SPECIAL_REBOOT_TARGET, "replace-irreversibly"); else if (status.si_code == CLD_EXITED && (status.si_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED))) /* Some other problem */ - start_target(SPECIAL_EMERGENCY_TARGET); + start_target(SPECIAL_EMERGENCY_TARGET, "replace"); else { log_warning("Ignoring error."); r = 0; diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index dcbad99ae9..0724fcc16d 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -19,21 +19,21 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <getopt.h> #include <locale.h> +#include <stdbool.h> +#include <stdlib.h> #include <string.h> #include "sd-bus.h" #include "sd-id128.h" -#include "hostname-util.h" -#include "bus-util.h" + +#include "architecture.h" #include "bus-error.h" -#include "util.h" +#include "bus-util.h" +#include "hostname-util.h" #include "spawn-polkit-agent.h" -#include "build.h" -#include "architecture.h" +#include "util.h" static bool arg_ask_password = true; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; @@ -387,9 +387,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'H': arg_transport = BUS_TRANSPORT_REMOTE; @@ -519,7 +517,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = bus_open_transport(arg_transport, arg_host, false, &bus); + r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index 446de3a2fc..1e415db845 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -17,21 +17,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> +#include <ctype.h> #include <getopt.h> +#include <stdlib.h> #include <string.h> -#include <ctype.h> -#include "util.h" -#include "strbuf.h" #include "conf-files.h" -#include "strv.h" -#include "mkdir.h" -#include "verbs.h" -#include "build.h" - #include "hwdb-internal.h" #include "hwdb-util.h" +#include "mkdir.h" +#include "strbuf.h" +#include "strv.h" +#include "util.h" +#include "verbs.h" /* * Generic udev properties, key/value database based on modalias strings. @@ -688,9 +686,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_USR: arg_hwdb_bin_dir = UDEVLIBEXECDIR; diff --git a/src/import/export.c b/src/import/export.c index b88d71fec6..d34105e4ca 100644 --- a/src/import/export.c +++ b/src/import/export.c @@ -22,15 +22,15 @@ #include <getopt.h> #include "sd-event.h" + #include "event-util.h" -#include "signal-util.h" +#include "export-raw.h" +#include "export-tar.h" #include "hostname-util.h" -#include "verbs.h" -#include "build.h" -#include "machine-image.h" #include "import-util.h" -#include "export-tar.h" -#include "export-raw.h" +#include "machine-image.h" +#include "signal-util.h" +#include "verbs.h" static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN; @@ -260,9 +260,7 @@ static int parse_argv(int argc, char *argv[]) { return help(0, NULL, NULL); case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_FORMAT: if (streq(optarg, "uncompressed")) diff --git a/src/import/import.c b/src/import/import.c index 929a840298..1c92312585 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -22,15 +22,15 @@ #include <getopt.h> #include "sd-event.h" + #include "event-util.h" -#include "verbs.h" -#include "build.h" -#include "signal-util.h" #include "hostname-util.h" -#include "machine-image.h" -#include "import-util.h" -#include "import-tar.h" #include "import-raw.h" +#include "import-tar.h" +#include "import-util.h" +#include "machine-image.h" +#include "signal-util.h" +#include "verbs.h" static bool arg_force = false; static bool arg_read_only = false; @@ -280,9 +280,7 @@ static int parse_argv(int argc, char *argv[]) { return help(0, NULL, NULL); case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_FORCE: arg_force = true; diff --git a/src/import/importd.c b/src/import/importd.c index c90ada5da4..a29e9d4bd5 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -600,11 +600,11 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void cmsg_close_all(&msghdr); - CMSG_FOREACH(cmsg, &msghdr) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) - + CMSG_FOREACH(cmsg, &msghdr) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) ucred = (struct ucred*) CMSG_DATA(cmsg); - } if (msghdr.msg_flags & MSG_TRUNC) { log_warning("Got overly long notification datagram, ignoring."); diff --git a/src/import/pull.c b/src/import/pull.c index 98c22aeec9..29e9424b52 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -22,16 +22,16 @@ #include <getopt.h> #include "sd-event.h" + #include "event-util.h" -#include "verbs.h" -#include "build.h" -#include "signal-util.h" #include "hostname-util.h" -#include "machine-image.h" #include "import-util.h" -#include "pull-tar.h" -#include "pull-raw.h" +#include "machine-image.h" #include "pull-dkr.h" +#include "pull-raw.h" +#include "pull-tar.h" +#include "signal-util.h" +#include "verbs.h" static bool arg_force = false; static const char *arg_image_root = "/var/lib/machines"; @@ -381,9 +381,7 @@ static int parse_argv(int argc, char *argv[]) { return help(0, NULL, NULL); case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_FORCE: arg_force = true; diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c index 6d08db74ef..2d5f7501e7 100644 --- a/src/initctl/initctl.c +++ b/src/initctl/initctl.c @@ -318,7 +318,7 @@ static int server_init(Server *s, unsigned n_sockets) { s->n_fifos ++; } - r = bus_open_system_systemd(&s->bus); + r = bus_connect_system_systemd(&s->bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); r = -EIO; diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index 4e5572db0b..29df842277 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -24,9 +24,7 @@ #include <unistd.h> #include <fcntl.h> #include <getopt.h> - #include <microhttpd.h> - #ifdef HAVE_GNUTLS #include <gnutls/gnutls.h> #endif @@ -34,15 +32,15 @@ #include "sd-journal.h" #include "sd-daemon.h" #include "sd-bus.h" -#include "log.h" -#include "util.h" + #include "bus-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "log.h" #include "logs-show.h" #include "microhttpd-util.h" -#include "build.h" -#include "fileio.h" #include "sigbus.h" -#include "hostname-util.h" +#include "util.h" static char *arg_key_pem = NULL; static char *arg_cert_pem = NULL; @@ -909,9 +907,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_KEY: if (arg_key_pem) { diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index d6ebca20ec..50f41a575d 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -21,31 +21,30 @@ #include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/prctl.h> #include <sys/socket.h> #include <unistd.h> -#include <getopt.h> + +#ifdef HAVE_GNUTLS +#include <gnutls/gnutls.h> +#endif #include "sd-daemon.h" -#include "signal-util.h" + +#include "conf-parser.h" +#include "fileio.h" #include "journal-file.h" #include "journald-native.h" -#include "socket-util.h" -#include "build.h" #include "macro.h" +#include "signal-util.h" +#include "socket-util.h" #include "strv.h" -#include "fileio.h" -#include "conf-parser.h" - -#ifdef HAVE_GNUTLS -#include <gnutls/gnutls.h> -#endif - -#include "journal-remote.h" #include "journal-remote-write.h" +#include "journal-remote.h" #define REMOTE_JOURNAL_PATH "/var/log/journal/remote" @@ -1259,9 +1258,7 @@ static int parse_argv(int argc, char *argv[]) { return 0 /* done */; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0 /* done */; + return version(); case ARG_URL: if (arg_url) { diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index 311bd3fdda..92ce56805a 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -19,22 +19,22 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> -#include <curl/curl.h> -#include <sys/stat.h> #include <fcntl.h> #include <getopt.h> +#include <stdio.h> +#include <sys/stat.h> +#include <curl/curl.h> #include "sd-daemon.h" -#include "log.h" -#include "util.h" -#include "build.h" + +#include "conf-parser.h" #include "fileio.h" +#include "formats-util.h" +#include "log.h" #include "mkdir.h" -#include "conf-parser.h" #include "sigbus.h" -#include "formats-util.h" #include "signal-util.h" +#include "util.h" #include "journal-upload.h" #define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem" @@ -619,9 +619,7 @@ static int parse_argv(int argc, char *argv[]) { return 0 /* done */; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0 /* done */; + return version(); case 'u': if (arg_url) { diff --git a/src/journal/cat.c b/src/journal/cat.c index be2c2e3354..f9b279d7de 100644 --- a/src/journal/cat.c +++ b/src/journal/cat.c @@ -19,17 +19,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> -#include <getopt.h> -#include <unistd.h> -#include <stdlib.h> #include <errno.h> #include <fcntl.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> -#include "systemd/sd-journal.h" +#include "sd-journal.h" #include "util.h" -#include "build.h" static char *arg_identifier = NULL; static int arg_priority = LOG_INFO; @@ -76,9 +75,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 't': free(arg_identifier); @@ -95,7 +92,7 @@ static int parse_argv(int argc, char *argv[]) { arg_priority = log_level_from_string(optarg); if (arg_priority < 0) { log_error("Failed to parse priority value."); - return arg_priority; + return -EINVAL; } break; @@ -103,10 +100,9 @@ static int parse_argv(int argc, char *argv[]) { int k; k = parse_boolean(optarg); - if (k < 0) { - log_error("Failed to parse level prefix value."); - return k; - } + if (k < 0) + return log_error_errno(k, "Failed to parse level prefix value."); + arg_level_prefix = k; break; } @@ -122,7 +118,8 @@ static int parse_argv(int argc, char *argv[]) { } int main(int argc, char *argv[]) { - int r, fd = -1, saved_stderr = -1; + _cleanup_close_ int fd = -1, saved_stderr = -1; + int r; log_parse_environment(); log_open(); @@ -133,8 +130,7 @@ int main(int argc, char *argv[]) { fd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix); if (fd < 0) { - log_error_errno(fd, "Failed to create stream fd: %m"); - r = fd; + r = log_error_errno(fd, "Failed to create stream fd: %m"); goto finish; } @@ -148,25 +144,20 @@ int main(int argc, char *argv[]) { if (fd >= 3) safe_close(fd); - fd = -1; if (argc <= optind) - execl("/bin/cat", "/bin/cat", NULL); + (void) execl("/bin/cat", "/bin/cat", NULL); else - execvp(argv[optind], argv + optind); - + (void) execvp(argv[optind], argv + optind); r = -errno; /* Let's try to restore a working stderr, so we can print the error message */ if (saved_stderr >= 0) - dup3(saved_stderr, STDERR_FILENO, 0); + (void) dup3(saved_stderr, STDERR_FILENO, 0); log_error_errno(r, "Failed to execute process: %m"); finish: - safe_close(fd); - safe_close(saved_stderr); - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index 6628e82421..dde56008c1 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -19,27 +19,27 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <fcntl.h> +#include <getopt.h> #include <locale.h> #include <stdio.h> #include <string.h> -#include <getopt.h> -#include <fcntl.h> #include <unistd.h> #include "sd-journal.h" -#include "build.h" -#include "set.h" -#include "util.h" + +#include "compress.h" +#include "journal-internal.h" #include "log.h" -#include "path-util.h" -#include "pager.h" #include "macro.h" -#include "journal-internal.h" -#include "compress.h" -#include "sigbus.h" +#include "pager.h" +#include "path-util.h" #include "process-util.h" -#include "terminal-util.h" +#include "set.h" +#include "sigbus.h" #include "signal-util.h" +#include "terminal-util.h" +#include "util.h" static enum { ACTION_NONE, @@ -175,9 +175,7 @@ static int parse_argv(int argc, char *argv[], Set *matches) { case ARG_VERSION: arg_action = ACTION_NONE; - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_PAGER: arg_no_pager = true; diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c index 1e3a463504..dc1b2105dd 100644 --- a/src/journal/journal-send.c +++ b/src/journal/journal-send.c @@ -212,11 +212,6 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) { .msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path), }; ssize_t k; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(int))]; - } control; - struct cmsghdr *cmsg; bool have_syslog_identifier = false; bool seal = true; @@ -335,26 +330,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) { return r; } - mh.msg_iov = NULL; - mh.msg_iovlen = 0; - - zero(control); - mh.msg_control = &control; - mh.msg_controllen = sizeof(control); - - cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int)); - - mh.msg_controllen = cmsg->cmsg_len; - - k = sendmsg(fd, &mh, MSG_NOSIGNAL); - if (k < 0) - return -errno; - - return 0; + return send_one_fd(fd, buffer_fd, 0); } static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) { diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index b38b151485..b42c51a29b 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -19,48 +19,47 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <locale.h> +#include <errno.h> #include <fcntl.h> #include <fnmatch.h> -#include <errno.h> +#include <getopt.h> +#include <linux/fs.h> +#include <locale.h> +#include <poll.h> +#include <signal.h> #include <stddef.h> -#include <string.h> #include <stdio.h> -#include <unistd.h> #include <stdlib.h> -#include <getopt.h> -#include <signal.h> -#include <poll.h> -#include <sys/stat.h> +#include <string.h> #include <sys/inotify.h> -#include <linux/fs.h> +#include <sys/stat.h> +#include <unistd.h> -#include "sd-journal.h" #include "sd-bus.h" -#include "log.h" -#include "logs-show.h" -#include "util.h" +#include "sd-journal.h" + #include "acl-util.h" -#include "path-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "catalog.h" #include "fileio.h" -#include "build.h" -#include "pager.h" -#include "strv.h" -#include "set.h" -#include "sigbus.h" -#include "journal-internal.h" +#include "fsprg.h" +#include "hostname-util.h" #include "journal-def.h" -#include "journal-verify.h" +#include "journal-internal.h" #include "journal-qrcode.h" #include "journal-vacuum.h" -#include "fsprg.h" -#include "unit-name.h" -#include "catalog.h" +#include "journal-verify.h" +#include "log.h" +#include "logs-show.h" #include "mkdir.h" -#include "bus-util.h" -#include "bus-error.h" +#include "pager.h" +#include "path-util.h" +#include "set.h" +#include "sigbus.h" +#include "strv.h" #include "terminal-util.h" -#include "hostname-util.h" +#include "unit-name.h" #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) @@ -122,6 +121,7 @@ static enum { ACTION_UPDATE_CATALOG, ACTION_LIST_BOOTS, ACTION_FLUSH, + ACTION_ROTATE, ACTION_VACUUM, } arg_action = ACTION_SHOW; @@ -237,6 +237,7 @@ static void help(void) { " --vacuum-size=BYTES Reduce disk usage below specified size\n" " --vacuum-time=TIME Remove journal files older than specified date\n" " --flush Flush all journal data from /run into /var\n" + " --rotate Request immediate rotation of the journal files\n" " --header Show journal header information\n" " --list-catalog Show all message IDs in the catalog\n" " --dump-catalog Show entries in the message catalog\n" @@ -278,6 +279,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_FORCE, ARG_UTC, ARG_FLUSH, + ARG_ROTATE, ARG_VACUUM_SIZE, ARG_VACUUM_TIME, }; @@ -331,6 +333,7 @@ static int parse_argv(int argc, char *argv[]) { { "machine", required_argument, NULL, 'M' }, { "utc", no_argument, NULL, ARG_UTC }, { "flush", no_argument, NULL, ARG_FLUSH }, + { "rotate", no_argument, NULL, ARG_ROTATE }, { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE }, { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME }, {} @@ -350,9 +353,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_PAGER: arg_no_pager = true; @@ -699,6 +700,10 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_FLUSH; break; + case ARG_ROTATE: + arg_action = ACTION_ROTATE; + break; + case '?': return -EINVAL; @@ -1725,7 +1730,7 @@ static int flush_to_var(void) { /* OK, let's actually do the full logic, send SIGUSR1 to the * daemon and set up inotify to wait for the flushed file to appear */ - r = bus_open_system_systemd(&bus); + r = bus_connect_system_systemd(&bus); if (r < 0) return log_error_errno(r, "Failed to get D-Bus connection: %m"); @@ -1772,6 +1777,30 @@ static int flush_to_var(void) { return 0; } +static int rotate(void) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; + int r; + + r = bus_connect_system_systemd(&bus); + if (r < 0) + return log_error_errno(r, "Failed to get D-Bus connection: %m"); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "KillUnit", + &error, + NULL, + "ssi", "systemd-journald.service", "main", SIGUSR2); + if (r < 0) + return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r)); + + return 0; +} + int main(int argc, char *argv[]) { int r; _cleanup_journal_close_ sd_journal *j = NULL; @@ -1807,6 +1836,11 @@ int main(int argc, char *argv[]) { goto finish; } + if (arg_action == ACTION_ROTATE) { + r = rotate(); + goto finish; + } + if (arg_action == ACTION_SETUP_KEYS) { r = setup_keys(); goto finish; diff --git a/src/libsystemd-network/sd-pppoe.c b/src/libsystemd-network/sd-pppoe.c index 439d4eff38..f2baafdeb9 100644 --- a/src/libsystemd-network/sd-pppoe.c +++ b/src/libsystemd-network/sd-pppoe.c @@ -385,7 +385,7 @@ static int pppoe_send_initiation(sd_pppoe *ppp) { return r; log_debug("PPPoE: sent DISCOVER (Service-Name: %s)", - ppp->service_name ? : ""); + strempty(ppp->service_name)); pppoe_arm_timeout(ppp); @@ -625,8 +625,8 @@ static int pppoe_handle_message(sd_pppoe *ppp, struct pppoe_hdr *packet, struct mac->ether_addr_octet[3], mac->ether_addr_octet[4], mac->ether_addr_octet[5], - ppp->tags.service_name ? : "", - ppp->tags.ac_name ? : ""); + strempty(ppp->tags.service_name), + strempty(ppp->tags.ac_name)); memcpy(&ppp->peer_mac, mac, ETH_ALEN); diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c index 5c607f49b1..435ec92d6f 100644 --- a/src/libsystemd/sd-bus/bus-container.c +++ b/src/libsystemd/sd-bus/bus-container.c @@ -217,15 +217,8 @@ int bus_container_connect_kernel(sd_bus *b) { _exit(EXIT_FAILURE); } - cmsg = CMSG_FIRSTHDR(&mh); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); - - mh.msg_controllen = cmsg->cmsg_len; - - if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0) + r = send_one_fd(pair[1], fd, 0); + if (r < 0) _exit(EXIT_FAILURE); _exit(EXIT_SUCCESS); diff --git a/src/libsystemd/sd-bus/busctl.c b/src/libsystemd/sd-bus/busctl.c index 5d07d5809c..ab8816942c 100644 --- a/src/libsystemd/sd-bus/busctl.c +++ b/src/libsystemd/sd-bus/busctl.c @@ -21,22 +21,21 @@ #include <getopt.h> -#include "strv.h" -#include "util.h" -#include "log.h" -#include "build.h" -#include "pager.h" -#include "path-util.h" -#include "set.h" - #include "sd-bus.h" -#include "bus-internal.h" -#include "bus-util.h" + #include "bus-dump.h" +#include "bus-internal.h" #include "bus-signature.h" #include "bus-type.h" +#include "bus-util.h" #include "busctl-introspect.h" +#include "log.h" +#include "pager.h" +#include "path-util.h" +#include "set.h" +#include "strv.h" #include "terminal-util.h" +#include "util.h" static bool arg_no_pager = false; static bool arg_legend = true; @@ -1786,9 +1785,7 @@ static int parse_argv(int argc, char *argv[]) { return help(); case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_PAGER: arg_no_pager = true; diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 9ec73406c6..ba7b8da85f 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -498,16 +498,11 @@ _public_ int sd_notifyf(int unset_environment, const char *format, ...) { } _public_ int sd_booted(void) { - struct stat st; - /* We test whether the runtime unit file directory has been * created. This takes place in mount-setup.c, so is * guaranteed to happen very early during boot. */ - if (lstat("/run/systemd/system/", &st) < 0) - return 0; - - return !!S_ISDIR(st.st_mode); + return laccess("/run/systemd/system/", F_OK) >= 0; } _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 48a5219275..1a82c4c940 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -242,12 +242,6 @@ static int pending_prioq_compare(const void *a, const void *b) { if (x->pending_iteration > y->pending_iteration) return 1; - /* Stability for the rest */ - if (x < y) - return -1; - if (x > y) - return 1; - return 0; } @@ -277,12 +271,6 @@ static int prepare_prioq_compare(const void *a, const void *b) { if (x->priority > y->priority) return 1; - /* Stability for the rest */ - if (x < y) - return -1; - if (x > y) - return 1; - return 0; } @@ -310,12 +298,6 @@ static int earliest_time_prioq_compare(const void *a, const void *b) { if (x->time.next > y->time.next) return 1; - /* Stability for the rest */ - if (x < y) - return -1; - if (x > y) - return 1; - return 0; } @@ -343,12 +325,6 @@ static int latest_time_prioq_compare(const void *a, const void *b) { if (x->time.next + x->time.accuracy > y->time.next + y->time.accuracy) return 1; - /* Stability for the rest */ - if (x < y) - return -1; - if (x > y) - return 1; - return 0; } @@ -370,12 +346,6 @@ static int exit_prioq_compare(const void *a, const void *b) { if (x->priority > y->priority) return 1; - /* Stability for the rest */ - if (x < y) - return -1; - if (x > y) - return 1; - return 0; } diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h index fedccdec72..13fddfc8ad 100644 --- a/src/libsystemd/sd-hwdb/hwdb-internal.h +++ b/src/libsystemd/sd-hwdb/hwdb-internal.h @@ -19,6 +19,7 @@ #pragma once #include "sparse-endian.h" +#include "util.h" #define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' } diff --git a/src/locale/localectl.c b/src/locale/localectl.c index 4a91c7420a..880a1794aa 100644 --- a/src/locale/localectl.c +++ b/src/locale/localectl.c @@ -20,26 +20,26 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <ftw.h> +#include <getopt.h> #include <locale.h> -#include <stdlib.h> #include <stdbool.h> -#include <getopt.h> +#include <stdlib.h> #include <string.h> -#include <ftw.h> #include "sd-bus.h" -#include "bus-util.h" + #include "bus-error.h" -#include "util.h" -#include "spawn-polkit-agent.h" -#include "build.h" -#include "strv.h" -#include "pager.h" -#include "set.h" +#include "bus-util.h" #include "def.h" -#include "virt.h" #include "fileio.h" #include "locale-util.h" +#include "pager.h" +#include "set.h" +#include "spawn-polkit-agent.h" +#include "strv.h" +#include "util.h" +#include "virt.h" static bool arg_no_pager = false; static bool arg_ask_password = true; @@ -546,9 +546,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_CONVERT: arg_convert = false; @@ -678,7 +676,7 @@ int main(int argc, char*argv[]) { if (r <= 0) goto finish; - r = bus_open_transport(arg_transport, arg_host, false, &bus); + r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; diff --git a/src/login/inhibit.c b/src/login/inhibit.c index c53ea8add7..e671341b42 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -19,21 +19,21 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <fcntl.h> #include <getopt.h> -#include <stdlib.h> #include <stdio.h> +#include <stdlib.h> #include <unistd.h> -#include <fcntl.h> #include "sd-bus.h" -#include "bus-util.h" + #include "bus-error.h" -#include "util.h" -#include "build.h" -#include "strv.h" +#include "bus-util.h" #include "formats-util.h" #include "process-util.h" #include "signal-util.h" +#include "strv.h" +#include "util.h" static const char* arg_what = "idle:sleep:shutdown"; static const char* arg_who = NULL; @@ -179,9 +179,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_WHAT: arg_what = optarg; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index be52518161..bfc8716009 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -19,31 +19,31 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> #include <errno.h> -#include <string.h> #include <getopt.h> #include <locale.h> +#include <string.h> +#include <unistd.h> #include "sd-bus.h" -#include "bus-util.h" + #include "bus-error.h" +#include "bus-util.h" +#include "cgroup-show.h" +#include "cgroup-util.h" #include "log.h" -#include "util.h" +#include "logs-show.h" #include "macro.h" #include "pager.h" -#include "build.h" +#include "process-util.h" +#include "signal-util.h" +#include "spawn-polkit-agent.h" #include "strv.h" -#include "unit-name.h" #include "sysfs-show.h" -#include "logs-show.h" -#include "cgroup-show.h" -#include "cgroup-util.h" -#include "spawn-polkit-agent.h" -#include "verbs.h" -#include "process-util.h" #include "terminal-util.h" -#include "signal-util.h" +#include "unit-name.h" +#include "util.h" +#include "verbs.h" static char **arg_property = NULL; static bool arg_all = false; @@ -1416,9 +1416,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'p': { r = strv_extend(&arg_property, optarg); @@ -1544,7 +1542,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = bus_open_transport(arg_transport, arg_host, false, &bus); + r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 22e37a1638..40d587ddb8 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1352,24 +1352,26 @@ static int bus_manager_log_shutdown( return 0; if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) { - p = "MESSAGE=System is powering down."; + p = "MESSAGE=System is powering down"; q = "SHUTDOWN=power-off"; } else if (streq(unit_name, SPECIAL_HALT_TARGET)) { - p = "MESSAGE=System is halting."; + p = "MESSAGE=System is halting"; q = "SHUTDOWN=halt"; } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) { - p = "MESSAGE=System is rebooting."; + p = "MESSAGE=System is rebooting"; q = "SHUTDOWN=reboot"; } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) { - p = "MESSAGE=System is rebooting with kexec."; + p = "MESSAGE=System is rebooting with kexec"; q = "SHUTDOWN=kexec"; } else { - p = "MESSAGE=System is shutting down."; + p = "MESSAGE=System is shutting down"; q = NULL; } - if (!isempty(m->wall_message)) - p = strjoina(p, " (", m->wall_message, ")"); + if (isempty(m->wall_message)) + p = strjoina(p, "."); + else + p = strjoina(p, " (", m->wall_message, ")."); return log_struct(LOG_NOTICE, LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN), diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c index 9a9fb7622d..f38f06baf9 100644 --- a/src/login/sysfs-show.c +++ b/src/login/sysfs-show.c @@ -114,7 +114,7 @@ static int show_sysfs_one( "%s%s:%s%s%s%s", is_master ? "[MASTER] " : "", subsystem, sysname, - name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) + name ? " \"" : "", strempty(name), name ? "\"" : "") < 0) return -ENOMEM; free(k); diff --git a/src/machine-id-commit/Makefile b/src/machine-id-commit/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/machine-id-commit/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile
\ No newline at end of file diff --git a/src/machine-id-commit/machine-id-commit.c b/src/machine-id-commit/machine-id-commit.c deleted file mode 100644 index 0f7748e453..0000000000 --- a/src/machine-id-commit/machine-id-commit.c +++ /dev/null @@ -1,107 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2014 Didier Roche - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <stdlib.h> -#include <stdio.h> -#include <getopt.h> -#include <errno.h> - -#include "machine-id-setup.h" -#include "log.h" -#include "build.h" - -static const char *arg_root = NULL; - -static void help(void) { - printf("%s [OPTIONS...]\n\n" - "Commit a transient /etc/machine-id on disk if writable.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --root=ROOT Filesystem root\n", - program_invocation_short_name); -} - -static int parse_argv(int argc, char *argv[]) { - - enum { - ARG_VERSION = 0x100, - ARG_ROOT, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "root", required_argument, NULL, ARG_ROOT }, - {} - }; - - int c; - - assert(argc >= 0); - assert(argv); - - while ((c = getopt_long(argc, argv, "hqcv", options, NULL)) >= 0) - switch (c) { - - case 'h': - help(); - return 0; - - case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; - - case ARG_ROOT: - arg_root = optarg; - break; - - case '?': - return -EINVAL; - - default: - assert_not_reached("Unhandled option"); - } - - if (optind < argc) { - log_error("Extraneous arguments"); - return -EINVAL; - } - - return 1; -} - -int main(int argc, char *argv[]) { - int r; - - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); - - r = parse_argv(argc, argv); - if (r <= 0) - goto finish; - - r = machine_id_commit(arg_root); - -finish: - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c index 20cb60b804..a9c4e3fadf 100644 --- a/src/machine-id-setup/machine-id-setup-main.c +++ b/src/machine-id-setup/machine-id-setup-main.c @@ -19,24 +19,26 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdio.h> -#include <getopt.h> #include <errno.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> -#include "machine-id-setup.h" #include "log.h" -#include "build.h" +#include "machine-id-setup.h" +#include "util.h" -static const char *arg_root = ""; +static const char *arg_root = NULL; +static bool arg_commit = false; static void help(void) { printf("%s [OPTIONS...]\n\n" "Initialize /etc/machine-id from a random source.\n\n" " -h --help Show this help\n" " --version Show package version\n" - " --root=ROOT Filesystem root\n", - program_invocation_short_name); + " --root=ROOT Filesystem root\n" + " --commit Commit transient ID\n" + , program_invocation_short_name); } static int parse_argv(int argc, char *argv[]) { @@ -44,12 +46,14 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ROOT, + ARG_COMMIT, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "root", required_argument, NULL, ARG_ROOT }, + { "commit", no_argument, NULL, ARG_COMMIT }, {} }; @@ -67,14 +71,16 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_ROOT: arg_root = optarg; break; + case ARG_COMMIT: + arg_commit = true; + break; + case '?': return -EINVAL; @@ -100,5 +106,11 @@ int main(int argc, char *argv[]) { if (r <= 0) return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; - return machine_id_setup(arg_root) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + if (arg_commit) + r = machine_id_commit(arg_root); + else + r = machine_id_setup(arg_root); + + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index b010c90989..21026829a9 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -735,7 +735,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu description = strjoina("Shell for User ", isempty(user) ? "root" : user); r = sd_bus_message_append(tm, - "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)", + "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)", "Description", "s", description, "StandardInput", "s", "tty", "StandardOutput", "s", "tty", @@ -748,7 +748,8 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu "TTYReset", "b", true, "UtmpIdentifier", "s", utmp_id, "UtmpMode", "s", "user", - "PAMName", "s", "login"); + "PAMName", "s", "login", + "WorkingDirectory", "s", "-~"); if (r < 0) return r; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index d276fbe956..17a186eb0e 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -19,44 +19,44 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <sys/socket.h> -#include <unistd.h> +#include <arpa/inet.h> #include <errno.h> -#include <string.h> +#include <fcntl.h> #include <getopt.h> #include <locale.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <arpa/inet.h> #include <net/if.h> +#include <netinet/in.h> +#include <string.h> #include <sys/mount.h> +#include <sys/socket.h> +#include <unistd.h> #include "sd-bus.h" -#include "log.h" -#include "util.h" -#include "macro.h" -#include "pager.h" -#include "spawn-polkit-agent.h" -#include "bus-util.h" + #include "bus-error.h" -#include "build.h" -#include "strv.h" -#include "unit-name.h" +#include "bus-util.h" #include "cgroup-show.h" -#include "logs-show.h" #include "cgroup-util.h" -#include "ptyfwd.h" -#include "event-util.h" -#include "path-util.h" -#include "mkdir.h" #include "copy.h" -#include "verbs.h" +#include "env-util.h" +#include "event-util.h" +#include "hostname-util.h" #include "import-util.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "mkdir.h" +#include "pager.h" +#include "path-util.h" #include "process-util.h" -#include "terminal-util.h" +#include "ptyfwd.h" #include "signal-util.h" -#include "env-util.h" -#include "hostname-util.h" +#include "spawn-polkit-agent.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "util.h" +#include "verbs.h" static char **arg_property = NULL; static bool arg_all = false; @@ -2554,9 +2554,7 @@ static int parse_argv(int argc, char *argv[]) { return help(0, NULL, NULL); case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'p': r = strv_extend(&arg_property, optarg); @@ -2747,7 +2745,7 @@ int main(int argc, char*argv[]) { if (r <= 0) goto finish; - r = bus_open_transport(arg_transport, arg_host, false, &bus); + r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 5bbe314ba0..55bb35b9f7 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -20,17 +20,16 @@ ***/ #include <errno.h> +#include <getopt.h> +#include <limits.h> #include <string.h> #include <sys/stat.h> -#include <limits.h> -#include <getopt.h> #include <libkmod.h> +#include "conf-files.h" #include "log.h" -#include "util.h" #include "strv.h" -#include "conf-files.h" -#include "build.h" +#include "util.h" static char **arg_proc_cmdline_modules = NULL; @@ -199,9 +198,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case '?': return -EINVAL; diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 75572b6388..c78b9444b6 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -19,29 +19,28 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdbool.h> #include <getopt.h> #include <net/if.h> +#include <stdbool.h> -#include "sd-network.h" -#include "sd-netlink.h" -#include "sd-hwdb.h" #include "sd-device.h" +#include "sd-hwdb.h" +#include "sd-netlink.h" +#include "sd-network.h" -#include "strv.h" -#include "build.h" -#include "util.h" -#include "pager.h" -#include "lldp.h" -#include "netlink-util.h" +#include "arphrd-list.h" #include "device-util.h" +#include "ether-addr-util.h" #include "hwdb-util.h" -#include "arphrd-list.h" +#include "lldp.h" #include "local-addresses.h" +#include "netlink-util.h" +#include "pager.h" #include "socket-util.h" -#include "ether-addr-util.h" -#include "verbs.h" +#include "strv.h" #include "terminal-util.h" +#include "util.h" +#include "verbs.h" static bool arg_no_pager = false; static bool arg_legend = true; @@ -1063,9 +1062,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_NO_PAGER: arg_no_pager = true; diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c index d958b48771..3220c4b7ef 100644 --- a/src/network/networkd-wait-online.c +++ b/src/network/networkd-wait-online.c @@ -21,10 +21,10 @@ #include <getopt.h> #include "sd-daemon.h" -#include "strv.h" -#include "build.h" -#include "signal-util.h" + #include "networkd-wait-online.h" +#include "signal-util.h" +#include "strv.h" static bool arg_quiet = false; static usec_t arg_timeout = 120 * USEC_PER_SEC; @@ -79,9 +79,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'i': if (strv_extend(&arg_interfaces, optarg) < 0) diff --git a/src/notify/notify.c b/src/notify/notify.c index 7d53cb6d75..805ea1a627 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -27,7 +27,6 @@ #include "sd-daemon.h" -#include "build.h" #include "env-util.h" #include "formats-util.h" #include "log.h" @@ -85,9 +84,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_READY: arg_ready = true; diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c index 9e63d88b69..3658f45381 100644 --- a/src/nspawn/nspawn-expose-ports.c +++ b/src/nspawn/nspawn-expose-ports.c @@ -194,7 +194,7 @@ int expose_port_send_rtnl(int send_fd) { /* Store away the fd in the socket, so that it stays open as * long as we run the child */ - r = send_one_fd(send_fd, fd); + r = send_one_fd(send_fd, fd, 0); if (r < 0) return log_error_errno(r, "Failed to send netlink fd: %m"); @@ -214,7 +214,7 @@ int expose_port_watch_rtnl( assert(recv_fd >= 0); assert(ret); - fd = receive_one_fd(recv_fd); + fd = receive_one_fd(recv_fd, 0); if (fd < 0) return log_error_errno(fd, "Failed to recv netlink fd: %m"); diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index 2bca39f45d..3d302ef9ad 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -216,8 +216,55 @@ static int tmpfs_patch_options( return !!buf; } +int mount_sysfs(const char *dest) { + const char *full, *top, *x; + + top = prefix_roota(dest, "/sys"); + full = prefix_roota(top, "/full"); + + (void) mkdir(full, 0755); + + if (mount("sysfs", full, "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) + return log_error_errno(errno, "Failed to mount sysfs to %s: %m", full); + + FOREACH_STRING(x, "block", "bus", "class", "dev", "devices", "kernel") { + _cleanup_free_ char *from = NULL, *to = NULL; + + from = prefix_root(full, x); + if (!from) + return log_oom(); + + to = prefix_root(top, x); + if (!to) + return log_oom(); + + (void) mkdir(to, 0755); + + if (mount(from, to, NULL, MS_BIND, NULL) < 0) + return log_error_errno(errno, "Failed to mount /sys/%s into place: %m", x); + + if (mount(NULL, to, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) + return log_error_errno(errno, "Failed to mount /sys/%s read-only: %m", x); + } + + if (umount(full) < 0) + return log_error_errno(errno, "Failed to unmount %s: %m", full); + + if (rmdir(full) < 0) + return log_error_errno(errno, "Failed to remove %s: %m", full); + + x = prefix_roota(top, "/fs/kdbus"); + (void) mkdir(x, 0755); + + if (mount(NULL, top, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0) + return log_error_errno(errno, "Failed to make %s read-only: %m", top); + + return 0; +} + int mount_all(const char *dest, - bool userns, uid_t uid_shift, uid_t uid_range, + bool use_userns, bool in_userns, + uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context) { typedef struct MountPoint { @@ -234,7 +281,7 @@ int mount_all(const char *dest, { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, true, true }, { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, true, true }, /* Bind mount first */ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true, true }, /* Then, make it r/o */ - { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false }, + { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, true, false }, { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, true, false }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, true, false }, @@ -252,7 +299,7 @@ int mount_all(const char *dest, _cleanup_free_ char *where = NULL, *options = NULL; const char *o; - if (userns != mount_table[k].userns) + if (in_userns != mount_table[k].userns) continue; where = prefix_root(dest, mount_table[k].where); @@ -278,7 +325,7 @@ int mount_all(const char *dest, o = mount_table[k].options; if (streq_ptr(mount_table[k].type, "tmpfs")) { - r = tmpfs_patch_options(o, userns, uid_shift, uid_range, selinux_apifs_context, &options); + r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, selinux_apifs_context, &options); if (r < 0) return log_oom(); if (r > 0) @@ -534,7 +581,7 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle char *to; int r; - to = strjoina(dest, "/sys/fs/cgroup/", hierarchy); + to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy); r = path_is_mount_point(to, 0); if (r < 0 && r != -ENOENT) @@ -569,6 +616,8 @@ static int mount_legacy_cgroups( cgroup_root = prefix_roota(dest, "/sys/fs/cgroup"); + (void) mkdir_p(cgroup_root, 0755); + /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */ r = path_is_mount_point(cgroup_root, AT_SYMLINK_FOLLOW); if (r < 0) diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 5abd44cc4b..54cab87665 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -57,7 +57,8 @@ int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s); int custom_mount_compare(const void *a, const void *b); -int mount_all(const char *dest, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); +int mount_all(const char *dest, bool use_userns, bool in_userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); +int mount_sysfs(const char *dest); int mount_cgroups(const char *dest, bool unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); int mount_systemd_cgroup_writable(const char *dest, bool unified_requested); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 7451c2bf64..f4a2e3d9ba 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -50,7 +50,6 @@ #include "base-filesystem.h" #include "blkid-util.h" #include "btrfs-util.h" -#include "build.h" #include "cap-list.h" #include "capability.h" #include "cgroup-util.h" @@ -84,12 +83,12 @@ #include "udev-util.h" #include "util.h" -#include "nspawn-settings.h" +#include "nspawn-cgroup.h" +#include "nspawn-expose-ports.h" #include "nspawn-mount.h" #include "nspawn-network.h" -#include "nspawn-expose-ports.h" -#include "nspawn-cgroup.h" #include "nspawn-register.h" +#include "nspawn-settings.h" #include "nspawn-setuid.h" typedef enum ContainerStatus { @@ -414,9 +413,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'D': r = set_sanitized_path(&arg_directory, optarg); @@ -1291,7 +1288,7 @@ static int setup_kmsg(const char *dest, int kmsg_socket) { /* Store away the fd in the socket, so that it stays open as * long as we run the child */ - r = send_one_fd(kmsg_socket, fd); + r = send_one_fd(kmsg_socket, fd, 0); safe_close(fd); if (r < 0) @@ -2282,8 +2279,6 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) { return r; } -static void nop_handler(int sig) {} - static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { pid_t pid; @@ -2455,7 +2450,11 @@ static int inner_child( } } - r = mount_all(NULL, true, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); + r = mount_all(NULL, arg_userns, true, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); + if (r < 0) + return r; + + r = mount_sysfs(NULL); if (r < 0) return r; @@ -2706,7 +2705,7 @@ static int outer_child( return log_error_errno(r, "Failed to make tree read-only: %m"); } - r = mount_all(directory, false, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); + r = mount_all(directory, arg_userns, false, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); if (r < 0) return r; @@ -3241,7 +3240,7 @@ int main(int argc, char *argv[]) { ContainerStatus container_status; _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; static const struct sigaction sa = { - .sa_handler = nop_handler, + .sa_handler = nop_signal_handler, .sa_flags = SA_NOCLDSTOP, }; int ifi = 0; @@ -3338,8 +3337,7 @@ int main(int argc, char *argv[]) { barrier_set_role(&barrier, BARRIER_PARENT); - fdset_free(fds); - fds = NULL; + fds = fdset_free(fds); kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]); rtnl_socket_pair[1] = safe_close(rtnl_socket_pair[1]); diff --git a/src/path/path.c b/src/path/path.c index f7736a4202..73b7bd2c01 100644 --- a/src/path/path.c +++ b/src/path/path.c @@ -19,16 +19,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> -#include <getopt.h> #include <errno.h> +#include <getopt.h> +#include <stdio.h> #include <stdlib.h> #include "sd-path.h" -#include "build.h" + +#include "log.h" #include "macro.h" #include "util.h" -#include "log.h" static const char *arg_suffix = NULL; @@ -155,9 +155,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_SUFFIX: arg_suffix = optarg; diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c index 22af092cc0..97516a87a8 100644 --- a/src/resolve-host/resolve-host.c +++ b/src/resolve-host/resolve-host.c @@ -23,14 +23,13 @@ #include <getopt.h> #include "sd-bus.h" -#include "bus-util.h" + +#include "af-list.h" #include "bus-error.h" +#include "bus-util.h" #include "in-addr-util.h" -#include "af-list.h" -#include "build.h" - -#include "resolved-dns-packet.h" #include "resolved-def.h" +#include "resolved-dns-packet.h" #define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC) @@ -507,9 +506,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; /* done */; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0 /* done */; + return version(); case '4': arg_family = AF_INET; diff --git a/src/run/run.c b/src/run/run.c index 657c6fcaf1..62687591f4 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -19,24 +19,24 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> #include <getopt.h> +#include <stdio.h> #include "sd-bus.h" #include "sd-event.h" + +#include "bus-error.h" #include "bus-util.h" -#include "event-util.h" -#include "strv.h" -#include "build.h" -#include "unit-name.h" +#include "calendarspec.h" #include "env-util.h" +#include "event-util.h" +#include "formats-util.h" #include "path-util.h" -#include "bus-error.h" -#include "calendarspec.h" #include "ptyfwd.h" -#include "formats-util.h" #include "signal-util.h" #include "spawn-polkit-agent.h" +#include "strv.h" +#include "unit-name.h" static bool arg_ask_password = true; static bool arg_scope = false; @@ -199,9 +199,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_USER: arg_user = true; @@ -1176,7 +1174,7 @@ int main(int argc, char* argv[]) { arg_description = description; } - r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus); + r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; diff --git a/src/shared/architecture.h b/src/shared/architecture.h index f5bbf65a90..61d067cad7 100644 --- a/src/shared/architecture.h +++ b/src/shared/architecture.h @@ -78,9 +78,11 @@ int uname_architecture(void); #if defined(__x86_64__) # define native_architecture() ARCHITECTURE_X86_64 # define LIB_ARCH_TUPLE "x86_64-linux-gnu" +# define PROC_CPUINFO_MODEL "model name" #elif defined(__i386__) # define native_architecture() ARCHITECTURE_X86 # define LIB_ARCH_TUPLE "i386-linux-gnu" +# define PROC_CPUINFO_MODEL "model name" #elif defined(__powerpc64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC64 @@ -89,6 +91,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_PPC64_LE # define LIB_ARCH_TUPLE "powerpc64le-linux-gnu" # endif +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__powerpc__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC @@ -97,15 +100,18 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_PPC_LE # error "Missing LIB_ARCH_TUPLE for PPCLE" # endif +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__ia64__) # define native_architecture() ARCHITECTURE_IA64 # define LIB_ARCH_TUPLE "ia64-linux-gnu" #elif defined(__hppa64__) # define native_architecture() ARCHITECTURE_PARISC64 # error "Missing LIB_ARCH_TUPLE for HPPA64" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__hppa__) # define native_architecture() ARCHITECTURE_PARISC # define LIB_ARCH_TUPLE "hppa‑linux‑gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__s390x__) # define native_architecture() ARCHITECTURE_S390X # define LIB_ARCH_TUPLE "s390x-linux-gnu" @@ -115,9 +121,11 @@ int uname_architecture(void); #elif defined(__sparc64__) # define native_architecture() ARCHITECTURE_SPARC64 # define LIB_ARCH_TUPLE "sparc64-linux-gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__sparc__) # define native_architecture() ARCHITECTURE_SPARC # define LIB_ARCH_TUPLE "sparc-linux-gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__mips64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS64 @@ -126,6 +134,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_MIPS64_LE # error "Missing LIB_ARCH_TUPLE for MIPS64_LE" # endif +# define PROC_CPUINFO_MODEL "cpu model" #elif defined(__mips__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS @@ -134,6 +143,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_MIPS_LE # define LIB_ARCH_TUPLE "mipsel-linux-gnu" # endif +# define PROC_CPUINFO_MODEL "cpu model" #elif defined(__alpha__) # define native_architecture() ARCHITECTURE_ALPHA # define LIB_ARCH_TUPLE "alpha-linux-gnu" @@ -169,6 +179,7 @@ int uname_architecture(void); # define LIB_ARCH_TUPLE "arm-linux-gnu" # endif # endif +# define PROC_CPUINFO_MODEL "model name" #elif defined(__sh64__) # define native_architecture() ARCHITECTURE_SH64 # error "Missing LIB_ARCH_TUPLE for SH64" @@ -188,5 +199,10 @@ int uname_architecture(void); # error "Please register your architecture here!" #endif +#ifndef PROC_CPUINFO_MODEL +#warning "PROC_CPUINFO_MODEL not defined for your architecture" +#define PROC_CPUINFO_MODEL "model name" +#endif + const char *architecture_to_string(int a) _const_; int architecture_from_string(const char *s) _pure_; diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 0954e072be..ccb3be0fca 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -21,6 +21,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <stdbool.h> + +#include "time-util.h" int ask_password_tty(const char *message, usec_t until, bool echo, const char *flag_file, char **_passphrase); diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index ab6fc171b0..48492ed13d 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -34,12 +34,13 @@ typedef struct BaseFilesystem { mode_t mode; const char *target; const char *exists; + bool ignore_failure; } BaseFilesystem; static const BaseFilesystem table[] = { { "bin", 0, "usr/bin\0", NULL }, { "lib", 0, "usr/lib\0", NULL }, - { "root", 0755, NULL, NULL }, + { "root", 0755, NULL, NULL, true }, { "sbin", 0, "usr/sbin\0", NULL }, { "usr", 0755, NULL, NULL }, { "var", 0755, NULL, NULL }, @@ -104,8 +105,13 @@ int base_filesystem_create(const char *root, uid_t uid, gid_t gid) { RUN_WITH_UMASK(0000) r = mkdirat(fd, table[i].dir, table[i].mode); - if (r < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create directory at %s/%s: %m", root, table[i].dir); + if (r < 0 && errno != EEXIST) { + log_full_errno(table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno, + "Failed to create directory at %s/%s: %m", root, table[i].dir); + + if (!table[i].ignore_failure) + return -errno; + } if (uid != UID_INVALID || gid != UID_INVALID) { if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 16b17c2c82..10df3fc3d6 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -574,14 +574,14 @@ int bus_check_peercred(sd_bus *c) { return 1; } -int bus_open_system_systemd(sd_bus **_bus) { +int bus_connect_system_systemd(sd_bus **_bus) { _cleanup_bus_unref_ sd_bus *bus = NULL; int r; assert(_bus); if (geteuid() != 0) - return sd_bus_open_system(_bus); + return sd_bus_default_system(_bus); /* If we are root and kdbus is not available, then let's talk * directly to the system instance, instead of going via the @@ -616,7 +616,7 @@ int bus_open_system_systemd(sd_bus **_bus) { r = sd_bus_start(bus); if (r < 0) - return sd_bus_open_system(_bus); + return sd_bus_default_system(_bus); r = bus_check_peercred(bus); if (r < 0) @@ -628,7 +628,7 @@ int bus_open_system_systemd(sd_bus **_bus) { return 0; } -int bus_open_user_systemd(sd_bus **_bus) { +int bus_connect_user_systemd(sd_bus **_bus) { _cleanup_bus_unref_ sd_bus *bus = NULL; _cleanup_free_ char *ee = NULL; const char *e; @@ -658,7 +658,7 @@ int bus_open_user_systemd(sd_bus **_bus) { e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) - return sd_bus_open_user(_bus); + return sd_bus_default_user(_bus); ee = bus_address_escape(e); if (!ee) @@ -674,7 +674,7 @@ int bus_open_user_systemd(sd_bus **_bus) { r = sd_bus_start(bus); if (r < 0) - return sd_bus_open_user(_bus); + return sd_bus_default_user(_bus); r = bus_check_peercred(bus); if (r < 0) @@ -1209,7 +1209,7 @@ int bus_map_all_properties( return bus_message_map_all_properties(m, map, userdata); } -int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); @@ -1244,7 +1244,7 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b return r; } -int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); @@ -1258,9 +1258,9 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us case BUS_TRANSPORT_LOCAL: if (user) - r = bus_open_user_systemd(bus); + r = bus_connect_user_systemd(bus); else - r = bus_open_system_systemd(bus); + r = bus_connect_system_systemd(bus); break; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index d2b2d701ce..f03f951dc7 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -65,11 +65,11 @@ int bus_test_polkit(sd_bus_message *call, int capability, const char *action, co int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error); void bus_verify_polkit_async_registry_free(Hashmap *registry); -int bus_open_system_systemd(sd_bus **_bus); -int bus_open_user_systemd(sd_bus **_bus); +int bus_connect_system_systemd(sd_bus **_bus); +int bus_connect_user_systemd(sd_bus **_bus); -int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); -int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_print_property(const char *name, sd_bus_message *property, bool all); int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all); diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 963d05d32e..1845068adb 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -78,7 +78,7 @@ int write_drop_in(const char *dir, const char *unit, unsigned level, if (r < 0) return r; - mkdir_p(p, 0755); + (void) mkdir_p(p, 0755); return write_string_file_atomic_label(q, data); } @@ -132,8 +132,7 @@ static int iterate_dir( if (errno == ENOENT) return 0; - log_error_errno(errno, "Failed to open directory %s: %m", path); - return -errno; + return log_error_errno(errno, "Failed to open directory %s: %m", path); } for (;;) { diff --git a/src/shared/pager.c b/src/shared/pager.c index 41da820938..d8f0fb404d 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -48,24 +48,27 @@ noreturn static void pager_fallback(void) { } int pager_open(bool jump_to_end) { - int fd[2]; + _cleanup_close_pair_ int fd[2] = { -1, -1 }; const char *pager; pid_t parent_pid; - int r; if (pager_pid > 0) return 1; - if ((pager = getenv("SYSTEMD_PAGER")) || (pager = getenv("PAGER"))) - if (!*pager || streq(pager, "cat")) - return 0; - if (!on_tty()) return 0; + pager = getenv("SYSTEMD_PAGER"); + if (!pager) + pager = getenv("PAGER"); + + /* If the pager is explicitly turned off, honour it */ + if (pager && (pager[0] == 0 || streq(pager, "cat"))) + return 0; + /* Determine and cache number of columns before we spawn the * pager so that we get the value from the actual tty */ - columns(); + (void) columns(); if (pipe(fd) < 0) return log_error_errno(errno, "Failed to create pager pipe: %m"); @@ -73,11 +76,8 @@ int pager_open(bool jump_to_end) { parent_pid = getpid(); pager_pid = fork(); - if (pager_pid < 0) { - r = log_error_errno(errno, "Failed to fork pager: %m"); - safe_close_pair(fd); - return r; - } + if (pager_pid < 0) + return log_error_errno(errno, "Failed to fork pager: %m"); /* In the child start the pager */ if (pager_pid == 0) { @@ -86,7 +86,7 @@ int pager_open(bool jump_to_end) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); - dup2(fd[0], STDIN_FILENO); + (void) dup2(fd[0], STDIN_FILENO); safe_close_pair(fd); /* Initialize a good set of less options */ @@ -141,7 +141,6 @@ int pager_open(bool jump_to_end) { if (dup2(fd[1], STDERR_FILENO) < 0) return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); - safe_close_pair(fd); return 1; } diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 1064fd5cbd..3dedbd1f62 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -226,7 +226,7 @@ static bool enough_memory_for_hibernation(void) { if (r < 0) return false; - r = get_status_field("/proc/meminfo", "\nActive(anon):", &active); + r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active); if (r < 0) { log_error_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m"); return false; diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c index 1de0b94fd5..b2cab948ef 100644 --- a/src/shared/sysctl-util.c +++ b/src/shared/sysctl-util.c @@ -19,18 +19,17 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <errno.h> -#include <string.h> -#include <stdio.h> -#include <limits.h> #include <getopt.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "fileio.h" #include "log.h" #include "util.h" -#include "fileio.h" -#include "build.h" #include "sysctl-util.h" char *sysctl_normalize(char *s) { diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 2b2310152d..1ba66eb998 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -20,18 +20,18 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdio.h> #include <errno.h> #include <getopt.h> +#include <stdio.h> #include "sd-messages.h" -#include "log.h" -#include "util.h" -#include "strv.h" + +#include "def.h" #include "fileio.h" -#include "build.h" +#include "log.h" #include "sleep-config.h" -#include "def.h" +#include "strv.h" +#include "util.h" static char* arg_verb = NULL; @@ -165,9 +165,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; /* done */ case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0 /* done */; + return version(); case '?': return -EINVAL; diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c index 715f440cb1..73c04fdfc0 100644 --- a/src/socket-proxy/socket-proxyd.c +++ b/src/socket-proxy/socket-proxyd.c @@ -20,12 +20,12 @@ ***/ #include <errno.h> +#include <fcntl.h> #include <getopt.h> +#include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <netdb.h> -#include <fcntl.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> @@ -33,12 +33,12 @@ #include "sd-daemon.h" #include "sd-event.h" #include "sd-resolve.h" + #include "log.h" +#include "path-util.h" +#include "set.h" #include "socket-util.h" #include "util.h" -#include "build.h" -#include "set.h" -#include "path-util.h" #define BUFFER_SIZE (256 * 1024) #define CONNECTIONS_MAX 256 @@ -603,9 +603,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case '?': return -EINVAL; diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 618844382f..ee34209a30 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -19,23 +19,22 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <errno.h> -#include <string.h> -#include <stdio.h> -#include <limits.h> #include <getopt.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> -#include "log.h" -#include "strv.h" -#include "util.h" -#include "hashmap.h" -#include "path-util.h" #include "conf-files.h" #include "fileio.h" -#include "build.h" +#include "hashmap.h" +#include "log.h" +#include "path-util.h" +#include "strv.h" #include "sysctl-util.h" +#include "util.h" static char **arg_prefixes = NULL; @@ -195,9 +194,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_PREFIX: { char *p; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index d0be59ec89..b8ffcdadec 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -37,7 +37,6 @@ #include "sd-daemon.h" #include "sd-login.h" -#include "build.h" #include "bus-common-errors.h" #include "bus-error.h" #include "bus-message.h" @@ -74,6 +73,7 @@ #include "unit-name.h" #include "util.h" #include "utmp-wtmp.h" +#include "verbs.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -134,23 +134,61 @@ static enum action { _ACTION_MAX } arg_action = ACTION_SYSTEMCTL; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; -static char *arg_host = NULL; +static const char *arg_host = NULL; static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; static bool arg_plain = false; static bool arg_firmware_setup = false; static bool arg_now = false; -static bool original_stdout_is_tty; - -static int daemon_reload(sd_bus *bus, char **args); +static int daemon_reload(int argc, char *argv[], void* userdata); static int halt_now(enum action a); static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet); -static char** strv_skip_first(char **strv) { - if (strv_length(strv) > 0) - return strv + 1; - return NULL; +static bool original_stdout_is_tty; + +typedef enum BusFocus { + BUS_FULL, /* The full bus indicated via --system or --user */ + BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */ + _BUS_FOCUS_MAX +} BusFocus; + +static sd_bus *busses[_BUS_FOCUS_MAX] = {}; + +static int acquire_bus(BusFocus focus, sd_bus **ret) { + int r; + + assert(focus < _BUS_FOCUS_MAX); + assert(ret); + + /* We only go directly to the manager, if we are using a local transport */ + if (arg_transport != BUS_TRANSPORT_LOCAL) + focus = BUS_FULL; + + if (!busses[focus]) { + bool user; + + user = arg_scope != UNIT_FILE_SYSTEM; + + if (focus == BUS_MANAGER) + r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]); + else + r = bus_connect_transport(arg_transport, arg_host, user, &busses[focus]); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + (void) sd_bus_set_allow_interactive_authorization(busses[focus], arg_ask_password); + } + + *ret = busses[focus]; + return 0; +} + +static void release_busses(void) { + BusFocus w; + + for (w = 0; w < _BUS_FOCUS_MAX; w++) + busses[w] = sd_bus_flush_close_unref(busses[w]); } static void pager_open_if_enabled(void) { @@ -230,42 +268,10 @@ static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) return EXIT_FAILURE; } -static void warn_wall(enum action a) { - static const char *table[_ACTION_MAX] = { - [ACTION_HALT] = "The system is going down for system halt NOW!", - [ACTION_REBOOT] = "The system is going down for reboot NOW!", - [ACTION_POWEROFF] = "The system is going down for power-off NOW!", - [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!", - [ACTION_RESCUE] = "The system is going down to rescue mode NOW!", - [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!", - [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!" - }; - - if (arg_no_wall) - return; - - if (arg_wall) { - _cleanup_free_ char *p; +static bool install_client_side(void) { - p = strv_join(arg_wall, " "); - if (!p) { - log_oom(); - return; - } - - if (*p) { - utmp_wall(p, NULL, NULL, NULL, NULL); - return; - } - } - - if (!table[a]) - return; - - utmp_wall(table[a], NULL, NULL, NULL, NULL); -} - -static bool avoid_bus(void) { + /* Decides when to execute enable/disable/... operations + * client-side rather than server-side. */ if (running_in_chroot() > 0) return true; @@ -652,15 +658,20 @@ static int get_unit_list_recursive( return c; } -static int list_units(sd_bus *bus, char **args) { +static int list_units(int argc, char *argv[], void *userdata) { _cleanup_free_ UnitInfo *unit_infos = NULL; _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; + sd_bus *bus; int r; pager_open_if_enabled(); - r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (r < 0) return r; @@ -676,6 +687,10 @@ static int get_triggered_units( _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; int r; + assert(bus); + assert(path); + assert(ret); + r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", @@ -684,9 +699,8 @@ static int get_triggered_units( "Triggers", &error, ret); - if (r < 0) - log_error("Failed to determine triggers: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r)); return 0; } @@ -710,10 +724,8 @@ static int get_listening( &error, &reply, "a(ss)"); - if (r < 0) { - log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) @@ -853,7 +865,7 @@ static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) { return 0; } -static int list_sockets(sd_bus *bus, char **args) { +static int list_sockets(int argc, char *argv[], void *userdata) { _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; @@ -863,10 +875,15 @@ static int list_sockets(sd_bus *bus, char **args) { unsigned cs = 0; size_t size = 0; int r = 0, n; + sd_bus *bus; pager_open_if_enabled(); - n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (n < 0) return n; @@ -947,10 +964,8 @@ static int get_next_elapse( &error, 't', &t.monotonic); - if (r < 0) { - log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r)); r = sd_bus_get_property_trivial( bus, @@ -961,10 +976,8 @@ static int get_next_elapse( &error, 't', &t.realtime); - if (r < 0) { - log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r)); *next = t; return 0; @@ -991,10 +1004,8 @@ static int get_last_trigger( &error, 't', last); - if (r < 0) { - log_error("Failed to get last trigger time: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r)); return 0; } @@ -1160,7 +1171,7 @@ static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) { return next_elapse; } -static int list_timers(sd_bus *bus, char **args) { +static int list_timers(int argc, char *argv[], void *userdata) { _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; _cleanup_free_ struct timer_info *timer_infos = NULL; @@ -1170,11 +1181,16 @@ static int list_timers(sd_bus *bus, char **args) { size_t size = 0; int n, c = 0; dual_timestamp nw; + sd_bus *bus; int r = 0; pager_open_if_enabled(); - n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (n < 0) return n; @@ -1326,7 +1342,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { printf("\n%u unit files listed.\n", c); } -static int list_unit_files(sd_bus *bus, char **args) { +static int list_unit_files(int argc, char *argv[], void *userdata) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ UnitFileList *units = NULL; UnitFileList *unit; @@ -1338,7 +1354,7 @@ static int list_unit_files(sd_bus *bus, char **args) { pager_open_if_enabled(); - if (avoid_bus()) { + if (install_client_side()) { Hashmap *h; UnitFileList *u; Iterator i; @@ -1351,8 +1367,7 @@ static int list_unit_files(sd_bus *bus, char **args) { r = unit_file_get_list(arg_scope, arg_root, h); if (r < 0) { unit_file_list_free(h); - log_error_errno(r, "Failed to get unit file list: %m"); - return r; + return log_error_errno(r, "Failed to get unit file list: %m"); } n_units = hashmap_size(h); @@ -1364,7 +1379,7 @@ static int list_unit_files(sd_bus *bus, char **args) { } HASHMAP_FOREACH(u, h, i) { - if (!output_show_unit_file(u, strv_skip_first(args))) + if (!output_show_unit_file(u, strv_skip(argv, 1))) continue; units[c++] = *u; @@ -1375,6 +1390,11 @@ static int list_unit_files(sd_bus *bus, char **args) { hashmap_free(h); } else { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; r = sd_bus_call_method( bus, @@ -1385,10 +1405,8 @@ static int list_unit_files(sd_bus *bus, char **args) { &error, &reply, NULL); - if (r < 0) { - log_error("Failed to list unit files: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to list unit files: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)"); if (r < 0) @@ -1404,7 +1422,7 @@ static int list_unit_files(sd_bus *bus, char **args) { unit_file_state_from_string(state) }; - if (output_show_unit_file(&units[c], strv_skip_first(args))) + if (output_show_unit_file(&units[c], strv_skip(argv, 1))) c ++; } @@ -1419,7 +1437,7 @@ static int list_unit_files(sd_bus *bus, char **args) { qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list); output_unit_file_list(units, c); - if (avoid_bus()) { + if (install_client_side()) { for (unit = units; unit < units + c; unit++) free(unit->path); } @@ -1511,10 +1529,8 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha &error, &reply, "s", "org.freedesktop.systemd1.Unit"); - if (r < 0) { - log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) @@ -1638,16 +1654,15 @@ static int list_dependencies_one( return 0; } -static int list_dependencies(sd_bus *bus, char **args) { +static int list_dependencies(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **units = NULL; _cleanup_free_ char *unit = NULL; const char *u; + sd_bus *bus; int r; - assert(bus); - - if (args[1]) { - r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &unit); + if (argv[1]) { + r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &unit); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); @@ -1657,6 +1672,10 @@ static int list_dependencies(sd_bus *bus, char **args) { pager_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + puts(u); return list_dependencies_one(bus, u, 0, &units, 0); @@ -1872,12 +1891,11 @@ static void output_machines_list(struct machine_info *machine_infos, unsigned n) printf("\n%u machines listed.\n", n); } -static int list_machines(sd_bus *bus, char **args) { +static int list_machines(int argc, char *argv[], void *userdata) { struct machine_info *machine_infos = NULL; + sd_bus *bus; int r; - assert(bus); - if (geteuid() != 0) { log_error("Must be root."); return -EPERM; @@ -1885,7 +1903,11 @@ static int list_machines(sd_bus *bus, char **args) { pager_open_if_enabled(); - r = get_machine_list(bus, &machine_infos, strv_skip_first(args)); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1)); if (r < 0) return r; @@ -1896,13 +1918,13 @@ static int list_machines(sd_bus *bus, char **args) { return 0; } -static int get_default(sd_bus *bus, char **args) { +static int get_default(int argc, char *argv[], void *userdata) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ char *_path = NULL; const char *path; int r; - if (!bus || avoid_bus()) { + if (install_client_side()) { r = unit_file_get_default(arg_scope, arg_root, &_path); if (r < 0) return log_error_errno(r, "Failed to get default target: %m"); @@ -1910,6 +1932,11 @@ static int get_default(sd_bus *bus, char **args) { } else { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; r = sd_bus_call_method( bus, @@ -1920,10 +1947,8 @@ static int get_default(sd_bus *bus, char **args) { &error, &reply, NULL); - if (r < 0) { - log_error("Failed to get default target: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &path); if (r < 0) @@ -1949,17 +1974,21 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha } } -static int set_default(sd_bus *bus, char **args) { +static int set_default(int argc, char *argv[], void *userdata) { _cleanup_free_ char *unit = NULL; - UnitFileChange *changes = NULL; - unsigned n_changes = 0; int r; - r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".target", &unit); + assert(argc >= 2); + assert(argv); + + r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &unit); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); - if (!bus || avoid_bus()) { + if (install_client_side()) { + UnitFileChange *changes = NULL; + unsigned n_changes = 0; + r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes); if (r < 0) return log_error_errno(r, "Failed to set default target: %m"); @@ -1967,13 +1996,19 @@ static int set_default(sd_bus *bus, char **args) { if (!arg_quiet) dump_unit_file_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); r = 0; } else { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + sd_bus *bus; polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -1983,10 +2018,8 @@ static int set_default(sd_bus *bus, char **args) { &error, &reply, "sb", unit, 1); - if (r < 0) { - log_error("Failed to set default target: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r)); r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) @@ -1994,13 +2027,11 @@ static int set_default(sd_bus *bus, char **args) { /* Try to reload if enabled */ if (!arg_no_reload) - r = daemon_reload(bus, args); + r = daemon_reload(argc, argv, userdata); else r = 0; } - unit_file_changes_free(changes, n_changes); - return r; } @@ -2085,17 +2116,24 @@ static bool output_show_job(struct job_info *job, char **patterns) { return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE); } -static int list_jobs(sd_bus *bus, char **args) { +static int list_jobs(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; const char *name, *type, *state, *job_path, *unit_path; _cleanup_free_ struct job_info *jobs = NULL; size_t size = 0; unsigned c = 0; + sd_bus *bus; uint32_t id; int r; bool skipped = false; + pager_open_if_enabled(); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -2105,10 +2143,8 @@ static int list_jobs(sd_bus *bus, char **args) { &error, &reply, NULL); - if (r < 0) { - log_error("Failed to list jobs: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, 'a', "(usssoo)"); if (r < 0) @@ -2117,7 +2153,7 @@ static int list_jobs(sd_bus *bus, char **args) { while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) { struct job_info job = { id, name, type, state }; - if (!output_show_job(&job, strv_skip_first(args))) { + if (!output_show_job(&job, strv_skip(argv, 1))) { skipped = true; continue; } @@ -2138,18 +2174,21 @@ static int list_jobs(sd_bus *bus, char **args) { return r; } -static int cancel_job(sd_bus *bus, char **args) { +static int cancel_job(int argc, char *argv[], void *userdata) { + sd_bus *bus; char **name; int r = 0; - assert(args); - - if (strv_length(args) <= 1) - return daemon_reload(bus, args); + if (argc <= 1) + return daemon_reload(argc, argv, userdata); polkit_agent_open_if_enabled(); - STRV_FOREACH(name, args+1) { + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + STRV_FOREACH(name, strv_skip(argv, 1)) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; uint32_t id; int q; @@ -2168,7 +2207,7 @@ static int cancel_job(sd_bus *bus, char **args) { NULL, "u", id); if (q < 0) { - log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q)); + log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q)); if (r == 0) r = q; } @@ -2253,7 +2292,6 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un static int unit_find_paths( sd_bus *bus, const char *unit_name, - bool avoid_bus_cache, LookupPaths *lp, char **fragment_path, char ***dropin_paths) { @@ -2274,7 +2312,7 @@ static int unit_find_paths( assert(fragment_path); assert(lp); - if (!avoid_bus_cache && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { + if (!install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL; _cleanup_free_ char *unit = NULL; @@ -2471,10 +2509,8 @@ static int check_triggering_units( "LoadState", &error, &state); - if (r < 0) { - log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r)); if (streq(state, "masked")) return 0; @@ -2487,10 +2523,8 @@ static int check_triggering_units( "TriggeredBy", &error, &triggered_by); - if (r < 0) { - log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r)); STRV_FOREACH(i, triggered_by) { r = check_one_unit(bus, *i, "active\0reloading\0", true); @@ -2586,8 +2620,7 @@ static int start_unit_one( verb = method_to_verb(method); - log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r)); - return r; + return log_error_errno(r, "Failed to %s %s: %s", verb, name, bus_error_message(error, r)); } r = sd_bus_message_read(reply, "o", &path); @@ -2608,11 +2641,13 @@ static int start_unit_one( } static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) { - _cleanup_strv_free_ char **mangled = NULL, **globs = NULL; char **name; int r, i; + assert(bus); + assert(ret); + STRV_FOREACH(name, names) { char *t; @@ -2637,9 +2672,6 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; - if (!bus) - return log_error_errno(EOPNOTSUPP, "Unit name globbing without bus is not implemented."); - r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply); if (r < 0) return r; @@ -2687,24 +2719,28 @@ static enum action verb_to_action(const char *verb) { return _ACTION_INVALID; } -static int start_unit(sd_bus *bus, char **args) { +static int start_unit(int argc, char *argv[], void *userdata) { _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; const char *method, *mode, *one_name, *suffix = NULL; _cleanup_strv_free_ char **names = NULL; + sd_bus *bus; char **name; int r = 0; - assert(bus); - ask_password_agent_open_if_enabled(); polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + if (arg_action == ACTION_SYSTEMCTL) { enum action action; - method = verb_to_method(args[0]); - action = verb_to_action(args[0]); - if (streq(args[0], "isolate")) { + method = verb_to_method(argv[0]); + action = verb_to_action(argv[0]); + + if (streq(argv[0], "isolate")) { mode = "isolate"; suffix = ".target"; } else @@ -2724,9 +2760,9 @@ static int start_unit(sd_bus *bus, char **args) { if (one_name) names = strv_new(one_name, NULL); else { - r = expand_names(bus, args + 1, suffix, &names); + r = expand_names(bus, strv_skip(argv, 1), suffix, &names); if (r < 0) - log_error_errno(r, "Failed to expand names: %m"); + return log_error_errno(r, "Failed to expand names: %m"); } if (!arg_no_block) { @@ -2761,18 +2797,55 @@ static int start_unit(sd_bus *bus, char **args) { return r; } +static int logind_set_wall_message(void) { +#ifdef HAVE_LOGIND + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + _cleanup_free_ char *m = NULL; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + m = strv_join(arg_wall, " "); + if (!m) + return log_oom(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetWallMessage", + &error, + NULL, + "sb", + m, + !arg_no_wall); + + if (r < 0) + return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r)); + +#endif + return 0; +} + /* Ask systemd-logind, which might grant access to unprivileged users * through PolicyKit */ -static int reboot_with_logind(sd_bus *bus, enum action a) { +static int logind_reboot(enum action a) { #ifdef HAVE_LOGIND _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *method, *description; + sd_bus *bus; int r; - if (!bus) - return -EIO; - polkit_agent_open_if_enabled(); + (void) logind_set_wall_message(); + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; switch (a) { @@ -2805,33 +2878,6 @@ static int reboot_with_logind(sd_bus *bus, enum action a) { return -EINVAL; } - if (!strv_isempty(arg_wall)) { - _cleanup_free_ char *m; - - m = strv_join(arg_wall, " "); - if (!m) - return log_oom(); - - r = sd_bus_call_method( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetWallMessage", - &error, - NULL, - "sb", - m, - !arg_no_wall); - - if (r < 0) { - log_warning_errno(r, "Failed to set wall message, ignoring: %s", - bus_error_message(&error, r)); - sd_bus_error_free(&error); - } - } - - r = sd_bus_call_method( bus, "org.freedesktop.login1", @@ -2842,27 +2888,25 @@ static int reboot_with_logind(sd_bus *bus, enum action a) { NULL, "b", arg_ask_password); if (r < 0) - log_error("Failed to %s via logind: %s", description, bus_error_message(&error, r)); + return log_error_errno(r, "Failed to %s via logind: %s", description, bus_error_message(&error, r)); - return r; + return 0; #else return -ENOSYS; #endif } -static int check_inhibitors(sd_bus *bus, enum action a) { +static int logind_check_inhibitors(enum action a) { #ifdef HAVE_LOGIND _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_strv_free_ char **sessions = NULL; const char *what, *who, *why, *mode; uint32_t uid, pid; + sd_bus *bus; unsigned c = 0; char **s; int r; - if (!bus) - return 0; - if (arg_ignore_inhibitors || arg_force > 0) return 0; @@ -2875,6 +2919,10 @@ static int check_inhibitors(sd_bus *bus, enum action a) { if (!on_tty()) return 0; + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + r = sd_bus_call_method( bus, "org.freedesktop.login1", @@ -2964,10 +3012,36 @@ static int check_inhibitors(sd_bus *bus, enum action a) { #endif } -static int prepare_firmware_setup(sd_bus *bus) { +static int logind_prepare_firmware_setup(void) { #ifdef HAVE_LOGIND _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetRebootToFirmwareSetup", + &error, + NULL, + "b", true); + if (r < 0) + return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r)); + + return 0; +#else + log_error("Cannot remotely indicate to EFI to boot into setup mode."); + return -ENOSYS; #endif +} + +static int prepare_firmware_setup(void) { int r; if (!arg_firmware_setup) @@ -2982,38 +3056,42 @@ static int prepare_firmware_setup(sd_bus *bus) { return r; } -#ifdef HAVE_LOGIND + return logind_prepare_firmware_setup(); +} + +static int set_exit_code(uint8_t code) { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_call_method( bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetRebootToFirmwareSetup", + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetExitCode", &error, NULL, - "b", true); - if (r < 0) { - log_error("Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r)); - return r; - } + "y", code); + if (r < 0) + return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); return 0; -#else - log_error("Cannot remotely indicate to EFI to boot into setup mode."); - return -EINVAL; -#endif } -static int start_special(sd_bus *bus, char **args) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; +static int start_special(int argc, char *argv[], void *userdata) { enum action a; int r; - assert(args); + assert(argv); - a = verb_to_action(args[0]); + a = verb_to_action(argv[0]); - r = check_inhibitors(bus, a); + r = logind_check_inhibitors(a); if (r < 0) return r; @@ -3022,39 +3100,29 @@ static int start_special(sd_bus *bus, char **args) { return -EPERM; } - r = prepare_firmware_setup(bus); + r = prepare_firmware_setup(); if (r < 0) return r; - if (a == ACTION_REBOOT && args[1]) { - r = update_reboot_param_file(args[1]); + if (a == ACTION_REBOOT && argc > 1) { + r = update_reboot_param_file(argv[1]); if (r < 0) return r; - } else if (a == ACTION_EXIT && strv_length(args) > 1) { - /* If the exit code is not given on the command line, don't - * reset it to zero: just keep it as it might have been set - * previously. */ + + } else if (a == ACTION_EXIT && argc > 1) { uint8_t code = 0; - r = safe_atou8(args[1], &code); - if (r < 0) { - log_error("Invalid exit code."); - return -EINVAL; - } + /* If the exit code is not given on the command line, + * don't reset it to zero: just keep it as it might + * have been set previously. */ - r = sd_bus_call_method( - bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "SetExitCode", - &error, - NULL, - "y", code); - if (r < 0) { - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); + r = safe_atou8(argv[1], &code); + if (r < 0) + return log_error_errno(r, "Invalid exit code."); + + r = set_exit_code(code); + if (r < 0) return r; - } } if (arg_force >= 2 && @@ -3071,39 +3139,37 @@ static int start_special(sd_bus *bus, char **args) { ACTION_REBOOT, ACTION_KEXEC, ACTION_EXIT)) - return daemon_reload(bus, args); + return daemon_reload(argc, argv, userdata); - /* first try logind, to allow authentication with polkit */ - if (geteuid() != 0 && - IN_SET(a, + /* First try logind, to allow authentication with polkit */ + if (IN_SET(a, ACTION_POWEROFF, ACTION_REBOOT, ACTION_SUSPEND, ACTION_HIBERNATE, ACTION_HYBRID_SLEEP)) { - r = reboot_with_logind(bus, a); + r = logind_reboot(a); if (r >= 0) return r; if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) /* requested operation is not supported or already in progress */ return r; - /* on all other errors, try low-level operation */ - } - r = start_unit(bus, args); - if (r == EXIT_SUCCESS) - warn_wall(a); + /* On all other errors, try low-level operation */ + } - return r; + return start_unit(argc, argv, userdata); } -static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) { +static int check_unit_generic(int code, const char *good_states, char **args) { _cleanup_strv_free_ char **names = NULL; + sd_bus *bus; char **name; int r; - assert(bus); - assert(args); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; r = expand_names(bus, args, NULL, &names); if (r < 0) @@ -3122,25 +3188,27 @@ static int check_unit_generic(sd_bus *bus, int code, const char *good_states, ch return r; } -static int check_unit_active(sd_bus *bus, char **args) { +static int check_unit_active(int argc, char *argv[], void *userdata) { /* According to LSB: 3, "program is not running" */ - return check_unit_generic(bus, 3, "active\0reloading\0", args + 1); + return check_unit_generic(3, "active\0reloading\0", strv_skip(argv, 1)); } -static int check_unit_failed(sd_bus *bus, char **args) { - return check_unit_generic(bus, 1, "failed\0", args + 1); +static int check_unit_failed(int argc, char *argv[], void *userdata) { + return check_unit_generic(1, "failed\0", strv_skip(argv, 1)); } -static int kill_unit(sd_bus *bus, char **args) { +static int kill_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; char *kill_who = NULL, **name; + sd_bus *bus; int r, q; - assert(bus); - assert(args); - polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + if (!arg_kill_who) arg_kill_who = "all"; @@ -3148,9 +3216,9 @@ static int kill_unit(sd_bus *bus, char **args) { if (streq(arg_job_mode, "fail")) kill_who = strjoina(arg_kill_who, "-fail", NULL); - r = expand_names(bus, args + 1, NULL, &names); + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) - log_error_errno(r, "Failed to expand names: %m"); + return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; @@ -3165,7 +3233,7 @@ static int kill_unit(sd_bus *bus, char **args) { NULL, "ssi", *names, kill_who ? kill_who : arg_kill_who, arg_signal); if (q < 0) { - log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q)); + log_error_errno(q, "Failed to kill unit %s: %s", *names, bus_error_message(&error, q)); if (r == 0) r = q; } @@ -3456,7 +3524,7 @@ static void print_status_info( printf("Condition: start %scondition failed%s at %s%s%s\n", ansi_highlight_yellow(), ansi_normal(), - s2, s1 ? "; " : "", s1 ? s1 : ""); + s2, s1 ? "; " : "", strempty(s1)); if (i->failed_condition_trigger) printf(" none of the trigger conditions were met\n"); else if (i->failed_condition) @@ -3472,7 +3540,7 @@ static void print_status_info( printf(" Assert: start %sassertion failed%s at %s%s%s\n", ansi_highlight_red(), ansi_normal(), - s2, s1 ? "; " : "", s1 ? s1 : ""); + s2, s1 ? "; " : "", strempty(s1)); if (i->failed_assert_trigger) printf(" none of the trigger assertions were met\n"); else if (i->failed_assert) @@ -3861,13 +3929,13 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo * info->name = strdup(name); if (!info->name) - log_oom(); + return log_oom(); LIST_PREPEND(exec, i->exec, info); info = new0(ExecStatusInfo, 1); if (!info) - log_oom(); + return log_oom(); } if (r < 0) @@ -4439,10 +4507,8 @@ static int get_unit_dbus_path_by_pid( &error, &reply, "u", pid); - if (r < 0) { - log_error("Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r)); r = sd_bus_message_read(reply, "o", &u); if (r < 0) @@ -4551,16 +4617,22 @@ static int show_system_status(sd_bus *bus) { return 0; } -static int show(sd_bus *bus, char **args) { - bool show_properties, show_status, new_line = false; +static int show(int argc, char *argv[], void *userdata) { + bool show_properties, show_status, show_help, new_line = false; bool ellipsized = false; int r, ret = 0; + sd_bus *bus; - assert(bus); - assert(args); + assert(argv); + + show_properties = streq(argv[0], "show"); + show_status = streq(argv[0], "status"); + show_help = streq(argv[0], "help"); - show_properties = streq(args[0], "show"); - show_status = streq(args[0], "status"); + if (show_help && argc <= 1) { + log_error("This command expects one or more unit names. Did you mean --help?"); + return -EINVAL; + } if (show_properties) pager_open_if_enabled(); @@ -4571,24 +4643,27 @@ static int show(sd_bus *bus, char **args) { * be split up into many files. */ setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384)); - /* If no argument is specified inspect the manager itself */ + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; - if (show_properties && strv_length(args) <= 1) - return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized); + /* If no argument is specified inspect the manager itself */ + if (show_properties && argc <= 1) + return show_one(argv[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized); - if (show_status && strv_length(args) <= 1) { + if (show_status && argc <= 1) { pager_open_if_enabled(); show_system_status(bus); new_line = true; if (arg_all) - ret = show_all(args[0], bus, false, &new_line, &ellipsized); + ret = show_all(argv[0], bus, false, &new_line, &ellipsized); } else { _cleanup_free_ char **patterns = NULL; char **name; - STRV_FOREACH(name, args + 1) { + STRV_FOREACH(name, strv_skip(argv, 1)) { _cleanup_free_ char *unit = NULL; uint32_t id; @@ -4611,8 +4686,7 @@ static int show(sd_bus *bus, char **args) { } } - r = show_one(args[0], bus, unit, show_properties, - &new_line, &ellipsized); + r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) @@ -4624,7 +4698,7 @@ static int show(sd_bus *bus, char **args) { r = expand_names(bus, patterns, NULL, &names); if (r < 0) - log_error_errno(r, "Failed to expand names: %m"); + return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_free_ char *unit; @@ -4633,8 +4707,7 @@ static int show(sd_bus *bus, char **args) { if (!unit) return log_oom(); - r = show_one(args[0], bus, unit, show_properties, - &new_line, &ellipsized); + r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) @@ -4694,19 +4767,18 @@ static int cat_file(const char *filename, bool newline) { return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false); } -static int cat(sd_bus *bus, char **args) { +static int cat(int argc, char *argv[], void *userdata) { _cleanup_free_ char *user_home = NULL; _cleanup_free_ char *user_runtime = NULL; _cleanup_lookup_paths_free_ LookupPaths lp = {}; _cleanup_strv_free_ char **names = NULL; char **name; - bool first = true, avoid_bus_cache; + sd_bus *bus; + bool first = true; int r; - assert(args); - if (arg_transport != BUS_TRANSPORT_LOCAL) { - log_error("Cannot remotely cat units"); + log_error("Cannot remotely cat units."); return -EINVAL; } @@ -4714,11 +4786,13 @@ static int cat(sd_bus *bus, char **args) { if (r < 0) return r; - r = expand_names(bus, args + 1, NULL, &names); + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) - return log_error_errno(r, "Failed to expand names: %m"); + return r; - avoid_bus_cache = !bus || avoid_bus(); + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); pager_open_if_enabled(); @@ -4727,7 +4801,7 @@ static int cat(sd_bus *bus, char **args) { _cleanup_strv_free_ char **dropin_paths = NULL; char **path; - r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths); + r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths); if (r < 0) return r; else if (r == 0) @@ -4754,15 +4828,20 @@ static int cat(sd_bus *bus, char **args) { return 0; } -static int set_property(sd_bus *bus, char **args) { +static int set_property(int argc, char *argv[], void *userdata) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *n = NULL; + sd_bus *bus; char **i; int r; polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_message_new_method_call( bus, &m, @@ -4773,7 +4852,7 @@ static int set_property(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &n); + r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); @@ -4785,7 +4864,7 @@ static int set_property(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - STRV_FOREACH(i, args + 2) { + STRV_FOREACH(i, strv_skip(argv, 2)) { r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); if (r < 0) return bus_log_create_error(r); @@ -4804,25 +4883,24 @@ static int set_property(sd_bus *bus, char **args) { return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); - if (r < 0) { - log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r)); return 0; } -static int snapshot(sd_bus *bus, char **args) { +static int snapshot(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ char *n = NULL, *id = NULL; const char *path; + sd_bus *bus; int r; polkit_agent_open_if_enabled(); - if (strv_length(args) > 1) { - r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".snapshot", &n); + if (argc > 1) { + r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".snapshot", &n); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); } else { @@ -4831,6 +4909,10 @@ static int snapshot(sd_bus *bus, char **args) { return log_oom(); } + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -4840,10 +4922,8 @@ static int snapshot(sd_bus *bus, char **args) { &error, &reply, "sb", n, false); - if (r < 0) { - log_error("Failed to create snapshot: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to create snapshot: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "o", &path); if (r < 0) @@ -4857,10 +4937,8 @@ static int snapshot(sd_bus *bus, char **args) { "Id", &error, &id); - if (r < 0) { - log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get ID of snapshot: %s", bus_error_message(&error, r)); if (!arg_quiet) puts(id); @@ -4868,18 +4946,21 @@ static int snapshot(sd_bus *bus, char **args) { return 0; } -static int delete_snapshot(sd_bus *bus, char **args) { +static int delete_snapshot(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; + sd_bus *bus; char **name; int r; - assert(args); - polkit_agent_open_if_enabled(); - r = expand_names(bus, args + 1, ".snapshot", &names); + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) - log_error_errno(r, "Failed to expand names: %m"); + return r; + + r = expand_names(bus, strv_skip(argv, 1), ".snapshot", &names); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; @@ -4895,7 +4976,7 @@ static int delete_snapshot(sd_bus *bus, char **args) { NULL, "s", *name); if (q < 0) { - log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q)); + log_error_errno(q, "Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q)); if (r == 0) r = q; } @@ -4904,13 +4985,18 @@ static int delete_snapshot(sd_bus *bus, char **args) { return r; } -static int daemon_reload(sd_bus *bus, char **args) { +static int daemon_reload(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *method; + sd_bus *bus; int r; polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + if (arg_action == ACTION_RELOAD) method = "Reload"; else if (arg_action == ACTION_REEXEC) @@ -4919,15 +5005,15 @@ static int daemon_reload(sd_bus *bus, char **args) { assert(arg_action == ACTION_SYSTEMCTL); method = - streq(args[0], "clear-jobs") || - streq(args[0], "cancel") ? "ClearJobs" : - streq(args[0], "daemon-reexec") ? "Reexecute" : - streq(args[0], "reset-failed") ? "ResetFailed" : - streq(args[0], "halt") ? "Halt" : - streq(args[0], "poweroff") ? "PowerOff" : - streq(args[0], "reboot") ? "Reboot" : - streq(args[0], "kexec") ? "KExec" : - streq(args[0], "exit") ? "Exit" : + streq(argv[0], "clear-jobs") || + streq(argv[0], "cancel") ? "ClearJobs" : + streq(argv[0], "daemon-reexec") ? "Reexecute" : + streq(argv[0], "reset-failed") ? "ResetFailed" : + streq(argv[0], "halt") ? "Halt" : + streq(argv[0], "poweroff") ? "PowerOff" : + streq(argv[0], "reboot") ? "Reboot" : + streq(argv[0], "kexec") ? "KExec" : + streq(argv[0], "exit") ? "Exit" : /* "daemon-reload" */ "Reload"; } @@ -4949,24 +5035,29 @@ static int daemon_reload(sd_bus *bus, char **args) { * reply */ r = 0; else if (r < 0) - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); + return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); return r < 0 ? r : 0; } -static int reset_failed(sd_bus *bus, char **args) { +static int reset_failed(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; + sd_bus *bus; char **name; int r, q; - if (strv_length(args) <= 1) - return daemon_reload(bus, args); + if (argc <= 1) + return daemon_reload(argc, argv, userdata); polkit_agent_open_if_enabled(); - r = expand_names(bus, args + 1, NULL, &names); + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) - log_error_errno(r, "Failed to expand names: %m"); + return r; + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); STRV_FOREACH(name, names) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; @@ -4981,7 +5072,7 @@ static int reset_failed(sd_bus *bus, char **args) { NULL, "s", *name); if (q < 0) { - log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q)); + log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q)); if (r == 0) r = q; } @@ -4990,14 +5081,19 @@ static int reset_failed(sd_bus *bus, char **args) { return r; } -static int show_environment(sd_bus *bus, char **args) { +static int show_environment(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; const char *text; + sd_bus *bus; int r; pager_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_get_property( bus, "org.freedesktop.systemd1", @@ -5007,10 +5103,8 @@ static int show_environment(sd_bus *bus, char **args) { &error, &reply, "as"); - if (r < 0) { - log_error("Failed to get environment: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r)); r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"); if (r < 0) @@ -5028,23 +5122,27 @@ static int show_environment(sd_bus *bus, char **args) { return 0; } -static int switch_root(sd_bus *bus, char **args) { +static int switch_root(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *cmdline_init = NULL; const char *root, *init; - unsigned l; + sd_bus *bus; int r; - l = strv_length(args); - if (l < 2 || l > 3) { + if (arg_transport != BUS_TRANSPORT_LOCAL) { + log_error("Cannot switch root remotely."); + return -EINVAL; + } + + if (argc < 2 || argc > 3) { log_error("Wrong number of arguments."); return -EINVAL; } - root = args[1]; + root = argv[1]; - if (l >= 3) - init = args[2]; + if (argc >= 3) + init = argv[2]; else { r = parse_env_file("/proc/cmdline", WHITESPACE, "init", &cmdline_init, @@ -5070,6 +5168,10 @@ static int switch_root(sd_bus *bus, char **args) { init = NULL; } + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + log_debug("Switching root - root: %s; init: %s", root, strna(init)); r = sd_bus_call_method( @@ -5081,26 +5183,29 @@ static int switch_root(sd_bus *bus, char **args) { &error, NULL, "ss", root, init); - if (r < 0) { - log_error("Failed to switch root: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r)); return 0; } -static int set_environment(sd_bus *bus, char **args) { +static int set_environment(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; const char *method; + sd_bus *bus; int r; - assert(bus); - assert(args); + assert(argc > 1); + assert(argv); polkit_agent_open_if_enabled(); - method = streq(args[0], "set-environment") + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + method = streq(argv[0], "set-environment") ? "SetEnvironment" : "UnsetEnvironment"; @@ -5114,29 +5219,29 @@ static int set_environment(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_append_strv(m, args + 1); + r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); if (r < 0) return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); - if (r < 0) { - log_error("Failed to set environment: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r)); return 0; } -static int import_environment(sd_bus *bus, char **args) { +static int import_environment(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; + sd_bus *bus; int r; - assert(bus); - assert(args); - polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_message_new_method_call( bus, &m, @@ -5147,7 +5252,7 @@ static int import_environment(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - if (strv_isempty(args + 1)) + if (argc < 2) r = sd_bus_message_append_strv(m, environ); else { char **a, **b; @@ -5156,7 +5261,7 @@ static int import_environment(sd_bus *bus, char **args) { if (r < 0) return bus_log_create_error(r); - STRV_FOREACH(a, args + 1) { + STRV_FOREACH(a, strv_skip(argv, 1)) { if (!env_name_is_valid(*a)) { log_error("Not a valid environment variable name: %s", *a); @@ -5184,10 +5289,8 @@ static int import_environment(sd_bus *bus, char **args) { return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, NULL); - if (r < 0) { - log_error("Failed to import environment: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r)); return 0; } @@ -5290,13 +5393,13 @@ static int enable_sysv_units(const char *verb, char **args) { (void) reset_signal_mask(); execv(argv[0], (char**) argv); - log_error("Failed to execute %s: %m", argv[0]); + log_error_errno(r, "Failed to execute %s: %m", argv[0]); _exit(EXIT_FAILURE); } j = wait_for_terminate(pid, &status); if (j < 0) { - log_error_errno(r, "Failed to wait for child: %m"); + log_error_errno(j, "Failed to wait for child: %m"); return j; } @@ -5366,18 +5469,18 @@ static int mangle_names(char **original_names, char ***mangled_names) { return 0; } -static int enable_unit(sd_bus *bus, char **args) { +static int enable_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; - const char *verb = args[0]; + const char *verb = argv[0]; UnitFileChange *changes = NULL; unsigned n_changes = 0; int carries_install_info = -1; int r; - if (!args[1]) + if (!argv[1]) return 0; - r = mangle_names(args+1, &names); + r = mangle_names(strv_skip(argv, 1), &names); if (r < 0) return r; @@ -5390,7 +5493,7 @@ static int enable_unit(sd_bus *bus, char **args) { if (strv_isempty(names)) return 0; - if (!bus || avoid_bus()) { + if (install_client_side()) { if (streq(verb, "enable")) { r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes); carries_install_info = r; @@ -5426,9 +5529,14 @@ static int enable_unit(sd_bus *bus, char **args) { int expect_carries_install_info = false; bool send_force = true, send_preset_mode = false; const char *method; + sd_bus *bus; polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + if (streq(verb, "enable")) { method = "EnableUnitFiles"; expect_carries_install_info = true; @@ -5488,10 +5596,8 @@ static int enable_unit(sd_bus *bus, char **args) { } r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) { - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); if (expect_carries_install_info) { r = sd_bus_message_read(reply, "b", &carries_install_info); @@ -5505,7 +5611,7 @@ static int enable_unit(sd_bus *bus, char **args) { /* Try to reload if enabled */ if (!arg_no_reload) - r = daemon_reload(bus, args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -5521,16 +5627,21 @@ static int enable_unit(sd_bus *bus, char **args) { "3) A unit may be started when needed via activation (socket, path, timer,\n" " D-Bus, udev, scripted systemctl call, ...).\n"); - if (arg_now && n_changes > 0 && STR_IN_SET(args[0], "enable", "disable", "mask")) { + if (arg_now && n_changes > 0 && STR_IN_SET(argv[0], "enable", "disable", "mask")) { char *new_args[n_changes + 2]; + sd_bus *bus; unsigned i; - new_args[0] = streq(args[0], "enable") ? (char *)"start" : (char *)"stop"; + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop"); for (i = 0; i < n_changes; i++) new_args[i + 1] = basename(changes[i].path); new_args[i + 1] = NULL; - r = start_unit(bus, new_args); + r = start_unit(strv_length(new_args), new_args, userdata); } finish: @@ -5539,21 +5650,21 @@ finish: return r; } -static int add_dependency(sd_bus *bus, char **args) { +static int add_dependency(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; _cleanup_free_ char *target = NULL; - const char *verb = args[0]; + const char *verb = argv[0]; UnitDependency dep; int r = 0; - if (!args[1]) + if (!argv[1]) return 0; - r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".target", &target); + r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &target); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); - r = mangle_names(args+2, &names); + r = mangle_names(strv_skip(argv, 2), &names); if (r < 0) return r; @@ -5564,7 +5675,7 @@ static int add_dependency(sd_bus *bus, char **args) { else assert_not_reached("Unknown verb"); - if (!bus || avoid_bus()) { + if (install_client_side()) { UnitFileChange *changes = NULL; unsigned n_changes = 0; @@ -5581,9 +5692,14 @@ static int add_dependency(sd_bus *bus, char **args) { } else { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_message_new_method_call( bus, &m, @@ -5603,17 +5719,15 @@ static int add_dependency(sd_bus *bus, char **args) { return bus_log_create_error(r); r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) { - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; if (!arg_no_reload) - r = daemon_reload(bus, args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -5621,12 +5735,12 @@ static int add_dependency(sd_bus *bus, char **args) { return r; } -static int preset_all(sd_bus *bus, char **args) { +static int preset_all(int argc, char *argv[], void *userdata) { UnitFileChange *changes = NULL; unsigned n_changes = 0; int r; - if (!bus || avoid_bus()) { + if (install_client_side()) { r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes); if (r < 0) { @@ -5642,9 +5756,14 @@ static int preset_all(sd_bus *bus, char **args) { } else { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + sd_bus *bus; polkit_agent_open_if_enabled(); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_call_method( bus, "org.freedesktop.systemd1", @@ -5657,17 +5776,15 @@ static int preset_all(sd_bus *bus, char **args) { unit_file_preset_mode_to_string(arg_preset_mode), arg_runtime, arg_force); - if (r < 0) { - log_error("Failed to execute operation: %s", bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, NULL, NULL); if (r < 0) return r; if (!arg_no_reload) - r = daemon_reload(bus, args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -5678,25 +5795,24 @@ finish: return r; } -static int unit_is_enabled(sd_bus *bus, char **args) { +static int unit_is_enabled(int argc, char *argv[], void *userdata) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **names = NULL; bool enabled; char **name; int r; - r = mangle_names(args+1, &names); + r = mangle_names(strv_skip(argv, 1), &names); if (r < 0) return r; - r = enable_sysv_units(args[0], names); + r = enable_sysv_units(argv[0], names); if (r < 0) return r; enabled = r > 0; - if (!bus || avoid_bus()) { + if (install_client_side()) { STRV_FOREACH(name, names) { UnitFileState state; @@ -5717,6 +5833,13 @@ static int unit_is_enabled(sd_bus *bus, char **args) { } } else { + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + STRV_FOREACH(name, names) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; const char *s; @@ -5730,10 +5853,8 @@ static int unit_is_enabled(sd_bus *bus, char **args) { &error, &reply, "s", *name); - if (r < 0) { - log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &s); if (r < 0) @@ -5750,10 +5871,21 @@ static int unit_is_enabled(sd_bus *bus, char **args) { return !enabled; } -static int is_system_running(sd_bus *bus, char **args) { +static int is_system_running(int argc, char *argv[], void *userdata) { _cleanup_free_ char *state = NULL; + sd_bus *bus; int r; + if (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted()) { + if (!arg_quiet) + puts("offline"); + return EXIT_FAILURE; + } + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", @@ -5775,7 +5907,7 @@ static int is_system_running(sd_bus *bus, char **args) { } static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) { - char *t; + _cleanup_free_ char *t = NULL; int r; assert(new_path); @@ -5787,27 +5919,21 @@ static int create_edit_temp_file(const char *new_path, const char *original_path return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path); r = mkdir_parents(new_path, 0755); - if (r < 0) { - log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path); - free(t); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path); r = copy_file(original_path, t, 0, 0644, 0); if (r == -ENOENT) { + r = touch(t); - if (r < 0) { - log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); - free(t); - return r; - } - } else if (r < 0) { - log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t); - free(t); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); + + } else if (r < 0) + return log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t); *ret_tmp_fn = t; + t = NULL; return 0; } @@ -5815,6 +5941,9 @@ static int create_edit_temp_file(const char *new_path, const char *original_path static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) { _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL; + assert(name); + assert(ret_path); + switch (arg_scope) { case UNIT_FILE_SYSTEM: path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name); @@ -5845,12 +5974,16 @@ static int get_file_to_edit(const char *name, const char *user_home, const char return log_oom(); if (arg_runtime) { - if (access(path, F_OK) >= 0) - return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", - run, path); - if (path2 && access(path2, F_OK) >= 0) - return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", - run, path2); + if (access(path, F_OK) >= 0) { + log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path); + return -EEXIST; + } + + if (path2 && access(path2, F_OK) >= 0) { + log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path2); + return -EEXIST; + } + *ret_path = run; run = NULL; } else { @@ -5862,8 +5995,7 @@ static int get_file_to_edit(const char *name, const char *user_home, const char } static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) { - char *tmp_new_path, *ending; - char *tmp_tmp_path; + char *tmp_new_path, *tmp_tmp_path, *ending; int r; assert(unit_name); @@ -5895,8 +6027,7 @@ static int unit_file_create_copy( char **ret_new_path, char **ret_tmp_path) { - char *tmp_new_path; - char *tmp_tmp_path; + char *tmp_new_path, *tmp_tmp_path; int r; assert(fragment_path); @@ -5943,10 +6074,8 @@ static int run_editor(char **paths) { assert(paths); pid = fork(); - if (pid < 0) { - log_error_errno(errno, "Failed to fork: %m"); - return -errno; - } + if (pid < 0) + return log_error_errno(errno, "Failed to fork: %m"); if (pid == 0) { const char **args; @@ -6004,7 +6133,7 @@ static int run_editor(char **paths) { * failing. */ if (errno != ENOENT) { - log_error("Failed to execute %s: %m", editor); + log_error_errno(errno, "Failed to execute %s: %m", editor); _exit(EXIT_FAILURE); } } @@ -6017,14 +6146,13 @@ static int run_editor(char **paths) { if (r < 0) return log_error_errno(r, "Failed to wait for child: %m"); - return r; + return 0; } static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { _cleanup_free_ char *user_home = NULL; _cleanup_free_ char *user_runtime = NULL; _cleanup_lookup_paths_free_ LookupPaths lp = {}; - bool avoid_bus_cache; char **name; int r; @@ -6035,13 +6163,11 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { if (r < 0) return r; - avoid_bus_cache = !bus || avoid_bus(); - STRV_FOREACH(name, names) { _cleanup_free_ char *path = NULL; char *new_path, *tmp_path; - r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL); + r = unit_find_paths(bus, *name, &lp, &path, NULL); if (r < 0) return r; else if (r == 0) @@ -6067,25 +6193,28 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { return 0; } -static int edit(sd_bus *bus, char **args) { +static int edit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; _cleanup_strv_free_ char **paths = NULL; char **original, **tmp; + sd_bus *bus; int r; - assert(args); - if (!on_tty()) { - log_error("Cannot edit units if not on a tty"); + log_error("Cannot edit units if not on a tty."); return -EINVAL; } if (arg_transport != BUS_TRANSPORT_LOCAL) { - log_error("Cannot remotely edit units"); + log_error("Cannot edit units remotely."); return -EINVAL; } - r = expand_names(bus, args + 1, NULL, &names); + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); @@ -6101,13 +6230,14 @@ static int edit(sd_bus *bus, char **args) { goto end; STRV_FOREACH_PAIR(original, tmp, paths) { - /* If the temporary file is empty we ignore it. - * It's useful if the user wants to cancel its modification + /* If the temporary file is empty we ignore it. It's + * useful if the user wants to cancel its modification */ if (null_or_empty_path(*tmp)) { - log_warning("Editing \"%s\" canceled: temporary file is empty", *original); + log_warning("Editing \"%s\" canceled: temporary file is empty.", *original); continue; } + r = rename(*tmp, *original); if (r < 0) { r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original); @@ -6115,12 +6245,14 @@ static int edit(sd_bus *bus, char **args) { } } - if (!arg_no_reload && bus && !avoid_bus()) - r = daemon_reload(bus, args); + r = 0; + + if (!arg_no_reload && !install_client_side()) + r = daemon_reload(argc, argv, userdata); end: STRV_FOREACH_PAIR(original, tmp, paths) - unlink_noerrno(*tmp); + (void) unlink(*tmp); return r; } @@ -6497,9 +6629,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 't': { const char *word, *state; @@ -6673,7 +6803,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { break; case 's': - if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) { + arg_signal = signal_from_string_try_harder(optarg); + if (arg_signal < 0) { log_error("Failed to parse signal string %s.", optarg); return -EINVAL; } @@ -6880,7 +7011,7 @@ static int halt_parse_argv(int argc, char *argv[]) { return 1; } -static int parse_time_spec(const char *t, usec_t *_u) { +static int parse_shutdown_time_spec(const char *t, usec_t *_u) { assert(t); assert(_u); @@ -6946,12 +7077,13 @@ static int shutdown_parse_argv(int argc, char *argv[]) { {} }; + char **wall = NULL; int c, r; assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "HPrhkKtafFc", options, NULL)) >= 0) switch (c) { case ARG_HELP: @@ -7009,7 +7141,7 @@ static int shutdown_parse_argv(int argc, char *argv[]) { } if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) { - r = parse_time_spec(argv[optind], &arg_when); + r = parse_shutdown_time_spec(argv[optind], &arg_when); if (r < 0) { log_error("Failed to parse time specification: %s", argv[optind]); return r; @@ -7019,10 +7151,16 @@ static int shutdown_parse_argv(int argc, char *argv[]) { if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN) /* No time argument for shutdown cancel */ - arg_wall = argv + optind; + wall = argv + optind; else if (argc > optind + 1) /* We skip the time argument */ - arg_wall = argv + optind + 1; + wall = argv + optind + 1; + + if (wall) { + arg_wall = strv_copy(wall); + if (!arg_wall) + return log_oom(); + } optind = argc; @@ -7086,8 +7224,7 @@ static int telinit_parse_argv(int argc, char *argv[]) { } if (optind >= argc) { - log_error("%s: required argument missing.", - program_invocation_short_name); + log_error("%s: required argument missing.", program_invocation_short_name); return -EINVAL; } @@ -7222,7 +7359,7 @@ _pure_ static int action_to_runlevel(void) { } static int talk_initctl(void) { - +#ifdef HAVE_SYSV_COMPAT struct init_request request = { .magic = INIT_MAGIC, .sleeptime = 0, @@ -7244,8 +7381,7 @@ static int talk_initctl(void) { if (errno == ENOENT) return 0; - log_error_errno(errno, "Failed to open "INIT_FIFO": %m"); - return -errno; + return log_error_errno(errno, "Failed to open "INIT_FIFO": %m"); } r = loop_write(fd, &request, sizeof(request), false); @@ -7253,177 +7389,91 @@ static int talk_initctl(void) { return log_error_errno(r, "Failed to write to "INIT_FIFO": %m"); return 1; +#else + return 0; +#endif } -static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) { - - static const struct { - const char* verb; - const enum { - MORE, - LESS, - EQUAL - } argc_cmp; - const int argc; - int (* const dispatch)(sd_bus *bus, char **args); - const enum { - NOBUS = 1, - FORCE, - } bus; - } verbs[] = { - { "list-units", MORE, 0, list_units }, - { "list-unit-files", MORE, 1, list_unit_files, NOBUS }, - { "list-sockets", MORE, 1, list_sockets }, - { "list-timers", MORE, 1, list_timers }, - { "list-jobs", MORE, 1, list_jobs }, - { "list-machines", MORE, 1, list_machines }, - { "clear-jobs", EQUAL, 1, daemon_reload }, - { "cancel", MORE, 2, cancel_job }, - { "start", MORE, 2, start_unit }, - { "stop", MORE, 2, start_unit }, - { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */ - { "reload", MORE, 2, start_unit }, - { "restart", MORE, 2, start_unit }, - { "try-restart", MORE, 2, start_unit }, - { "reload-or-restart", MORE, 2, start_unit }, - { "reload-or-try-restart", MORE, 2, start_unit }, - { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */ - { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */ - { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */ - { "isolate", EQUAL, 2, start_unit }, - { "kill", MORE, 2, kill_unit }, - { "is-active", MORE, 2, check_unit_active }, - { "check", MORE, 2, check_unit_active }, - { "is-failed", MORE, 2, check_unit_failed }, - { "show", MORE, 1, show }, - { "cat", MORE, 2, cat, NOBUS }, - { "status", MORE, 1, show }, - { "help", MORE, 2, show }, - { "snapshot", LESS, 2, snapshot }, - { "delete", MORE, 2, delete_snapshot }, - { "daemon-reload", EQUAL, 1, daemon_reload }, - { "daemon-reexec", EQUAL, 1, daemon_reload }, - { "show-environment", EQUAL, 1, show_environment }, - { "set-environment", MORE, 2, set_environment }, - { "unset-environment", MORE, 2, set_environment }, - { "import-environment", MORE, 1, import_environment}, - { "halt", EQUAL, 1, start_special, FORCE }, - { "poweroff", EQUAL, 1, start_special, FORCE }, - { "reboot", MORE, 1, start_special, FORCE }, - { "kexec", EQUAL, 1, start_special }, - { "suspend", EQUAL, 1, start_special }, - { "hibernate", EQUAL, 1, start_special }, - { "hybrid-sleep", EQUAL, 1, start_special }, - { "default", EQUAL, 1, start_special }, - { "rescue", EQUAL, 1, start_special }, - { "emergency", EQUAL, 1, start_special }, - { "exit", LESS, 2, start_special }, - { "reset-failed", MORE, 1, reset_failed }, - { "enable", MORE, 2, enable_unit, NOBUS }, - { "disable", MORE, 2, enable_unit, NOBUS }, - { "is-enabled", MORE, 2, unit_is_enabled, NOBUS }, - { "reenable", MORE, 2, enable_unit, NOBUS }, - { "preset", MORE, 2, enable_unit, NOBUS }, - { "preset-all", EQUAL, 1, preset_all, NOBUS }, - { "mask", MORE, 2, enable_unit, NOBUS }, - { "unmask", MORE, 2, enable_unit, NOBUS }, - { "link", MORE, 2, enable_unit, NOBUS }, - { "switch-root", MORE, 2, switch_root }, - { "list-dependencies", LESS, 2, list_dependencies }, - { "set-default", EQUAL, 2, set_default, NOBUS }, - { "get-default", EQUAL, 1, get_default, NOBUS }, - { "set-property", MORE, 3, set_property }, - { "is-system-running", EQUAL, 1, is_system_running }, - { "add-wants", MORE, 3, add_dependency, NOBUS }, - { "add-requires", MORE, 3, add_dependency, NOBUS }, - { "edit", MORE, 2, edit, NOBUS }, +static int systemctl_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "list-units", VERB_ANY, 1, VERB_DEFAULT, list_units }, + { "list-unit-files", VERB_ANY, 1, 0, list_unit_files }, + { "list-sockets", VERB_ANY, 1, 0, list_sockets }, + { "list-timers", VERB_ANY, 1, 0, list_timers }, + { "list-jobs", VERB_ANY, 1, 0, list_jobs }, + { "list-machines", VERB_ANY, 1, 0, list_machines }, + { "clear-jobs", VERB_ANY, 1, 0, daemon_reload }, + { "cancel", 2, VERB_ANY, 0, cancel_job }, + { "start", 2, VERB_ANY, 0, start_unit }, + { "stop", 2, VERB_ANY, 0, start_unit }, + { "condstop", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */ + { "reload", 2, VERB_ANY, 0, start_unit }, + { "restart", 2, VERB_ANY, 0, start_unit }, + { "try-restart", 2, VERB_ANY, 0, start_unit }, + { "reload-or-restart", 2, VERB_ANY, 0, start_unit }, + { "reload-or-try-restart", 2, VERB_ANY, 0, start_unit }, + { "force-reload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with SysV */ + { "condreload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */ + { "condrestart", 2, VERB_ANY, 0, start_unit }, /* For compatibility with RH */ + { "isolate", 2, 2, 0, start_unit }, + { "kill", 2, VERB_ANY, 0, kill_unit }, + { "is-active", 2, VERB_ANY, 0, check_unit_active }, + { "check", 2, VERB_ANY, 0, check_unit_active }, + { "is-failed", 2, VERB_ANY, 0, check_unit_failed }, + { "show", VERB_ANY, VERB_ANY, 0, show }, + { "cat", 2, VERB_ANY, 0, cat }, + { "status", VERB_ANY, VERB_ANY, 0, show }, + { "help", VERB_ANY, VERB_ANY, 0, show }, + { "snapshot", VERB_ANY, 2, 0, snapshot }, + { "delete", 2, VERB_ANY, 0, delete_snapshot }, + { "daemon-reload", VERB_ANY, 1, 0, daemon_reload }, + { "daemon-reexec", VERB_ANY, 1, 0, daemon_reload }, + { "show-environment", VERB_ANY, 1, 0, show_environment }, + { "set-environment", 2, VERB_ANY, 0, set_environment }, + { "unset-environment", 2, VERB_ANY, 0, set_environment }, + { "import-environment", VERB_ANY, VERB_ANY, 0, import_environment}, + { "halt", VERB_ANY, 1, 0, start_special }, + { "poweroff", VERB_ANY, 1, 0, start_special }, + { "reboot", VERB_ANY, 2, 0, start_special }, + { "kexec", VERB_ANY, 1, 0, start_special }, + { "suspend", VERB_ANY, 1, 0, start_special }, + { "hibernate", VERB_ANY, 1, 0, start_special }, + { "hybrid-sleep", VERB_ANY, 1, 0, start_special }, + { "default", VERB_ANY, 1, 0, start_special }, + { "rescue", VERB_ANY, 1, 0, start_special }, + { "emergency", VERB_ANY, 1, 0, start_special }, + { "exit", VERB_ANY, 2, 0, start_special }, + { "reset-failed", VERB_ANY, VERB_ANY, 0, reset_failed }, + { "enable", 2, VERB_ANY, 0, enable_unit }, + { "disable", 2, VERB_ANY, 0, enable_unit }, + { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, + { "reenable", 2, VERB_ANY, 0, enable_unit }, + { "preset", 2, VERB_ANY, 0, enable_unit }, + { "preset-all", VERB_ANY, 1, 0, preset_all }, + { "mask", 2, VERB_ANY, 0, enable_unit }, + { "unmask", 2, VERB_ANY, 0, enable_unit }, + { "link", 2, VERB_ANY, 0, enable_unit }, + { "switch-root", 2, VERB_ANY, 0, switch_root }, + { "list-dependencies", VERB_ANY, 2, 0, list_dependencies }, + { "set-default", 2, 2, 0, set_default }, + { "get-default", VERB_ANY, 1, 0, get_default, }, + { "set-property", 3, VERB_ANY, 0, set_property }, + { "is-system-running", VERB_ANY, 1, 0, is_system_running }, + { "add-wants", 3, VERB_ANY, 0, add_dependency }, + { "add-requires", 3, VERB_ANY, 0, add_dependency }, + { "edit", 2, VERB_ANY, 0, edit }, {} - }, *verb = verbs; - - int left; - - assert(argc >= 0); - assert(argv); - - left = argc - optind; - - /* Special rule: no arguments (left == 0) means "list-units" */ - if (left > 0) { - if (streq(argv[optind], "help") && !argv[optind+1]) { - log_error("This command expects one or more " - "unit names. Did you mean --help?"); - return -EINVAL; - } - - for (; verb->verb; verb++) - if (streq(argv[optind], verb->verb)) - goto found; - - log_error("Unknown operation '%s'.", argv[optind]); - return -EINVAL; - } -found: - - switch (verb->argc_cmp) { - - case EQUAL: - if (left != verb->argc) { - log_error("Invalid number of arguments."); - return -EINVAL; - } - - break; - - case MORE: - if (left < verb->argc) { - log_error("Too few arguments."); - return -EINVAL; - } - - break; - - case LESS: - if (left > verb->argc) { - log_error("Too many arguments."); - return -EINVAL; - } - - break; - - default: - assert_not_reached("Unknown comparison operator."); - } - - /* Require a bus connection for all operations but - * enable/disable */ - if (verb->bus == NOBUS) { - if (!bus && !avoid_bus()) { - log_error_errno(bus_error, "Failed to get D-Bus connection: %m"); - return -EIO; - } - - } else { - if (running_in_chroot() > 0) { - log_info("Running in chroot, ignoring request."); - return 0; - } - - if ((verb->bus != FORCE || arg_force <= 0) && !bus) { - log_error_errno(bus_error, "Failed to get D-Bus connection: %m"); - return -EIO; - } - } + }; - return verb->dispatch(bus, argv + optind); + return dispatch_verb(argc, argv, verbs, NULL); } -static int reload_with_fallback(sd_bus *bus) { +static int reload_with_fallback(void) { - if (bus) { - /* First, try systemd via D-Bus. */ - if (daemon_reload(bus, NULL) >= 0) - return 0; - } + /* First, try systemd via D-Bus. */ + if (daemon_reload(0, NULL, NULL) >= 0) + return 0; /* Nothing else worked, so let's try signals */ assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC); @@ -7434,25 +7484,19 @@ static int reload_with_fallback(sd_bus *bus) { return 0; } -static int start_with_fallback(sd_bus *bus) { +static int start_with_fallback(void) { - if (bus) { - /* First, try systemd via D-Bus. */ - if (start_unit(bus, NULL) >= 0) - goto done; - } + /* First, try systemd via D-Bus. */ + if (start_unit(0, NULL, NULL) >= 0) + return 0; /* Nothing else worked, so let's try * /dev/initctl */ if (talk_initctl() > 0) - goto done; + return 0; log_error("Failed to talk to init daemon."); return -EIO; - -done: - warn_wall(arg_action); - return 0; } static int halt_now(enum action a) { @@ -7460,22 +7504,22 @@ static int halt_now(enum action a) { /* The kernel will automaticall flush ATA disks and suchlike * on reboot(), but the file systems need to be synce'd * explicitly in advance. */ - sync(); + (void) sync(); /* Make sure C-A-D is handled by the kernel from this point * on... */ - reboot(RB_ENABLE_CAD); + (void) reboot(RB_ENABLE_CAD); switch (a) { case ACTION_HALT: log_info("Halting."); - reboot(RB_HALT_SYSTEM); + (void) reboot(RB_HALT_SYSTEM); return -errno; case ACTION_POWEROFF: log_info("Powering off."); - reboot(RB_POWER_OFF); + (void) reboot(RB_POWER_OFF); return -errno; case ACTION_KEXEC: @@ -7484,12 +7528,11 @@ static int halt_now(enum action a) { if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) { log_info("Rebooting with argument '%s'.", param); - syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_RESTART2, param); + (void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param); } log_info("Rebooting."); - reboot(RB_AUTOBOOT); + (void) reboot(RB_AUTOBOOT); return -errno; } @@ -7498,17 +7541,77 @@ static int halt_now(enum action a) { } } -static int halt_main(sd_bus *bus) { +static int logind_schedule_shutdown(void) { + +#ifdef HAVE_LOGIND + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + char date[FORMAT_TIMESTAMP_MAX]; + const char *action; + sd_bus *bus; + int r; + + (void) logind_set_wall_message(); + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + switch (arg_action) { + case ACTION_HALT: + action = "halt"; + break; + case ACTION_POWEROFF: + action = "poweroff"; + break; + case ACTION_KEXEC: + action = "kexec"; + break; + case ACTION_EXIT: + action = "exit"; + break; + case ACTION_REBOOT: + default: + action = "reboot"; + break; + } + + if (arg_dry) + action = strjoina("dry-", action); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ScheduleShutdown", + &error, + NULL, + "st", + action, + arg_when); + if (r < 0) + return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r)); + + log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when)); + return 0; +#else + log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown."); + return -ENOSYS; +#endif +} + +static int halt_main(void) { int r; - r = check_inhibitors(bus, arg_action); + r = logind_check_inhibitors(arg_action); if (r < 0) return r; + if (arg_when > 0) + return logind_schedule_shutdown(); + if (geteuid() != 0) { - if (arg_when > 0 || - arg_dry || - arg_force > 0) { + if (arg_dry || arg_force > 0) { log_error("Must be root."); return -EPERM; } @@ -7516,101 +7619,21 @@ static int halt_main(sd_bus *bus) { /* Try logind if we are a normal user and no special * mode applies. Maybe PolicyKit allows us to shutdown * the machine. */ - if (IN_SET(arg_action, - ACTION_POWEROFF, - ACTION_REBOOT)) { - r = reboot_with_logind(bus, arg_action); + if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) { + r = logind_reboot(arg_action); if (r >= 0) return r; if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) - /* requested operation is not supported or already in progress */ + /* requested operation is not + * supported on the local system or + * already in progress */ return r; /* on all other errors, try low-level operation */ } } - if (arg_when > 0) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_flush_close_unref_ sd_bus *b = NULL; - _cleanup_free_ char *m = NULL; - const char *action; - - assert(geteuid() == 0); - - if (avoid_bus()) { - log_error("Unable to perform operation without bus connection."); - return -ENOSYS; - } - - r = sd_bus_open_system(&b); - if (r < 0) - return log_error_errno(r, "Unable to open system bus: %m"); - - m = strv_join(arg_wall, " "); - if (!m) - return log_oom(); - - r = sd_bus_call_method( - b, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetWallMessage", - &error, - NULL, - "sb", - m, - !arg_no_wall); - - if (r < 0) { - log_warning_errno(r, "Failed to set wall message, ignoring: %s", - bus_error_message(&error, r)); - sd_bus_error_free(&error); - } - - switch (arg_action) { - case ACTION_HALT: - action = "halt"; - break; - case ACTION_POWEROFF: - action = "poweroff"; - break; - case ACTION_KEXEC: - action = "kexec"; - break; - default: - action = "reboot"; - break; - } - - if (arg_dry) - action = strjoina("dry-", action); - - r = sd_bus_call_method( - b, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "ScheduleShutdown", - &error, - NULL, - "st", - action, - arg_when); - if (r < 0) - log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", - bus_error_message(&error, r)); - else { - char date[FORMAT_TIMESTAMP_MAX]; - - log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", - format_timestamp(date, sizeof(date), arg_when)); - return 0; - } - } - if (!arg_dry && !arg_force) - return start_with_fallback(bus); + return start_with_fallback(); assert(geteuid() == 0); @@ -7628,9 +7651,7 @@ static int halt_main(sd_bus *bus) { return 0; r = halt_now(arg_action); - log_error_errno(r, "Failed to reboot: %m"); - - return r; + return log_error_errno(r, "Failed to reboot: %m"); } static int runlevel_main(void) { @@ -7649,8 +7670,37 @@ static int runlevel_main(void) { return 0; } +static int logind_cancel_shutdown(void) { +#ifdef HAVE_LOGIND + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + (void) logind_set_wall_message(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "CancelScheduledShutdown", + &error, + NULL, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r)); + + return 0; +#else + log_error("Not compiled with logind support, cannot cancel scheduled shutdowns."); + return -ENOSYS; +#endif +} + int main(int argc, char*argv[]) { - _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL; int r; setlocale(LC_ALL, ""); @@ -7666,39 +7716,26 @@ int main(int argc, char*argv[]) { if (r <= 0) goto finish; - /* /sbin/runlevel doesn't need to communicate via D-Bus, so - * let's shortcut this */ - if (arg_action == ACTION_RUNLEVEL) { - r = runlevel_main(); - goto finish; - } - if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) { log_info("Running in chroot, ignoring request."); r = 0; goto finish; } - if (!avoid_bus()) - r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus); - - if (bus) - sd_bus_set_allow_interactive_authorization(bus, arg_ask_password); - /* systemctl_main() will print an error message for the bus * connection, but only if it needs to */ switch (arg_action) { case ACTION_SYSTEMCTL: - r = systemctl_main(bus, argc, argv, r); + r = systemctl_main(argc, argv); break; case ACTION_HALT: case ACTION_POWEROFF: case ACTION_REBOOT: case ACTION_KEXEC: - r = halt_main(bus); + r = halt_main(); break; case ACTION_RUNLEVEL2: @@ -7708,69 +7745,22 @@ int main(int argc, char*argv[]) { case ACTION_RESCUE: case ACTION_EMERGENCY: case ACTION_DEFAULT: - r = start_with_fallback(bus); + r = start_with_fallback(); break; case ACTION_RELOAD: case ACTION_REEXEC: - r = reload_with_fallback(bus); + r = reload_with_fallback(); break; - case ACTION_CANCEL_SHUTDOWN: { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_flush_close_unref_ sd_bus *b = NULL; - _cleanup_free_ char *m = NULL; - - if (avoid_bus()) { - log_error("Unable to perform operation without bus connection."); - return -ENOSYS; - } - - r = sd_bus_open_system(&b); - if (r < 0) - return log_error_errno(r, "Unable to open system bus: %m"); - - if (arg_wall) { - m = strv_join(arg_wall, " "); - if (!m) { - r = log_oom(); - goto finish; - } - } - - r = sd_bus_call_method( - b, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetWallMessage", - &error, - NULL, - "sb", - m, - !arg_no_wall); - - if (r < 0) { - log_warning_errno(r, "Failed to set wall message, ignoring: %s", - bus_error_message(&error, r)); - sd_bus_error_free(&error); - } - - r = sd_bus_call_method( - b, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "CancelScheduledShutdown", - &error, - NULL, NULL); - if (r < 0) - log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", - bus_error_message(&error, r)); + case ACTION_CANCEL_SHUTDOWN: + r = logind_cancel_shutdown(); break; - } case ACTION_RUNLEVEL: + r = runlevel_main(); + break; + case _ACTION_INVALID: default: assert_not_reached("Unknown action"); @@ -7785,7 +7775,9 @@ finish: strv_free(arg_states); strv_free(arg_properties); - sd_bus_default_flush_close(); + strv_free(arg_wall); + + release_busses(); return r < 0 ? EXIT_FAILURE : r; } diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index aaa33354f4..07494e764b 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -19,26 +19,25 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <pwd.h> +#include <getopt.h> #include <grp.h> -#include <shadow.h> #include <gshadow.h> -#include <getopt.h> +#include <pwd.h> +#include <shadow.h> #include <utmp.h> -#include "util.h" -#include "hashmap.h" -#include "specifier.h" -#include "path-util.h" -#include "build.h" -#include "strv.h" #include "conf-files.h" #include "copy.h" -#include "utf8.h" #include "fileio-label.h" -#include "uid-range.h" -#include "selinux-util.h" #include "formats-util.h" +#include "hashmap.h" +#include "path-util.h" +#include "selinux-util.h" +#include "specifier.h" +#include "strv.h" +#include "uid-range.h" +#include "utf8.h" +#include "util.h" typedef enum ItemType { ADD_USER = 'u', @@ -1767,9 +1766,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_ROOT: free(arg_root); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index be3a87958f..ad547822e7 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -241,18 +241,18 @@ static void test_status_field(void) { unsigned long long total = 0, buffers = 0; int r; - assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0); + assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0); puts(t); assert_se(streq(t, "1")); - r = get_status_field("/proc/meminfo", "MemTotal:", &p); + r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p); if (r != -ENOENT) { assert_se(r == 0); puts(p); assert_se(safe_atollu(p, &total) == 0); } - r = get_status_field("/proc/meminfo", "\nBuffers:", &s); + r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s); if (r != -ENOENT) { assert_se(r == 0); puts(s); @@ -263,7 +263,7 @@ static void test_status_field(void) { assert_se(buffers < total); /* Seccomp should be a good test for field full of zeros. */ - r = get_status_field("/proc/meminfo", "\nSeccomp:", &z); + r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z); if (r != -ENOENT) { assert_se(r == 0); puts(z); diff --git a/src/test/test-strv.c b/src/test/test-strv.c index bff43950a9..cc47fd4d34 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -569,6 +569,28 @@ static void test_strv_shell_escape(void) { assert_se(streq_ptr(v[3], NULL)); } +static void test_strv_skip_one(char **a, size_t n, char **b) { + a = strv_skip(a, n); + assert_se(strv_equal(a, b)); +} + +static void test_strv_skip(void) { + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz")); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz")); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz")); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL)); + + test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux")); + test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL)); + + test_strv_skip_one(STRV_MAKE(NULL), 0, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE(NULL), 1, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE(NULL), 55, STRV_MAKE(NULL)); +} + int main(int argc, char *argv[]) { test_specifier_printf(); test_strv_foreach(); @@ -627,6 +649,7 @@ int main(int argc, char *argv[]) { test_strv_is_uniq(); test_strv_reverse(); test_strv_shell_escape(); + test_strv_skip(); return 0; } diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 12a7ed6718..68fbe3f5b8 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -20,20 +20,20 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdlib.h> -#include <stdbool.h> #include <getopt.h> #include <locale.h> +#include <stdbool.h> +#include <stdlib.h> #include "sd-bus.h" -#include "bus-util.h" + #include "bus-error.h" -#include "util.h" +#include "bus-util.h" +#include "pager.h" #include "spawn-polkit-agent.h" -#include "build.h" #include "strv.h" -#include "pager.h" #include "terminal-util.h" +#include "util.h" static bool arg_no_pager = false; static bool arg_ask_password = true; @@ -374,9 +374,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case 'H': arg_transport = BUS_TRANSPORT_REMOTE; @@ -502,7 +500,7 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; - r = bus_open_transport(arg_transport, arg_host, false, &bus); + r = bus_connect_transport(arg_transport, arg_host, false, &bus); if (r < 0) { log_error_errno(r, "Failed to create bus connection: %m"); goto finish; diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 8f29256c6d..d219764bc6 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -20,43 +20,42 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <unistd.h> -#include <fcntl.h> +#include <dirent.h> #include <errno.h> -#include <string.h> +#include <fcntl.h> +#include <fnmatch.h> +#include <getopt.h> +#include <glob.h> #include <limits.h> -#include <dirent.h> +#include <linux/fs.h> +#include <stdbool.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> -#include <stddef.h> -#include <getopt.h> -#include <stdbool.h> -#include <time.h> -#include <glob.h> -#include <fnmatch.h> +#include <string.h> #include <sys/stat.h> #include <sys/xattr.h> -#include <linux/fs.h> +#include <time.h> +#include <unistd.h> +#include "acl-util.h" +#include "btrfs-util.h" +#include "capability.h" +#include "conf-files.h" +#include "copy.h" +#include "formats-util.h" +#include "label.h" #include "log.h" -#include "util.h" #include "macro.h" #include "missing.h" #include "mkdir.h" #include "path-util.h" -#include "strv.h" -#include "label.h" -#include "set.h" -#include "conf-files.h" -#include "capability.h" -#include "specifier.h" -#include "build.h" -#include "copy.h" #include "rm-rf.h" #include "selinux-util.h" -#include "btrfs-util.h" -#include "acl-util.h" -#include "formats-util.h" +#include "set.h" +#include "specifier.h" +#include "strv.h" +#include "util.h" /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates * them in the file system. This is intended to be used to create @@ -2090,9 +2089,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_CREATE: arg_create = true; diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 82cbf95f1e..4630eb94f1 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -19,32 +19,31 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <stdbool.h> #include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <poll.h> +#include <stdbool.h> +#include <stddef.h> #include <string.h> +#include <sys/inotify.h> +#include <sys/signalfd.h> #include <sys/socket.h> #include <sys/un.h> -#include <stddef.h> -#include <poll.h> -#include <sys/inotify.h> #include <unistd.h> -#include <getopt.h> -#include <sys/signalfd.h> -#include <fcntl.h> -#include "util.h" +#include "ask-password-api.h" +#include "conf-parser.h" +#include "def.h" #include "mkdir.h" #include "path-util.h" -#include "conf-parser.h" -#include "utmp-wtmp.h" +#include "process-util.h" +#include "signal-util.h" #include "socket-util.h" -#include "ask-password-api.h" #include "strv.h" -#include "build.h" -#include "def.h" -#include "process-util.h" #include "terminal-util.h" -#include "signal-util.h" +#include "util.h" +#include "utmp-wtmp.h" static enum { ACTION_LIST, @@ -257,7 +256,7 @@ static int parse_password(const char *filename, char **wall) { if (asprintf(&_wall, "%s%sPassword entry required for \'%s\' (PID %u).\r\n" "Please enter password with the systemd-tty-ask-password-agent tool!", - *wall ? *wall : "", + strempty(*wall), *wall ? "\r\n\r\n" : "", message, pid) < 0) @@ -571,9 +570,7 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_LIST: arg_action = ACTION_LIST; @@ -628,15 +625,14 @@ int main(int argc, char *argv[]) { goto finish; if (arg_console) { - setsid(); - release_terminal(); + (void) setsid(); + (void) release_terminal(); } if (IN_SET(arg_action, ACTION_WATCH, ACTION_WALL)) r = watch_passwords(); else r = show_passwords(); - if (r < 0) log_error_errno(r, "Error: %m"); diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c index b2998dce43..bcabf65a36 100644 --- a/src/update-utmp/update-utmp.c +++ b/src/update-utmp/update-utmp.c @@ -62,7 +62,7 @@ static usec_t get_startup_time(Context *c) { &error, 't', &t); if (r < 0) { - log_error("Failed to get timestamp: %s", bus_error_message(&error, -r)); + log_error_errno(r, "Failed to get timestamp: %s", bus_error_message(&error, r)); return 0; } @@ -105,10 +105,8 @@ static int get_current_runlevel(Context *c) { "ActiveState", &error, &state); - if (r < 0) { - log_warning("Failed to get state: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r)); if (streq(state, "active") || streq(state, "reloading")) return table[i].runlevel; @@ -130,8 +128,7 @@ static int on_reboot(Context *c) { if (c->audit_fd >= 0) if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) { - r = log_error_errno(errno, - "Failed to send audit message: %m"); + r = log_error_errno(errno, "Failed to send audit message: %m"); } #endif @@ -160,8 +157,7 @@ static int on_shutdown(Context *c) { if (c->audit_fd >= 0) if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) { - r = log_error_errno(errno, - "Failed to send audit message: %m"); + r = log_error_errno(errno, "Failed to send audit message: %m"); } #endif @@ -211,8 +207,7 @@ static int on_runlevel(Context *c) { return log_oom(); if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) - r = log_error_errno(errno, - "Failed to send audit message: %m"); + r = log_error_errno(errno, "Failed to send audit message: %m"); } #endif @@ -256,7 +251,7 @@ int main(int argc, char *argv[]) { if (c.audit_fd < 0 && errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT) log_error_errno(errno, "Failed to connect to audit log: %m"); #endif - r = bus_open_system_systemd(&c.bus); + r = bus_connect_system_systemd(&c.bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); r = -EIO; @@ -284,6 +279,6 @@ finish: audit_close(c.audit_fd); #endif - sd_bus_unref(c.bus); + sd_bus_flush_close_unref(c.bus); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/units/systemd-hostnamed.service.in b/units/systemd-hostnamed.service.in index cc88ecd0db..b7079e4a7c 100644 --- a/units/systemd-hostnamed.service.in +++ b/units/systemd-hostnamed.service.in @@ -14,7 +14,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/hostnamed ExecStart=@rootlibexecdir@/systemd-hostnamed BusName=org.freedesktop.hostname1 CapabilityBoundingSet=CAP_SYS_ADMIN -WatchdogSec=1min +WatchdogSec=3min PrivateTmp=yes PrivateDevices=yes PrivateNetwork=yes diff --git a/units/systemd-importd.service.in b/units/systemd-importd.service.in index 403f15316d..d3238cf8f5 100644 --- a/units/systemd-importd.service.in +++ b/units/systemd-importd.service.in @@ -14,5 +14,5 @@ ExecStart=@rootlibexecdir@/systemd-importd BusName=org.freedesktop.import1 CapabilityBoundingSet=CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD CAP_SETFCAP CAP_SYS_ADMIN CAP_SETPCAP CAP_DAC_OVERRIDE NoNewPrivileges=yes -WatchdogSec=1min +WatchdogSec=3min KillMode=mixed diff --git a/units/systemd-journal-remote.service.in b/units/systemd-journal-remote.service.in index 4a898d62f3..2928a23021 100644 --- a/units/systemd-journal-remote.service.in +++ b/units/systemd-journal-remote.service.in @@ -18,7 +18,7 @@ Group=systemd-journal-remote PrivateTmp=yes PrivateDevices=yes PrivateNetwork=yes -WatchdogSec=10min +WatchdogSec=3min [Install] Also=systemd-journal-remote.socket diff --git a/units/systemd-journal-upload.service.in b/units/systemd-journal-upload.service.in index b2e3c769cc..a757673a62 100644 --- a/units/systemd-journal-upload.service.in +++ b/units/systemd-journal-upload.service.in @@ -15,7 +15,7 @@ ExecStart=@rootlibexecdir@/systemd-journal-upload \ User=systemd-journal-upload PrivateTmp=yes PrivateDevices=yes -WatchdogSec=20min +WatchdogSec=3min # If there are many split up journal files we need a lot of fds to # access them all and combine diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index a3540c65d2..41bfde5be3 100644 --- a/units/systemd-journald.service.in +++ b/units/systemd-journald.service.in @@ -22,7 +22,7 @@ RestartSec=0 NotifyAccess=all StandardOutput=null CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE -WatchdogSec=1min +WatchdogSec=3min FileDescriptorStoreMax=1024 # Increase the default a bit in order to allow many simultaneous diff --git a/units/systemd-localed.service.in b/units/systemd-localed.service.in index bfa097844f..9b13f901a3 100644 --- a/units/systemd-localed.service.in +++ b/units/systemd-localed.service.in @@ -14,7 +14,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/localed ExecStart=@rootlibexecdir@/systemd-localed BusName=org.freedesktop.locale1 CapabilityBoundingSet= -WatchdogSec=1min +WatchdogSec=3min PrivateTmp=yes PrivateDevices=yes PrivateNetwork=yes diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in index f087e99ce2..ff049134ee 100644 --- a/units/systemd-logind.service.in +++ b/units/systemd-logind.service.in @@ -24,7 +24,7 @@ Restart=always RestartSec=0 BusName=org.freedesktop.login1 CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CAP_KILL CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_FOWNER CAP_SYS_TTY_CONFIG -WatchdogSec=1min +WatchdogSec=3min # Increase the default a bit in order to allow many simultaneous # logins since we keep one fd open per session. diff --git a/units/systemd-machine-id-commit.service.in b/units/systemd-machine-id-commit.service.in index cccbf7b626..1f3f5da0f3 100644 --- a/units/systemd-machine-id-commit.service.in +++ b/units/systemd-machine-id-commit.service.in @@ -18,5 +18,5 @@ ConditionPathIsMountPoint=/etc/machine-id [Service] Type=oneshot RemainAfterExit=yes -ExecStart=@rootlibexecdir@/systemd-machine-id-commit +ExecStart=@rootbindir@/systemd-machine-id-setup --commit TimeoutSec=30s diff --git a/units/systemd-machined.service.in b/units/systemd-machined.service.in index fb1f383cdc..3710c595ca 100644 --- a/units/systemd-machined.service.in +++ b/units/systemd-machined.service.in @@ -16,7 +16,7 @@ After=machine.slice ExecStart=@rootlibexecdir@/systemd-machined BusName=org.freedesktop.machine1 CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID -WatchdogSec=1min +WatchdogSec=3min # Note that machined cannot be placed in a mount namespace, since it # needs access to the host's mount namespace in order to implement the diff --git a/units/systemd-networkd.service.m4.in b/units/systemd-networkd.service.m4.in index 35be713ade..27d4d58962 100644 --- a/units/systemd-networkd.service.m4.in +++ b/units/systemd-networkd.service.m4.in @@ -30,7 +30,7 @@ ExecStart=@rootlibexecdir@/systemd-networkd CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER ProtectSystem=full ProtectHome=yes -WatchdogSec=1min +WatchdogSec=3min [Install] WantedBy=multi-user.target diff --git a/units/systemd-resolved.service.m4.in b/units/systemd-resolved.service.m4.in index dce5402458..c674b27ced 100644 --- a/units/systemd-resolved.service.m4.in +++ b/units/systemd-resolved.service.m4.in @@ -23,7 +23,7 @@ ExecStart=@rootlibexecdir@/systemd-resolved CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER ProtectSystem=full ProtectHome=yes -WatchdogSec=1min +WatchdogSec=3min [Install] WantedBy=multi-user.target diff --git a/units/systemd-timedated.service.in b/units/systemd-timedated.service.in index fe5ccb4601..0c9599db20 100644 --- a/units/systemd-timedated.service.in +++ b/units/systemd-timedated.service.in @@ -14,7 +14,7 @@ Documentation=http://www.freedesktop.org/wiki/Software/systemd/timedated ExecStart=@rootlibexecdir@/systemd-timedated BusName=org.freedesktop.timedate1 CapabilityBoundingSet=CAP_SYS_TIME -WatchdogSec=1min +WatchdogSec=3min PrivateTmp=yes ProtectSystem=yes ProtectHome=yes diff --git a/units/systemd-timesyncd.service.in b/units/systemd-timesyncd.service.in index 8219c95a08..a856dad709 100644 --- a/units/systemd-timesyncd.service.in +++ b/units/systemd-timesyncd.service.in @@ -27,7 +27,7 @@ PrivateTmp=yes PrivateDevices=yes ProtectSystem=full ProtectHome=yes -WatchdogSec=1min +WatchdogSec=3min [Install] WantedBy=sysinit.target diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in index e7216d61f2..79f28c87c6 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -23,4 +23,4 @@ RestartSec=0 ExecStart=@rootlibexecdir@/systemd-udevd MountFlags=slave KillMode=mixed -WatchdogSec=1min +WatchdogSec=3min |