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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user