1
0
mirror of https://github.com/systemd/systemd synced 2025-10-06 20:24:45 +02:00

Compare commits

...

14 Commits

Author SHA1 Message Date
Luca Boccassi
7ebbe57ece
Kill several SysV compat functionalities (v258) (#38178) 2025-07-15 01:21:13 +01:00
Luca Boccassi
9ae2dbf7f4
Two fixlets for coverage test (#38183) 2025-07-14 21:16:36 +01:00
Luca Boccassi
6eab4cd44c boot: add LoaderTpm2ActivePcrBanks runtime variable
It turns out checking sysfs is not 100% reliable to figure out whether
the firmware had TPM2 support enabled or not. For example with EDK2 arm64, the
default upstream build config bundles TPM2 support with SecureBoot support,
so if the latter is disabled, TPM2 is also unavailable. But still, the ACPI
TPM2 table is created just as if it was enabled. So /sys/firmware/acpi/tables/TPM2
exists and looks correct, but there are no measurements, neither the firmware
nor the loader/stub can do them, and /sys/kernel/security/tpm0/binary_bios_measurements
does not exist.

The loader can use the apposite UEFI protocol to check, which is a more
definitive answer. Given userspace can also make use of this information, export
the bitmask with the list of active banks as-is. If it's not 0, then we can be
sure a working TPM2 was available in EFI mode.

Partially fixes https://github.com/systemd/systemd/issues/38071
2025-07-14 20:56:22 +01:00
Yu Watanabe
f12cc0d3be mkosi: update debian commit reference to a8ad8e30e70c0b82ecb8fe016f2dde3a084236f0
* a8ad8e30e7 Stop installing legacy sysv tools/units for upstream builds
* 9856b1b1bd Install new files for upstream build
* b68bfb52d4 Update changelog for 257.7-2 release
* 3bd5f6d2e0 systemd-boot-tools: change architecture to linux-any
* 057ce29542 Move bootctl zsh completion file too to new package
* b47be01659 Revert "Revert installing systemd-networkd-varlink.socket"
* 71a425dd3b ukify: recommend sbsigntool | pesign for signing
* 54f67475ee Revert installing systemd-networkd-varlink.socket
2025-07-13 05:49:09 +09:00
Yu Watanabe
c3116558ad mkosi: drop SysV compat files from packages
These workarounds can be dropped when the downstream .spec or filelists
are updated.
2025-07-13 05:49:09 +09:00
Yu Watanabe
75df71d180 NEWS: mention removal of several SysV compat features 2025-07-13 05:49:09 +09:00
Yu Watanabe
e58ba80a40 units: drop runlevel[0-6].target 2025-07-13 05:49:09 +09:00
Yu Watanabe
dc1505555b utmp: drop setting runlevel entry in utmp
This removes systemd-update-utmp-runlevel.service and related command.
2025-07-13 05:49:00 +09:00
Yu Watanabe
8ba48d4bf8 core,initctl,systemctl: kill /dev/initctl support
This also kills support for controlling system state through
/sbin/init, initctl, and telinit.
2025-07-13 05:38:14 +09:00
Yu Watanabe
af925f7eb3 systemctl: kill SysV compat 'runlevel' command 2025-07-13 05:38:13 +09:00
Yu Watanabe
5572fb18c0 systemctl/halt: drop support for calling in SysV init script
Traditionally, halt is called at the end of the init script on
reboot/shutdown. To support such usecase, previously we read the current
runlevel from utmp and set force flag on reboot/shutdown.

This drops the support for such the usecase.
Note, neither supported nor tested, but hopefully still the command can
be used in the end of the sysv init script by specifying -ff.
2025-07-13 05:38:13 +09:00
Yu Watanabe
c17516a84a systemctl: move functions in systemctl-sysv-compat.[ch]
- parse_shutdown_time_spec() is used only by systemctl-compat-shutdown.c,
- talk_initctl() and action_to_runlevel() are used only by systemctl-compat-telinit.c,
- the exit code enum is widely used in systemctl, hence moved to systemctl-util.h.

No functional change, preparation for later changes.
2025-07-13 05:38:13 +09:00
Yu Watanabe
2cc6c651ee test: skip one test case when running on coverage
Since 90fa161b5ba29d58953e9f08ddca49121b51efe6, --bind= or Bind=
settings for coverage directory does not work with managed mode:
```
[  158.105361] systemd-nspawn[3718]: Failed to open tree and set mount attributes: Operation not permitted
[  158.105364] systemd-nspawn[3718]: Failed to clone /coverage: Operation not permitted
[  158.118655] systemd-nspawn[3707]: (sd-namespace) failed with exit status 1.
```
Let's tentatively skip the test case when running on coverage.

Workaround for #38163.
2025-07-12 21:19:01 +09:00
Yu Watanabe
5921c48fcf meson: fix coverage build
This moves coverage.h to src/coverage/, and specifies path to coverage.h
with files() directive, to make it can be included even when located
outside of the include directories. Otherwise, libc-wrapper cannot be
built when -Db_coverage=true option is enabled.

Follow-up for 543a48b653ff25cc562ce4dcffec377a875f604e.
2025-07-12 21:19:01 +09:00
58 changed files with 230 additions and 1676 deletions

View File

@ -38,9 +38,7 @@ The following exceptions apply:
verbatim from the Linux kernel source tree and are licensed under **GPL-2.0 WITH
Linux-syscall-note** and are used within the scope of the Linux-syscall-note
exception provisions
* the following sources are licensed under the **LGPL-2.0-or-later** license:
- src/basic/utf8.c
- src/shared/initreq.h
* the src/basic/utf8.c source is licensed under the **LGPL-2.0-or-later** license.
* the src/basic/include/linux/bpf_insn.h header is copied from the Linux kernel
source tree and is licensed under either **BSD-2-Clause** or **GPL-2.0-only**,
and thus is included in the systemd build under the BSD-2-Clause license.

9
NEWS
View File

@ -139,6 +139,15 @@ CHANGES WITH 258 in spe:
* The command 'journalctl --follow' now exits with success on
SIGTERM/SIGINT, or its pipe STDOUT is disconnected.
* Support for System V style system state control has been removed:
- The /dev/initctl device node has been removed.
- The initctl, runlevel and telinit commands have been removed.
- Support for system state control via the init command (e.g.
'init 3') has been removed.
- The units runlevel[0-6].target have been removed.
- The concept of runlevels has been removed, so runlevel transitions
are no longer recorded in the utmp/wtmp databases.
Announcements of Future Feature Removals:
* Support for System V service scripts is deprecated and will be

2
TODO
View File

@ -2268,7 +2268,7 @@ Features:
* clean up date formatting and parsing so that all absolute/relative timestamps we format can also be parsed
* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?), get rid of systemd-update-utmp-runlevel
* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?)
* make repeated alt-ctrl-del presses printing a dump

View File

@ -11,13 +11,7 @@ Also check out the [Tips & Tricks](/TIPS_AND_TRICKS)!
**Q: How do I change the current runlevel?**
A: In systemd runlevels are exposed via "target units". You can change them like this:
```sh
# systemctl isolate runlevel5.target
```
Note however, that the concept of runlevels is a bit out of date, and it is usually nicer to use modern names for this. e.g.:
A: The concept of runlevels is obsolete. A set of target units are exposed that carry similar semantics, e.g. runlevel 5 -> `graphical.target`:
```sh
# systemctl isolate graphical.target
@ -47,8 +41,6 @@ A: Note that there might be more than one target active at the same time. So the
$ systemctl list-units --type=target
```
If you are just interested in a single number, you can use the venerable _runlevel_ command, but again, its output might be misleading.
**Q: I want to change a service file, but rpm keeps overwriting it in /usr/lib/systemd/system all the time, how should I handle this?**
A: The recommended way is to copy the service file from /usr/lib/systemd/system to /etc/systemd/system and edit it there. The latter directory takes precedence over the former, and rpm will never overwrite it. If you want to use the distributed service file again you can simply delete (or rename) the service file in /etc/systemd/system again.

View File

