mirror of
https://github.com/systemd/systemd
synced 2024-07-22 10:44:58 +00:00
battery-check: several follow-ups
Follow-ups for e3d4148d50
.
- add reference to initrd-battery-check.service in man page, and move
its section from 1 to 8,
- add link to man page in help message,
- introduce ERRNO_IS_NO_PLYMOUTH(),
- propagate error in battery_check_send_plymouth_message(),
- rename battery_check_send_plymouth_message() -> plymouth_send_message(),
- return earlier when the first battery level check passed to reduce
indentation,
- fix potential use of invalid fd on battery restored,
- do not use emoji for /dev/console,
- add simple test (mostly for coverity),
etc, etc...
This commit is contained in:
parent
d625f717db
commit
be994c2640
72
man/initrd-battery-check.service.xml
Normal file
72
man/initrd-battery-check.service.xml
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
|
||||
<refentry id="initrd-battery-check.service" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>systemd-battery-check</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>initrd-battery-check.service</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>initrd-battery-check.service</refname>
|
||||
<refname>systemd-battery-check</refname>
|
||||
<refpurpose>Check battery level whether there's enough charge, and power off if not.</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>initrd-battery-check.service</filename></para>
|
||||
<cmdsynopsis>
|
||||
<command>/usr/lib/systemd/systemd-battery-check</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
<filename>initrd-battery-check.service</filename> is used to check the battery level during the early
|
||||
boot stage to determine whether there's sufficient battery power to carry on with the booting process.
|
||||
</para>
|
||||
<para>
|
||||
<command>systemd-battery-check</command> returns success if the device is connected to an AC power
|
||||
source or if the battery charge is greater than 5%. It returns failure otherwise.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<para>The following options are understood by <command>systemd-battery-check</command>:</para>
|
||||
|
||||
<variablelist>
|
||||
<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 (running on AC power or battery capacity greater than 5%), 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>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
|
@ -23,6 +23,7 @@ manpages = [
|
|||
['hostname', '5', [], ''],
|
||||
['hostnamectl', '1', [], 'ENABLE_HOSTNAMED'],
|
||||
['hwdb', '7', [], 'ENABLE_HWDB'],
|
||||
['initrd-battery-check.service', '8', ['systemd-battery-check'], ''],
|
||||
['integritytab', '5', [], 'HAVE_LIBCRYPTSETUP'],
|
||||
['iocost.conf', '5', [], ''],
|
||||
['journal-remote.conf', '5', ['journal-remote.conf.d'], 'HAVE_MICROHTTPD'],
|
||||
|
@ -887,7 +888,6 @@ manpages = [
|
|||
''],
|
||||
['systemd-ask-password', '1', [], ''],
|
||||
['systemd-backlight@.service', '8', ['systemd-backlight'], 'ENABLE_BACKLIGHT'],
|
||||
['systemd-battery-check', '1', [], ''],
|
||||
['systemd-binfmt.service', '8', ['systemd-binfmt'], 'ENABLE_BINFMT'],
|
||||
['systemd-bless-boot-generator', '8', [], 'ENABLE_BOOTLOADER'],
|
||||
['systemd-bless-boot.service',
|
||||
|
|
|
@ -1,63 +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.2/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
|
||||
<refentry id="systemd-battery-check" xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>systemd-battery-check</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>systemd-battery-check</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-battery-check</refname>
|
||||
<refpurpose>Checks battery level to see whether there's enough charge.</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-battery-check</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><command>systemd-battery-check</command> is used to check the battery level during the early boot
|
||||
stage to determine whether there's sufficient battery power to carry on with the booting process.
|
||||
The tool returns success if the device is connected to an AC power source
|
||||
or if the battery charge is greater than 5%. It returns failure otherwise.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<para>The following options are understood:</para>
|
||||
|
||||
<variablelist>
|
||||
<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 (running on AC power or battery capacity greater than 5%), 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>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
|
@ -50,18 +50,14 @@ typedef enum SpecialGlyph {
|
|||
_SPECIAL_GLYPH_INVALID = -EINVAL,
|
||||
} SpecialGlyph;
|
||||
|
||||
const char *special_glyph_full(SpecialGlyph code, bool force_utf) _const_;
|
||||
|
||||
bool emoji_enabled(void);
|
||||
|
||||
const char *special_glyph_full(SpecialGlyph code, bool force_utf) _const_;
|
||||
|
||||
static inline const char *special_glyph(SpecialGlyph code) {
|
||||
return special_glyph_full(code, false);
|
||||
}
|
||||
|
||||
static inline const char *special_glyph_force_utf(SpecialGlyph code) {
|
||||
return special_glyph_full(code, true);
|
||||
}
|
||||
|
||||
static inline const char *special_glyph_check_mark(bool b) {
|
||||
return b ? special_glyph(SPECIAL_GLYPH_CHECK_MARK) : special_glyph(SPECIAL_GLYPH_CROSS_MARK);
|
||||
}
|
||||
|
|
|
@ -14,47 +14,74 @@
|
|||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "pretty-print.h"
|
||||
#include "socket-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define BATTERY_LOW_MESSAGE \
|
||||
"Battery level critically low. Please connect your charger or the system will power off in 10 seconds."
|
||||
#define BATTERY_RESTORED_MESSAGE \
|
||||
"A.C. power restored, continuing."
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-battery-check", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
static void help(void) {
|
||||
printf("%s\n\n"
|
||||
"Checks battery level to see whether there's enough charge.\n\n"
|
||||
"%sCheck battery level to see whether there's enough charge.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n",
|
||||
program_invocation_short_name);
|
||||
" --version Show package version\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void battery_check_send_plymouth_message(char *message, const char *mode) {
|
||||
assert(message);
|
||||
assert(mode);
|
||||
static bool ERRNO_IS_NO_PLYMOUTH(int r) {
|
||||
return IN_SET(abs(r), EAGAIN, ENOENT) || ERRNO_IS_DISCONNECT(r);
|
||||
}
|
||||
|
||||
int r;
|
||||
static int plymouth_send_message(const char *mode, const char *message) {
|
||||
static const union sockaddr_union sa = PLYMOUTH_SOCKET;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_free_ char *plymouth_message = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int c, r;
|
||||
|
||||
int c = asprintf(&plymouth_message,
|
||||
"C\x02%c%s%c"
|
||||
"M\x02%c%s%c",
|
||||
(int) strlen(mode) + 1, mode, '\x00',
|
||||
(int) strlen(message) + 1, message, '\x00');
|
||||
assert(mode);
|
||||
assert(message);
|
||||
|
||||
c = asprintf(&plymouth_message,
|
||||
"C\x02%c%s%c"
|
||||
"M\x02%c%s%c",
|
||||
(int) strlen(mode) + 1, mode, '\x00',
|
||||
(int) strlen(message) + 1, message, '\x00');
|
||||
if (c < 0)
|
||||
return (void) log_oom();
|
||||
return log_oom();
|
||||
|
||||
/* We set SOCK_NONBLOCK here so that we rather drop the
|
||||
* message than wait for plymouth */
|
||||
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (fd < 0)
|
||||
return (void) log_warning_errno(errno, "socket() failed: %m");
|
||||
return log_warning_errno(errno, "socket() failed: %m");
|
||||
|
||||
if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
|
||||
return (void) log_full_errno(IN_SET(errno, EAGAIN, ENOENT) || ERRNO_IS_DISCONNECT(errno) ? LOG_DEBUG : LOG_WARNING, errno, "Connection to plymouth failed: %m");
|
||||
return log_full_errno(ERRNO_IS_NO_PLYMOUTH(errno) ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
"Failed to connect to plymouth: %m");
|
||||
|
||||
r = loop_write(fd, plymouth_message, c, /* do_poll = */ false);
|
||||
if (r < 0)
|
||||
return (void) log_full_errno(IN_SET(r, -EAGAIN, -ENOENT) || ERRNO_IS_DISCONNECT(r) ?
|
||||
LOG_DEBUG : LOG_WARNING, r, "Failed to write to plymouth, ignoring: %m");
|
||||
return log_full_errno(ERRNO_IS_NO_PLYMOUTH(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to write to plymouth: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char * argv[]) {
|
||||
|
@ -79,8 +106,7 @@ static int parse_argv(int argc, char * argv[]) {
|
|||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
@ -100,10 +126,11 @@ static int parse_argv(int argc, char * argv[]) {
|
|||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_free_ char *plymouth_message = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
log_setup();
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r <= 0)
|
||||
|
@ -114,44 +141,40 @@ static int run(int argc, char *argv[]) {
|
|||
log_warning_errno(r, "Failed to check battery status, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
log_emergency("%s " BATTERY_LOW_MESSAGE, special_glyph(SPECIAL_GLYPH_LOW_BATTERY));
|
||||
|
||||
fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
log_warning_errno(fd, "Failed to open console, ignoring: %m");
|
||||
else
|
||||
dprintf(fd, ANSI_HIGHLIGHT_RED "%s " BATTERY_LOW_MESSAGE ANSI_NORMAL "\n",
|
||||
special_glyph_full(SPECIAL_GLYPH_LOW_BATTERY, /* force_utf = */ false));
|
||||
|
||||
if (asprintf(&plymouth_message, "%s " BATTERY_LOW_MESSAGE,
|
||||
special_glyph_full(SPECIAL_GLYPH_LOW_BATTERY, /* force_utf = */ true)) < 0)
|
||||
return log_oom();
|
||||
|
||||
(void) plymouth_send_message("shutdown", plymouth_message);
|
||||
|
||||
usleep_safe(10 * USEC_PER_SEC);
|
||||
|
||||
r = battery_is_discharging_and_low();
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to check battery status, assuming not charged yet, powering off: %m");
|
||||
if (r > 0) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_free_ char *message = NULL, *plymouth_message = NULL, *ac_message = NULL;
|
||||
|
||||
if (asprintf(&message, "%s Battery level critically low. Please connect your charger or the system will power off in 10 seconds.", special_glyph(SPECIAL_GLYPH_LOW_BATTERY)) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (asprintf(&plymouth_message, "%s Battery level critically low. Please connect your charger or the system will power off in 10 seconds.", special_glyph_force_utf(SPECIAL_GLYPH_LOW_BATTERY)) < 0)
|
||||
return log_oom();
|
||||
|
||||
log_emergency("%s", message);
|
||||
|
||||
fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
log_warning_errno(fd, "Failed to open console, ignoring: %m");
|
||||
else
|
||||
dprintf(fd, ANSI_HIGHLIGHT_RED "%s" ANSI_NORMAL "\n", message);
|
||||
|
||||
battery_check_send_plymouth_message(plymouth_message, "shutdown");
|
||||
sleep(10);
|
||||
|
||||
r = battery_is_discharging_and_low();
|
||||
if (r > 0) {
|
||||
log_emergency("Battery level critically low, powering off.");
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to check battery status, ignoring: %m");
|
||||
|
||||
if (asprintf(&ac_message, "A.C. power restored, continuing") < 0)
|
||||
return log_oom();
|
||||
|
||||
log_info("%s",ac_message);
|
||||
dprintf(fd, "%s\n", ac_message);
|
||||
battery_check_send_plymouth_message(ac_message, "boot-up");
|
||||
log_emergency("Battery level critically low, powering off.");
|
||||
return r;
|
||||
}
|
||||
return r;
|
||||
|
||||
log_info(BATTERY_RESTORED_MESSAGE);
|
||||
if (fd >= 0)
|
||||
dprintf(fd, BATTERY_RESTORED_MESSAGE "\n");
|
||||
(void) plymouth_send_message("boot-up", BATTERY_RESTORED_MESSAGE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
|
||||
|
|
9
test/units/testsuite-74.battery-check.sh
Executable file
9
test/units/testsuite-74.battery-check.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
systemd-battery-check --help
|
||||
systemd-battery-check --version
|
||||
|
||||
systemd-battery-check || :
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
[Unit]
|
||||
Description=Check battery level during early boot
|
||||
Documentation=man:systemd-battery-check(1)
|
||||
Documentation=man:initrd-battery-check.service(8)
|
||||
DefaultDependencies=no
|
||||
AssertPathExists=/etc/initrd-release
|
||||
Before=local-fs-pre.target
|
||||
|
|
Loading…
Reference in a new issue