]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
battery-check: several follow-ups
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 28 Jun 2023 17:43:17 +0000 (02:43 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 29 Jun 2023 06:41:00 +0000 (15:41 +0900)
Follow-ups for e3d4148d50909119c4e9327e6ad96d3ca7f4661a.

- 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...

man/initrd-battery-check.service.xml [new file with mode: 0644]
man/rules/meson.build
man/systemd-battery-check.xml [deleted file]
src/basic/glyph-util.h
src/battery-check/battery-check.c
test/units/testsuite-74.battery-check.sh [new file with mode: 0755]
units/initrd-battery-check.service.in

diff --git a/man/initrd-battery-check.service.xml b/man/initrd-battery-check.service.xml
new file mode 100644 (file)
index 0000000..582b226
--- /dev/null
@@ -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>
index f924f551ebc1899596c4234342f99290133726c8..e5a36c43d889ad89fb24a1180b64b62b0eeaf00f 100644 (file)
@@ -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',
diff --git a/man/systemd-battery-check.xml b/man/systemd-battery-check.xml
deleted file mode 100644 (file)
index 58719c7..0000000
+++ /dev/null
@@ -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>
index 876a5a91e604ddd156fbf79f5f59186c676d4c3f..e26ef64c18766deca43a06fa2c1ce5fa120b7390 100644 (file)
@@ -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);
 }
index 14bb870ca405cdc807171d185532f709b3956709..ca13251ae09e56d790ee51d4184d1227324b5fb2 100644 (file)
 #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;
+
+        assert(mode);
+        assert(message);
 
-        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');
+        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;
 
-        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();
+        log_emergency("%s " BATTERY_LOW_MESSAGE, special_glyph(SPECIAL_GLYPH_LOW_BATTERY));
 
-                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();
+        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));
 
-                log_emergency("%s", message);
+        if (asprintf(&plymouth_message, "%s " BATTERY_LOW_MESSAGE,
+                     special_glyph_full(SPECIAL_GLYPH_LOW_BATTERY, /* force_utf = */ true)) < 0)
+                return log_oom();
 
-                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);
+        (void) plymouth_send_message("shutdown", plymouth_message);
 
-                battery_check_send_plymouth_message(plymouth_message, "shutdown");
-                sleep(10);
+        usleep_safe(10 * USEC_PER_SEC);
 
-                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");
+        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) {
+                log_emergency("Battery level critically low, powering off.");
+                return r;
+        }
 
-                if (asprintf(&ac_message, "A.C. power restored, continuing") < 0)
-                        return log_oom();
+        log_info(BATTERY_RESTORED_MESSAGE);
+        if (fd >= 0)
+                dprintf(fd, BATTERY_RESTORED_MESSAGE "\n");
+        (void) plymouth_send_message("boot-up", BATTERY_RESTORED_MESSAGE);
 
-                log_info("%s",ac_message);
-                dprintf(fd, "%s\n", ac_message);
-                battery_check_send_plymouth_message(ac_message, "boot-up");
-        }
-        return r;
+        return 0;
 }
 
 DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
diff --git a/test/units/testsuite-74.battery-check.sh b/test/units/testsuite-74.battery-check.sh
new file mode 100755 (executable)
index 0000000..ec5a0c8
--- /dev/null
@@ -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 || :
index 4b140497462e10c6f14f8b5b8b2574112ade1503..052586f3c78c482223b9ccac86dc202d0e738f46 100644 (file)
@@ -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