@ -79,7 +79,6 @@ manpages = [
['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'],
['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'],
['run0', '1', [], ''],
['runlevel', '8', [], 'HAVE_SYSV_COMPAT'],
['sd-bus-errors',
'3',
['SD_BUS_ERROR_ACCESS_DENIED',
@ -998,10 +997,6 @@ manpages = [
['systemd-import-generator', '8', [], ''],
['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'],
['systemd-inhibit', '1', [], ''],
['systemd-initctl.service',
'8',
['systemd-initctl', 'systemd-initctl.socket'],
'HAVE_SYSV_COMPAT'],
['systemd-integritysetup-generator', '8', [], 'HAVE_LIBCRYPTSETUP'],
['systemd-integritysetup@.service',
'8',
@ -1190,10 +1185,7 @@ manpages = [
'systemd-udevd-varlink.socket'],
''],
['systemd-update-done.service', '8', ['systemd-update-done'], ''],
['systemd-update-utmp.service',
'8',
['systemd-update-utmp', 'systemd-update-utmp-runlevel.service'],
'ENABLE_UTMP'],
['systemd-update-utmp.service', '8', ['systemd-update-utmp'], 'ENABLE_UTMP'],
['systemd-user-sessions.service', '8', ['systemd-user-sessions'], 'HAVE_PAM'],
['systemd-userdbd.service', '8', ['systemd-userdbd'], 'ENABLE_USERDB'],
['systemd-validatefs@.service', '8', [], 'HAVE_BLKID'],
@ -1249,7 +1241,6 @@ manpages = [
['sysupdate.d', '5', [], 'ENABLE_SYSUPDATE'],
['sysupdate.features', '5', [], 'ENABLE_SYSUPDATE'],
['sysusers.d', '5', [], 'ENABLE_SYSUSERS'],
['telinit', '8', [], 'HAVE_SYSV_COMPAT'],
['timedatectl', '1', [], 'ENABLE_TIMEDATECTL'],
['timesyncd.conf', '5', ['timesyncd.conf.d'], 'ENABLE_TIMESYNCD'],
['tmpfiles.d', '5', [], ''],

View File

@ -1,164 +0,0 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="runlevel" conditional='HAVE_SYSV_COMPAT'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>runlevel</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>runlevel</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>runlevel</refname>
<refpurpose>Print previous and current SysV runlevel</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>runlevel</command>
<arg choice="opt" rep="repeat">options</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Overview</title>
<para>"Runlevels" are an obsolete way to start and stop groups of
services used in SysV init. systemd provides a compatibility layer
that maps runlevels to targets, and associated binaries like
<command>runlevel</command>. Nevertheless, only one runlevel can
be "active" at a given time, while systemd can activate multiple
targets concurrently, so the mapping to runlevels is confusing
and only approximate. Runlevels should not be used in new code,
and are mostly useful as a shorthand way to refer the matching
systemd targets in kernel boot parameters.</para>
<table>
<title>Mapping between runlevels and systemd targets</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="runlevel" />
<colspec colname="target" />
<thead>
<row>
<entry>Runlevel</entry>
<entry>Target</entry>
</row>
</thead>
<tbody>
<row>
<entry>0</entry>
<entry><filename>poweroff.target</filename></entry>
</row>
<row>
<entry>1</entry>
<entry><filename>rescue.target</filename></entry>
</row>
<row>
<entry>2, 3, 4</entry>
<entry><filename>multi-user.target</filename></entry>
</row>
<row>
<entry>5</entry>
<entry><filename>graphical.target</filename></entry>
</row>
<row>
<entry>6</entry>
<entry><filename>reboot.target</filename></entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<refsect1>
<title>Description</title>
<para><command>runlevel</command> prints the previous and current
SysV runlevel if they are known.</para>
<para>The two runlevel characters are separated by a single space
character. If a runlevel cannot be determined, N is printed
instead. If neither can be determined, the word "unknown" is
printed.</para>
<para>Unless overridden in the environment, this will check the
utmp database for recent runlevel changes.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following option is understood:</para>
<variablelist>
<varlistentry>
<term><option>--help</option></term>
<xi:include href="standard-options.xml" xpointer="help-text" />
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>If one or both runlevels could be determined, 0 is returned,
a non-zero failure code otherwise.</para>
</refsect1>
<refsect1>
<title>Environment</title>
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$RUNLEVEL</varname></term>
<listitem><para>If <varname>$RUNLEVEL</varname> is set,
<command>runlevel</command> will print this value as current
runlevel and ignore utmp.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$PREVLEVEL</varname></term>
<listitem><para>If <varname>$PREVLEVEL</varname> is set,
<command>runlevel</command> will print this value as previous
runlevel and ignore utmp.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Files</title>
<variablelist>
<varlistentry>
<term><filename>/run/utmp</filename></term>
<listitem><para>The utmp database <command>runlevel</command> reads the previous and current runlevel
from.</para>
<xi:include href="version-info.xml" xpointer="v237"/></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd.target</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
</refentry>

View File

@ -527,6 +527,18 @@
<xi:include href="version-info.xml" xpointer="v240"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderTpm2ActivePcrBanks</varname></term>
<listitem><para>Hexadecimal string representation of a bitmask with values defined by the TCG EFI
Protocol Specification for TPM 2.0 as EFI_TCG2_BOOT_HASH_ALG_*. If no TPM2 support or no active
banks were detected, will be set to <constant>0</constant>. Set by the boot loader. Use
<citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to view this data.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderImageIdentifier</varname></term>

View File

@ -1,49 +0,0 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd-initctl.service" conditional='HAVE_SYSV_COMPAT'>
<refentryinfo>
<title>systemd-initctl.service</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-initctl.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-initctl.service</refname>
<refname>systemd-initctl.socket</refname>
<refname>systemd-initctl</refname>
<refpurpose>/dev/initctl compatibility</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-initctl.service</filename></para>
<para><filename>systemd-initctl.socket</filename></para>
<para><filename>/usr/lib/systemd/systemd-initctl</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><filename>systemd-initctl</filename> is a system service
that implements compatibility with the
<filename>/dev/initctl</filename> FIFO file system object, as
implemented by the SysV init system.
<filename>systemd-initctl</filename> is automatically activated on
request and terminates itself when it is unused.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
</refentry>

View File

@ -544,6 +544,18 @@
<xi:include href="version-info.xml" xpointer="v250"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderTpm2ActivePcrBanks</varname></term>
<listitem><para>Hexadecimal string representation of a bitmask with values defined by the TCG EFI
Protocol Specification for TPM 2.0 as EFI_TCG2_BOOT_HASH_ALG_*. If no TPM2 support or no active
banks were detected, will be set to <constant>0</constant>. Set by the boot loader. Use
<citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>
to view this data.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>LoaderImageIdentifier</varname></term>

View File

@ -49,10 +49,6 @@
<para>Note that compatibility is quite comprehensive but not 100%, for more details see <ulink
url="https://systemd.io/INCOMPATIBILITIES">Compatibility with SysV</ulink>.</para>
<para>SysV runlevels have corresponding systemd targets
(<filename>runlevel<replaceable>X</replaceable>.target</filename>). The wrapper unit that is generated
will be wanted by those targets which correspond to runlevels for which the script is enabled.</para>
<para><command>systemd</command> does not support SysV scripts as part of early boot, so all wrapper
units are ordered after <filename>basic.target</filename>.</para>

View File

@ -17,26 +17,21 @@
<refnamediv>
<refname>systemd-update-utmp.service</refname>
<refname>systemd-update-utmp-runlevel.service</refname>
<refname>systemd-update-utmp</refname>
<refpurpose>Write audit and utmp updates at bootup, runlevel
changes and shutdown</refpurpose>
<refpurpose>Write audit and utmp updates at bootup and shutdown</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-update-utmp.service</filename></para>
<para><filename>systemd-update-utmp-runlevel.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-update-utmp</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><filename>systemd-update-utmp-runlevel.service</filename> is
a service that writes SysV runlevel changes to utmp and wtmp, as
well as the audit logs, as they occur.
<filename>systemd-update-utmp.service</filename> does the same for
system reboots and shutdown requests.</para>
<para>
<filename>systemd-update-utmp.service</filename> is a service that writes system reboots and shutdown
requests to utmp and wtmp, as well as the audit logs.</para>
</refsect1>
<refsect1>

View File

@ -73,10 +73,6 @@
<filename>remote-fs.target</filename>,
<filename>rescue.target</filename>,
<filename>rpcbind.target</filename>,
<filename>runlevel2.target</filename>,
<filename>runlevel3.target</filename>,
<filename>runlevel4.target</filename>,
<filename>runlevel5.target</filename>,
<filename>shutdown.target</filename>,
<filename>sigpwr.target</filename>,
<filename>sleep.target</filename>,
@ -627,9 +623,6 @@
<citerefentry><refentrytitle>systemd-logind</refentrytitle><manvolnum>8</manvolnum></citerefentry>'s
<command>org.freedesktop.login1.Manager.PowerOff</command> D-Bus method
directly.</para>
<para><filename>runlevel0.target</filename> is an alias for
this target unit, for compatibility with SysV.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -646,9 +639,6 @@
<para>See
<citerefentry><refentrytitle>systemd-reboot.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for further details of the operation this target pulls in.</para>
<para><filename>runlevel6.target</filename> is an alias for this target unit, for compatibility
with SysV.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -707,28 +697,11 @@
<filename>multi-user.target</filename>, this target could be seen as
<filename>single-user.target</filename>.</para>
<para><filename>runlevel1.target</filename> is an alias for this target unit, for
compatibility with SysV.</para>
<para>Use the <literal>systemd.unit=rescue.target</literal> kernel command line option
to boot into this mode. A short alias for this kernel command line option is
<literal>1</literal>, for compatibility with SysV.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>runlevel2.target</filename></term>
<term><filename>runlevel3.target</filename></term>
<term><filename>runlevel4.target</filename></term>
<term><filename>runlevel5.target</filename></term>
<listitem>
<para>These are targets that are called whenever the SysV
compatibility code asks for runlevel 2, 3, 4, 5,
respectively. It is a good idea to make this an alias for
(i.e. symlink to) <filename>graphical.target</filename>
(for runlevel 5) or <filename>multi-user.target</filename>
(the others).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>shutdown.target</filename></term>
<listitem>

View File

@ -45,10 +45,7 @@
for examples and descriptions of standard systemd targets.</para>
<para>Target units provide a more flexible replacement for SysV runlevels in the classic SysV init
system. For compatibility reasons special target units such as <filename>runlevel3.target</filename>
exist which are used by the SysV runlevel compatibility code in systemd, see
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
details.</para>
system.</para>
<para>Note that a target unit file must not be empty, lest it be considered a masked unit. It is
recommended to provide a [Unit] section which includes informative <varname>Description=</varname> and

View File

@ -1,151 +0,0 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="telinit" conditional='HAVE_SYSV_COMPAT'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>telinit</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>telinit</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>telinit</refname>
<refpurpose>Change SysV runlevel</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>telinit</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg choice="req">COMMAND</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>telinit</command> may be used to change the SysV
system runlevel. Since the concept of SysV runlevels is obsolete
the runlevel requests will be transparently translated into
systemd unit activation requests.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--help</option></term>
<xi:include href="standard-options.xml" xpointer="help-text" />
</varlistentry>
<varlistentry>
<term><option>--no-wall</option></term>
<listitem><para>Do not send wall message before
reboot/halt/power-off.</para></listitem>
</varlistentry>
</variablelist>
<para>The following commands are understood:</para>
<variablelist>
<varlistentry>
<term><command>0</command></term>
<listitem><para>Power-off the machine. This is translated into
an activation request for <filename>poweroff.target</filename>
and is equivalent to <command>systemctl
poweroff</command>.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>6</command></term>
<listitem><para>Reboot the machine. This is translated into an
activation request for <filename>reboot.target</filename> and
is equivalent to <command>systemctl
reboot</command>.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>2</command></term>
<term><command>3</command></term>
<term><command>4</command></term>
<term><command>5</command></term>
<listitem><para>Change the SysV runlevel. This is translated
into an activation request for
<filename>runlevel2.target</filename>,
<filename>runlevel3.target</filename>, … and is equivalent
to <command>systemctl isolate runlevel2.target</command>,
<command>systemctl isolate runlevel3.target</command>,
</para></listitem>
</varlistentry>
<varlistentry>
<term><command>1</command></term>
<term><command>s</command></term>
<term><command>S</command></term>
<listitem><para>Change into system rescue mode. This is
translated into an activation request for
<filename>rescue.target</filename> and is equivalent to
<command>systemctl rescue</command>.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>q</command></term>
<term><command>Q</command></term>
<listitem><para>Reload daemon configuration. This is
equivalent to <command>systemctl
daemon-reload</command>.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>u</command></term>
<term><command>U</command></term>
<listitem><para>Serialize state, reexecute daemon and
deserialize state again. This is equivalent to
<command>systemctl daemon-reexec</command>.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure
code otherwise.</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>This is a legacy command available for compatibility only.
It should not be used anymore, as the concept of runlevels is
obsolete.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry project='man-pages'><refentrytitle>wall</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
</refentry>

View File

@ -344,6 +344,7 @@ conf.set10('ENABLE_FIRST_BOOT_FULL_PRESET', get_option('first-
cc = meson.get_compiler('c')
userspace_c_args = []
userspace_c_ld_args = []
userspace_sources = []
meson_build_sh = find_program('tools/meson-build.sh')
want_tests = get_option('tests')
@ -1963,9 +1964,7 @@ endif
#####################################################################
if get_option('b_coverage')
userspace_c_args += ['-include', 'coverage.h']
endif
subdir('src/coverage')
#####################################################################
@ -1980,7 +1979,7 @@ jinja2_cmdline = [meson_render_jinja2, config_h]
userspace = declare_dependency(
compile_args : userspace_c_args,
link_args : userspace_c_ld_args,
sources : version_h,
sources : userspace_sources,
)
man_page_depends = []
@ -2319,7 +2318,6 @@ subdir('src/hostname')
subdir('src/hwdb')
subdir('src/id128')
subdir('src/import')
subdir('src/initctl')
subdir('src/integritysetup')
subdir('src/journal')
subdir('src/journal-remote')

View File

@ -5,5 +5,5 @@ Environment=
GIT_URL=https://salsa.debian.org/systemd-team/systemd.git
GIT_SUBDIR=debian
GIT_BRANCH=debian/master
GIT_COMMIT=cc380fbc8af2e17165623d16630b7fc3ab4291d0
GIT_COMMIT=a8ad8e30e70c0b82ecb8fe016f2dde3a084236f0
PKG_SUBDIR=debian

View File

@ -19,9 +19,10 @@ TS="${SOURCE_DATE_EPOCH:-$(date +%s)}"
# disable manpage compression as the files cannot be found. Fix the issue by removing the compression
# extension.
#
# TODO: remove manual cgroups-agent and pubring patches when the upstream spec is updated
# TODO: remove patches for removal of cgroups-agent, renaming pubring file, and removal of sysv files
# when the upstream spec is updated
while read -r filelist; do
sed 's/\.gz$//; /systemd-cgroups-agent/d; s/import-pubring.gpg/import-pubring.pgp/' "$filelist" >"/tmp/$(basename "$filelist")"
sed -E 's/\.gz$//; /systemd-cgroups-agent/d; s/import-pubring.gpg/import-pubring.pgp/; /(initctl|runlevel|telinit)/ d' "$filelist" >"/tmp/$(basename "$filelist")"
mount --bind "/tmp/$(basename "$filelist")" "$filelist"
done < <(find "pkg/$PKG_SUBDIR${GIT_SUBDIR:+/$GIT_SUBDIR}" -name "files.*")

View File

@ -2849,6 +2849,7 @@ static void export_loader_variables(
EFI_LOADER_FEATURE_REPORT_URL |
EFI_LOADER_FEATURE_TYPE1_UKI |
EFI_LOADER_FEATURE_TYPE1_UKI_URL |
EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS |
0;
assert(loaded_image);

View File

@ -3,6 +3,7 @@
#include "device-path-util.h"
#include "efi-efivars.h"
#include "export-vars.h"
#include "measure.h"
#include "part-discovery.h"
#include "url-discovery.h"
#include "util.h"
@ -51,4 +52,12 @@ void export_common_variables(EFI_LOADED_IMAGE_PROTOCOL *loaded_image) {
s = xasprintf("UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
efivar_set_str16(MAKE_GUID_PTR(LOADER), u"LoaderFirmwareType", s, 0);
}
/* ditto for LoaderTpm2ActivePcrBanks */
if (efivar_get_raw(MAKE_GUID_PTR(LOADER), u"LoaderTpm2ActivePcrBanks", NULL, NULL) != EFI_SUCCESS) {
uint32_t active_pcr_banks = tpm_get_active_pcr_banks();
_cleanup_free_ char16_t *s = NULL;
s = xasprintf("0x%08x", active_pcr_banks);
efivar_set_str16(MAKE_GUID_PTR(LOADER), u"LoaderTpm2ActivePcrBanks", s, 0);
}
}

View File

@ -183,6 +183,24 @@ bool tpm_present(void) {
return tcg2_interface_check();
}
uint32_t tpm_get_active_pcr_banks(void) {
uint32_t active_pcr_banks = 0;
EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err;
tpm2 = tcg2_interface_check();
if (!tpm2)
return 0;
err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks);
if (err != EFI_SUCCESS) {
log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m");
return 0;
}
return active_pcr_banks;
}
static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err = EFI_SUCCESS;

View File

@ -6,6 +6,7 @@
#if ENABLE_TPM
bool tpm_present(void);
uint32_t tpm_get_active_pcr_banks(void);
/* Routines for boot-time TPM PCR measurement as well as submitting an event log entry about it. The latter
* can be done with two different event log record types. For old stuff we use EV_IPL (which is legacy, and
@ -28,6 +29,10 @@ static inline bool tpm_present(void) {
return false;
}
static inline uint32_t tpm_get_active_pcr_banks(void) {
return 0;
}
static inline EFI_STATUS tpm_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
if (ret_measured)
*ret_measured = false;

View File

@ -79,7 +79,9 @@ struct EFI_TCG2_PROTOCOL {
uint64_t DataToHashLen,
EFI_TCG2_EVENT *EfiTcgEvent);
void *SubmitCommand;
void *GetActivePcrBanks;
EFI_STATUS (EFIAPI *GetActivePcrBanks)(
EFI_TCG2_PROTOCOL *This,
uint32_t *ActivePcrBanks);
void *SetActivePcrBanks;
void *GetResultOfSetActivePcrBanks;
};

View File

@ -413,6 +413,7 @@ int verb_status(int argc, char *argv[], void *userdata) {
{ EFI_LOADER_FEATURE_REPORT_URL, "Loader reports network boot URL" },
{ EFI_LOADER_FEATURE_TYPE1_UKI, "Support Type #1 uki field" },
{ EFI_LOADER_FEATURE_TYPE1_UKI_URL, "Support Type #1 uki-url field" },
{ EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS, "Loader reports TPM2 active PCR banks" },
};
static const struct {
uint64_t flag;

View File

@ -1591,23 +1591,6 @@ static int fixup_environment(void) {
return 0;
}
static void redirect_telinit(int argc, char *argv[]) {
/* This is compatibility support for SysV, where calling init as a user is identical to telinit. */
#if HAVE_SYSV_COMPAT
if (getpid_cached() == 1)
return;
if (!invoked_as(argv, "init"))
return;
execv(SYSTEMCTL_BINARY_PATH, argv);
log_error_errno(errno, "Failed to execute %s: %m", SYSTEMCTL_BINARY_PATH);
exit(EXIT_FAILURE);
#endif
}
static int become_shutdown(int objective, int retval) {
static const char* const table[_MANAGER_OBJECTIVE_MAX] = {
[MANAGER_EXIT] = "exit",
@ -3041,9 +3024,6 @@ int main(int argc, char *argv[]) {
assert_se(argc > 0 && !isempty(argv[0]));
/* SysV compatibility: redirect init → telinit */
redirect_telinit(argc, argv);
/* Take timestamps early on */
dual_timestamp_from_monotonic(&kernel_timestamp, 0);
dual_timestamp_now(&userspace_timestamp);

6
src/coverage/meson.build Normal file
View File

@ -0,0 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if get_option('b_coverage')
userspace_c_args += ['-include', meson.current_source_dir() / 'coverage.h']
userspace_sources += files('coverage.h')
endif

View File

@ -27,6 +27,7 @@
#define EFI_LOADER_FEATURE_REPORT_URL (UINT64_C(1) << 15)
#define EFI_LOADER_FEATURE_TYPE1_UKI (UINT64_C(1) << 16)
#define EFI_LOADER_FEATURE_TYPE1_UKI_URL (UINT64_C(1) << 17)
#define EFI_LOADER_FEATURE_TPM2_ACTIVE_PCR_BANKS (UINT64_C(1) << 18)
/* Features of the stub, i.e. systemd-stub */
#define EFI_STUB_FEATURE_REPORT_BOOT_PARTITION (UINT64_C(1) << 0)

View File

@ -1,351 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <unistd.h>
#include "sd-bus.h"
#include "sd-daemon.h"
#include "alloc-util.h"
#include "bus-error.h"
#include "bus-locator.h"
#include "bus-util.h"
#include "constants.h"
#include "daemon-util.h"
#include "fd-util.h"
#include "initreq.h"
#include "list.h"
#include "log.h"
#include "main-func.h"
#include "reboot-util.h"
#include "special.h"
#include "time-util.h"
#define SERVER_FD_MAX 16
#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))
typedef struct Fifo Fifo;
typedef struct Server {
int epoll_fd;
LIST_HEAD(Fifo, fifos);
unsigned n_fifos;
sd_bus *bus;
bool quit;
} Server;
struct Fifo {
Server *server;
int fd;
struct init_request buffer;
size_t bytes_read;
LIST_FIELDS(Fifo, fifo);
};
static const char *translate_runlevel(int runlevel, bool *isolate) {
static const struct {
const int runlevel;
const char *special;
bool isolate;
} table[] = {
{ '0', SPECIAL_POWEROFF_TARGET, false },
{ '1', SPECIAL_RESCUE_TARGET, true },
{ 's', SPECIAL_RESCUE_TARGET, true },
{ 'S', SPECIAL_RESCUE_TARGET, true },
{ '2', SPECIAL_MULTI_USER_TARGET, true },
{ '3', SPECIAL_MULTI_USER_TARGET, true },
{ '4', SPECIAL_MULTI_USER_TARGET, true },
{ '5', SPECIAL_GRAPHICAL_TARGET, true },
{ '6', SPECIAL_REBOOT_TARGET, false },
};
assert(isolate);
FOREACH_ELEMENT(i, table)
if (i->runlevel == runlevel) {
*isolate = i->isolate;
if (runlevel == '6' && kexec_loaded())
return SPECIAL_KEXEC_TARGET;
return i->special;
}
return NULL;
}
static int change_runlevel(Server *s, int runlevel) {
const char *target;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
const char *mode;
bool isolate = false;
int r;
assert(s);
target = translate_runlevel(runlevel, &isolate);
if (!target) {
log_warning("Got request for unknown runlevel %c, ignoring.", runlevel);
return 0;
}
if (isolate)
mode = "isolate";
else
mode = "replace-irreversibly";
log_debug("Requesting %s/start/%s", target, mode);
r = bus_call_method(s->bus, bus_systemd_mgr, "StartUnit", &error, NULL, "ss", target, mode);
if (r < 0)
return log_error_errno(r, "Failed to change runlevel: %s", bus_error_message(&error, r));
return 0;
}
static void request_process(Server *s, const struct init_request *req) {
assert(s);
assert(req);
if (req->magic != INIT_MAGIC) {
log_error("Got initctl request with invalid magic. Ignoring.");
return;
}
switch (req->cmd) {
case INIT_CMD_RUNLVL:
if (!isprint(req->runlevel))
log_error("Got invalid runlevel. Ignoring.");
else
switch (req->runlevel) {
/* we are async anyway, so just use kill for reexec/reload */
case 'u':
case 'U':
if (kill(1, SIGTERM) < 0)
log_error_errno(errno, "kill() failed: %m");
/* The bus connection will be
* terminated if PID 1 is reexecuted,
* hence let's just exit here, and
* rely on that we'll be restarted on
* the next request */
s->quit = true;
break;
case 'q':
case 'Q':
if (kill(1, SIGHUP) < 0)
log_error_errno(errno, "kill() failed: %m");
break;
default:
(void) change_runlevel(s, req->runlevel);
}
return;
case INIT_CMD_POWERFAIL:
case INIT_CMD_POWERFAILNOW:
case INIT_CMD_POWEROK:
log_warning("Received UPS/power initctl request. This is not implemented in systemd. Upgrade your UPS daemon!");
return;
case INIT_CMD_CHANGECONS:
log_warning("Received console change initctl request. This is not implemented in systemd.");
return;
case INIT_CMD_SETENV:
case INIT_CMD_UNSETENV:
log_warning("Received environment initctl request. This is not implemented in systemd.");
return;
default:
log_warning("Received unknown initctl request. Ignoring.");
return;
}
}
static int fifo_process(Fifo *f) {
ssize_t l;
assert(f);
errno = EIO;
l = read(f->fd,
((uint8_t*) &f->buffer) + f->bytes_read,
sizeof(f->buffer) - f->bytes_read);
if (l <= 0) {
if (errno == EAGAIN)
return 0;
return log_warning_errno(errno, "Failed to read from fifo: %m");
}
f->bytes_read += l;
assert(f->bytes_read <= sizeof(f->buffer));
if (f->bytes_read == sizeof(f->buffer)) {
request_process(f->server, &f->buffer);
f->bytes_read = 0;
}
return 0;
}
static Fifo* fifo_free(Fifo *f) {
if (!f)
return NULL;
if (f->server) {
assert(f->server->n_fifos > 0);
f->server->n_fifos--;
LIST_REMOVE(fifo, f->server->fifos, f);
}
if (f->fd >= 0) {
if (f->server)
(void) epoll_ctl(f->server->epoll_fd, EPOLL_CTL_DEL, f->fd, NULL);
safe_close(f->fd);
}
return mfree(f);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Fifo*, fifo_free);
static void server_done(Server *s) {
assert(s);
while (s->fifos)
fifo_free(s->fifos);
s->epoll_fd = safe_close(s->epoll_fd);
s->bus = sd_bus_flush_close_unref(s->bus);
}
static int server_init(Server *s, unsigned n_sockets) {
int r;
/* This function will leave s partially initialized on failure. Caller needs to clean up. */
assert(s);
assert(n_sockets > 0);
s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (s->epoll_fd < 0)
return log_error_errno(errno, "Failed to create epoll object: %m");
for (unsigned i = 0; i < n_sockets; i++) {
_cleanup_(fifo_freep) Fifo *f = NULL;
int fd = SD_LISTEN_FDS_START + i;
r = sd_is_fifo(fd, NULL);
if (r < 0)
return log_error_errno(r, "Failed to determine file descriptor type: %m");
if (!r)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong file descriptor type.");
f = new0(Fifo, 1);
if (!f)
return log_oom();
struct epoll_event ev = {
.events = EPOLLIN,
.data.ptr = f,
};
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
return log_error_errno(errno, "Failed to add fifo fd to epoll object: %m");
f->fd = fd;
f->server = s;
LIST_PREPEND(fifo, s->fifos, TAKE_PTR(f));
s->n_fifos++;
}
r = bus_connect_system_systemd(&s->bus);
if (r < 0)
return log_error_errno(r, "Failed to get D-Bus connection: %m");
return 0;
}
static int process_event(Server *s, struct epoll_event *ev) {
int r;
_cleanup_(fifo_freep) Fifo *f = NULL;
assert(s);
assert(ev);
if (!(ev->events & EPOLLIN))
return log_info_errno(SYNTHETIC_ERRNO(EIO),
"Got invalid event from epoll. (3)");
f = (Fifo*) ev->data.ptr;
r = fifo_process(f);
if (r < 0)
return log_info_errno(r, "Got error on fifo: %m");
TAKE_PTR(f);
return 0;
}
static int run(int argc, char *argv[]) {
_cleanup_(server_done) Server server = { .epoll_fd = -EBADF };
_unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r, n;
if (argc > 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"This program does not take arguments.");
log_setup();
umask(0022);
n = sd_listen_fds(true);
if (n < 0)
return log_error_errno(n, "Failed to read listening file descriptors from environment: %m");
if (n <= 0 || n > SERVER_FD_MAX)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"No or too many file descriptors passed.");
r = server_init(&server, (unsigned) n);
if (r < 0)
return r;
notify_stop = notify_start(NOTIFY_READY_MESSAGE, NOTIFY_STOPPING_MESSAGE);
while (!server.quit) {
struct epoll_event event;
int k;
k = epoll_wait(server.epoll_fd, &event, 1, TIMEOUT_MSEC);
if (k < 0) {
if (errno == EINTR)
continue;
return log_error_errno(errno, "epoll_wait() failed: %m");
}
if (k == 0)
break;
r = process_event(&server, &event);
if (r < 0)
return r;
}
return 0;
}
DEFINE_MAIN_FUNCTION(run);

View File

@ -1,9 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
executables += [
libexec_template + {
'name' : 'systemd-initctl',
'conditions' : ['HAVE_SYSV_COMPAT'],
'sources' : files('initctl.c'),
},
]

View File

@ -10,6 +10,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "parse-util.h"
#include "sort-util.h"
#include "stat-util.h"
#include "stdio-util.h"
@ -516,6 +517,27 @@ int efi_get_boot_options(uint16_t **ret_options) {
#endif
}
#if ENABLE_EFI
static int loader_has_tpm2(void) {
_cleanup_free_ char *active_pcr_banks = NULL;
uint32_t active_pcr_banks_value;
int r;
r = efi_get_variable_string(EFI_LOADER_VARIABLE_STR("LoaderTpm2ActivePcrBanks"), &active_pcr_banks);
if (r < 0) {
if (r != -ENOENT)
log_debug_errno(r, "Failed to read LoaderTpm2ActivePcrBanks variable: %m");
return r;
}
r = safe_atou32_full(active_pcr_banks, 16, &active_pcr_banks_value);
if (r < 0)
return log_debug_errno(r, "Failed to parse LoaderTpm2ActivePcrBanks variable: %m");
return active_pcr_banks_value != 0;
}
#endif
bool efi_has_tpm2(void) {
#if ENABLE_EFI
static int cache = -1;
@ -530,9 +552,17 @@ bool efi_has_tpm2(void) {
if (!is_efi_boot())
return (cache = false);
/* Secondly, check if the loader told us, as that is the most accurate source of information
* regarding the firmware's setup */
r = loader_has_tpm2();
if (r >= 0)
return (cache = r);
/* Then, check if the ACPI table "TPM2" exists, which is the TPM2 event log table, see:
* https://trustedcomputinggroup.org/wp-content/uploads/TCG_ACPIGeneralSpecification_v1.20_r8.pdf
* This table exists whenever the firmware knows ACPI and is hooked up to TPM2. */
* This table exists whenever the firmware knows ACPI and is hooked up to TPM2.
* Note that in some cases, for example with EDK2 2025.2 with the default arm64 config, this ACPI
* table is present even if TPM2 support is not enabled in the firmware. */
if (access("/sys/firmware/acpi/tables/TPM2", F_OK) >= 0)
return (cache = true);
if (errno != ENOENT)

View File

@ -1,59 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.0-or-later */
/*
* Copyright (C) 1995-2004 Miquel van Smoorenburg
* Version: @(#)initreq.h 1.28 31-Mar-2004 MvS
*/
#pragma once
#include "forward.h"
#if defined(__FreeBSD_kernel__)
# define INIT_FIFO "/etc/.initctl"
#else
# define INIT_FIFO "/dev/initctl"
#endif
#define INIT_MAGIC 0x03091969
#define INIT_CMD_START 0
#define INIT_CMD_RUNLVL 1
#define INIT_CMD_POWERFAIL 2
#define INIT_CMD_POWERFAILNOW 3
#define INIT_CMD_POWEROK 4
#define INIT_CMD_BSD 5
#define INIT_CMD_SETENV 6
#define INIT_CMD_UNSETENV 7
#define INIT_CMD_CHANGECONS 12345
/*
* This is what BSD 4.4 uses when talking to init.
* Linux doesn't use this right now.
*/
struct init_request_bsd {
char gen_id[8]; /* Beats me.. telnetd uses "fe" */
char tty_id[16]; /* Tty name minus /dev/tty */
char host[HOST_NAME_MAX]; /* Hostname */
char term_type[16]; /* Terminal type */
int signal; /* Signal to send */
int pid; /* Process to send to */
char exec_name[128]; /* Program to execute */
char reserved[128]; /* For future expansion. */
};
/*
* Because of legacy interfaces, "runlevel" and "sleeptime"
* aren't in a separate struct in the union.
*
* The weird sizes are because init expects the whole
* struct to be 384 bytes.
*/
struct init_request {
int magic; /* Magic number */
int cmd; /* What kind of request */
int runlevel; /* Runlevel to change to */
int sleeptime; /* Time between TERM and KILL */
union {
struct init_request_bsd bsd;
char data[368];
} i;
};

View File

@ -11,44 +11,6 @@
#include "time-util.h"
#include "utmp-wtmp.h"
int utmp_get_runlevel(int *runlevel, int *previous) {
_unused_ _cleanup_(utxent_cleanup) bool utmpx = false;
struct utmpx *found, lookup = { .ut_type = RUN_LVL };
const char *e;
assert(runlevel);
/* If these values are set in the environment this takes
* precedence. Presumably, sysvinit does this to work around a
* race condition that would otherwise exist where we'd always
* go to disk and hence might read runlevel data that might be
* very new and not apply to the current script being executed. */
e = getenv("RUNLEVEL");
if (!isempty(e)) {
*runlevel = e[0];
if (previous)
*previous = 0;
return 0;
}
if (utmpxname(UTMPX_FILE) < 0)
return -errno;
utmpx = utxent_start();
found = getutxid(&lookup);
if (!found)
return -errno;
*runlevel = found->ut_pid & 0xFF;
if (previous)
*previous = (found->ut_pid >> 8) & 0xFF;
return 0;
}
static void init_timestamp(struct utmpx *store, usec_t t) {
assert(store);
@ -237,33 +199,3 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
return write_utmp_wtmp(&store, &store_wtmp);
}
int utmp_put_runlevel(int runlevel, int previous) {
struct utmpx store = {};
int r;
assert(runlevel > 0);
if (previous <= 0) {
/* Find the old runlevel automatically */
r = utmp_get_runlevel(&previous, NULL);
if (r < 0) {
if (r != -ESRCH)
return r;
previous = 0;
}
}
if (previous == runlevel)
return 0;
init_entry(&store, 0);
store.ut_type = RUN_LVL;
store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8);
strncpy(store.ut_user, "runlevel", sizeof(store.ut_user));
return write_entry_both(&store);
}

View File

@ -6,11 +6,8 @@
#if ENABLE_UTMP
#include <utmpx.h>
int utmp_get_runlevel(int *runlevel, int *previous);
int utmp_put_shutdown(void);
int utmp_put_reboot(usec_t timestamp);
int utmp_put_runlevel(int runlevel, int previous);
int utmp_put_dead_process(const char *id, pid_t pid, int code, int status);
int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user);
@ -27,18 +24,12 @@ static inline void utxent_cleanup(bool *initialized) {
#else /* ENABLE_UTMP */
static inline int utmp_get_runlevel(int *runlevel, int *previous) {
return -ESRCH;
}
static inline int utmp_put_shutdown(void) {
return 0;
}
static inline int utmp_put_reboot(usec_t timestamp) {
return 0;
}
static inline int utmp_put_runlevel(int runlevel, int previous) {
return 0;
}
static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
return 0;
}

View File

@ -32,9 +32,7 @@ systemctl_sources = files(
)
systemctl_extract_sources = files(
'systemctl-compat-halt.c',
'systemctl-compat-runlevel.c',
'systemctl-compat-shutdown.c',
'systemctl-compat-telinit.c',
'systemctl-daemon-reload.c',
'systemctl-logind.c',
'systemctl-start-unit.c',
@ -74,8 +72,7 @@ executables += [
},
]
foreach alias : (['halt', 'poweroff', 'reboot', 'shutdown'] +
(conf.get('HAVE_SYSV_COMPAT') == 1 ? ['runlevel', 'telinit'] : []))
foreach alias : ['halt', 'poweroff', 'reboot', 'shutdown']
install_symlink(alias,
pointing_to : sbin_to_bin + 'systemctl',
install_dir : sbindir)

View File

@ -11,7 +11,6 @@
#include "reboot-util.h"
#include "systemctl.h"
#include "systemctl-compat-halt.h"
#include "systemctl-compat-telinit.h"
#include "systemctl-logind.h"
#include "systemctl-start-unit.h"
#include "systemctl-util.h"
@ -77,16 +76,11 @@ int halt_parse_argv(int argc, char *argv[]) {
{}
};
int c, r, runlevel;
int c, r;
assert(argc >= 0);
assert(argv);
/* called in sysvinit system as last command in shutdown/reboot so this is always forceful */
if (utmp_get_runlevel(&runlevel, NULL) >= 0)
if (IN_SET(runlevel, '0', '6'))
arg_force = 2;
while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
switch (c) {
@ -176,7 +170,7 @@ int halt_main(void) {
arg_no_block = true;
if (!arg_dry_run)
return start_with_fallback();
return verb_start(0, NULL, NULL);
}
r = must_be_root();

View File

@ -1,81 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <getopt.h>
#include "alloc-util.h"
#include "log.h"
#include "pretty-print.h"
#include "systemctl-compat-runlevel.h"
#include "utmp-wtmp.h"
static int runlevel_help(void) {
_cleanup_free_ char *link = NULL;
int r;
r = terminal_urlify_man("runlevel", "8", &link);
if (r < 0)
return log_oom();
printf("%s [OPTIONS...]\n"
"\n%sPrints the previous and current runlevel of the init system.%s\n"
"\nOptions:\n"
" --help Show this help\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
link);
return 0;
}
int runlevel_parse_argv(int argc, char *argv[]) {
enum {
ARG_HELP = 0x100,
};
static const struct option options[] = {
{ "help", no_argument, NULL, ARG_HELP },
{}
};
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
switch (c) {
case ARG_HELP:
return runlevel_help();
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (optind < argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too many arguments.");
return 1;
}
int runlevel_main(void) {
int r, runlevel, previous;
r = utmp_get_runlevel(&runlevel, &previous);
if (r < 0) {
puts("unknown");
return r;
}
printf("%c %c\n",
previous <= 0 ? 'N' : previous,
runlevel <= 0 ? 'N' : runlevel);
return 0;
}

View File

@ -1,6 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int runlevel_parse_argv(int argc, char *argv[]);
int runlevel_main(void);

View File

@ -4,12 +4,15 @@
#include "alloc-util.h"
#include "log.h"
#include "parse-util.h"
#include "pretty-print.h"
#include "reboot-util.h"
#include "string-util.h"
#include "strv.h"
#include "systemctl.h"
#include "systemctl-compat-shutdown.h"
#include "systemctl-sysv-compat.h"
#include "systemctl-logind.h"
#include "time-util.h"
static int shutdown_help(void) {
_cleanup_free_ char *link = NULL;
@ -47,6 +50,61 @@ static int shutdown_help(void) {
return 0;
}
static int parse_shutdown_time_spec(const char *t, usec_t *ret) {
int r;
assert(t);
assert(ret);
/* This parses SysV compat time spec. */
if (streq(t, "now"))
*ret = 0;
else if (!strchr(t, ':')) {
uint64_t u;
if (safe_atou64(t, &u) < 0)
return -EINVAL;
*ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
} else {
char *e = NULL;
long hour, minute;
errno = 0;
hour = strtol(t, &e, 10);
if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
return -EINVAL;
minute = strtol(e+1, &e, 10);
if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
return -EINVAL;
usec_t n = now(CLOCK_REALTIME);
struct tm tm = {};
r = localtime_or_gmtime_usec(n, /* utc= */ false, &tm);
if (r < 0)
return r;
tm.tm_hour = (int) hour;
tm.tm_min = (int) minute;
tm.tm_sec = 0;
usec_t s;
r = mktime_or_timegm_usec(&tm, /* utc= */ false, &s);
if (r < 0)
return r;
while (s <= n)
s += USEC_PER_DAY;
*ret = s;
}
return 0;
}
int shutdown_parse_argv(int argc, char *argv[]) {
enum {
ARG_HELP = 0x100,

View File

@ -1,156 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <getopt.h>
#include <signal.h>
#include "alloc-util.h"
#include "log.h"
#include "pretty-print.h"
#include "systemctl.h"
#include "systemctl-compat-telinit.h"
#include "systemctl-daemon-reload.h"
#include "systemctl-start-unit.h"
#include "systemctl-sysv-compat.h"
static int telinit_help(void) {
_cleanup_free_ char *link = NULL;
int r;
r = terminal_urlify_man("telinit", "8", &link);
if (r < 0)
return log_oom();
printf("%s [OPTIONS...] COMMAND\n\n"
"%sSend control commands to the init daemon.%s\n"
"\nCommands:\n"
" 0 Power-off the machine\n"
" 6 Reboot the machine\n"
" 2, 3, 4, 5 Start runlevelX.target unit\n"
" 1, s, S Enter rescue mode\n"
" q, Q Reload init daemon configuration\n"
" u, U Reexecute init daemon\n"
"\nOptions:\n"
" --help Show this help\n"
" --no-wall Don't send wall message before halt/power-off/reboot\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
link);
return 0;
}
int telinit_parse_argv(int argc, char *argv[]) {
enum {
ARG_HELP = 0x100,
ARG_NO_WALL
};
static const struct option options[] = {
{ "help", no_argument, NULL, ARG_HELP },
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
{}
};
static const struct {
char from;
enum action to;
} table[] = {
{ '0', ACTION_POWEROFF },
{ '6', ACTION_REBOOT },
{ '1', ACTION_RESCUE },
{ '2', ACTION_RUNLEVEL2 },
{ '3', ACTION_RUNLEVEL3 },
{ '4', ACTION_RUNLEVEL4 },
{ '5', ACTION_RUNLEVEL5 },
{ 's', ACTION_RESCUE },
{ 'S', ACTION_RESCUE },
{ 'q', ACTION_RELOAD },
{ 'Q', ACTION_RELOAD },
{ 'u', ACTION_REEXEC },
{ 'U', ACTION_REEXEC }
};
unsigned i;
int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
switch (c) {
case ARG_HELP:
return telinit_help();
case ARG_NO_WALL:
arg_no_wall = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (optind >= argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: required argument missing.",
program_invocation_short_name);
if (optind + 1 < argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Too many arguments.");
if (strlen(argv[optind]) != 1)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Expected single character argument.");
for (i = 0; i < ELEMENTSOF(table); i++)
if (table[i].from == argv[optind][0])
break;
if (i >= ELEMENTSOF(table))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown command '%s'.", argv[optind]);
arg_action = table[i].to;
optind++;
return 1;
}
int start_with_fallback(void) {
int r;
/* First, try systemd via D-Bus. */
r = verb_start(0, NULL, NULL);
if (r == 0)
return 0;
#if HAVE_SYSV_COMPAT
/* Nothing else worked, so let's try /dev/initctl */
if (talk_initctl(action_to_runlevel()) > 0)
return 0;
#endif
return log_error_errno(r, "Failed to talk to init daemon: %m");
}
int reload_with_fallback(void) {
assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
/* First, try systemd via D-Bus */
if (daemon_reload(arg_action, /* graceful= */ true) > 0)
return 0;
/* That didn't work, so let's try signals */
if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
return log_error_errno(errno, "kill() failed: %m");
return 0;
}

View File

@ -1,6 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int telinit_parse_argv(int argc, char *argv[]);
int start_with_fallback(void);
int reload_with_fallback(void);

View File

@ -11,7 +11,6 @@
#include "strv.h"
#include "systemctl.h"
#include "systemctl-is-active.h"
#include "systemctl-sysv-compat.h"
#include "systemctl-util.h"
#include "unit-def.h"

View File

@ -16,8 +16,6 @@
#include "systemctl-cancel-job.h"
#include "systemctl-clean-or-freeze.h"
#include "systemctl-compat-halt.h"
#include "systemctl-compat-runlevel.h"
#include "systemctl-compat-telinit.h"
#include "systemctl-daemon-reload.h"
#include "systemctl-edit.h"
#include "systemctl-enable.h"
@ -214,19 +212,6 @@ static int run(int argc, char *argv[]) {
r = halt_main();
break;
case ACTION_RUNLEVEL2:
case ACTION_RUNLEVEL3:
case ACTION_RUNLEVEL4:
case ACTION_RUNLEVEL5:
case ACTION_RESCUE:
r = start_with_fallback();
break;
case ACTION_RELOAD:
case ACTION_REEXEC:
r = reload_with_fallback();
break;
case ACTION_CANCEL_SHUTDOWN:
r = logind_cancel_shutdown();
break;
@ -236,10 +221,9 @@ static int run(int argc, char *argv[]) {
r = logind_show_shutdown();
break;
case ACTION_RUNLEVEL:
r = runlevel_main();
break;
case ACTION_RESCUE:
case ACTION_RELOAD:
case ACTION_REEXEC:
case ACTION_EXIT:
case ACTION_SLEEP:
case ACTION_SUSPEND:

View File

@ -48,7 +48,6 @@
#include "systemctl.h"
#include "systemctl-list-machines.h"
#include "systemctl-show.h"
#include "systemctl-sysv-compat.h"
#include "systemctl-util.h"
#include "terminal-util.h"
#include "utf8.h"

View File

@ -232,10 +232,6 @@ const struct action_metadata action_table[_ACTION_MAX] = {
[ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
[ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
[ACTION_SOFT_REBOOT] = { SPECIAL_SOFT_REBOOT_TARGET, "soft-reboot", "replace-irreversibly" },
[ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
[ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
[ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
[ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
[ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
[ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
[ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },

View File

@ -5,12 +5,8 @@
#include <unistd.h>
#include "env-util.h"
#include "fd-util.h"
#include "initreq.h"
#include "install.h"
#include "io-util.h"
#include "log.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
#include "process-util.h"
@ -18,101 +14,6 @@
#include "strv.h"
#include "systemctl.h"
#include "systemctl-sysv-compat.h"
#include "time-util.h"
int talk_initctl(char rl) {
#if HAVE_SYSV_COMPAT
_cleanup_close_ int fd = -EBADF;
const char *path;
int r;
/* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this
* system, and > 0 on success. */
if (rl == 0)
return 0;
FOREACH_STRING(_path, "/run/initctl", "/dev/initctl") {
path = _path;
fd = open(path, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
if (fd < 0 && errno != ENOENT)
return log_error_errno(errno, "Failed to open %s: %m", path);
if (fd >= 0)
break;
}
if (fd < 0)
return 0;
struct init_request request = {
.magic = INIT_MAGIC,
.sleeptime = 0,
.cmd = INIT_CMD_RUNLVL,
.runlevel = rl,
};
r = loop_write(fd, &request, sizeof(request));
if (r < 0)
return log_error_errno(r, "Failed to write to %s: %m", path);
return 1;
#else
return -EOPNOTSUPP;
#endif
}
int parse_shutdown_time_spec(const char *t, usec_t *ret) {
int r;
assert(t);
assert(ret);
if (streq(t, "now"))
*ret = 0;
else if (!strchr(t, ':')) {
uint64_t u;
if (safe_atou64(t, &u) < 0)
return -EINVAL;
*ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
} else {
char *e = NULL;
long hour, minute;
errno = 0;
hour = strtol(t, &e, 10);
if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
return -EINVAL;
minute = strtol(e+1, &e, 10);
if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
return -EINVAL;
usec_t n = now(CLOCK_REALTIME);
struct tm tm = {};
r = localtime_or_gmtime_usec(n, /* utc= */ false, &tm);
if (r < 0)
return r;
tm.tm_hour = (int) hour;
tm.tm_min = (int) minute;
tm.tm_sec = 0;
usec_t s;
r = mktime_or_timegm_usec(&tm, /* utc= */ false, &s);
if (r < 0)
return r;
while (s <= n)
s += USEC_PER_DAY;
*ret = s;
}
return 0;
}
int enable_sysv_units(const char *verb, char **args) {
int r = 0;
@ -264,23 +165,3 @@ int enable_sysv_units(const char *verb, char **args) {
#endif
return r;
}
int action_to_runlevel(void) {
#if HAVE_SYSV_COMPAT
static const char table[_ACTION_MAX] = {
[ACTION_HALT] = '0',
[ACTION_POWEROFF] = '0',
[ACTION_REBOOT] = '6',
[ACTION_RUNLEVEL2] = '2',
[ACTION_RUNLEVEL3] = '3',
[ACTION_RUNLEVEL4] = '4',
[ACTION_RUNLEVEL5] = '5',
[ACTION_RESCUE] = '1'
};
assert(arg_action >= 0 && arg_action < _ACTION_MAX);
return table[arg_action];
#else
return -EOPNOTSUPP;
#endif
}

View File

@ -1,35 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "forward.h"
int talk_initctl(char runlevel);
int parse_shutdown_time_spec(const char *t, usec_t *ret);
/* The init script exit codes for the LSB 'status' verb. (This is different from the 'start' verb, whose exit
codes are defined in exit-status.h.)
0 program is running or service is OK
1 program is dead and /var/run pid file exists
2 program is dead and /var/lock lock file exists
3 program is not running
4 program or service status is unknown
5-99 reserved for future LSB use
100-149 reserved for distribution use
150-199 reserved for application use
200-254 reserved
https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
*/
enum {
EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0,
EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1,
EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2,
EXIT_PROGRAM_NOT_RUNNING = 3,
EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
};
typedef enum SysVUnitEnableState {
SYSV_UNIT_NOT_FOUND = 0,
SYSV_UNIT_DISABLED,
@ -37,5 +8,3 @@ typedef enum SysVUnitEnableState {
} SysVUnitEnableState;
int enable_sysv_units(const char *verb, char **args);
int action_to_runlevel(void) _pure_;

View File

@ -3,6 +3,29 @@
#include "systemctl.h"
/* The init script exit codes for the LSB 'status' verb. (This is different from the 'start' verb, whose exit
codes are defined in exit-status.h.)
0 program is running or service is OK
1 program is dead and /var/run pid file exists
2 program is dead and /var/lock lock file exists
3 program is not running
4 program or service status is unknown
5-99 reserved for future LSB use
100-149 reserved for distribution use
150-199 reserved for application use
200-254 reserved
https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
*/
enum {
EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0,
EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1,
EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2,
EXIT_PROGRAM_NOT_RUNNING = 3,
EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
};
typedef enum BusFocus {
BUS_FULL, /* The full bus indicated via --system or --user */
BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */

View File

@ -24,9 +24,7 @@
#include "strv.h"
#include "systemctl.h"
#include "systemctl-compat-halt.h"
#include "systemctl-compat-runlevel.h"
#include "systemctl-compat-shutdown.h"
#include "systemctl-compat-telinit.h"
#include "systemctl-logind.h"
#include "time-util.h"
@ -1124,28 +1122,6 @@ int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
} else if (invoked_as(argv, "shutdown")) {
arg_action = ACTION_POWEROFF;
return shutdown_parse_argv(argc, argv);
} else if (invoked_as(argv, "init")) {
/* Matches invocations as "init" as well as "telinit", which are synonymous when run
* as PID != 1 on SysV.
*
* On SysV "telinit" was the official command to communicate with PID 1, but "init" would
* redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
* though we add one level of indirection, as we implement "telinit" in "systemctl". Hence,
* for us if you invoke "init" you get "systemd", but it will execve() "systemctl"
* immediately with argv[] unmodified if PID is != 1. If you invoke "telinit" you directly
* get "systemctl". In both cases we shall do the same thing, which is why we do
* invoked_as(argv, "init") here, as a quick way to match both.
*
* Also see redirect_telinit() in src/core/main.c. */
arg_action = _ACTION_INVALID; /* telinit_parse_argv() will figure out the actual action we'll execute */
return telinit_parse_argv(argc, argv);
} else if (invoked_as(argv, "runlevel")) {
arg_action = ACTION_RUNLEVEL;
return runlevel_parse_argv(argc, argv);
}
arg_action = ACTION_SYSTEMCTL;

View File

@ -16,16 +16,11 @@ enum action {
ACTION_HIBERNATE,
ACTION_HYBRID_SLEEP,
ACTION_SUSPEND_THEN_HIBERNATE,
ACTION_RUNLEVEL2,
ACTION_RUNLEVEL3,
ACTION_RUNLEVEL4,
ACTION_RUNLEVEL5,
ACTION_RESCUE,
ACTION_EMERGENCY,
ACTION_DEFAULT,
ACTION_RELOAD,
ACTION_REEXEC,
ACTION_RUNLEVEL,
ACTION_CANCEL_SHUTDOWN,
ACTION_SHOW_SHUTDOWN,
ACTION_SYSTEMCTL_SHOW_SHUTDOWN,

View File

@ -57,81 +57,6 @@ static int get_startup_monotonic_time(Context *c, usec_t *ret) {
return 0;
}
#define MAX_ATTEMPTS 64u
static int get_current_runlevel(Context *c) {
static const struct {
const int runlevel;
const char *special;
} table[] = {
/* The first target of this list that is active or has a job scheduled wins. We prefer
* runlevels 5 and 3 here over the others, since these are the main runlevels used on Fedora.
* It might make sense to change the order on some distributions. */
{ '5', SPECIAL_GRAPHICAL_TARGET },
{ '3', SPECIAL_MULTI_USER_TARGET },
{ '1', SPECIAL_RESCUE_TARGET },
};
int r;
assert(c);
for (unsigned n_attempts = 0;;) {
if (n_attempts++ > 0) {
/* systemd might have dropped off momentarily, let's not make this an error,
* and wait some random time. Let's pick a random time in the range 100ms2000ms,
* linearly scaled by the number of failed attempts. */
c->bus = sd_bus_flush_close_unref(c->bus);
usec_t usec =
UINT64_C(100) * USEC_PER_MSEC +
random_u64_range(UINT64_C(1900) * USEC_PER_MSEC * n_attempts / MAX_ATTEMPTS);
(void) usleep_safe(usec);
}
if (!c->bus) {
r = bus_connect_system_systemd(&c->bus);
if (r == -ECONNREFUSED && n_attempts < 64) {
log_debug_errno(r, "Failed to %s to system bus, retrying after a slight delay: %m",
n_attempts <= 1 ? "connect" : "reconnect");
continue;
}
if (r < 0)
return log_error_errno(r, "Failed to reconnect to system bus: %m");
}
FOREACH_ELEMENT(e, table) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *state = NULL, *path = NULL;
path = unit_dbus_path_from_name(e->special);
if (!path)
return log_oom();
r = sd_bus_get_property_string(
c->bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Unit",
"ActiveState",
&error,
&state);
if ((r == -ENOTCONN || bus_error_is_connection(&error)) &&
n_attempts < MAX_ATTEMPTS) {
log_debug_errno(r, "Failed to get state of %s, retrying after a slight delay: %s",
e->special, bus_error_message(&error, r));
break;
}
if (r < 0)
return log_warning_errno(r, "Failed to get state of %s: %s", e->special, bus_error_message(&error, r));
if (STR_IN_SET(state, "active", "reloading"))
return e->runlevel;
}
if (r >= 0)
return 0;
}
}
static int on_reboot(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
usec_t t = 0, boottime;
@ -182,59 +107,10 @@ static int on_shutdown(int argc, char *argv[], void *userdata) {
return q;
}
static int on_runlevel(int argc, char *argv[], void *userdata) {
Context *c = ASSERT_PTR(userdata);
int r, q = 0, previous, runlevel;
/* We finished changing runlevel, so let's write the utmp record and send the audit msg. */
/* First, get last runlevel */
r = utmp_get_runlevel(&previous, NULL);
if (r < 0) {
if (!IN_SET(r, -ESRCH, -ENOENT))
return log_error_errno(r, "Failed to get the last runlevel from utmp: %m");
previous = 0;
}
/* Secondly, get new runlevel */
runlevel = get_current_runlevel(c);
if (runlevel < 0)
return runlevel;
if (runlevel == 0) {
log_warning("Failed to get the current runlevel, utmp update skipped.");
return 0;
}
if (previous == runlevel)
return 0;
#if HAVE_AUDIT
if (c->audit_fd >= 0) {
char s[STRLEN("old-level=_ new-level=_") + 1];
xsprintf(s, "old-level=%c new-level=%c",
previous > 0 ? previous : 'N',
runlevel);
if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s,
"systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM)
q = log_error_errno(errno, "Failed to send audit message: %m");
}
#endif
r = utmp_put_runlevel(runlevel, previous);
if (r < 0 && !IN_SET(r, -ESRCH, -ENOENT))
return log_error_errno(r, "Failed to write utmp record: %m");
return q;
}
static int run(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "reboot", 1, 1, 0, on_reboot },
{ "shutdown", 1, 1, 0, on_shutdown },
{ "runlevel", 1, 1, 0, on_runlevel },
{}
};

View File

@ -13,3 +13,4 @@ version_h = custom_target('version',
vcs_tag ? '1' : '0',
])
version_include = include_directories('.')
userspace_sources += [version_h]

View File

@ -45,19 +45,4 @@ systemctl daemon-reload
# of systemd-analyze blame. See issue #27187.
systemd-analyze blame
# Test for 'systemd-update-utmp runlevel' vs 'systemctl daemon-reexec'.
# See issue #27163.
# shellcheck disable=SC2034
if [[ -x /usr/lib/systemd/systemd-update-utmp ]]; then
for _ in {0..10}; do
systemctl daemon-reexec &
pid_reexec=$!
# shellcheck disable=SC2034
for _ in {0..10}; do
SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/systemd-update-utmp runlevel
done
wait "$pid_reexec"
done
fi
touch /testok

View File

@ -1422,7 +1422,18 @@ testcase_unpriv_dir() {
# Use an image owned by the foreign UID range first via direct mapping, and than via the managed uid logic
systemd-dissect --shift "$root" foreign
assert_eq "$(systemd-nspawn --pipe --register=no -D "$root" --private-users=pick --private-users-ownership=foreign bash -c 'echo foobar')" "foobar"
assert_eq "$(systemd-nspawn --pipe --register=no -D "$root" --private-users=managed --private-network bash -c 'echo foobar')" "foobar"
# FIXME:
# Since 90fa161b5ba29d58953e9f08ddca49121b51efe6, --bind= or Bind= settings for coverage directory does
# not work with managed mode:
# ========
# [ 158.105361] systemd-nspawn[3718]: Failed to open tree and set mount attributes: Operation not permitted
# [ 158.105364] systemd-nspawn[3718]: Failed to clone /coverage: Operation not permitted
# [ 158.118655] systemd-nspawn[3707]: (sd-namespace) failed with exit status 1.
# ========
# Let's tentatively skip the test case when running on coverage.
if [[ -z "${COVERAGE_BUILD_DIR:-}" ]]; then
assert_eq "$(systemd-nspawn --pipe --register=no -D "$root" --private-users=managed --private-network bash -c 'echo foobar')" "foobar"
fi
# Test unprivileged operation
chown testuser:testuser "$root/.."

View File

@ -63,10 +63,6 @@ os-release.xml ./refsect1[title="Options"]/refsect2[title="Presentation informat
pam_systemd.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="debug="]
pam_systemd.xml ./refsect1[title="Environment"]/variablelist[1]/varlistentry[term="$XDG_SESSION_ID"]
pam_systemd.xml ./refsect1[title="Environment"]/variablelist[1]/varlistentry[term="$XDG_RUNTIME_DIR"]
runlevel.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--help"]
runlevel.xml ./refsect1[title="Environment"]/variablelist/varlistentry[term="$RUNLEVEL"]
runlevel.xml ./refsect1[title="Environment"]/variablelist/varlistentry[term="$PREVLEVEL"]
runlevel.xml ./refsect1[title="Files"]/variablelist/varlistentry[term="/run/utmp"]
shutdown.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="--help"]
shutdown.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="-H"]
shutdown.xml ./refsect1[title="Options"]/variablelist/varlistentry[term="-P"]
@ -330,7 +326,6 @@ systemd.special.xml ./refsect1[title="Units managed by the system service manage
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special Passive System Units "]/variablelist/varlistentry[term="remote-fs-pre.target"]
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special System Units"]/variablelist/varlistentry[term="rescue.target"]
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special Passive System Units "]/variablelist/varlistentry[term="rpcbind.target"]
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special System Units"]/variablelist/varlistentry[term="runlevel2.target"]
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special System Units"]/variablelist/varlistentry[term="shutdown.target"]
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special System Units"]/variablelist/varlistentry[term="sigpwr.target"]
systemd.special.xml ./refsect1[title="Units managed by the system service manager"]/refsect2[title="Special System Units"]/variablelist/varlistentry[term="sleep.target"]
@ -404,15 +399,6 @@ systemd.xml ./refsect1[title="Kernel Command Line"]/variablelist/varlistentry[te
systemd.xml ./refsect1[title="Kernel Command Line"]/variablelist/varlistentry[term="systemd.setenv="]
systemd.xml ./refsect1[title="Files"]/variablelist/varlistentry[term="/run/systemd/notify"]
systemd.xml ./refsect1[title="Files"]/variablelist/varlistentry[term="/run/systemd/private"]
systemd.xml ./refsect1[title="Files"]/variablelist/varlistentry[term="/dev/initctl"]
telinit.xml ./refsect1[title="Options"]/variablelist[1]/varlistentry[term="--help"]
telinit.xml ./refsect1[title="Options"]/variablelist[1]/varlistentry[term="--no-wall"]
telinit.xml ./refsect1[title="Options"]/variablelist[2]/varlistentry[term="0"]
telinit.xml ./refsect1[title="Options"]/variablelist[2]/varlistentry[term="6"]
telinit.xml ./refsect1[title="Options"]/variablelist[2]/varlistentry[term="2"]
telinit.xml ./refsect1[title="Options"]/variablelist[2]/varlistentry[term="1"]
telinit.xml ./refsect1[title="Options"]/variablelist[2]/varlistentry[term="q"]
telinit.xml ./refsect1[title="Options"]/variablelist[2]/varlistentry[term="u"]
tmpfiles.d.xml ./refsect1[title="Configuration File Format"]/refsect2[title="Type"]/variablelist/varlistentry[term="f"]
tmpfiles.d.xml ./refsect1[title="Configuration File Format"]/refsect2[title="Type"]/variablelist/varlistentry[term="w"]
tmpfiles.d.xml ./refsect1[title="Configuration File Format"]/refsect2[title="Type"]/variablelist/varlistentry[term="d"]

View File

@ -1,7 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
with_runlevels = conf.get('HAVE_SYSV_COMPAT') == 1
units = [
{ 'file' : 'basic.target' },
{ 'file' : 'blockdev@.target' },
@ -51,7 +49,7 @@ units = [
},
{
'file' : 'graphical.target',
'symlinks' : ['default.target'] + (with_runlevels ? ['runlevel5.target'] : []),
'symlinks' : ['default.target'],
},
{ 'file' : 'halt.target' },
{
@ -144,20 +142,14 @@ units = [
'conditions' : ['ENABLE_MACHINED'],
},
{ 'file' : 'modprobe@.service' },
{
'file' : 'multi-user.target',
'symlinks' : with_runlevels ? ['runlevel2.target', 'runlevel3.target', 'runlevel4.target'] : [],
},
{ 'file' : 'multi-user.target' },
{ 'file' : 'network-online.target' },
{ 'file' : 'network-pre.target' },
{ 'file' : 'network.target' },
{ 'file' : 'nss-lookup.target' },
{ 'file' : 'nss-user-lookup.target' },
{ 'file' : 'paths.target' },
{
'file' : 'poweroff.target',
'symlinks' : with_runlevels ? ['runlevel0.target'] : [],
},
{ 'file' : 'poweroff.target' },
{ 'file' : 'printer.target' },
{
'file' : 'proc-sys-fs-binfmt_misc.automount',
@ -182,7 +174,7 @@ units = [
},
{
'file' : 'reboot.target',
'symlinks' : ['ctrl-alt-del.target'] + (with_runlevels ? ['runlevel6.target'] : []),
'symlinks' : ['ctrl-alt-del.target'],
},
{
'file' : 'remote-cryptsetup.target',
@ -202,10 +194,7 @@ units = [
'symlinks' : ['initrd-root-device.target.wants/'],
},
{ 'file' : 'rescue.service.in' },
{
'file' : 'rescue.target',
'symlinks' : with_runlevels ? ['runlevel1.target'] : [],
},
{ 'file' : 'rescue.target' },
{ 'file' : 'rpcbind.target' },
{ 'file' : 'serial-getty@.service.in' },
{ 'file' : 'shutdown.target' },
@ -412,15 +401,6 @@ units = [
'conditions' : ['ENABLE_IMPORTD'],
'symlinks' : ['sysinit.target.wants/'],
},
{
'file' : 'systemd-initctl.service.in',
'conditions' : ['HAVE_SYSV_COMPAT'],
},
{
'file' : 'systemd-initctl.socket',
'conditions' : ['HAVE_SYSV_COMPAT'],
'symlinks' : ['sockets.target.wants/'],
},
{
'file' : 'systemd-journal-catalog-update.service',
'symlinks' : ['sysinit.target.wants/'],
@ -827,11 +807,6 @@ units = [
'file' : 'systemd-update-done.service.in',
'symlinks' : ['sysinit.target.wants/'],
},
{
'file' : 'systemd-update-utmp-runlevel.service.in',
'conditions' : ['ENABLE_UTMP', 'HAVE_SYSV_COMPAT'],
'symlinks' : ['multi-user.target.wants/', 'graphical.target.wants/', 'rescue.target.wants/'],
},
{
'file' : 'systemd-update-utmp.service.in',
'conditions' : ['ENABLE_UTMP'],
@ -997,10 +972,4 @@ else
dbussessionservicedir / 'org.freedesktop.systemd1.service'))
endif
if conf.get('HAVE_SYSV_COMPAT') == 1
foreach i : [1, 2, 3, 4, 5]
install_emptydir(systemunitdir / 'runlevel@0@.target.wants'.format(i))
endforeach
endif
subdir('user')

View File

@ -1,19 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# 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.
[Unit]
Description=initctl Compatibility Daemon
Documentation=man:systemd-initctl.service(8)
DefaultDependencies=no
[Service]
ExecStart={{LIBEXECDIR}}/systemd-initctl
NoNewPrivileges=yes
NotifyAccess=all
SystemCallArchitectures=native

View File

@ -1,19 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# 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.
[Unit]
Description=initctl Compatibility Named Pipe
Documentation=man:systemd-initctl.socket(8)
DefaultDependencies=no
Before=sockets.target
[Socket]
ListenFIFO=/run/initctl
Symlinks=/dev/initctl
SocketMode=0600

View File

@ -1,25 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# 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.
[Unit]
Description=Record Runlevel Change in UTMP
Documentation=man:systemd-update-utmp-runlevel.service(8) man:utmp(5)
ConditionPathExists=!/etc/initrd-release
DefaultDependencies=no
RequiresMountsFor=/var/log/wtmp
Conflicts=shutdown.target
Requisite=systemd-update-utmp.service
After=systemd-update-utmp.service
After=runlevel1.target runlevel2.target runlevel3.target runlevel4.target runlevel5.target
Before=shutdown.target
[Service]
Type=oneshot
ExecStart={{LIBEXECDIR}}/systemd-update-utmp runlevel