From caaeb1ea160c1ae21d4a6c0a5efdfa1d0e5145c6 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Fri, 10 Feb 2023 16:18:02 +0000 Subject: [PATCH] Split out the console handling to a new module This simplifies a lot of confusion. --- po/POTFILES.in | 2 +- src/fu-console.c | 779 +++++++++++++++++++++++++++++++++++++ src/fu-console.h | 69 ++++ src/fu-progressbar.c | 475 ---------------------- src/fu-progressbar.h | 27 -- src/fu-self-test.c | 24 +- src/fu-tool.c | 325 +++++++++------- src/fu-util-bios-setting.c | 7 +- src/fu-util-bios-setting.h | 7 +- src/fu-util-common.c | 399 ++++--------------- src/fu-util-common.h | 49 +-- src/fu-util.c | 641 ++++++++++++++++-------------- src/meson.build | 2 +- 13 files changed, 1489 insertions(+), 1317 deletions(-) create mode 100644 src/fu-console.c create mode 100644 src/fu-console.h delete mode 100644 src/fu-progressbar.c delete mode 100644 src/fu-progressbar.h diff --git a/po/POTFILES.in b/po/POTFILES.in index fb1a1d115..7feb0fece 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -8,11 +8,11 @@ plugins/tpm/fu-tpm-eventlog.c plugins/uefi-capsule/fu-uefi-capsule-plugin.c plugins/uefi-capsule/fu-uefi-tool.c plugins/uefi-dbx/fu-dbxtool.c +src/fu-console.c src/fu-debug.c src/fu-engine-helper.c src/fu-main.c src/fu-offline.c -src/fu-progressbar.c src/fu-remote-list.c src/fu-security-attr-common.c src/fu-tool.c diff --git a/src/fu-console.c b/src/fu-console.c new file mode 100644 index 000000000..933d29229 --- /dev/null +++ b/src/fu-console.c @@ -0,0 +1,779 @@ +/* + * Copyright (C) 2017 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#define G_LOG_DOMAIN "FuProgressBar" + +#include "config.h" + +#include +#include + +#include "fu-console.h" + +#ifdef _WIN32 +#include +#include +#endif + +struct _FuConsole { + GObject parent_instance; + GMainContext *main_ctx; + FwupdStatus status; + gboolean spinner_count_up; /* width in visible chars */ + guint spinner_idx; /* width in visible chars */ + guint length_percentage; /* width in visible chars */ + guint length_status; /* width in visible chars */ + guint percentage; + GSource *timer_source; + gint64 last_animated; /* monotonic */ + GTimer *time_elapsed; + gdouble last_estimate; + gboolean interactive; + gboolean contents_to_clear; +}; + +G_DEFINE_TYPE(FuConsole, fu_console, G_TYPE_OBJECT) + +gboolean +fu_console_setup(FuConsole *self, GError **error) +{ +#ifdef _WIN32 + HANDLE hOut; + DWORD dwMode = 0; + + /* enable VT sequences */ + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "failed to get stdout [%u]", + (guint)GetLastError()); + return FALSE; + } + if (!GetConsoleMode(hOut, &dwMode)) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "failed to get mode [%u]", + (guint)GetLastError()); + return FALSE; + } + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (!SetConsoleMode(hOut, dwMode)) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "failed to set mode [%u]", + (guint)GetLastError()); + return FALSE; + } + if (!SetConsoleOutputCP(CP_UTF8)) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "failed to set output UTF-8 [%u]", + (guint)GetLastError()); + return FALSE; + } + if (!SetConsoleCP(CP_UTF8)) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "failed to set UTF-8 [%u]", + (guint)GetLastError()); + return FALSE; + } +#else + if (isatty(fileno(stdout)) == 0) { + g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "not a TTY"); + return FALSE; + } +#endif + /* success */ + return TRUE; +} + +static void +fu_console_erase_line(FuConsole *self) +{ + if (!self->interactive) + return; + g_print("\033[G"); +} + +static void +fu_console_reset_line(FuConsole *self) +{ + if (self->contents_to_clear) { + fu_console_erase_line(self); + g_print("\n"); + self->contents_to_clear = FALSE; + } +} + +void +fu_console_print_kv(FuConsole *self, const gchar *title, const gchar *msg) +{ + gsize title_len; + g_auto(GStrv) lines = NULL; + + if (msg == NULL) + return; + fu_console_reset_line(self); + g_print("%s:", title); + + /* pad */ + title_len = fu_strwidth(title) + 1; + lines = g_strsplit(msg, "\n", -1); + for (guint j = 0; lines[j] != NULL; j++) { + for (gsize i = title_len; i < 25; i++) + g_print(" "); + g_print("%s\n", lines[j]); + title_len = 0; + } +} + +guint +fu_console_input_uint(FuConsole *self, guint maxnum) +{ + gint retval; + guint answer = 0; + + do { + char buffer[64]; + + /* swallow the \n at end of line too */ + if (!fgets(buffer, sizeof(buffer), stdin)) + break; + if (strlen(buffer) == sizeof(buffer) - 1) + continue; + + /* get a number */ + retval = sscanf(buffer, "%u", &answer); + + /* positive */ + if (retval == 1 && answer <= maxnum) + break; + + /* TRANSLATORS: the user isn't reading the question */ + fu_console_print_full(self, + FU_CONSOLE_PRINT_FLAG_NONE, + _("Please enter a number from 0 to %u: "), + maxnum); + } while (TRUE); + return answer; +} + +gboolean +fu_console_input_bool(FuConsole *self, gboolean def, const gchar *format, ...) +{ + va_list args; + g_autofree gchar *tmp = NULL; + g_autoptr(GString) str = g_string_new(NULL); + + va_start(args, format); + tmp = g_strdup_vprintf(format, args); + va_end(args); + + g_string_append_printf(str, "%s [%s]: ", tmp, def ? "Y|n" : "y|N"); + fu_console_print_literal(self, str->str); + + do { + char buffer[4]; + if (!fgets(buffer, sizeof(buffer), stdin)) + continue; + if (strlen(buffer) == sizeof(buffer) - 1) + continue; + if (g_strcmp0(buffer, "\n") == 0) + return def; + buffer[0] = g_ascii_toupper(buffer[0]); + if (g_strcmp0(buffer, "Y\n") == 0) + return TRUE; + if (g_strcmp0(buffer, "N\n") == 0) + return FALSE; + } while (TRUE); + return FALSE; +} + +static GPtrArray * +fu_console_strsplit_words(const gchar *text, guint line_len) +{ + g_auto(GStrv) tokens = NULL; + g_autoptr(GPtrArray) lines = g_ptr_array_new_with_free_func(g_free); + g_autoptr(GString) curline = g_string_new(NULL); + + /* sanity check */ + if (text == NULL || text[0] == '\0') + return NULL; + if (line_len == 0) + return NULL; + + /* tokenize the string */ + tokens = g_strsplit(text, " ", -1); + for (guint i = 0; tokens[i] != NULL; i++) { + /* current line plus new token is okay */ + if (curline->len + fu_strwidth(tokens[i]) < line_len) { + g_string_append_printf(curline, "%s ", tokens[i]); + continue; + } + + /* too long, so remove space, add newline and dump */ + if (curline->len > 0) + g_string_truncate(curline, curline->len - 1); + g_ptr_array_add(lines, g_strdup(curline->str)); + g_string_truncate(curline, 0); + g_string_append_printf(curline, "%s ", tokens[i]); + } + + /* any incomplete line? */ + if (curline->len > 0) { + g_string_truncate(curline, curline->len - 1); + g_ptr_array_add(lines, g_strdup(curline->str)); + } + return g_steal_pointer(&lines); +} + +static void +fu_console_box_line(const gchar *start, + const gchar *text, + const gchar *end, + const gchar *padding, + guint width) +{ + guint offset = 0; + if (start != NULL) { + offset += fu_strwidth(start); + g_print("%s", start); + } + if (text != NULL) { + offset += fu_strwidth(text); + g_print("%s", text); + } + if (end != NULL) + offset += fu_strwidth(end); + for (guint i = offset; i < width; i++) + g_print("%s", padding); + if (end != NULL) + g_print("%s\n", end); +} + +void +fu_console_line(FuConsole *self, guint width) +{ + g_autoptr(GString) str = g_string_new_len(NULL, width); + for (guint i = 0; i < width; i++) + g_string_append(str, "─"); + fu_console_print_literal(self, str->str); +} + +void +fu_console_box(FuConsole *self, const gchar *title, const gchar *body, guint width) +{ + /* nothing to do */ + if (title == NULL && body == NULL) + return; + + /* header */ + fu_console_reset_line(self); + fu_console_box_line("╔", NULL, "╗", "═", width); + + /* optional title */ + if (title != NULL) { + g_autoptr(GPtrArray) lines = fu_console_strsplit_words(title, width - 4); + for (guint j = 0; j < lines->len; j++) { + const gchar *line = g_ptr_array_index(lines, j); + fu_console_box_line("║ ", line, " ║", " ", width); + } + } + + /* join */ + if (title != NULL && body != NULL) + fu_console_box_line("╠", NULL, "╣", "═", width); + + /* optional body */ + if (body != NULL) { + gboolean has_nonempty = FALSE; + g_auto(GStrv) split = g_strsplit(body, "\n", -1); + for (guint i = 0; split[i] != NULL; i++) { + g_autoptr(GPtrArray) lines = fu_console_strsplit_words(split[i], width - 4); + if (lines == NULL) { + if (has_nonempty) { + fu_console_box_line("║ ", NULL, " ║", " ", width); + has_nonempty = FALSE; + } + continue; + } + for (guint j = 0; j < lines->len; j++) { + const gchar *line = g_ptr_array_index(lines, j); + fu_console_box_line("║ ", line, " ║", " ", width); + } + has_nonempty = TRUE; + } + } + + /* footer */ + fu_console_box_line("╚", NULL, "╝", "═", width); +} + +static const gchar * +fu_console_status_to_string(FwupdStatus status) +{ + switch (status) { + case FWUPD_STATUS_IDLE: + /* TRANSLATORS: daemon is inactive */ + return _("Idle…"); + break; + case FWUPD_STATUS_DECOMPRESSING: + /* TRANSLATORS: decompressing the firmware file */ + return _("Decompressing…"); + break; + case FWUPD_STATUS_LOADING: + /* TRANSLATORS: parsing the firmware information */ + return _("Loading…"); + break; + case FWUPD_STATUS_DEVICE_RESTART: + /* TRANSLATORS: restarting the device to pick up new F/W */ + return _("Restarting device…"); + break; + case FWUPD_STATUS_DEVICE_READ: + /* TRANSLATORS: reading from the flash chips */ + return _("Reading…"); + break; + case FWUPD_STATUS_DEVICE_WRITE: + /* TRANSLATORS: writing to the flash chips */ + return _("Writing…"); + break; + case FWUPD_STATUS_DEVICE_ERASE: + /* TRANSLATORS: erasing contents of the flash chips */ + return _("Erasing…"); + break; + case FWUPD_STATUS_DEVICE_VERIFY: + /* TRANSLATORS: verifying we wrote the firmware correctly */ + return _("Verifying…"); + break; + case FWUPD_STATUS_SCHEDULING: + /* TRANSLATORS: scheduling an update to be done on the next boot */ + return _("Scheduling…"); + break; + case FWUPD_STATUS_DOWNLOADING: + /* TRANSLATORS: downloading from a remote server */ + return _("Downloading…"); + break; + case FWUPD_STATUS_WAITING_FOR_AUTH: + /* TRANSLATORS: waiting for user to authenticate */ + return _("Authenticating…"); + break; + case FWUPD_STATUS_DEVICE_BUSY: + /* TRANSLATORS: waiting for device to do something */ + return _("Waiting…"); + break; + default: + break; + } + + /* TRANSLATORS: current daemon status is unknown */ + return _("Unknown"); +} + +static gboolean +_fu_status_is_predictable(FwupdStatus status) +{ + if (status == FWUPD_STATUS_DEVICE_ERASE) + return TRUE; + if (status == FWUPD_STATUS_DEVICE_VERIFY) + return TRUE; + if (status == FWUPD_STATUS_DEVICE_READ) + return TRUE; + if (status == FWUPD_STATUS_DEVICE_WRITE) + return TRUE; + if (status == FWUPD_STATUS_DOWNLOADING) + return TRUE; + return FALSE; +} + +static gboolean +fu_console_estimate_ready(FuConsole *self, guint percentage) +{ + gdouble old; + gdouble elapsed; + + /* now invalid */ + if (percentage == 0 || percentage == 100) { + g_timer_start(self->time_elapsed); + self->last_estimate = 0; + return FALSE; + } + + /* allow-list things that make sense... */ + if (!_fu_status_is_predictable(self->status)) + return FALSE; + + old = self->last_estimate; + elapsed = g_timer_elapsed(self->time_elapsed, NULL); + self->last_estimate = elapsed / percentage * (100 - percentage); + + /* estimate is ready if we have decreased */ + return old > self->last_estimate; +} + +static gchar * +fu_console_time_remaining_str(FuConsole *self) +{ + /* less than 5 seconds remaining */ + if (self->last_estimate < 5) + return NULL; + + /* less than 60 seconds remaining */ + if (self->last_estimate < 60) { + /* TRANSLATORS: time remaining for completing firmware flash */ + return g_strdup(_("Less than one minute remaining")); + } + + return g_strdup_printf( + /* TRANSLATORS: more than a minute */ + ngettext("%.0f minute remaining", "%.0f minutes remaining", self->last_estimate / 60), + self->last_estimate / 60); +} + +static void +fu_console_refresh(FuConsole *self) +{ + const gchar *title; + guint i; + g_autoptr(GString) str = g_string_new(NULL); + + /* sanity check */ + if (self->status == FWUPD_STATUS_IDLE || self->status == FWUPD_STATUS_UNKNOWN) + return; + + /* erase previous line */ + fu_console_erase_line(self); + + /* add status */ + title = fu_console_status_to_string(self->status); + g_string_append(str, title); + for (i = fu_strwidth(str->str); i < self->length_status; i++) + g_string_append_c(str, ' '); + + /* add console */ + g_string_append(str, "["); + if (self->percentage > 0) { + for (i = 0; i < (self->length_percentage - 1) * self->percentage / 100; i++) + g_string_append_c(str, '*'); + for (i = i + 1; i < self->length_percentage; i++) + g_string_append_c(str, ' '); + } else { + const gchar chars[] = { + '-', + '\\', + '|', + '/', + }; + for (i = 0; i < self->spinner_idx; i++) + g_string_append_c(str, ' '); + g_string_append_c(str, chars[i / 4 % G_N_ELEMENTS(chars)]); + for (i = i + 1; i < self->length_percentage - 1; i++) + g_string_append_c(str, ' '); + } + g_string_append_c(str, ']'); + + /* once we have good data show an estimate of time remaining */ + if (fu_console_estimate_ready(self, self->percentage)) { + g_autofree gchar *remaining = fu_console_time_remaining_str(self); + if (remaining != NULL) + g_string_append_printf(str, " %s…", remaining); + } + + /* dump to screen */ + g_print("%s", str->str); + self->contents_to_clear = TRUE; +} + +/** + * fu_console_print_full: + * @self: a #FuConsole + * @flags; a #FuConsolePrintFlags, e.g. %FU_CONSOLE_PRINT_FLAG_STDERR + * @text: string + * + * Clears the console, and prints the text. + **/ +void +fu_console_print_full(FuConsole *self, FuConsolePrintFlags flags, const gchar *format, ...) +{ + va_list args; + g_autoptr(GString) str = g_string_new(NULL); + + va_start(args, format); + g_string_append_vprintf(str, format, args); + va_end(args); + + if (flags & FU_CONSOLE_PRINT_FLAG_WARNING) { + /* TRANSLATORS: this is a prefix on the console */ + g_autofree gchar *fmt = fu_console_color_format(_("WARNING"), FU_CONSOLE_COLOR_RED); + g_string_prepend(str, ": "); + g_string_prepend(str, fmt); + flags |= FU_CONSOLE_PRINT_FLAG_STDERR; + } + + fu_console_reset_line(self); + if (flags & FU_CONSOLE_PRINT_FLAG_STDERR) { + g_printerr("%s", str->str); + } else { + g_print("%s", str->str); + } +} + +void +fu_console_print_literal(FuConsole *self, const gchar *text) +{ + fu_console_reset_line(self); + g_print("%s\n", text); +} + +/** + * fu_console_print: + * @self: a #FuConsole + * @text: string + * + * Clears the console, prints the text and prints a newline. + **/ +void +fu_console_print(FuConsole *self, const gchar *format, ...) +{ + va_list args; + g_autofree gchar *tmp = NULL; + + va_start(args, format); + tmp = g_strdup_vprintf(format, args); + va_end(args); + fu_console_print_literal(self, tmp); +} + +/** + * fu_console_set_progress_title: + * @self: A #FuConsole + * @title: A string + * + * Sets console title + **/ +void +fu_console_set_progress_title(FuConsole *self, const gchar *title) +{ + fu_console_erase_line(self); + g_print("%s\n", title); + fu_console_refresh(self); +} + +/** + * fu_console_set_main_context: + * @self: A #FuConsole + * @main_ctx: (nullable): main context + * + * Sets console main context to use for animations. + **/ +void +fu_console_set_main_context(FuConsole *self, GMainContext *main_ctx) +{ + self->main_ctx = g_main_context_ref(main_ctx); +} + +static void +fu_console_spin_inc(FuConsole *self) +{ + /* reset */ + self->last_animated = g_get_monotonic_time(); + + /* up to down */ + if (self->spinner_count_up) { + if (++self->spinner_idx > self->length_percentage - 3) + self->spinner_count_up = FALSE; + } else { + if (--self->spinner_idx == 0) + self->spinner_count_up = TRUE; + } +} + +static gboolean +fu_console_spin_cb(gpointer user_data) +{ + FuConsole *self = FU_CONSOLE(user_data); + + /* move the spinner index up to down */ + fu_console_spin_inc(self); + + /* update the terminal */ + fu_console_refresh(self); + + return G_SOURCE_CONTINUE; +} + +static void +fu_console_spin_end(FuConsole *self) +{ + if (self->timer_source != NULL) { + g_source_destroy(self->timer_source); + self->timer_source = NULL; + + /* reset when the spinner has been stopped */ + g_timer_start(self->time_elapsed); + } + + /* go back to the start when we next go into unknown percentage mode */ + self->spinner_idx = 0; + self->spinner_count_up = TRUE; +} + +static void +fu_console_spin_start(FuConsole *self) +{ + if (self->timer_source != NULL) + g_source_destroy(self->timer_source); + self->timer_source = g_timeout_source_new(40); + g_source_set_callback(self->timer_source, fu_console_spin_cb, self, NULL); + g_source_attach(self->timer_source, self->main_ctx); +} + +/** + * fu_console_set_progress: + * @self: A #FuConsole + * @status: A #FwupdStatus + * @percentage: unsigned integer + * + * Refreshes the progress bar with the new percentage and status. + **/ +void +fu_console_set_progress(FuConsole *self, FwupdStatus status, guint percentage) +{ + g_return_if_fail(FU_IS_CONSOLE(self)); + + /* not useful */ + if (status == FWUPD_STATUS_UNKNOWN) + return; + + /* ignore duplicates */ + if (self->status == status && self->percentage == percentage) + return; + + /* cache */ + self->status = status; + self->percentage = percentage; + + /* dumb */ + if (!self->interactive) { + g_printerr("%s: %u%%\n", fu_console_status_to_string(status), percentage); + return; + } + + /* if the main loop isn't spinning and we've not had a chance to + * execute the callback just do the refresh now manually */ + if (percentage == 0 && status != FWUPD_STATUS_IDLE && + self->status != FWUPD_STATUS_UNKNOWN) { + if ((g_get_monotonic_time() - self->last_animated) / 1000 > 40) { + fu_console_spin_inc(self); + fu_console_refresh(self); + } + } + + /* enable or disable the spinner timeout */ + if (percentage > 0) { + fu_console_spin_end(self); + } else { + fu_console_spin_start(self); + } + + /* update the terminal */ + fu_console_refresh(self); +} + +/** + * fu_console_set_interactive: + * @self: A #FuConsole + * @interactive: #gboolean + * + * Marks the console as interactive or not + **/ +void +fu_console_set_interactive(FuConsole *self, gboolean interactive) +{ + g_return_if_fail(FU_IS_CONSOLE(self)); + self->interactive = interactive; +} + +/** + * fu_console_set_status_length: + * @self: A #FuConsole + * @len: unsigned integer + * + * Sets the width of the progressbar status, which must be greater that 3. + **/ +void +fu_console_set_status_length(FuConsole *self, guint len) +{ + g_return_if_fail(FU_IS_CONSOLE(self)); + g_return_if_fail(len > 3); + self->length_status = len; +} + +/** + * fu_console_set_percentage_length: + * @self: A #FuConsole + * @len: unsigned integer + * + * Sets the width of the progressbar percentage, which must be greater that 3. + **/ +void +fu_console_set_percentage_length(FuConsole *self, guint len) +{ + g_return_if_fail(FU_IS_CONSOLE(self)); + g_return_if_fail(len > 3); + self->length_percentage = len; +} + +static void +fu_console_init(FuConsole *self) +{ + self->length_percentage = 40; + self->length_status = 25; + self->spinner_count_up = TRUE; + self->time_elapsed = g_timer_new(); + self->interactive = TRUE; +} + +static void +fu_console_finalize(GObject *obj) +{ + FuConsole *self = FU_CONSOLE(obj); + + fu_console_reset_line(self); + if (self->timer_source != 0) + g_source_destroy(self->timer_source); + if (self->main_ctx != NULL) + g_main_context_unref(self->main_ctx); + g_timer_destroy(self->time_elapsed); + + G_OBJECT_CLASS(fu_console_parent_class)->finalize(obj); +} + +static void +fu_console_class_init(FuConsoleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = fu_console_finalize; +} + +/** + * fu_console_new: + * + * Creates a new #FuConsole + **/ +FuConsole * +fu_console_new(void) +{ + FuConsole *self; + self = g_object_new(FU_TYPE_CONSOLE, NULL); + return FU_CONSOLE(self); +} diff --git a/src/fu-console.h b/src/fu-console.h new file mode 100644 index 000000000..d31066152 --- /dev/null +++ b/src/fu-console.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#pragma once + +#include + +#define FU_TYPE_CONSOLE (fu_console_get_type()) +G_DECLARE_FINAL_TYPE(FuConsole, fu_console, FU, CONSOLE, GObject) + +typedef enum { + FU_CONSOLE_COLOR_BLACK = 30, + FU_CONSOLE_COLOR_RED = 31, + FU_CONSOLE_COLOR_GREEN = 32, + FU_CONSOLE_COLOR_YELLOW = 33, + FU_CONSOLE_COLOR_BLUE = 34, + FU_CONSOLE_COLOR_MAGENTA = 35, + FU_CONSOLE_COLOR_CYAN = 36, + FU_CONSOLE_COLOR_WHITE = 37, +} FuConsoleColor; + +typedef enum { + FU_CONSOLE_PRINT_FLAG_NONE = 0, + FU_CONSOLE_PRINT_FLAG_STDERR = 1 << 0, + FU_CONSOLE_PRINT_FLAG_WARNING = 1 << 1, +} FuConsolePrintFlags; + +gchar * +fu_console_color_format(const gchar *text, FuConsoleColor fg_color); + +FuConsole * +fu_console_new(void); +gboolean +fu_console_setup(FuConsole *self, GError **error); + +guint +fu_console_input_uint(FuConsole *self, guint maxnum); +gboolean +fu_console_input_bool(FuConsole *self, gboolean def, const gchar *format, ...) G_GNUC_PRINTF(3, 4); + +void +fu_console_print_full(FuConsole *self, FuConsolePrintFlags flags, const gchar *format, ...) + G_GNUC_PRINTF(3, 4); +void +fu_console_print(FuConsole *self, const gchar *format, ...) G_GNUC_PRINTF(2, 3); +void +fu_console_print_literal(FuConsole *self, const gchar *text); +void +fu_console_print_kv(FuConsole *self, const gchar *title, const gchar *msg); +void +fu_console_line(FuConsole *self, guint width); +void +fu_console_box(FuConsole *self, const gchar *title, const gchar *body, guint width); + +void +fu_console_set_progress(FuConsole *self, FwupdStatus status, guint percentage); +void +fu_console_set_status_length(FuConsole *self, guint len); +void +fu_console_set_percentage_length(FuConsole *self, guint len); +void +fu_console_set_progress_title(FuConsole *self, const gchar *title); +void +fu_console_set_interactive(FuConsole *self, gboolean interactive); +void +fu_console_set_main_context(FuConsole *self, GMainContext *main_ctx); diff --git a/src/fu-progressbar.c b/src/fu-progressbar.c deleted file mode 100644 index f747c759b..000000000 --- a/src/fu-progressbar.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2017 Richard Hughes - * - * SPDX-License-Identifier: LGPL-2.1+ - */ - -#define G_LOG_DOMAIN "FuProgressBar" - -#include "config.h" - -#include - -#include "fu-progressbar.h" - -static void -fu_progressbar_finalize(GObject *obj); - -struct _FuProgressbar { - GObject parent_instance; - GMainContext *main_ctx; - FwupdStatus status; - gboolean spinner_count_up; /* chars */ - guint spinner_idx; /* chars */ - guint length_percentage; /* chars */ - guint length_status; /* chars */ - guint percentage; - GSource *timer_source; - gint64 last_animated; /* monotonic */ - GTimer *time_elapsed; - gdouble last_estimate; - gboolean interactive; -}; - -G_DEFINE_TYPE(FuProgressbar, fu_progressbar, G_TYPE_OBJECT) - -static const gchar * -fu_progressbar_status_to_string(FwupdStatus status) -{ - switch (status) { - case FWUPD_STATUS_IDLE: - /* TRANSLATORS: daemon is inactive */ - return _("Idle…"); - break; - case FWUPD_STATUS_DECOMPRESSING: - /* TRANSLATORS: decompressing the firmware file */ - return _("Decompressing…"); - break; - case FWUPD_STATUS_LOADING: - /* TRANSLATORS: parsing the firmware information */ - return _("Loading…"); - break; - case FWUPD_STATUS_DEVICE_RESTART: - /* TRANSLATORS: restarting the device to pick up new F/W */ - return _("Restarting device…"); - break; - case FWUPD_STATUS_DEVICE_READ: - /* TRANSLATORS: reading from the flash chips */ - return _("Reading…"); - break; - case FWUPD_STATUS_DEVICE_WRITE: - /* TRANSLATORS: writing to the flash chips */ - return _("Writing…"); - break; - case FWUPD_STATUS_DEVICE_ERASE: - /* TRANSLATORS: erasing contents of the flash chips */ - return _("Erasing…"); - break; - case FWUPD_STATUS_DEVICE_VERIFY: - /* TRANSLATORS: verifying we wrote the firmware correctly */ - return _("Verifying…"); - break; - case FWUPD_STATUS_SCHEDULING: - /* TRANSLATORS: scheduling an update to be done on the next boot */ - return _("Scheduling…"); - break; - case FWUPD_STATUS_DOWNLOADING: - /* TRANSLATORS: downloading from a remote server */ - return _("Downloading…"); - break; - case FWUPD_STATUS_WAITING_FOR_AUTH: - /* TRANSLATORS: waiting for user to authenticate */ - return _("Authenticating…"); - break; - case FWUPD_STATUS_DEVICE_BUSY: - /* TRANSLATORS: waiting for device to do something */ - return _("Waiting…"); - break; - default: - break; - } - - /* TRANSLATORS: current daemon status is unknown */ - return _("Unknown"); -} - -static void -fu_progressbar_erase_line(FuProgressbar *self) -{ - if (!self->interactive) - return; - g_print("\033[G"); -} - -static gboolean -_fu_status_is_predictable(FwupdStatus status) -{ - if (status == FWUPD_STATUS_DEVICE_ERASE) - return TRUE; - if (status == FWUPD_STATUS_DEVICE_VERIFY) - return TRUE; - if (status == FWUPD_STATUS_DEVICE_READ) - return TRUE; - if (status == FWUPD_STATUS_DEVICE_WRITE) - return TRUE; - if (status == FWUPD_STATUS_DOWNLOADING) - return TRUE; - return FALSE; -} - -static gboolean -fu_progressbar_estimate_ready(FuProgressbar *self, guint percentage) -{ - gdouble old; - gdouble elapsed; - - /* now invalid */ - if (percentage == 0 || percentage == 100) { - g_timer_start(self->time_elapsed); - self->last_estimate = 0; - return FALSE; - } - - /* allow-list things that make sense... */ - if (!_fu_status_is_predictable(self->status)) - return FALSE; - - old = self->last_estimate; - elapsed = g_timer_elapsed(self->time_elapsed, NULL); - self->last_estimate = elapsed / percentage * (100 - percentage); - - /* estimate is ready if we have decreased */ - return old > self->last_estimate; -} - -static gchar * -fu_progressbar_time_remaining_str(FuProgressbar *self) -{ - /* less than 5 seconds remaining */ - if (self->last_estimate < 5) - return NULL; - - /* less than 60 seconds remaining */ - if (self->last_estimate < 60) { - /* TRANSLATORS: time remaining for completing firmware flash */ - return g_strdup(_("Less than one minute remaining")); - } - - return g_strdup_printf( - /* TRANSLATORS: more than a minute */ - ngettext("%.0f minute remaining", "%.0f minutes remaining", self->last_estimate / 60), - self->last_estimate / 60); -} - -static void -fu_progressbar_refresh(FuProgressbar *self, FwupdStatus status, guint percentage) -{ - const gchar *title; - guint i; - gboolean is_idle_newline = FALSE; - g_autoptr(GString) str = g_string_new(NULL); - - g_return_if_fail(percentage <= 100); - - /* erase previous line */ - fu_progressbar_erase_line(self); - - /* add status */ - if (status == FWUPD_STATUS_IDLE || status == FWUPD_STATUS_UNKNOWN) { - status = self->status; - is_idle_newline = TRUE; - } - if (percentage == 100) - is_idle_newline = TRUE; - title = fu_progressbar_status_to_string(status); - g_string_append(str, title); - for (i = fu_strwidth(str->str); i < self->length_status; i++) - g_string_append_c(str, ' '); - - /* add progressbar */ - g_string_append(str, "["); - if (percentage > 0) { - for (i = 0; i < (self->length_percentage - 1) * percentage / 100; i++) - g_string_append_c(str, '*'); - for (i = i + 1; i < self->length_percentage; i++) - g_string_append_c(str, ' '); - } else { - const gchar chars[] = { - '-', - '\\', - '|', - '/', - }; - for (i = 0; i < self->spinner_idx; i++) - g_string_append_c(str, ' '); - g_string_append_c(str, chars[i / 4 % G_N_ELEMENTS(chars)]); - for (i = i + 1; i < self->length_percentage - 1; i++) - g_string_append_c(str, ' '); - } - g_string_append_c(str, ']'); - - /* once we have good data show an estimate of time remaining */ - if (fu_progressbar_estimate_ready(self, percentage)) { - g_autofree gchar *remaining = fu_progressbar_time_remaining_str(self); - if (remaining != NULL) - g_string_append_printf(str, " %s…", remaining); - } - - /* dump to screen */ - g_print("%s", str->str); - - /* done */ - if (is_idle_newline) { - g_print("\n"); - return; - } -} - -/** - * fu_progressbar_set_title: - * @self: A #FuProgressbar - * @title: A string - * - * Sets progressbar title - * - * Since: 0.9.7 - **/ -void -fu_progressbar_set_title(FuProgressbar *self, const gchar *title) -{ - fu_progressbar_erase_line(self); - g_print("%s\n", title); - fu_progressbar_refresh(self, self->status, self->percentage); -} - -/** - * fu_progressbar_set_main_context: - * @self: A #FuProgressbar - * @main_ctx: (nullable): main context - * - * Sets progressbar main context to use for animations. - * - * Since: 1.6.2 - **/ -void -fu_progressbar_set_main_context(FuProgressbar *self, GMainContext *main_ctx) -{ - self->main_ctx = g_main_context_ref(main_ctx); -} - -static void -fu_progressbar_spin_inc(FuProgressbar *self) -{ - /* reset */ - self->last_animated = g_get_monotonic_time(); - - /* up to down */ - if (self->spinner_count_up) { - if (++self->spinner_idx > self->length_percentage - 3) - self->spinner_count_up = FALSE; - } else { - if (--self->spinner_idx == 0) - self->spinner_count_up = TRUE; - } -} - -static gboolean -fu_progressbar_spin_cb(gpointer user_data) -{ - FuProgressbar *self = FU_PROGRESSBAR(user_data); - - /* ignore */ - if (self->status == FWUPD_STATUS_IDLE || self->status == FWUPD_STATUS_UNKNOWN) - return G_SOURCE_CONTINUE; - - /* move the spinner index up to down */ - fu_progressbar_spin_inc(self); - - /* update the terminal */ - fu_progressbar_refresh(self, self->status, self->percentage); - - return G_SOURCE_CONTINUE; -} - -static void -fu_progressbar_spin_end(FuProgressbar *self) -{ - if (self->timer_source != NULL) { - g_source_destroy(self->timer_source); - self->timer_source = NULL; - - /* reset when the spinner has been stopped */ - g_timer_start(self->time_elapsed); - } - - /* go back to the start when we next go into unknown percentage mode */ - self->spinner_idx = 0; - self->spinner_count_up = TRUE; -} - -static void -fu_progressbar_spin_start(FuProgressbar *self) -{ - if (self->timer_source != NULL) - g_source_destroy(self->timer_source); - self->timer_source = g_timeout_source_new(40); - g_source_set_callback(self->timer_source, fu_progressbar_spin_cb, self, NULL); - g_source_attach(self->timer_source, self->main_ctx); -} - -/** - * fu_progressbar_update: - * @self: A #FuProgressbar - * @status: A #FwupdStatus - * @percentage: unsigned integer - * - * Refreshes a progressbar - * - * Since: 0.9.7 - **/ -void -fu_progressbar_update(FuProgressbar *self, FwupdStatus status, guint percentage) -{ - g_return_if_fail(FU_IS_PROGRESSBAR(self)); - - /* not useful */ - if (status == FWUPD_STATUS_UNKNOWN) - return; - - /* ignore initial client connection */ - if (self->status == FWUPD_STATUS_UNKNOWN && status == FWUPD_STATUS_IDLE) { - self->status = status; - return; - } - - if (!self->interactive) { - g_print("%s: %u%%\n", fu_progressbar_status_to_string(status), percentage); - self->status = status; - self->percentage = percentage; - return; - } - - /* if the main loop isn't spinning and we've not had a chance to - * execute the callback just do the refresh now manually */ - if (percentage == 0 && status != FWUPD_STATUS_IDLE && - self->status != FWUPD_STATUS_UNKNOWN) { - if ((g_get_monotonic_time() - self->last_animated) / 1000 > 40) { - fu_progressbar_spin_inc(self); - fu_progressbar_refresh(self, status, percentage); - } - } - - /* ignore duplicates */ - if (self->status == status && self->percentage == percentage) - return; - - /* enable or disable the spinner timeout */ - if (percentage > 0) { - fu_progressbar_spin_end(self); - } else { - fu_progressbar_spin_start(self); - } - - /* update the terminal */ - fu_progressbar_refresh(self, status, percentage); - - /* cache */ - self->status = status; - self->percentage = percentage; -} - -/** - * fu_progressbar_set_interactive: - * @self: A #FuProgressbar - * @interactive: #gboolean - * - * Marks the progressbar as interactive or not - * - * Since: 0.9.7 - **/ -void -fu_progressbar_set_interactive(FuProgressbar *self, gboolean interactive) -{ - g_return_if_fail(FU_IS_PROGRESSBAR(self)); - self->interactive = interactive; -} - -/** - * fu_progressbar_set_length_status: - * @self: A #FuProgressbar - * @len: unsigned integer - * - * Sets the length of the progressbar status - * - * Since: 0.9.7 - **/ -void -fu_progressbar_set_length_status(FuProgressbar *self, guint len) -{ - g_return_if_fail(FU_IS_PROGRESSBAR(self)); - g_return_if_fail(len > 3); - self->length_status = len; -} - -/** - * fu_progressbar_set_length_percentage: - * @self: A #FuProgressbar - * @len: unsigned integer - * - * Sets the length of the progressba percentage - * - * Since: 0.9.7 - **/ -void -fu_progressbar_set_length_percentage(FuProgressbar *self, guint len) -{ - g_return_if_fail(FU_IS_PROGRESSBAR(self)); - g_return_if_fail(len > 3); - self->length_percentage = len; -} - -static void -fu_progressbar_class_init(FuProgressbarClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - object_class->finalize = fu_progressbar_finalize; -} - -static void -fu_progressbar_init(FuProgressbar *self) -{ - self->length_percentage = 40; - self->length_status = 25; - self->spinner_count_up = TRUE; - self->time_elapsed = g_timer_new(); - self->interactive = TRUE; -} - -static void -fu_progressbar_finalize(GObject *obj) -{ - FuProgressbar *self = FU_PROGRESSBAR(obj); - - if (self->timer_source != 0) - g_source_destroy(self->timer_source); - if (self->main_ctx != NULL) - g_main_context_unref(self->main_ctx); - g_timer_destroy(self->time_elapsed); - - G_OBJECT_CLASS(fu_progressbar_parent_class)->finalize(obj); -} - -/** - * fu_progressbar_new: - * - * Creates a new #FuProgressbar - * - * Since: 0.9.7 - **/ -FuProgressbar * -fu_progressbar_new(void) -{ - FuProgressbar *self; - self = g_object_new(FU_TYPE_PROGRESSBAR, NULL); - return FU_PROGRESSBAR(self); -} diff --git a/src/fu-progressbar.h b/src/fu-progressbar.h deleted file mode 100644 index 1abee0b58..000000000 --- a/src/fu-progressbar.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2017 Richard Hughes - * - * SPDX-License-Identifier: LGPL-2.1+ - */ - -#pragma once - -#include - -#define FU_TYPE_PROGRESSBAR (fu_progressbar_get_type()) -G_DECLARE_FINAL_TYPE(FuProgressbar, fu_progressbar, FU, PROGRESSBAR, GObject) - -FuProgressbar * -fu_progressbar_new(void); -void -fu_progressbar_update(FuProgressbar *self, FwupdStatus status, guint percentage); -void -fu_progressbar_set_length_status(FuProgressbar *self, guint len); -void -fu_progressbar_set_length_percentage(FuProgressbar *self, guint len); -void -fu_progressbar_set_title(FuProgressbar *self, const gchar *title); -void -fu_progressbar_set_interactive(FuProgressbar *self, gboolean interactive); -void -fu_progressbar_set_main_context(FuProgressbar *self, GMainContext *main_ctx); diff --git a/src/fu-self-test.c b/src/fu-self-test.c index 94b20051c..dd6d683fb 100644 --- a/src/fu-self-test.c +++ b/src/fu-self-test.c @@ -21,6 +21,7 @@ #include "fu-bios-settings-private.h" #include "fu-cabinet-common.h" #include "fu-config.h" +#include "fu-console.h" #include "fu-context-private.h" #include "fu-device-list.h" #include "fu-device-private.h" @@ -28,7 +29,6 @@ #include "fu-history.h" #include "fu-plugin-list.h" #include "fu-plugin-private.h" -#include "fu-progressbar.h" #include "fu-release-common.h" #include "fu-security-attr-common.h" #include "fu-smbios-private.h" @@ -4089,31 +4089,31 @@ fu_memcpy_func(gconstpointer user_data) } static void -fu_progressbar_func(gconstpointer user_data) +fu_console_func(gconstpointer user_data) { - g_autoptr(FuProgressbar) progressbar = fu_progressbar_new(); + g_autoptr(FuConsole) console = fu_console_new(); - fu_progressbar_set_length_status(progressbar, 20); - fu_progressbar_set_length_percentage(progressbar, 50); + fu_console_set_status_length(console, 20); + fu_console_set_percentage_length(console, 50); g_print("\n"); for (guint i = 0; i < 100; i++) { - fu_progressbar_update(progressbar, FWUPD_STATUS_DECOMPRESSING, i); + fu_console_set_progress(console, FWUPD_STATUS_DECOMPRESSING, i); g_usleep(10000); } - fu_progressbar_update(progressbar, FWUPD_STATUS_IDLE, 0); + fu_console_set_progress(console, FWUPD_STATUS_IDLE, 0); for (guint i = 0; i < 100; i++) { guint pc = (i > 25 && i < 75) ? 0 : i; - fu_progressbar_update(progressbar, FWUPD_STATUS_LOADING, pc); + fu_console_set_progress(console, FWUPD_STATUS_LOADING, pc); g_usleep(10000); } - fu_progressbar_update(progressbar, FWUPD_STATUS_IDLE, 0); + fu_console_set_progress(console, FWUPD_STATUS_IDLE, 0); for (guint i = 0; i < 5000; i++) { - fu_progressbar_update(progressbar, FWUPD_STATUS_LOADING, 0); + fu_console_set_progress(console, FWUPD_STATUS_LOADING, 0); g_usleep(1000); } - fu_progressbar_update(progressbar, FWUPD_STATUS_IDLE, 0); + fu_console_set_progress(console, FWUPD_STATUS_IDLE, 0); } static gint @@ -4889,7 +4889,7 @@ main(int argc, char **argv) /* tests go here */ if (g_test_slow()) { - g_test_add_data_func("/fwupd/progressbar", self, fu_progressbar_func); + g_test_add_data_func("/fwupd/console", self, fu_console_func); } g_test_add_data_func("/fwupd/backend{usb}", self, fu_backend_usb_func); g_test_add_data_func("/fwupd/backend{usb-invalid}", self, fu_backend_usb_invalid_func); diff --git a/src/fu-tool.c b/src/fu-tool.c index acbcfe1be..c97ba3502 100644 --- a/src/fu-tool.c +++ b/src/fu-tool.c @@ -30,13 +30,13 @@ #include "fu-bios-settings-private.h" #include "fu-cabinet.h" +#include "fu-console.h" #include "fu-context-private.h" #include "fu-debug.h" #include "fu-device-private.h" #include "fu-engine.h" #include "fu-history.h" #include "fu-plugin-private.h" -#include "fu-progressbar.h" #include "fu-security-attr-common.h" #include "fu-security-attrs-private.h" #include "fu-smbios-private.h" @@ -66,7 +66,7 @@ struct FuUtilPrivate { FuEngine *engine; FuEngineRequest *request; FuProgress *progress; - FuProgressbar *progressbar; + FuConsole *console; FwupdClient *client; gboolean as_json; gboolean no_reboot_check; @@ -94,9 +94,9 @@ fu_util_client_notify_cb(GObject *object, GParamSpec *pspec, FuUtilPrivate *priv { if (priv->as_json) return; - fu_progressbar_update(priv->progressbar, - fwupd_client_get_status(priv->client), - fwupd_client_get_percentage(priv->client)); + fu_console_set_progress(priv->console, + fwupd_client_get_status(priv->client), + fwupd_client_get_percentage(priv->client)); } static void @@ -125,7 +125,6 @@ fu_util_show_plugin_warnings(FuUtilPrivate *priv) for (guint i = 0; i < 64; i++) { FwupdPluginFlags flag = (guint64)1 << i; const gchar *tmp; - g_autofree gchar *fmt = NULL; g_autofree gchar *url = NULL; g_autoptr(GString) str = g_string_new(NULL); if ((flags & flag) == 0) @@ -133,17 +132,11 @@ fu_util_show_plugin_warnings(FuUtilPrivate *priv) tmp = fu_util_plugin_flag_to_string((guint64)1 << i); if (tmp == NULL) continue; - /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_RED); - g_string_append_printf(str, "%s %s\n", fmt, tmp); - + fu_console_print_full(priv->console, FU_CONSOLE_PRINT_FLAG_WARNING, "%s\n", tmp); url = g_strdup_printf("https://github.com/fwupd/fwupd/wiki/PluginFlag:%s", fwupd_plugin_flag_to_string(flag)); - g_string_append(str, " "); /* TRANSLATORS: %s is a link to a website */ - g_string_append_printf(str, _("See %s for more information."), url); - g_string_append(str, "\n"); - g_printerr("%s", str->str); + fu_console_print(priv->console, _("See %s for more information."), url); } } @@ -234,7 +227,7 @@ fu_util_start_engine(FuUtilPrivate *priv, if (!fu_engine_load(priv->engine, flags, progress, error)) return FALSE; fu_util_show_plugin_warnings(priv); - fu_util_show_unsupported_warn(); + fu_util_show_unsupported_warning(priv->console); /* copy properties from engine to client */ g_object_set(priv->client, @@ -270,7 +263,7 @@ fu_util_cancelled_cb(GCancellable *cancellable, gpointer user_data) { FuUtilPrivate *priv = (FuUtilPrivate *)user_data; /* TRANSLATORS: this is when a device ctrl+c's a watch */ - g_print("%s\n", _("Cancelled")); + fu_console_print_literal(priv->console, _("Cancelled")); g_main_loop_quit(priv->loop); } @@ -290,7 +283,7 @@ fu_util_smbios_dump(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_smbios_setup_from_file(smbios, values[0], error)) return FALSE; tmp = fu_firmware_to_string(FU_FIRMWARE(smbios)); - g_print("%s\n", tmp); + fu_console_print_literal(priv->console, tmp); return TRUE; } @@ -332,8 +325,8 @@ fu_util_private_free(FuUtilPrivate *priv) g_main_loop_unref(priv->loop); if (priv->cancellable != NULL) g_object_unref(priv->cancellable); - if (priv->progressbar != NULL) - g_object_unref(priv->progressbar); + if (priv->console != NULL) + g_object_unref(priv->console); if (priv->progress != NULL) g_object_unref(priv->progress); if (priv->context != NULL) @@ -366,9 +359,9 @@ fu_util_update_device_request_cb(FwupdClient *client, FwupdRequest *request, FuU g_autofree gchar *tmp = NULL; /* TRANSLATORS: the user needs to do something, e.g. remove the device */ - fmt = fu_util_term_format(_("Action Required:"), FU_UTIL_TERM_COLOR_RED); + fmt = fu_console_color_format(_("Action Required:"), FU_CONSOLE_COLOR_RED); tmp = g_strdup_printf("%s %s", fmt, fwupd_request_get_message(request)); - fu_progressbar_set_title(priv->progressbar, tmp); + fu_console_set_progress_title(priv->console, tmp); } /* save for later */ @@ -395,7 +388,7 @@ fu_main_engine_status_changed_cb(FuEngine *engine, FwupdStatus status, FuUtilPri { if (priv->as_json) return; - fu_progressbar_update(priv->progressbar, status, 0); + fu_console_set_progress(priv->console, status, 0); } static void @@ -403,7 +396,7 @@ fu_util_progress_percentage_changed_cb(FuProgress *progress, guint percentage, F { if (priv->as_json) return; - fu_progressbar_update(priv->progressbar, fu_progress_get_status(progress), percentage); + fu_console_set_progress(priv->console, fu_progress_get_status(progress), percentage); } static void @@ -411,7 +404,7 @@ fu_util_progress_status_changed_cb(FuProgress *progress, FwupdStatus status, FuU { if (priv->as_json) return; - fu_progressbar_update(priv->progressbar, status, fu_progress_get_percentage(progress)); + fu_console_set_progress(priv->console, status, fu_progress_get_percentage(progress)); } static gboolean @@ -445,7 +438,7 @@ fu_util_get_plugins_as_json(FuUtilPrivate *priv, GPtrArray *plugins, GError **er } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -467,11 +460,11 @@ fu_util_get_plugins(FuUtilPrivate *priv, gchar **values, GError **error) for (guint i = 0; i < plugins->len; i++) { FuPlugin *plugin = g_ptr_array_index(plugins, i); g_autofree gchar *str = fu_util_plugin_to_string(FWUPD_PLUGIN(plugin), 0); - g_print("%s\n", str); + fu_console_print_literal(priv->console, str); } if (plugins->len == 0) { /* TRANSLATORS: nothing found */ - g_print("%s\n", _("No plugins found")); + fu_console_print_literal(priv->console, _("No plugins found")); } return TRUE; @@ -531,8 +524,12 @@ fu_util_prompt_for_device(FuUtilPrivate *priv, GPtrArray *devices_opt, GError ** if (devices_filtered->len == 1) { dev = g_ptr_array_index(devices_filtered, 0); if (!priv->as_json) { - /* TRANSLATORS: device has been chosen by the daemon for the user */ - g_print("%s: %s\n", _("Selected device"), fu_device_get_name(dev)); + fu_console_print( + priv->console, + "%s: %s", + /* TRANSLATORS: device has been chosen by the daemon for the user */ + _("Selected device"), + fu_device_get_name(dev)); } return g_object_ref(dev); } @@ -547,14 +544,18 @@ fu_util_prompt_for_device(FuUtilPrivate *priv, GPtrArray *devices_opt, GError ** } /* TRANSLATORS: get interactive prompt */ - g_print("%s\n", _("Choose a device:")); + fu_console_print_literal(priv->console, _("Choose a device:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < devices_filtered->len; i++) { dev = g_ptr_array_index(devices_filtered, i); - g_print("%u.\t%s (%s)\n", i + 1, fu_device_get_id(dev), fu_device_get_name(dev)); + fu_console_print(priv->console, + "%u.\t%s (%s)", + i + 1, + fu_device_get_id(dev), + fu_device_get_name(dev)); } - idx = fu_util_prompt_for_number(devices_filtered->len); + idx = fu_console_input_uint(priv->console, devices_filtered->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -666,20 +667,23 @@ fu_util_get_updates(FuUtilPrivate *priv, gchar **values, GError **error) /* devices that have no updates available for whatever reason */ if (devices_no_support->len > 0) { - /* TRANSLATORS: message letting the user know no device upgrade - * available due to missing on LVFS */ - g_printerr("%s\n", _("Devices with no available firmware updates: ")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: message letting the user know no device + * upgrade available due to missing on LVFS */ + _("Devices with no available firmware updates: ")); for (guint i = 0; i < devices_no_support->len; i++) { FwupdDevice *dev = g_ptr_array_index(devices_no_support, i); - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); } } if (devices_no_upgrades->len > 0) { - /* TRANSLATORS: message letting the user know no device upgrade available */ - g_printerr("%s\n", _("Devices with the latest available firmware version:")); + fu_console_print_literal( + priv->console, + /* TRANSLATORS: message letting the user know no device upgrade available */ + _("Devices with the latest available firmware version:")); for (guint i = 0; i < devices_no_upgrades->len; i++) { FwupdDevice *dev = g_ptr_array_index(devices_no_upgrades, i); - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); } } @@ -692,7 +696,7 @@ fu_util_get_updates(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -750,7 +754,7 @@ fu_util_get_details(FuUtilPrivate *priv, gchar **values, GError **error) if (rel != NULL) g_node_append_data(child, rel); } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -771,7 +775,7 @@ fu_util_get_device_flags(FuUtilPrivate *priv, gchar **values, GError **error) g_string_append(str, " ~"); g_string_append(str, tmp); } - g_print("%s\n", str->str); + fu_console_print_literal(priv->console, str->str); return TRUE; } @@ -817,11 +821,12 @@ fu_util_get_devices(FuUtilPrivate *priv, gchar **values, GError **error) /* print */ if (g_node_n_children(root) == 0) { - /* TRANSLATORS: nothing attached that can be upgraded */ - g_print("%s\n", _("No hardware detected with firmware update capability")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: nothing attached that can be upgraded */ + _("No hardware detected with firmware update capability")); return TRUE; } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -854,19 +859,19 @@ fu_util_update_device_changed_cb(FwupdClient *client, FwupdDevice *device, FuUti return; } - /* show message in progressbar */ + /* show message in console */ if (priv->current_operation == FU_UTIL_OPERATION_UPDATE) { /* TRANSLATORS: %1 is a device name */ str = g_strdup_printf(_("Updating %s…"), fwupd_device_get_name(device)); - fu_progressbar_set_title(priv->progressbar, str); + fu_console_set_progress_title(priv->console, str); } else if (priv->current_operation == FU_UTIL_OPERATION_INSTALL) { /* TRANSLATORS: %1 is a device name */ str = g_strdup_printf(_("Installing on %s…"), fwupd_device_get_name(device)); - fu_progressbar_set_title(priv->progressbar, str); + fu_console_set_progress_title(priv->console, str); } else if (priv->current_operation == FU_UTIL_OPERATION_READ) { /* TRANSLATORS: %1 is a device name */ str = g_strdup_printf(_("Reading from %s…"), fwupd_device_get_name(device)); - fu_progressbar_set_title(priv->progressbar, str); + fu_console_set_progress_title(priv->console, str); } else { g_warning("no FuUtilOperation set"); } @@ -879,7 +884,7 @@ fu_util_display_current_message(FuUtilPrivate *priv) /* print all POST requests */ for (guint i = 0; i < priv->post_requests->len; i++) { FwupdRequest *request = g_ptr_array_index(priv->post_requests, i); - g_print("%s\n", fu_util_request_get_message(request)); + fu_console_print_literal(priv->console, fu_util_request_get_message(request)); } } @@ -984,7 +989,7 @@ fu_util_install_blob(FuUtilPrivate *priv, gchar **values, GError **error) fu_util_display_current_message(priv); /* success */ - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -1251,7 +1256,7 @@ fu_util_install(FuUtilPrivate *priv, gchar **values, GError **error) if (device == NULL) return FALSE; if (!priv->no_safety_check) { - if (!fu_util_prompt_warning_fde(FWUPD_DEVICE(device), error)) + if (!fu_util_prompt_warning_fde(priv->console, FWUPD_DEVICE(device), error)) return FALSE; } devices_possible = @@ -1381,7 +1386,7 @@ fu_util_install(FuUtilPrivate *priv, gchar **values, GError **error) } /* success */ - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -1510,13 +1515,14 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) continue; if (!fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_SUPPORTED)) { if (!no_updates_header) { - g_printerr("%s\n", - /* TRANSLATORS: message letting the user know no device - * upgrade available due to missing on LVFS */ - _("Devices with no available firmware updates: ")); + fu_console_print_literal( + priv->console, + /* TRANSLATORS: message letting the user know no + * device upgrade available due to missing on LVFS */ + _("Devices with no available firmware updates: ")); no_updates_header = TRUE; } - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); continue; } if (!fu_util_filter_device(priv, dev)) @@ -1525,14 +1531,14 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) rels = fu_engine_get_upgrades(priv->engine, priv->request, device_id, &error_local); if (rels == NULL) { if (!latest_header) { - g_printerr( - "%s\n", + fu_console_print_literal( + priv->console, /* TRANSLATORS: message letting the user know no device upgrade * available */ _("Devices with the latest available firmware version:")); latest_header = TRUE; } - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); /* discard the actual reason from user, but leave for debugging */ g_debug("%s", error_local->message); continue; @@ -1544,14 +1550,14 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) g_strdup_printf("%s %s", fu_engine_get_host_vendor(priv->engine), fu_engine_get_host_product(priv->engine)); - if (!fu_util_prompt_warning(dev, rel, title, error)) + if (!fu_util_prompt_warning(priv->console, dev, rel, title, error)) return FALSE; - if (!fu_util_prompt_warning_fde(dev, error)) + if (!fu_util_prompt_warning_fde(priv->console, dev, error)) return FALSE; } if (!fu_util_install_release(priv, rel, &error_local)) { - g_printerr("%s\n", error_local->message); + fu_console_print_literal(priv->console, error_local->message); continue; } fu_util_display_current_message(priv); @@ -1563,7 +1569,7 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -1633,7 +1639,7 @@ fu_util_reinstall(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -1861,7 +1867,7 @@ fu_util_get_report_metadata(FuUtilPrivate *priv, gchar **values, GError **error) fu_progress_step_done(priv->progress); /* display */ - g_print("\n%s", str->str); + fu_console_print_literal(priv->console, str->str); /* success */ return TRUE; @@ -1951,8 +1957,12 @@ fu_util_activate(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION)) continue; has_pending = TRUE; - /* TRANSLATORS: shown when shutting down to switch to the new version */ - g_print("%s %s…\n", _("Activating firmware update"), fu_device_get_name(device)); + fu_console_print( + priv->console, + "%s %s…", + /* TRANSLATORS: shown when shutting down to switch to the new version */ + _("Activating firmware update"), + fu_device_get_name(device)); if (!fu_engine_activate(priv->engine, fu_device_get_id(device), fu_progress_get_child(priv->progress), @@ -2030,8 +2040,8 @@ fu_util_hwids(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; /* show debug output */ - g_print("Computer Information\n"); - g_print("--------------------\n"); + fu_console_print_literal(priv->console, "Computer Information"); + fu_console_print_literal(priv->console, "--------------------"); for (guint i = 0; i < hwid_keys->len; i++) { const gchar *hwid_key = g_ptr_array_index(hwid_keys, i); const gchar *value = fu_hwids_get_value(hwids, hwid_key); @@ -2040,15 +2050,15 @@ fu_util_hwids(FuUtilPrivate *priv, gchar **values, GError **error) if (g_strcmp0(hwid_key, FU_HWIDS_KEY_BIOS_MAJOR_RELEASE) == 0 || g_strcmp0(hwid_key, FU_HWIDS_KEY_BIOS_MINOR_RELEASE) == 0) { guint64 val = g_ascii_strtoull(value, NULL, 16); - g_print("%s: %" G_GUINT64_FORMAT "\n", hwid_key, val); + fu_console_print(priv->console, "%s: %" G_GUINT64_FORMAT, hwid_key, val); } else { - g_print("%s: %s\n", hwid_key, value); + fu_console_print(priv->console, "%s: %s", hwid_key, value); } } /* show GUIDs */ - g_print("\nHardware IDs\n"); - g_print("------------\n"); + fu_console_print_literal(priv->console, "Hardware IDs"); + fu_console_print_literal(priv->console, "------------"); for (guint i = 0; i < 15; i++) { const gchar *keys = NULL; g_autofree gchar *guid = NULL; @@ -2062,14 +2072,14 @@ fu_util_hwids(FuUtilPrivate *priv, gchar **values, GError **error) keys = fu_hwids_get_replace_keys(hwids, key); guid = fu_hwids_get_guid(hwids, key, &error_local); if (guid == NULL) { - g_print("%s\n", error_local->message); + fu_console_print_literal(priv->console, error_local->message); continue; } /* show what makes up the GUID */ keysv = g_strsplit(keys, "&", -1); keys_str = g_strjoinv(" + ", keysv); - g_print("{%s} <- %s\n", guid, keys_str); + fu_console_print(priv->console, "{%s} <- %s", guid, keys_str); } return TRUE; @@ -2098,7 +2108,7 @@ fu_util_self_sign(FuUtilPrivate *priv, gchar **values, GError **error) error); if (sig == NULL) return FALSE; - g_print("%s\n", sig); + fu_console_print_literal(priv->console, sig); return TRUE; } @@ -2108,7 +2118,7 @@ fu_util_device_added_cb(FwupdClient *client, FwupdDevice *device, gpointer user_ FuUtilPrivate *priv = (FuUtilPrivate *)user_data; g_autofree gchar *tmp = fu_util_device_to_string(priv->client, device, 0); /* TRANSLATORS: this is when a device is hotplugged */ - g_print("%s\n%s", _("Device added:"), tmp); + fu_console_print(priv->console, "%s\n%s", _("Device added:"), tmp); } static void @@ -2117,7 +2127,7 @@ fu_util_device_removed_cb(FwupdClient *client, FwupdDevice *device, gpointer use FuUtilPrivate *priv = (FuUtilPrivate *)user_data; g_autofree gchar *tmp = fu_util_device_to_string(priv->client, device, 0); /* TRANSLATORS: this is when a device is hotplugged */ - g_print("%s\n%s", _("Device removed:"), tmp); + fu_console_print(priv->console, "%s\n%s", _("Device removed:"), tmp); } static void @@ -2126,14 +2136,15 @@ fu_util_device_changed_cb(FwupdClient *client, FwupdDevice *device, gpointer use FuUtilPrivate *priv = (FuUtilPrivate *)user_data; g_autofree gchar *tmp = fu_util_device_to_string(priv->client, device, 0); /* TRANSLATORS: this is when a device has been updated */ - g_print("%s\n%s", _("Device changed:"), tmp); + fu_console_print(priv->console, "%s\n%s", _("Device changed:"), tmp); } static void fu_util_changed_cb(FwupdClient *client, gpointer user_data) { + FuUtilPrivate *priv = (FuUtilPrivate *)user_data; /* TRANSLATORS: this is when the daemon state changes */ - g_print("%s\n", _("Changed")); + fu_console_print_literal(priv->console, _("Changed")); } static gboolean @@ -2183,11 +2194,11 @@ fu_util_get_firmware_types(FuUtilPrivate *priv, gchar **values, GError **error) firmware_types = fu_context_get_firmware_gtype_ids(fu_engine_get_context(priv->engine)); for (guint i = 0; i < firmware_types->len; i++) { const gchar *id = g_ptr_array_index(firmware_types, i); - g_print("%s\n", id); + fu_console_print_literal(priv->console, id); } if (firmware_types->len == 0) { /* TRANSLATORS: nothing found */ - g_print("%s\n", _("No firmware IDs found")); + fu_console_print_literal(priv->console, _("No firmware IDs found")); return TRUE; } @@ -2202,14 +2213,14 @@ fu_util_prompt_for_firmware_type(FuUtilPrivate *priv, GError **error) firmware_types = fu_context_get_firmware_gtype_ids(fu_engine_get_context(priv->engine)); /* TRANSLATORS: get interactive prompt */ - g_print("%s\n", _("Choose a firmware type:")); + fu_console_print_literal(priv->console, _("Choose a firmware type:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < firmware_types->len; i++) { const gchar *id = g_ptr_array_index(firmware_types, i); - g_print("%u.\t%s\n", i + 1, id); + fu_console_print(priv->console, "%u.\t%s", i + 1, id); } - idx = fu_util_prompt_for_number(firmware_types->len); + idx = fu_console_input_uint(priv->console, firmware_types->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -2289,7 +2300,7 @@ fu_util_firmware_parse(FuUtilPrivate *priv, gchar **values, GError **error) } str = fu_firmware_to_string(firmware); - g_print("%s", str); + fu_console_print_literal(priv->console, str); return TRUE; } @@ -2350,7 +2361,7 @@ fu_util_firmware_export(FuUtilPrivate *priv, gchar **values, GError **error) str = fu_firmware_export_to_xml(firmware, flags, error); if (str == NULL) return FALSE; - g_print("%s", str); + fu_console_print_literal(priv->console, str); return TRUE; } @@ -2406,7 +2417,7 @@ fu_util_firmware_extract(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_firmware_parse(firmware, blob, priv->flags, error)) return FALSE; str = fu_firmware_to_string(firmware); - g_print("%s", str); + fu_console_print_literal(priv->console, str); images = fu_firmware_get_images(firmware); for (guint i = 0; i < images->len; i++) { FuFirmware *img = g_ptr_array_index(images, i); @@ -2431,7 +2442,7 @@ fu_util_firmware_extract(FuUtilPrivate *priv, gchar **values, GError **error) fn = g_strdup_printf("img-0x%x.fw", i); } /* TRANSLATORS: decompressing images from a container firmware */ - g_print("%s : %s\n", _("Writing file:"), fn); + fu_console_print(priv->console, "%s : %s", _("Writing file:"), fn); if (!fu_bytes_set_contents(fn, blob_img, error)) return FALSE; } @@ -2531,7 +2542,7 @@ fu_util_firmware_build(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_firmware_parse(firmware_dst, blob_dst, priv->flags, error)) return FALSE; str = fu_firmware_to_string(firmware_dst); - g_print("%s", str); + fu_console_print_literal(priv->console, str); /* success */ return TRUE; @@ -2611,7 +2622,7 @@ fu_util_firmware_convert(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; } str_src = fu_firmware_to_string(firmware_src); - g_print("%s", str_src); + fu_console_print_literal(priv->console, str_src); /* copy images */ firmware_dst = g_object_new(gtype_dst, NULL); @@ -2642,7 +2653,7 @@ fu_util_firmware_convert(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_bytes_set_contents(values[1], blob_dst, error)) return FALSE; str_dst = fu_firmware_to_string(firmware_dst); - g_print("%s", str_dst); + fu_console_print_literal(priv->console, str_dst); /* success */ return TRUE; @@ -2753,7 +2764,7 @@ fu_util_firmware_patch(FuUtilPrivate *priv, gchar **values, GError **error) if (!fu_bytes_set_contents(values[0], blob_dst, error)) return FALSE; str = fu_firmware_to_string(firmware); - g_print("%s", str); + fu_console_print_literal(priv->console, str); /* success */ return TRUE; @@ -2801,7 +2812,7 @@ fu_util_verify_update(FuUtilPrivate *priv, gchar **values, GError **error) /* show checksums */ str = fu_device_to_string(dev); - g_print("%s\n", str); + fu_console_print_literal(priv->console, str); return TRUE; } @@ -2874,7 +2885,7 @@ fu_util_get_history(FuUtilPrivate *priv, gchar **values, GError **error) continue; } } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -2987,7 +2998,7 @@ fu_util_get_remotes(FuUtilPrivate *priv, gchar **values, GError **error) FwupdRemote *remote_tmp = g_ptr_array_index(remotes, i); g_node_append_data(root, remote_tmp); } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -3051,17 +3062,18 @@ fu_util_security(FuUtilPrivate *priv, gchar **values, GError **error) str = fu_security_attrs_to_json_string(attrs, error); if (str == NULL) return FALSE; - g_print("%s\n", str); + fu_console_print_literal(priv->console, str); return TRUE; } - g_print("%s \033[1m%s\033[0m\n", - /* TRANSLATORS: this is a string like 'HSI:2-U' */ - _("Host Security ID:"), - fu_engine_get_host_security_id(priv->engine)); + fu_console_print(priv->console, + "%s \033[1m%s\033[0m", + /* TRANSLATORS: this is a string like 'HSI:2-U' */ + _("Host Security ID:"), + fu_engine_get_host_security_id(priv->engine)); str = fu_util_security_attrs_to_string(items, flags); - g_print("%s\n", str); + fu_console_print_literal(priv->console, str); /* print the "when" */ events = fu_engine_get_host_security_events(priv->engine, 10, error); @@ -3071,7 +3083,7 @@ fu_util_security(FuUtilPrivate *priv, gchar **values, GError **error) if (events_array->len > 0) { g_autofree gchar *estr = fu_util_security_events_to_string(events_array, flags); if (estr != NULL) - g_print("%s\n", estr); + fu_console_print_literal(priv->console, estr); } /* print the "also" */ @@ -3081,7 +3093,7 @@ fu_util_security(FuUtilPrivate *priv, gchar **values, GError **error) if (devices->len > 0) { g_autofree gchar *estr = fu_util_security_issues_to_string(devices); if (estr != NULL) - g_print("%s\n", estr); + fu_console_print_literal(priv->console, estr); } /* success */ @@ -3102,20 +3114,23 @@ fu_util_prompt_for_volume(FuUtilPrivate *priv, GError **error) return NULL; if (volumes->len == 1) { volume = g_ptr_array_index(volumes, 0); - /* TRANSLATORS: Volume has been chosen by the user */ - g_print("%s: %s\n", _("Selected volume"), fu_volume_get_id(volume)); + fu_console_print(priv->console, + "%s: %s", + /* TRANSLATORS: Volume has been chosen by the user */ + _("Selected volume"), + fu_volume_get_id(volume)); return g_object_ref(volume); } /* TRANSLATORS: get interactive prompt */ - g_print("%s\n", _("Choose a volume:")); + fu_console_print_literal(priv->console, _("Choose a volume:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < volumes->len; i++) { volume = g_ptr_array_index(volumes, i); - g_print("%u.\t%s\n", i + 1, fu_volume_get_id(volume)); + fu_console_print(priv->console, "%u.\t%s", i + 1, fu_volume_get_id(volume)); } - idx = fu_util_prompt_for_number(volumes->len); + idx = fu_console_input_uint(priv->console, volumes->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -3167,7 +3182,7 @@ fu_util_esp_list(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; for (guint i = 0; i < files->len; i++) { const gchar *fn = g_ptr_array_index(files, i); - g_print("%s\n", fn); + fu_console_print_literal(priv->console, fn); } return TRUE; } @@ -3238,14 +3253,17 @@ fu_util_switch_branch(FuUtilPrivate *priv, gchar **values, GError **error) /* TRANSLATORS: get interactive prompt, where branch is the * supplier of the firmware, e.g. "non-free" or "free" */ - g_print("%s\n", _("Choose a branch:")); + fu_console_print_literal(priv->console, _("Choose a branch:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < branches->len; i++) { const gchar *branch_tmp = g_ptr_array_index(branches, i); - g_print("%u.\t%s\n", i + 1, fu_util_branch_for_display(branch_tmp)); + fu_console_print(priv->console, + "%u.\t%s", + i + 1, + fu_util_branch_for_display(branch_tmp)); } - idx = fu_util_prompt_for_number(branches->len); + idx = fu_console_input_uint(priv->console, branches->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -3285,7 +3303,7 @@ fu_util_switch_branch(FuUtilPrivate *priv, gchar **values, GError **error) } /* we're switching branch */ - if (!fu_util_switch_branch_warning(FWUPD_DEVICE(dev), rel, FALSE, error)) + if (!fu_util_switch_branch_warning(priv->console, FWUPD_DEVICE(dev), rel, FALSE, error)) return FALSE; /* update the console if composite devices are also updated */ @@ -3306,7 +3324,7 @@ fu_util_switch_branch(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -3340,7 +3358,7 @@ fu_util_set_bios_setting(FuUtilPrivate *priv, gchar **input, GError **error) g_strdup_printf(_("Set BIOS setting '%s' using '%s'."), (const gchar *)key, (const gchar *)value); - g_print("\n%s\n", msg); + fu_console_print_literal(priv->console, msg); } } priv->completion_flags |= FWUPD_DEVICE_FLAG_NEEDS_REBOOT; @@ -3350,7 +3368,7 @@ fu_util_set_bios_setting(FuUtilPrivate *priv, gchar **input, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -3371,13 +3389,13 @@ fu_util_get_bios_setting(FuUtilPrivate *priv, gchar **values, GError **error) attrs = fu_context_get_bios_settings(ctx); items = fu_bios_settings_get_all(attrs); if (priv->as_json) - return fu_util_get_bios_setting_as_json(values, items, error); + return fu_util_get_bios_setting_as_json(priv->console, values, items, error); for (guint i = 0; i < items->len; i++) { FwupdBiosSetting *attr = g_ptr_array_index(items, i); if (fu_util_bios_setting_matches_args(attr, values)) { g_autofree gchar *tmp = fu_util_bios_setting_to_string(attr, 0); - g_print("%s\n", tmp); + fu_console_print_literal(priv->console, tmp); found = TRUE; } } @@ -3393,8 +3411,9 @@ fu_util_get_bios_setting(FuUtilPrivate *priv, gchar **values, GError **error) g_set_error(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_ARGS, + "%s: '%s'", /* TRANSLATORS: error message */ - "Unable to find attribute '%s'", + _("Unable to find attribute"), values[0]); return FALSE; } @@ -3422,9 +3441,9 @@ fu_util_version(FuUtilPrivate *priv, GError **error) /* dump to the screen in the most appropriate format */ if (priv->as_json) - return fu_util_project_versions_as_json(metadata, error); + return fu_util_project_versions_as_json(priv->console, metadata, error); str = fu_util_project_versions_to_string(metadata); - g_print("%s", str); + fu_console_print_literal(priv->console, str); return TRUE; } @@ -3442,17 +3461,17 @@ fu_util_setup_interactive(FuUtilPrivate *priv, GError **error) g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "using --json"); return FALSE; } - return fu_util_setup_interactive_console(error); + return fu_console_setup(priv->console, error); } static void fu_util_print_error(FuUtilPrivate *priv, const GError *error) { if (priv->as_json) { - fu_util_print_error_as_json(error); + fu_util_print_error_as_json(priv->console, error); return; } - g_printerr("%s\n", error->message); + fu_console_print_full(priv->console, FU_CONSOLE_PRINT_FLAG_STDERR, "%s\n", error->message); } int @@ -3652,9 +3671,9 @@ main(int argc, char *argv[]) /* create helper object */ priv->main_ctx = g_main_context_new(); priv->loop = g_main_loop_new(priv->main_ctx, FALSE); - priv->progressbar = fu_progressbar_new(); + priv->console = fu_console_new(); priv->post_requests = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref); - fu_progressbar_set_main_context(priv->progressbar, priv->main_ctx); + fu_console_set_main_context(priv->console, priv->main_ctx); priv->request = fu_engine_request_new(FU_ENGINE_REQUEST_KIND_ACTIVE); /* used for monitoring and downloading */ @@ -4001,7 +4020,7 @@ main(int argc, char *argv[]) FWUPD_FEATURE_FLAG_COMMUNITY_TEXT | FWUPD_FEATURE_FLAG_SHOW_PROBLEMS | FWUPD_FEATURE_FLAG_REQUESTS); } - fu_progressbar_set_interactive(priv->progressbar, priv->interactive); + fu_console_set_interactive(priv->console, priv->interactive); /* get a list of the commands */ priv->context = g_option_context_new(NULL); @@ -4019,23 +4038,24 @@ main(int argc, char *argv[]) g_option_context_add_group(priv->context, fu_debug_get_option_group()); ret = g_option_context_parse(priv->context, &argc, &argv, &error); if (!ret) { - /* TRANSLATORS: the user didn't read the man page */ - g_print("%s: %s\n", _("Failed to parse arguments"), error->message); + fu_console_print(priv->console, + "%s: %s", + /* TRANSLATORS: the user didn't read the man page */ + _("Failed to parse arguments"), + error->message); return EXIT_FAILURE; } fu_progress_set_profile(priv->progress, g_getenv("FWUPD_VERBOSE") != NULL); /* allow disabling SSL strict mode for broken corporate proxies */ if (priv->disable_ssl_strict) { - g_autofree gchar *fmt = NULL; - /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_RED); - g_printerr("%s %s\n", - fmt, - /* TRANSLATORS: try to help */ - _("Ignoring SSL strict checks, " - "to do this automatically in the future " - "export DISABLE_SSL_STRICT in your environment")); + fu_console_print_full(priv->console, + FU_CONSOLE_PRINT_FLAG_WARNING, + "%s\n", + /* TRANSLATORS: try to help */ + _("Ignoring SSL strict checks, " + "to do this automatically in the future " + "export DISABLE_SSL_STRICT in your environment")); (void)g_setenv("DISABLE_SSL_STRICT", "1", TRUE); } @@ -4112,8 +4132,9 @@ main(int argc, char *argv[]) #endif fu_util_print_error(priv, error); if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_ARGS)) { - /* TRANSLATORS: error message explaining command on how to get help */ - g_printerr("\n%s\n", _("Use fwupdtool --help for help")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: explain how to get help */ + _("Use fwupdtool --help for help")); } else if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO)) { g_debug("%s\n", error->message); return EXIT_NOTHING_TO_DO; @@ -4121,8 +4142,12 @@ main(int argc, char *argv[]) #ifdef HAVE_GETUID /* if not root, then notify users on the error path */ if (priv->interactive && (getuid() != 0 || geteuid() != 0)) { - /* TRANSLATORS: we're poking around as a power user */ - g_printerr("%s\n", _("NOTE: This program may only work correctly as root")); + fu_console_print_full(priv->console, + FU_CONSOLE_PRINT_FLAG_STDERR | + FU_CONSOLE_PRINT_FLAG_WARNING, + "%s\n", + /* TRANSLATORS: we're poking around as a power user */ + _("This program may only work correctly as root")); } #endif return EXIT_FAILURE; @@ -4132,7 +4157,7 @@ main(int argc, char *argv[]) if (fu_progress_get_profile(priv->progress)) { g_autofree gchar *str = fu_progress_traceback(priv->progress); if (str != NULL) - g_print("\n%s\n", str); + fu_console_print_literal(priv->console, str); } /* success */ diff --git a/src/fu-util-bios-setting.c b/src/fu-util-bios-setting.c index e684633ae..539a6042f 100644 --- a/src/fu-util-bios-setting.c +++ b/src/fu-util-bios-setting.c @@ -62,7 +62,10 @@ fu_util_bios_setting_matches_args(FwupdBiosSetting *setting, gchar **values) } gboolean -fu_util_get_bios_setting_as_json(gchar **values, GPtrArray *settings, GError **error) +fu_util_get_bios_setting_as_json(FuConsole *console, + gchar **values, + GPtrArray *settings, + GError **error) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); @@ -80,7 +83,7 @@ fu_util_get_bios_setting_as_json(gchar **values, GPtrArray *settings, GError **e } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(console, builder, error); } gchar * diff --git a/src/fu-util-bios-setting.h b/src/fu-util-bios-setting.h index 3f06eddf6..e7f09131c 100644 --- a/src/fu-util-bios-setting.h +++ b/src/fu-util-bios-setting.h @@ -10,11 +10,16 @@ #include "fwupd-bios-setting-private.h" +#include "fu-console.h" + gchar * fu_util_bios_setting_to_string(FwupdBiosSetting *setting, guint idt); gboolean fu_util_bios_setting_matches_args(FwupdBiosSetting *setting, gchar **values); gboolean -fu_util_get_bios_setting_as_json(gchar **values, GPtrArray *settings, GError **error); +fu_util_get_bios_setting_as_json(FuConsole *console, + gchar **values, + GPtrArray *settings, + GError **error); GHashTable * fu_util_bios_settings_parse_argv(gchar **input, GError **error); diff --git a/src/fu-util-common.c b/src/fu-util-common.c index 5ff65b448..1bcc084c6 100644 --- a/src/fu-util-common.c +++ b/src/fu-util-common.c @@ -20,11 +20,7 @@ #include #endif -#ifdef _WIN32 -#include -#include -#endif - +#include "fu-console.h" #include "fu-device-private.h" #include "fu-security-attr-common.h" #include "fu-util-common.h" @@ -45,7 +41,7 @@ fu_util_get_systemd_unit(void) } gchar * -fu_util_term_format(const gchar *text, FuUtilTermColor fg_color) +fu_console_color_format(const gchar *text, FuConsoleColor fg_color) { if (g_getenv("NO_COLOR") != NULL) return g_strdup(text); @@ -94,79 +90,15 @@ fu_util_using_correct_daemon(GError **error) return TRUE; } -void -fu_util_print_data(const gchar *title, const gchar *msg) -{ - gsize title_len; - g_auto(GStrv) lines = NULL; - - if (msg == NULL) - return; - g_print("%s:", title); - - /* pad */ - title_len = fu_strwidth(title) + 1; - lines = g_strsplit(msg, "\n", -1); - for (guint j = 0; lines[j] != NULL; j++) { - for (gsize i = title_len; i < 25; i++) - g_print(" "); - g_print("%s\n", lines[j]); - title_len = 0; - } -} - -guint -fu_util_prompt_for_number(guint maxnum) -{ - gint retval; - guint answer = 0; - - do { - char buffer[64]; - - /* swallow the \n at end of line too */ - if (!fgets(buffer, sizeof(buffer), stdin)) - break; - if (strlen(buffer) == sizeof(buffer) - 1) - continue; - - /* get a number */ - retval = sscanf(buffer, "%u", &answer); - - /* positive */ - if (retval == 1 && answer <= maxnum) - break; - - /* TRANSLATORS: the user isn't reading the question */ - g_print(_("Please enter a number from 0 to %u: "), maxnum); - } while (TRUE); - return answer; -} - -gboolean -fu_util_prompt_for_boolean(gboolean def) -{ - do { - char buffer[4]; - if (!fgets(buffer, sizeof(buffer), stdin)) - continue; - if (strlen(buffer) == sizeof(buffer) - 1) - continue; - if (g_strcmp0(buffer, "\n") == 0) - return def; - buffer[0] = g_ascii_toupper(buffer[0]); - if (g_strcmp0(buffer, "Y\n") == 0) - return TRUE; - if (g_strcmp0(buffer, "N\n") == 0) - return FALSE; - } while (TRUE); - return FALSE; -} +typedef struct { + FwupdClient *client; + FuConsole *console; +} FuUtilPrintTreeHelper; static gboolean fu_util_traverse_tree(GNode *n, gpointer data) { - FwupdClient *client = FWUPD_CLIENT(data); + FuUtilPrintTreeHelper *helper = (FuUtilPrintTreeHelper *)data; guint idx = g_node_depth(n) - 1; g_autofree gchar *tmp = NULL; g_auto(GStrv) split = NULL; @@ -174,7 +106,7 @@ fu_util_traverse_tree(GNode *n, gpointer data) /* get split lines */ if (FWUPD_IS_DEVICE(n->data)) { FwupdDevice *dev = FWUPD_DEVICE(n->data); - tmp = fu_util_device_to_string(client, dev, idx); + tmp = fu_util_device_to_string(helper->client, dev, idx); } else if (FWUPD_IS_REMOTE(n->data)) { FwupdRemote *remote = FWUPD_REMOTE(n->data); tmp = fu_util_remote_to_string(remote, idx); @@ -186,9 +118,10 @@ fu_util_traverse_tree(GNode *n, gpointer data) /* root node */ if (n->data == NULL && g_getenv("FWUPD_VERBOSE") == NULL) { - g_autofree gchar *str = g_strdup_printf("%s %s", - fwupd_client_get_host_vendor(client), - fwupd_client_get_host_product(client)); + g_autofree gchar *str = + g_strdup_printf("%s %s", + fwupd_client_get_host_vendor(helper->client), + fwupd_client_get_host_product(helper->client)); g_print("%s\n│\n", str); return FALSE; } @@ -227,22 +160,23 @@ fu_util_traverse_tree(GNode *n, gpointer data) /* empty line */ if (split[i][0] == '\0') { - g_print("%s\n", str->str); + fu_console_print_literal(helper->console, str->str); continue; } /* dump to the console */ g_string_append(str, split[i] + (idx * 2)); - g_print("%s\n", str->str); + fu_console_print_literal(helper->console, str->str); } return FALSE; } void -fu_util_print_tree(FwupdClient *client, GNode *n) +fu_util_print_tree(FuConsole *console, FwupdClient *client, GNode *n) { - g_node_traverse(n, G_PRE_ORDER, G_TRAVERSE_ALL, -1, fu_util_traverse_tree, client); + FuUtilPrintTreeHelper helper = {.client = client, .console = console}; + g_node_traverse(n, G_PRE_ORDER, G_TRAVERSE_ALL, -1, fu_util_traverse_tree, &helper); } static gboolean @@ -420,7 +354,8 @@ fu_util_get_release_description_with_fallback(FwupdRelease *rel) } gboolean -fu_util_prompt_warning(FwupdDevice *device, +fu_util_prompt_warning(FuConsole *console, + FwupdDevice *device, FwupdRelease *release, const gchar *machine, GError **error) @@ -507,13 +442,10 @@ fu_util_prompt_warning(FwupdDevice *device, } } } - fu_util_warning_box(title->str, str->str, 80); + fu_console_box(console, title->str, str->str, 80); - /* ask for confirmation */ - g_print("\n%s [Y|n]: ", - /* TRANSLATORS: prompt to apply the update */ - _("Perform operation?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + /* TRANSLATORS: prompt to apply the update */ + if (!fu_console_input_bool(console, TRUE, "%s", _("Perform operation?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, @@ -526,28 +458,31 @@ fu_util_prompt_warning(FwupdDevice *device, } gboolean -fu_util_prompt_complete(FwupdDeviceFlags flags, gboolean prompt, GError **error) +fu_util_prompt_complete(FuConsole *console, FwupdDeviceFlags flags, gboolean prompt, GError **error) { if (flags & FWUPD_DEVICE_FLAG_NEEDS_SHUTDOWN) { if (prompt) { - g_print("\n%s %s [y|N]: ", - /* TRANSLATORS: explain why we want to shutdown */ - _("An update requires the system to shutdown to complete."), - /* TRANSLATORS: shutdown to apply the update */ - _("Shutdown now?")); - if (!fu_util_prompt_for_boolean(FALSE)) + if (!fu_console_input_bool(console, + FALSE, + "%s %s", + /* TRANSLATORS: explain why */ + _("An update requires the system to shutdown " + "to complete."), + /* TRANSLATORS: shutdown to apply the update */ + _("Shutdown now?"))) return TRUE; } return fu_util_update_shutdown(error); } if (flags & FWUPD_DEVICE_FLAG_NEEDS_REBOOT) { if (prompt) { - g_print("\n%s %s [y|N]: ", - /* TRANSLATORS: explain why we want to reboot */ - _("An update requires a reboot to complete."), - /* TRANSLATORS: reboot to apply the update */ - _("Restart now?")); - if (!fu_util_prompt_for_boolean(FALSE)) + if (!fu_console_input_bool(console, + FALSE, + "%s %s", + /* TRANSLATORS: explain why we want to reboot */ + _("An update requires a reboot to complete."), + /* TRANSLATORS: reboot to apply the update */ + _("Restart now?"))) return TRUE; } return fu_util_update_reboot(error); @@ -849,116 +784,6 @@ fu_util_release_get_name(FwupdRelease *release) return g_strdup_printf(_("%s Update"), name); } -static GPtrArray * -fu_util_strsplit_words(const gchar *text, guint line_len) -{ - g_auto(GStrv) tokens = NULL; - g_autoptr(GPtrArray) lines = g_ptr_array_new_with_free_func(g_free); - g_autoptr(GString) curline = g_string_new(NULL); - - /* sanity check */ - if (text == NULL || text[0] == '\0') - return NULL; - if (line_len == 0) - return NULL; - - /* tokenize the string */ - tokens = g_strsplit(text, " ", -1); - for (guint i = 0; tokens[i] != NULL; i++) { - /* current line plus new token is okay */ - if (curline->len + fu_strwidth(tokens[i]) < line_len) { - g_string_append_printf(curline, "%s ", tokens[i]); - continue; - } - - /* too long, so remove space, add newline and dump */ - if (curline->len > 0) - g_string_truncate(curline, curline->len - 1); - g_ptr_array_add(lines, g_strdup(curline->str)); - g_string_truncate(curline, 0); - g_string_append_printf(curline, "%s ", tokens[i]); - } - - /* any incomplete line? */ - if (curline->len > 0) { - g_string_truncate(curline, curline->len - 1); - g_ptr_array_add(lines, g_strdup(curline->str)); - } - return g_steal_pointer(&lines); -} - -static void -fu_util_warning_box_line(const gchar *start, - const gchar *text, - const gchar *end, - const gchar *padding, - guint width) -{ - guint offset = 0; - if (start != NULL) { - offset += fu_strwidth(start); - g_print("%s", start); - } - if (text != NULL) { - offset += fu_strwidth(text); - g_print("%s", text); - } - if (end != NULL) - offset += fu_strwidth(end); - for (guint i = offset; i < width; i++) - g_print("%s", padding); - if (end != NULL) - g_print("%s\n", end); -} - -void -fu_util_warning_box(const gchar *title, const gchar *body, guint width) -{ - /* nothing to do */ - if (title == NULL && body == NULL) - return; - - /* header */ - fu_util_warning_box_line("╔", NULL, "╗", "═", width); - - /* optional title */ - if (title != NULL) { - g_autoptr(GPtrArray) lines = fu_util_strsplit_words(title, width - 4); - for (guint j = 0; j < lines->len; j++) { - const gchar *line = g_ptr_array_index(lines, j); - fu_util_warning_box_line("║ ", line, " ║", " ", width); - } - } - - /* join */ - if (title != NULL && body != NULL) - fu_util_warning_box_line("╠", NULL, "╣", "═", width); - - /* optional body */ - if (body != NULL) { - gboolean has_nonempty = FALSE; - g_auto(GStrv) split = g_strsplit(body, "\n", -1); - for (guint i = 0; split[i] != NULL; i++) { - g_autoptr(GPtrArray) lines = fu_util_strsplit_words(split[i], width - 4); - if (lines == NULL) { - if (has_nonempty) { - fu_util_warning_box_line("║ ", NULL, " ║", " ", width); - has_nonempty = FALSE; - } - continue; - } - for (guint j = 0; j < lines->len; j++) { - const gchar *line = g_ptr_array_index(lines, j); - fu_util_warning_box_line("║ ", line, " ║", " ", width); - } - has_nonempty = TRUE; - } - } - - /* footer */ - fu_util_warning_box_line("╚", NULL, "╝", "═", width); -} - gboolean fu_util_parse_filter_flags(const gchar *filter, FwupdDeviceFlags *include, @@ -1561,7 +1386,7 @@ fu_util_device_to_string(FwupdClient *client, FwupdDevice *dev, guint idt) tmp = fwupd_device_get_update_message(dev); if (tmp != NULL) { g_autofree gchar *color = - fu_util_term_format(tmp, FU_UTIL_TERM_COLOR_BLUE); + fu_console_color_format(tmp, FU_CONSOLE_COLOR_BLUE); fu_string_append( str, idt + 1, @@ -1596,7 +1421,8 @@ fu_util_device_to_string(FwupdClient *client, FwupdDevice *dev, guint idt) if (fwupd_device_get_problems(dev) == FWUPD_DEVICE_PROBLEM_NONE) { tmp = fwupd_device_get_update_error(dev); if (tmp != NULL) { - g_autofree gchar *color = fu_util_term_format(tmp, FU_UTIL_TERM_COLOR_RED); + g_autofree gchar *color = + fu_console_color_format(tmp, FU_CONSOLE_COLOR_RED); /* TRANSLATORS: error message from last update attempt */ fu_string_append(str, idt + 1, _("Update Error"), color); } @@ -1615,7 +1441,7 @@ fu_util_device_to_string(FwupdClient *client, FwupdDevice *dev, guint idt) if (desc == NULL) continue; bullet = g_strdup_printf("• %s", desc); - color = fu_util_term_format(bullet, FU_UTIL_TERM_COLOR_RED); + color = fu_console_color_format(bullet, FU_CONSOLE_COLOR_RED); fu_string_append(str, idt + 1, tmp, color); tmp = NULL; } @@ -1780,12 +1606,12 @@ fu_util_plugin_flag_to_cli_text(FwupdPluginFlags plugin_flag) case FWUPD_PLUGIN_FLAG_MODULAR: case FWUPD_PLUGIN_FLAG_MEASURE_SYSTEM_INTEGRITY: case FWUPD_PLUGIN_FLAG_SECURE_CONFIG: - return fu_util_term_format(fu_util_plugin_flag_to_string(plugin_flag), - FU_UTIL_TERM_COLOR_GREEN); + return fu_console_color_format(fu_util_plugin_flag_to_string(plugin_flag), + FU_CONSOLE_COLOR_GREEN); case FWUPD_PLUGIN_FLAG_DISABLED: case FWUPD_PLUGIN_FLAG_NO_HARDWARE: - return fu_util_term_format(fu_util_plugin_flag_to_string(plugin_flag), - FU_UTIL_TERM_COLOR_BLACK); + return fu_console_color_format(fu_util_plugin_flag_to_string(plugin_flag), + FU_CONSOLE_COLOR_BLACK); case FWUPD_PLUGIN_FLAG_LEGACY_BIOS: case FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED: case FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED: @@ -1793,8 +1619,8 @@ fu_util_plugin_flag_to_cli_text(FwupdPluginFlags plugin_flag) case FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED: case FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND: case FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD: - return fu_util_term_format(fu_util_plugin_flag_to_string(plugin_flag), - FU_UTIL_TERM_COLOR_RED); + return fu_console_color_format(fu_util_plugin_flag_to_string(plugin_flag), + FU_CONSOLE_COLOR_RED); default: break; } @@ -2334,16 +2160,16 @@ fu_security_attr_append_str(FwupdSecurityAttr *attr, for (guint i = fu_strwidth(name); i < 30; i++) g_string_append(str, " "); if (fwupd_security_attr_has_flag(attr, FWUPD_SECURITY_ATTR_FLAG_OBSOLETED)) { - g_autofree gchar *fmt = fu_util_term_format(fu_security_attr_get_result(attr), - FU_UTIL_TERM_COLOR_YELLOW); + g_autofree gchar *fmt = fu_console_color_format(fu_security_attr_get_result(attr), + FU_CONSOLE_COLOR_YELLOW); g_string_append(str, fmt); } else if (fwupd_security_attr_has_flag(attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS)) { - g_autofree gchar *fmt = fu_util_term_format(fu_security_attr_get_result(attr), - FU_UTIL_TERM_COLOR_GREEN); + g_autofree gchar *fmt = fu_console_color_format(fu_security_attr_get_result(attr), + FU_CONSOLE_COLOR_GREEN); g_string_append(str, fmt); } else { - g_autofree gchar *fmt = - fu_util_term_format(fu_security_attr_get_result(attr), FU_UTIL_TERM_COLOR_RED); + g_autofree gchar *fmt = fu_console_color_format(fu_security_attr_get_result(attr), + FU_CONSOLE_COLOR_RED); g_string_append(str, fmt); } if ((flags & FU_SECURITY_ATTR_TO_STRING_FLAG_SHOW_URLS) > 0 && @@ -2545,9 +2371,9 @@ fu_util_security_events_to_string(GPtrArray *events, FuSecurityAttrToStringFlags if (eventstr == NULL) continue; if (fwupd_security_attr_has_flag(attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS)) { - check = fu_util_term_format("✔", FU_UTIL_TERM_COLOR_GREEN); + check = fu_console_color_format("✔", FU_CONSOLE_COLOR_GREEN); } else { - check = fu_util_term_format("✘", FU_UTIL_TERM_COLOR_RED); + check = fu_console_color_format("✘", FU_CONSOLE_COLOR_RED); } if (str->len == 0) { /* TRANSLATORS: title for host security events */ @@ -2820,7 +2646,8 @@ fu_util_device_order_sort_cb(gconstpointer a, gconstpointer b) } gboolean -fu_util_switch_branch_warning(FwupdDevice *dev, +fu_util_switch_branch_warning(FuConsole *console, + FwupdDevice *dev, FwupdRelease *rel, gboolean assume_yes, GError **error) @@ -2863,13 +2690,14 @@ fu_util_switch_branch_warning(FwupdDevice *dev, title = g_strdup_printf(_("Switch branch from %s to %s?"), fu_util_branch_for_display(fwupd_device_get_branch(dev)), fu_util_branch_for_display(fwupd_release_get_branch(rel))); - fu_util_warning_box(title, desc_full->str, 80); + fu_console_box(console, title, desc_full->str, 80); if (!assume_yes) { - /* ask for permission */ - g_print("\n%s [y|N]: ", - /* TRANSLATORS: should the branch be changed */ - _("Do you understand the consequences of changing the firmware branch?")); - if (!fu_util_prompt_for_boolean(FALSE)) { + if (!fu_console_input_bool(console, + FALSE, + "%s", + /* TRANSLATORS: should the branch be changed */ + _("Do you understand the consequences " + "of changing the firmware branch?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, @@ -2881,7 +2709,7 @@ fu_util_switch_branch_warning(FwupdDevice *dev, } gboolean -fu_util_prompt_warning_fde(FwupdDevice *dev, GError **error) +fu_util_prompt_warning_fde(FuConsole *console, FwupdDevice *dev, GError **error) { const gchar *url = "https://github.com/fwupd/fwupd/wiki/Full-Disk-Encryption-Detected"; g_autoptr(GString) str = g_string_new(NULL); @@ -2904,13 +2732,10 @@ fu_util_prompt_warning_fde(FwupdDevice *dev, GError **error) _("See %s for more details."), url); /* TRANSLATORS: title text, shown as a warning */ - fu_util_warning_box(_("Full Disk Encryption Detected"), str->str, 80); + fu_console_box(console, _("Full Disk Encryption Detected"), str->str, 80); - /* ask for confirmation */ - g_print("\n%s [Y|n]: ", - /* TRANSLATORS: prompt to apply the update */ - _("Perform operation?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + /* TRANSLATORS: prompt to apply the update */ + if (!fu_console_input_bool(console, TRUE, "%s", _("Perform operation?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, @@ -2921,19 +2746,17 @@ fu_util_prompt_warning_fde(FwupdDevice *dev, GError **error) } void -fu_util_show_unsupported_warn(void) +fu_util_show_unsupported_warning(FuConsole *console) { #ifndef SUPPORTED_BUILD - g_autofree gchar *fmt = NULL; - if (g_getenv("FWUPD_SUPPORTED") != NULL) return; /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_YELLOW); - g_printerr("%s %s\n", - fmt, - /* TRANSLATORS: unsupported build of the package */ - _("This package has not been validated, it may not work properly.")); + fu_console_print_full(console, + FU_CONSOLE_PRINT_FLAG_WARNING | FU_CONSOLE_PRINT_FLAG_STDERR, + "%s\n", + /* TRANSLATORS: unsupported build of the package */ + _("This package has not been validated, it may not work properly.")); #endif } @@ -2954,67 +2777,7 @@ fu_util_is_url(const gchar *perhaps_url) } gboolean -fu_util_setup_interactive_console(GError **error) -{ -#ifdef _WIN32 - HANDLE hOut; - DWORD dwMode = 0; - - /* enable VT sequences */ - hOut = GetStdHandle(STD_OUTPUT_HANDLE); - if (hOut == INVALID_HANDLE_VALUE) { - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "failed to get stdout [%u]", - (guint)GetLastError()); - return FALSE; - } - if (!GetConsoleMode(hOut, &dwMode)) { - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "failed to get mode [%u]", - (guint)GetLastError()); - return FALSE; - } - dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if (!SetConsoleMode(hOut, dwMode)) { - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "failed to set mode [%u]", - (guint)GetLastError()); - return FALSE; - } - if (!SetConsoleOutputCP(CP_UTF8)) { - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "failed to set output UTF-8 [%u]", - (guint)GetLastError()); - return FALSE; - } - if (!SetConsoleCP(CP_UTF8)) { - g_set_error(error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "failed to set UTF-8 [%u]", - (guint)GetLastError()); - return FALSE; - } -#else - if (isatty(fileno(stdout)) == 0) { - g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "not a TTY"); - return FALSE; - } -#endif - /* success */ - return TRUE; -} - -gboolean -fu_util_print_builder(JsonBuilder *builder, GError **error) +fu_util_print_builder(FuConsole *console, JsonBuilder *builder, GError **error) { g_autofree gchar *data = NULL; g_autoptr(JsonGenerator) json_generator = NULL; @@ -3035,12 +2798,12 @@ fu_util_print_builder(JsonBuilder *builder, GError **error) } /* just print */ - g_print("%s\n", data); + fu_console_print_literal(console, data); return TRUE; } void -fu_util_print_error_as_json(const GError *error) +fu_util_print_error_as_json(FuConsole *console, const GError *error) { g_autoptr(JsonBuilder) builder = json_builder_new(); json_builder_begin_object(builder); @@ -3054,7 +2817,7 @@ fu_util_print_error_as_json(const GError *error) json_builder_add_string_value(builder, error->message); json_builder_end_object(builder); json_builder_end_object(builder); - fu_util_print_builder(builder, NULL); + fu_util_print_builder(console, builder, NULL); } typedef enum { @@ -3104,7 +2867,7 @@ fu_util_print_version_key_valid(const gchar *key) } gboolean -fu_util_project_versions_as_json(GHashTable *metadata, GError **error) +fu_util_project_versions_as_json(FuConsole *console, GHashTable *metadata, GError **error) { GHashTableIter iter; const gchar *key; @@ -3138,7 +2901,7 @@ fu_util_project_versions_as_json(GHashTable *metadata, GError **error) } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(console, builder, error); } gchar * diff --git a/src/fu-util-common.h b/src/fu-util-common.h index 3d93ac853..77b25ee50 100644 --- a/src/fu-util-common.h +++ b/src/fu-util-common.h @@ -13,6 +13,8 @@ #include "fwupd-bios-setting-private.h" #include "fwupd-security-attr-private.h" +#include "fu-console.h" + /* this is only valid for tools */ #define FWUPD_ERROR_INVALID_ARGS (FWUPD_ERROR_LAST + 1) @@ -33,44 +35,26 @@ typedef enum { FU_SECURITY_ATTR_TO_STRING_FLAG_LAST } FuSecurityAttrToStringFlags; -typedef enum { - FU_UTIL_TERM_COLOR_BLACK = 30, - FU_UTIL_TERM_COLOR_RED = 31, - FU_UTIL_TERM_COLOR_GREEN = 32, - FU_UTIL_TERM_COLOR_YELLOW = 33, - FU_UTIL_TERM_COLOR_BLUE = 34, - FU_UTIL_TERM_COLOR_MAGENTA = 35, - FU_UTIL_TERM_COLOR_CYAN = 36, - FU_UTIL_TERM_COLOR_WHITE = 37, -} FuUtilTermColor; - void -fu_util_print_data(const gchar *title, const gchar *msg); -gchar * -fu_util_term_format(const gchar *text, FuUtilTermColor fg_color); -guint -fu_util_prompt_for_number(guint maxnum); -gboolean -fu_util_prompt_for_boolean(gboolean def); - -void -fu_util_print_tree(FwupdClient *client, GNode *n); +fu_util_print_tree(FuConsole *console, FwupdClient *client, GNode *n); gboolean fu_util_is_interesting_device(FwupdDevice *dev); gchar * fu_util_get_user_cache_path(const gchar *fn); -void -fu_util_warning_box(const gchar *title, const gchar *body, guint width); gboolean -fu_util_prompt_warning(FwupdDevice *device, +fu_util_prompt_warning(FuConsole *console, + FwupdDevice *device, FwupdRelease *release, const gchar *machine, GError **error); gboolean -fu_util_prompt_warning_fde(FwupdDevice *dev, GError **error); +fu_util_prompt_warning_fde(FuConsole *console, FwupdDevice *dev, GError **error); gboolean -fu_util_prompt_complete(FwupdDeviceFlags flags, gboolean prompt, GError **error); +fu_util_prompt_complete(FuConsole *console, + FwupdDeviceFlags flags, + gboolean prompt, + GError **error); gboolean fu_util_update_reboot(GError **error); @@ -145,21 +129,20 @@ gint fu_util_device_order_sort_cb(gconstpointer a, gconstpointer b); gboolean -fu_util_switch_branch_warning(FwupdDevice *dev, +fu_util_switch_branch_warning(FuConsole *console, + FwupdDevice *dev, FwupdRelease *rel, gboolean assume_yes, GError **error); void -fu_util_show_unsupported_warn(void); +fu_util_show_unsupported_warning(FuConsole *console); gboolean fu_util_is_url(const gchar *perhaps_url); gboolean -fu_util_setup_interactive_console(GError **error); -gboolean -fu_util_print_builder(JsonBuilder *builder, GError **error); +fu_util_print_builder(FuConsole *console, JsonBuilder *builder, GError **error); void -fu_util_print_error_as_json(const GError *error); +fu_util_print_error_as_json(FuConsole *console, const GError *error); gchar * fu_util_project_versions_to_string(GHashTable *metadata); gboolean -fu_util_project_versions_as_json(GHashTable *metadata, GError **error); +fu_util_project_versions_as_json(FuConsole *console, GHashTable *metadata, GError **error); diff --git a/src/fu-util.c b/src/fu-util.c index 97967d549..9023987e8 100644 --- a/src/fu-util.c +++ b/src/fu-util.c @@ -27,9 +27,9 @@ #include "fwupd-release-private.h" #include "fwupd-remote-private.h" +#include "fu-console.h" #include "fu-plugin-private.h" #include "fu-polkit-agent.h" -#include "fu-progressbar.h" #include "fu-util-bios-setting.h" #include "fu-util-common.h" @@ -56,7 +56,7 @@ struct FuUtilPrivate { FwupdInstallFlags flags; FwupdClientDownloadFlags download_flags; FwupdClient *client; - FuProgressbar *progressbar; + FuConsole *console; gboolean no_remote_check; gboolean no_metadata_check; gboolean no_reboot_check; @@ -87,9 +87,9 @@ fu_util_client_notify_cb(GObject *object, GParamSpec *pspec, FuUtilPrivate *priv { if (priv->as_json) return; - fu_progressbar_update(priv->progressbar, - fwupd_client_get_status(priv->client), - fwupd_client_get_percentage(priv->client)); + fu_console_set_progress(priv->console, + fwupd_client_get_status(priv->client), + fwupd_client_get_percentage(priv->client)); } static void @@ -105,9 +105,9 @@ fu_util_update_device_request_cb(FwupdClient *client, FwupdRequest *request, FuU g_autofree gchar *tmp = NULL; /* TRANSLATORS: the user needs to do something, e.g. remove the device */ - fmt = fu_util_term_format(_("Action Required:"), FU_UTIL_TERM_COLOR_RED); + fmt = fu_console_color_format(_("Action Required:"), FU_CONSOLE_COLOR_RED); tmp = g_strdup_printf("%s %s", fmt, fwupd_request_get_message(request)); - fu_progressbar_set_title(priv->progressbar, tmp); + fu_console_set_progress_title(priv->console, tmp); } /* save for later */ @@ -147,19 +147,19 @@ fu_util_update_device_changed_cb(FwupdClient *client, FwupdDevice *device, FuUti return; } - /* show message in progressbar */ + /* show message in console */ if (priv->current_operation == FU_UTIL_OPERATION_UPDATE) { /* TRANSLATORS: %1 is a device name */ str = g_strdup_printf(_("Updating %s…"), fwupd_device_get_name(device)); - fu_progressbar_set_title(priv->progressbar, str); + fu_console_set_progress_title(priv->console, str); } else if (priv->current_operation == FU_UTIL_OPERATION_DOWNGRADE) { /* TRANSLATORS: %1 is a device name */ str = g_strdup_printf(_("Downgrading %s…"), fwupd_device_get_name(device)); - fu_progressbar_set_title(priv->progressbar, str); + fu_console_set_progress_title(priv->console, str); } else if (priv->current_operation == FU_UTIL_OPERATION_INSTALL) { /* TRANSLATORS: %1 is a device name */ str = g_strdup_printf(_("Installing on %s…"), fwupd_device_get_name(device)); - fu_progressbar_set_title(priv->progressbar, str); + fu_console_set_progress_title(priv->console, str); } else { g_warning("no FuUtilOperation set"); } @@ -212,8 +212,12 @@ fu_util_prompt_for_device(FuUtilPrivate *priv, GPtrArray *devices, GError **erro if (devices_filtered->len == 1) { dev = g_ptr_array_index(devices_filtered, 0); if (!priv->as_json) { - /* TRANSLATORS: device has been chosen by the daemon for the user */ - g_print("%s: %s\n", _("Selected device"), fwupd_device_get_name(dev)); + fu_console_print( + priv->console, + "%s: %s", + /* TRANSLATORS: device has been chosen by the daemon for the user */ + _("Selected device"), + fwupd_device_get_name(dev)); } return g_object_ref(dev); } @@ -228,17 +232,18 @@ fu_util_prompt_for_device(FuUtilPrivate *priv, GPtrArray *devices, GError **erro } /* TRANSLATORS: get interactive prompt */ - g_print("%s\n", _("Choose a device:")); + fu_console_print_literal(priv->console, _("Choose a device:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < devices_filtered->len; i++) { dev = g_ptr_array_index(devices_filtered, i); - g_print("%u.\t%s (%s)\n", - i + 1, - fwupd_device_get_id(dev), - fwupd_device_get_name(dev)); + fu_console_print(priv->console, + "%u.\t%s (%s)", + i + 1, + fwupd_device_get_id(dev), + fwupd_device_get_name(dev)); } - idx = fu_util_prompt_for_number(devices_filtered->len); + idx = fu_console_input_uint(priv->console, devices_filtered->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -352,51 +357,59 @@ fu_util_perhaps_show_unreported(FuUtilPrivate *priv, GError **error) /* show the success and failures */ if (!priv->assume_yes && !all_automatic) { /* delimit */ - g_print("________________________________________________\n"); + fu_console_line(priv->console, 48); /* failures */ if (devices_failed->len > 0) { - /* TRANSLATORS: a list of failed updates */ - g_print("\n%s\n\n", _("Devices that were not updated correctly:")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: a list of failed updates */ + _("Devices that were not updated correctly:")); for (guint i = 0; i < devices_failed->len; i++) { FwupdDevice *dev = g_ptr_array_index(devices_failed, i); FwupdRelease *rel = fwupd_device_get_release_default(dev); - g_print(" • %s (%s → %s)\n", - fwupd_device_get_name(dev), - fwupd_device_get_version(dev), - fwupd_release_get_version(rel)); + fu_console_print(priv->console, + " • %s (%s → %s)", + fwupd_device_get_name(dev), + fwupd_device_get_version(dev), + fwupd_release_get_version(rel)); } } /* success */ if (devices_success->len > 0) { - /* TRANSLATORS: a list of successful updates */ - g_print("\n%s\n\n", _("Devices that have been updated successfully:")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: a list of successful updates */ + _("Devices that have been updated successfully:")); for (guint i = 0; i < devices_success->len; i++) { FwupdDevice *dev = g_ptr_array_index(devices_success, i); FwupdRelease *rel = fwupd_device_get_release_default(dev); - g_print(" • %s (%s → %s)\n", - fwupd_device_get_name(dev), - fwupd_device_get_version(dev), - fwupd_release_get_version(rel)); + fu_console_print(priv->console, + " • %s (%s → %s)", + fwupd_device_get_name(dev), + fwupd_device_get_version(dev), + fwupd_release_get_version(rel)); } } /* ask for permission */ - g_print("\n%s\n%s (%s) [Y|n]:\n", - /* TRANSLATORS: explain why we want to upload */ - _("Uploading firmware reports helps hardware vendors" - " to quickly identify failing and successful updates" - " on real devices."), - /* TRANSLATORS: ask the user to upload */ - _("Upload report now?"), - /* TRANSLATORS: metadata is downloaded from the Internet */ - _("Requires internet connection")); - if (!fu_util_prompt_for_boolean(TRUE)) { - g_print("\n%s [y|N]:\n", - /* TRANSLATORS: offer to disable this nag */ - _("Do you want to disable this feature for future updates?")); - if (fu_util_prompt_for_boolean(FALSE)) { + fu_console_print_literal(priv->console, + /* TRANSLATORS: explain why we want to upload */ + _("Uploading firmware reports helps hardware vendors " + "to quickly identify failing and successful updates " + "on real devices.")); + if (!fu_console_input_bool(priv->console, + TRUE, + "%s (%s)", + /* TRANSLATORS: ask the user to upload */ + _("Upload report now?"), + /* TRANSLATORS: metadata is downloaded */ + _("Requires internet connection"))) { + if (fu_console_input_bool(priv->console, + FALSE, + "%s", + /* TRANSLATORS: offer to disable this nag */ + _("Do you want to disable this feature " + "for future updates?"))) { for (guint i = 0; i < remotes->len; i++) { FwupdRemote *remote = g_ptr_array_index(remotes, i); const gchar *remote_id = fwupd_remote_get_id(remote); @@ -425,10 +438,12 @@ fu_util_perhaps_show_unreported(FuUtilPrivate *priv, GError **error) /* offer to make automatic */ if (!priv->assume_yes && !all_automatic) { - g_print("\n%s [y|N]:\n", - /* TRANSLATORS: offer to stop asking the question */ - _("Do you want to upload reports automatically for future updates?")); - if (fu_util_prompt_for_boolean(FALSE)) { + if (fu_console_input_bool(priv->console, + FALSE, + "%s", + /* TRANSLATORS: offer to stop asking the question */ + _("Do you want to upload reports automatically for " + "future updates?"))) { for (guint i = 0; i < remotes->len; i++) { FwupdRemote *remote = g_ptr_array_index(remotes, i); const gchar *remote_id = fwupd_remote_get_id(remote); @@ -466,13 +481,13 @@ fu_util_modify_remote_warning(FuUtilPrivate *priv, FwupdRemote *remote, GError * return FALSE; /* TRANSLATORS: a remote here is like a 'repo' or software source */ - fu_util_warning_box(_("Enable new remote?"), warning_plain, 80); + fu_console_box(priv->console, _("Enable new remote?"), warning_plain, 80); if (!priv->assume_yes) { - /* ask for permission */ - g_print("\n%s [Y|n]: ", - /* TRANSLATORS: should the remote still be enabled */ - _("Agree and enable the remote?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + if (!fu_console_input_bool(priv->console, + TRUE, + "%s", + /* TRANSLATORS: should the remote still be enabled */ + _("Agree and enable the remote?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, @@ -517,7 +532,7 @@ fu_util_get_releases_as_json(FuUtilPrivate *priv, GPtrArray *rels, GError **erro } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -553,7 +568,7 @@ fu_util_get_devices_as_json(FuUtilPrivate *priv, GPtrArray *devs, GError **error } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -575,11 +590,12 @@ fu_util_get_devices(FuUtilPrivate *priv, gchar **values, GError **error) if (devs->len > 0) fu_util_build_device_tree(priv, root, devs, NULL); if (g_node_n_children(root) == 0) { - /* TRANSLATORS: nothing attached that can be upgraded */ - g_print("%s\n", _("No hardware detected with firmware update capability")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: nothing attached that can be upgraded */ + _("No hardware detected with firmware update capability")); return TRUE; } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); /* nag? */ if (!fu_util_perhaps_show_unreported(priv, error)) @@ -604,7 +620,7 @@ fu_util_get_plugins_as_json(FuUtilPrivate *priv, GPtrArray *plugins, GError **er } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -623,11 +639,11 @@ fu_util_get_plugins(FuUtilPrivate *priv, gchar **values, GError **error) for (guint i = 0; i < plugins->len; i++) { FuPlugin *plugin = g_ptr_array_index(plugins, i); g_autofree gchar *str = fu_util_plugin_to_string(FWUPD_PLUGIN(plugin), 0); - g_print("%s\n", str); + fu_console_print_literal(priv->console, str); } if (plugins->len == 0) { /* TRANSLATORS: nothing found */ - g_print("%s\n", _("No plugins found")); + fu_console_print_literal(priv->console, _("No plugins found")); } /* success */ @@ -670,12 +686,12 @@ static void fu_util_display_current_message(FuUtilPrivate *priv) { /* TRANSLATORS: success message */ - g_print("%s\n", _("Successfully installed firmware")); + fu_console_print_literal(priv->console, _("Successfully installed firmware")); /* print all POST requests */ for (guint i = 0; i < priv->post_requests->len; i++) { FwupdRequest *request = g_ptr_array_index(priv->post_requests, i); - g_print("%s\n", fu_util_request_get_message(request)); + fu_console_print_literal(priv->console, fu_util_request_get_message(request)); } } @@ -753,10 +769,11 @@ fu_util_device_test_component(FuUtilPrivate *priv, if (device == NULL) { if (!priv->as_json) { g_autofree gchar *msg = NULL; - /* TRANSLATORS: this is for the device tests */ - msg = fu_util_term_format(_("Did not find any devices with matching GUIDs"), - FU_UTIL_TERM_COLOR_RED); - g_print("%s: %s", name, msg); + msg = fu_console_color_format( + /* TRANSLATORS: this is for the device tests */ + _("Did not find any devices with matching GUIDs"), + FU_CONSOLE_COLOR_RED); + fu_console_print(priv->console, "%s: %s", name, msg); } json_builder_set_member_name(helper->builder, "error"); json_builder_add_string_value(helper->builder, "no devices found"); @@ -783,8 +800,8 @@ fu_util_device_test_component(FuUtilPrivate *priv, _("The device version did not match: got %s, expected %s"), fu_device_get_version(device), version); - msg = fu_util_term_format(str2, FU_UTIL_TERM_COLOR_RED); - g_print("%s: %s", name, msg); + msg = fu_console_color_format(str2, FU_CONSOLE_COLOR_RED); + fu_console_print(priv->console, "%s: %s", name, msg); } json_builder_set_member_name(helper->builder, "error"); json_builder_add_string_value(helper->builder, str); @@ -796,8 +813,8 @@ fu_util_device_test_component(FuUtilPrivate *priv, if (!priv->as_json) { g_autofree gchar *msg = NULL; /* TRANSLATORS: this is for the device tests */ - msg = fu_util_term_format(_("OK!"), FU_UTIL_TERM_COLOR_GREEN); - g_print("%s: %s\n", helper->name, msg); + msg = fu_console_color_format(_("OK!"), FU_CONSOLE_COLOR_GREEN); + fu_console_print(priv->console, "%s: %s", helper->name, msg); } helper->nr_success++; return TRUE; @@ -894,8 +911,8 @@ fu_util_device_test_step(FuUtilPrivate *priv, } if (!priv->as_json) { g_autofree gchar *msg = NULL; - msg = fu_util_term_format(error_local->message, FU_UTIL_TERM_COLOR_RED); - g_print("%s: %s", helper->name, msg); + msg = fu_console_color_format(error_local->message, FU_CONSOLE_COLOR_RED); + fu_console_print(priv->console, "%s: %s", helper->name, msg); } json_builder_set_member_name(helper->builder, "error"); json_builder_add_string_value(helper->builder, error_local->message); @@ -1029,7 +1046,7 @@ fu_util_inhibit(FuUtilPrivate *priv, gchar **values, GError **error) /* TRANSLATORS: CTRL^C [holding control, and then pressing C] will exit the program */ g_string_append(str, _("Use CTRL^C to cancel.")); /* TRANSLATORS: this CLI tool is now preventing system updates */ - fu_util_warning_box(_("System Update Inhibited"), str->str, 80); + fu_console_box(priv->console, _("System Update Inhibited"), str->str, 80); g_main_loop_run(priv->loop); return TRUE; } @@ -1095,7 +1112,7 @@ fu_util_device_test_full(FuUtilPrivate *priv, /* dump to screen as JSON format */ json_builder_end_object(builder); if (priv->as_json) { - if (!fu_util_print_builder(builder, error)) + if (!fu_util_print_builder(priv->console, builder, error)) return FALSE; } @@ -1217,7 +1234,7 @@ fu_util_local_install(FuUtilPrivate *priv, gchar **values, GError **error) /* detect bitlocker */ if (dev != NULL && !priv->no_safety_check && !priv->assume_yes) { - if (!fu_util_prompt_warning_fde(dev, error)) + if (!fu_util_prompt_warning_fde(priv->console, dev, error)) return FALSE; } @@ -1238,7 +1255,7 @@ fu_util_local_install(FuUtilPrivate *priv, gchar **values, GError **error) } /* show reboot if needed */ - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -1256,7 +1273,7 @@ fu_util_get_details_as_json(FuUtilPrivate *priv, GPtrArray *devs, GError **error } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -1284,7 +1301,7 @@ fu_util_get_details(FuUtilPrivate *priv, gchar **values, GError **error) return fu_util_get_details_as_json(priv, array, error); fu_util_build_device_tree(priv, root, array, NULL); - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -1322,12 +1339,13 @@ fu_util_report_history_for_remote(FuUtilPrivate *priv, /* ask for permission */ if (!priv->assume_yes && !fwupd_remote_get_automatic_reports(remote)) { - fu_util_print_data(_("Target"), fwupd_remote_get_report_uri(remote)); - fu_util_print_data(_("Payload"), data); + fu_console_print_kv(priv->console, + _("Target"), + fwupd_remote_get_report_uri(remote)); + fu_console_print_kv(priv->console, _("Payload"), data); if (sig != NULL) - fu_util_print_data(_("Signature"), sig); - g_print("%s [Y|n]: ", _("Proceed with upload?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + fu_console_print_kv(priv->console, _("Signature"), sig); + if (!fu_console_input_bool(priv->console, TRUE, "%s", _("Proceed with upload?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_PERMISSION_DENIED, @@ -1347,10 +1365,12 @@ fu_util_report_history_for_remote(FuUtilPrivate *priv, /* server wanted us to see a message */ if (uri != NULL) { - g_print("%s %s\n", - /* TRANSLATORS: the server sent the user a small message */ - _("Update failure is a known issue, visit this URL for more information:"), - uri); + fu_console_print( + priv->console, + "%s %s", + /* TRANSLATORS: the server sent the user a small message */ + _("Update failure is a known issue, visit this URL for more information:"), + uri); } /* success */ @@ -1464,7 +1484,7 @@ fu_util_report_history(FuUtilPrivate *priv, gchar **values, GError **error) "Successfully uploaded %u reports", g_hash_table_size(report_map)), g_hash_table_size(report_map)); - g_print("%s\n", str->str); + fu_console_print_literal(priv->console, str->str); return TRUE; } @@ -1540,7 +1560,7 @@ fu_util_get_history(FuUtilPrivate *priv, gchar **values, GError **error) } } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -1658,8 +1678,9 @@ fu_util_verify_update(FuUtilPrivate *priv, gchar **values, GError **error) g_prefix_error(error, "failed to verify update %s: ", fu_device_get_name(dev)); return FALSE; } + /* TRANSLATORS: success message when user refreshes device checksums */ - g_print("%s\n", _("Successfully updated device checksums")); + fu_console_print_literal(priv->console, _("Successfully updated device checksums")); return TRUE; } @@ -1673,14 +1694,15 @@ fu_util_download_metadata_enable_lvfs(FuUtilPrivate *priv, GError **error) remote = fwupd_client_get_remote_by_id(priv->client, "lvfs", priv->cancellable, error); if (remote == NULL) return TRUE; - g_print("%s\n%s\n%s [Y|n]: ", - /* TRANSLATORS: explain why no metadata available */ - _("No remotes are currently enabled so no metadata is available."), - /* TRANSLATORS: explain why no metadata available */ - _("Metadata can be obtained from the Linux Vendor Firmware Service."), - /* TRANSLATORS: Turn on the remote */ - _("Enable this remote?")); - if (!fu_util_prompt_for_boolean(TRUE)) + fu_console_print(priv->console, + /* TRANSLATORS: explain why no metadata available */ + _("No remotes are currently enabled so no metadata is available.")); + fu_console_print(priv->console, + /* TRANSLATORS: explain why no metadata available */ + _("Metadata can be obtained from the Linux Vendor Firmware Service.")); + + /* TRANSLATORS: Turn on the remote */ + if (!fu_console_input_bool(priv->console, TRUE, "%s", _("Enable this remote?"))) return TRUE; if (!fwupd_client_modify_remote(priv->client, fwupd_remote_get_id(remote), @@ -1768,7 +1790,10 @@ fu_util_download_metadata(FuUtilPrivate *priv, GError **error) if (fwupd_remote_get_kind(remote) != FWUPD_REMOTE_KIND_DOWNLOAD) continue; download_remote_enabled = TRUE; - g_print("%s %s\n", _("Updating"), fwupd_remote_get_id(remote)); + fu_console_print(priv->console, + "%s %s", + _("Updating"), + fwupd_remote_get_id(remote)); if (!fwupd_client_refresh_remote(priv->client, remote, priv->cancellable, error)) return FALSE; } @@ -1807,7 +1832,7 @@ fu_util_download_metadata(FuUtilPrivate *priv, GError **error) "%u local devices supported", devices_supported_cnt), devices_supported_cnt); - g_print("%s\n", str->str); + fu_console_print_literal(priv->console, str->str); return TRUE; } @@ -1834,7 +1859,7 @@ fu_util_refresh(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; /* TRANSLATORS: success message -- the user can do this by-hand too */ - g_print("%s\n", _("Successfully refreshed metadata manually")); + fu_console_print_literal(priv->console, _("Successfully refreshed metadata manually")); return TRUE; } @@ -1845,7 +1870,7 @@ fu_util_get_results_as_json(FuUtilPrivate *priv, FwupdDevice *res, GError **erro json_builder_begin_object(builder); fwupd_device_to_json_full(res, builder, FWUPD_DEVICE_FLAG_TRUSTED); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -1868,7 +1893,7 @@ fu_util_get_results(FuUtilPrivate *priv, gchar **values, GError **error) if (priv->as_json) return fu_util_get_results_as_json(priv, rel, error); tmp = fu_util_device_to_string(priv->client, rel, 0); - g_print("%s", tmp); + fu_console_print_literal(priv->console, tmp); return TRUE; } @@ -1897,14 +1922,14 @@ fu_util_get_releases(FuUtilPrivate *priv, gchar **values, GError **error) if (rels->len == 0) { /* TRANSLATORS: no repositories to download from */ - g_print("%s\n", _("No releases available")); + fu_console_print_literal(priv->console, _("No releases available")); return TRUE; } if (g_getenv("FWUPD_VERBOSE") != NULL) { for (guint i = 0; i < rels->len; i++) { FwupdRelease *rel = g_ptr_array_index(rels, i); g_autofree gchar *tmp = fwupd_release_to_string(rel); - g_print("%s\n", tmp); + fu_console_print_literal(priv->console, tmp); } } else { g_autoptr(GNode) root = g_node_new(NULL); @@ -1912,7 +1937,7 @@ fu_util_get_releases(FuUtilPrivate *priv, gchar **values, GError **error) FwupdRelease *rel = g_ptr_array_index(rels, i); g_node_append_data(root, rel); } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); } return TRUE; @@ -1940,14 +1965,17 @@ fu_util_prompt_for_release(FuUtilPrivate *priv, GPtrArray *rels, GError **error) } /* TRANSLATORS: get interactive prompt */ - g_print("%s\n", _("Choose a release:")); + fu_console_print_literal(priv->console, _("Choose a release:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < rels->len; i++) { FwupdRelease *rel_tmp = g_ptr_array_index(rels, i); - g_print("%u.\t%s\n", i + 1, fwupd_release_get_version(rel_tmp)); + fu_console_print(priv->console, + "%u.\t%s", + i + 1, + fwupd_release_get_version(rel_tmp)); } - idx = fu_util_prompt_for_number(rels->len); + idx = fu_console_input_uint(priv->console, rels->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -1976,8 +2004,9 @@ fu_util_verify(FuUtilPrivate *priv, gchar **values, GError **error) g_prefix_error(error, "failed to verify %s: ", fu_device_get_name(dev)); return FALSE; } + /* TRANSLATORS: success message when user verified device checksums */ - g_print("%s\n", _("Successfully verified device checksums")); + fu_console_print_literal(priv->console, _("Successfully verified device checksums")); return TRUE; } @@ -2001,7 +2030,7 @@ fu_util_unlock(FuUtilPrivate *priv, gchar **values, GError **error) if (fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT)) priv->completion_flags |= FWUPD_DEVICE_FLAG_NEEDS_REBOOT; - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -2025,20 +2054,22 @@ fu_util_perhaps_refresh_remotes(FuUtilPrivate *priv, GError **error) /* ask for permission */ if (!priv->assume_yes) { - /* TRANSLATORS: the metadata is very out of date; %u is a number > 1 */ - g_print(ngettext("Firmware metadata has not been updated for %u" - " day and may not be up to date.", - "Firmware metadata has not been updated for %u" - " days and may not be up to date.", - (gint)age_limit_days), - (guint)age_limit_days); - g_print("\n\n"); - g_print("%s (%s) [y|N]: ", - /* TRANSLATORS: ask the user if we can update the metadata */ - _("Update now?"), - /* TRANSLATORS: metadata is downloaded from the Internet */ - _("Requires internet connection")); - if (!fu_util_prompt_for_boolean(FALSE)) + fu_console_print( + priv->console, + /* TRANSLATORS: the metadata is very out of date; %u is a number > 1 */ + ngettext("Firmware metadata has not been updated for %u" + " day and may not be up to date.", + "Firmware metadata has not been updated for %u" + " days and may not be up to date.", + (gint)age_limit_days), + (guint)age_limit_days); + if (!fu_console_input_bool(priv->console, + FALSE, + "%s (%s)", + /* TRANSLATORS: ask if we can update metadata */ + _("Update now?"), + /* TRANSLATORS: metadata is downloaded */ + _("Requires internet connection"))) return TRUE; } @@ -2083,7 +2114,7 @@ fu_util_get_updates_as_json(FuUtilPrivate *priv, GPtrArray *devices, GError **er } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -2163,20 +2194,23 @@ fu_util_get_updates(FuUtilPrivate *priv, gchar **values, GError **error) /* devices that have no updates available for whatever reason */ if (devices_no_support->len > 0) { - /* TRANSLATORS: message letting the user know no device upgrade - * available due to missing on LVFS */ - g_printerr("%s\n", _("Devices with no available firmware updates: ")); + fu_console_print_literal(priv->console, + /* TRANSLATORS: message letting the user know no device + * upgrade available due to missing on LVFS */ + _("Devices with no available firmware updates: ")); for (guint i = 0; i < devices_no_support->len; i++) { FwupdDevice *dev = g_ptr_array_index(devices_no_support, i); - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); } } if (devices_no_upgrades->len > 0) { - /* TRANSLATORS: message letting the user know no device upgrade available */ - g_printerr("%s\n", _("Devices with the latest available firmware version:")); + fu_console_print_literal( + priv->console, + /* TRANSLATORS: message letting the user know no device upgrade available */ + _("Devices with the latest available firmware version:")); for (guint i = 0; i < devices_no_upgrades->len; i++) { FwupdDevice *dev = g_ptr_array_index(devices_no_upgrades, i); - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); } } @@ -2203,7 +2237,7 @@ fu_util_get_updates(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); /* success */ return TRUE; @@ -2224,7 +2258,7 @@ fu_util_get_remotes_as_json(FuUtilPrivate *priv, GPtrArray *remotes, GError **er } json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -2241,7 +2275,7 @@ fu_util_get_remotes(FuUtilPrivate *priv, gchar **values, GError **error) if (remotes->len == 0) { /* TRANSLATORS: no repositories to download from */ - g_print("%s\n", _("No remotes available")); + fu_console_print_literal(priv->console, _("No remotes available")); return TRUE; } @@ -2249,7 +2283,7 @@ fu_util_get_remotes(FuUtilPrivate *priv, gchar **values, GError **error) FwupdRemote *remote_tmp = g_ptr_array_index(remotes, i); g_node_append_data(root, remote_tmp); } - fu_util_print_tree(priv->client, root); + fu_util_print_tree(priv->console, priv->client, root); return TRUE; } @@ -2324,15 +2358,16 @@ fu_util_prompt_warning_bkc(FuUtilPrivate *priv, FwupdDevice *dev, FwupdRelease * fwupd_release_get_version(rel), cmd); - /* TRANSLATORS: the best known configuration is a set of software that we know works well - * together. In the OEM and ODM industries it is often called a BKC */ - fu_util_warning_box(_("Deviate from the best known configuration?"), str->str, 80); + fu_console_box( + priv->console, + /* TRANSLATORS: the best known configuration is a set of software that we know works + * well together. In the OEM and ODM industries it is often called a BKC */ + _("Deviate from the best known configuration?"), + str->str, + 80); - /* ask for confirmation */ - g_print("\n%s [Y|n]: ", - /* TRANSLATORS: prompt to apply the update */ - _("Perform operation?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + /* TRANSLATORS: prompt to apply the update */ + if (!fu_console_input_bool(priv->console, TRUE, "%s", _("Perform operation?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, @@ -2398,7 +2433,11 @@ fu_util_prompt_warning_composite(FuUtilPrivate *priv, g_strdup_printf("%s %s", fwupd_client_get_host_product(priv->client), fwupd_client_get_host_product(priv->client)); - if (!fu_util_prompt_warning(dev_tmp, rel_tmp, title, error)) + if (!fu_util_prompt_warning(priv->console, + dev_tmp, + rel_tmp, + title, + error)) return FALSE; break; } @@ -2431,9 +2470,9 @@ fu_util_update_device_with_release(FuUtilPrivate *priv, } if (!priv->no_safety_check && !priv->assume_yes) { const gchar *title = fwupd_client_get_host_product(priv->client); - if (!fu_util_prompt_warning(dev, rel, title, error)) + if (!fu_util_prompt_warning(priv->console, dev, rel, title, error)) return FALSE; - if (!fu_util_prompt_warning_fde(dev, error)) + if (!fu_util_prompt_warning_fde(priv->console, dev, error)) return FALSE; if (!fu_util_prompt_warning_composite(priv, dev, rel, error)) return FALSE; @@ -2529,13 +2568,14 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) continue; if (!fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_SUPPORTED)) { if (!no_updates_header) { - g_printerr("%s\n", - /* TRANSLATORS: message letting the user know no device - * upgrade available due to missing on LVFS */ - _("Devices with no available firmware updates: ")); + fu_console_print_literal( + priv->console, + /* TRANSLATORS: message letting the user know no + * device upgrade available due to missing on LVFS */ + _("Devices with no available firmware updates: ")); no_updates_header = TRUE; } - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); continue; } @@ -2560,14 +2600,14 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) &error_local); if (rels == NULL) { if (!latest_header) { - g_printerr( - "%s\n", + fu_console_print_literal( + priv->console, /* TRANSLATORS: message letting the user know no device upgrade * available */ _("Devices with the latest available firmware version:")); latest_header = TRUE; } - g_printerr(" • %s\n", fwupd_device_get_name(dev)); + fu_console_print(priv->console, " • %s", fwupd_device_get_name(dev)); /* discard the actual reason from user, but leave for debugging */ g_debug("%s", error_local->message); continue; @@ -2598,7 +2638,7 @@ fu_util_update(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -2626,7 +2666,7 @@ fu_util_remote_modify(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; /* TRANSLATORS: success message for a per-remote setting change */ - g_print("%s\n", _("Successfully modified remote")); + fu_console_print_literal(priv->console, _("Successfully modified remote")); return TRUE; } @@ -2657,18 +2697,19 @@ fu_util_remote_enable(FuUtilPrivate *priv, gchar **values, GError **error) /* ask for permission to refresh */ if (priv->no_remote_check || fwupd_remote_get_kind(remote) != FWUPD_REMOTE_KIND_DOWNLOAD) { /* TRANSLATORS: success message */ - g_print("%s\n", _("Successfully enabled remote")); + fu_console_print_literal(priv->console, _("Successfully enabled remote")); return TRUE; } if (!priv->assume_yes) { - g_print("%s (%s) [Y|n]: ", - /* TRANSLATORS: ask the user if we can update the metadata */ - _("Do you want to refresh this remote now?"), - /* TRANSLATORS: metadata is downloaded from the Internet */ - _("Requires internet connection")); - if (!fu_util_prompt_for_boolean(TRUE)) { + if (!fu_console_input_bool(priv->console, + TRUE, + "%s (%s)", + /* TRANSLATORS: ask if we can update the metadata */ + _("Do you want to refresh this remote now?"), + /* TRANSLATORS: metadata is downloaded */ + _("Requires internet connection"))) { /* TRANSLATORS: success message */ - g_print("%s\n", _("Successfully enabled remote")); + fu_console_print_literal(priv->console, _("Successfully enabled remote")); return TRUE; } } @@ -2676,7 +2717,7 @@ fu_util_remote_enable(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; /* TRANSLATORS: success message */ - g_print("\n%s\n", _("Successfully enabled and refreshed remote")); + fu_console_print_literal(priv->console, _("Successfully enabled and refreshed remote")); return TRUE; } @@ -2706,7 +2747,7 @@ fu_util_remote_disable(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; /* TRANSLATORS: success message */ - g_print("%s\n", _("Successfully disabled remote")); + fu_console_print_literal(priv->console, _("Successfully disabled remote")); return TRUE; } @@ -2767,7 +2808,7 @@ fu_util_downgrade(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -2803,7 +2844,7 @@ fu_util_reinstall(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -2860,7 +2901,7 @@ fu_util_install(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -2914,14 +2955,17 @@ fu_util_switch_branch(FuUtilPrivate *priv, gchar **values, GError **error) /* TRANSLATORS: get interactive prompt, where branch is the * supplier of the firmware, e.g. "non-free" or "free" */ - g_print("%s\n", _("Choose a branch:")); + fu_console_print_literal(priv->console, _("Choose a branch:")); /* TRANSLATORS: this is to abort the interactive prompt */ - g_print("0.\t%s\n", _("Cancel")); + fu_console_print(priv->console, "0.\t%s", _("Cancel")); for (guint i = 0; i < branches->len; i++) { const gchar *branch_tmp = g_ptr_array_index(branches, i); - g_print("%u.\t%s\n", i + 1, fu_util_branch_for_display(branch_tmp)); + fu_console_print(priv->console, + "%u.\t%s", + i + 1, + fu_util_branch_for_display(branch_tmp)); } - idx = fu_util_prompt_for_number(branches->len); + idx = fu_console_input_uint(priv->console, branches->len); if (idx == 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -2961,7 +3005,7 @@ fu_util_switch_branch(FuUtilPrivate *priv, gchar **values, GError **error) } /* we're switching branch */ - if (!fu_util_switch_branch_warning(dev, rel, priv->assume_yes, error)) + if (!fu_util_switch_branch_warning(priv->console, dev, rel, priv->assume_yes, error)) return FALSE; /* update the console if composite devices are also updated */ @@ -2982,7 +3026,7 @@ fu_util_switch_branch(FuUtilPrivate *priv, gchar **values, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -3038,10 +3082,12 @@ fu_util_activate(FuUtilPrivate *priv, gchar **values, GError **error) continue; if (!fu_device_has_flag(device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION)) continue; - g_print("%s %s…\n", - /* TRANSLATORS: shown when shutting down to switch to the new version */ - _("Activating firmware update for"), - fwupd_device_get_name(device)); + fu_console_print( + priv->console, + "%s %s…", + /* TRANSLATORS: shown when shutting down to switch to the new version */ + _("Activating firmware update for"), + fwupd_device_get_name(device)); if (!fwupd_client_activate(priv->client, priv->cancellable, fwupd_device_get_id(device), @@ -3051,7 +3097,7 @@ fu_util_activate(FuUtilPrivate *priv, gchar **values, GError **error) /* TRANSLATORS: success message -- where activation is making the new * firmware take effect, usually after updating offline */ - g_print("%s\n", _("Successfully activated all devices")); + fu_console_print_literal(priv->console, _("Successfully activated all devices")); return TRUE; } @@ -3097,7 +3143,7 @@ fu_util_get_checksums_as_json(FuUtilPrivate *priv, gchar **csums, GError **error json_builder_add_string_value(builder, csums[i]); json_builder_end_array(builder); json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -3123,15 +3169,15 @@ fu_util_get_approved_firmware(FuUtilPrivate *priv, gchar **values, GError **erro if (g_strv_length(checksums) == 0) { /* TRANSLATORS: approved firmware has been checked by * the domain administrator */ - g_print("%s\n", _("There is no approved firmware.")); + fu_console_print_literal(priv->console, _("There is no approved firmware.")); } else { - g_print( - "%s\n", + fu_console_print_literal( + priv->console, /* TRANSLATORS: approved firmware has been checked by * the domain administrator */ ngettext("Approved firmware:", "Approved firmware:", g_strv_length(checksums))); for (guint i = 0; checksums[i] != NULL; i++) - g_print(" * %s\n", checksums[i]); + fu_console_print(priv->console, " * %s", checksums[i]); } return TRUE; } @@ -3154,10 +3200,11 @@ fu_util_modify_config(FuUtilPrivate *priv, gchar **values, GError **error) error)) return FALSE; if (!priv->assume_yes) { - g_print("%s [Y|n]: ", - /* TRANSLATORS: configuration changes only take effect on restart */ - _("Restart the daemon to make the change effective?")); - if (!fu_util_prompt_for_boolean(FALSE)) + if (!fu_console_input_bool(priv->console, + FALSE, + "%s", + /* TRANSLATORS: changes only take effect on restart */ + _("Restart the daemon to make the change effective?"))) return TRUE; } #ifdef HAVE_SYSTEMD @@ -3165,7 +3212,7 @@ fu_util_modify_config(FuUtilPrivate *priv, gchar **values, GError **error) return FALSE; #endif /* TRANSLATORS: success message -- a per-system setting value */ - g_print("%s\n", _("Successfully modified configuration value")); + fu_console_print_literal(priv->console, _("Successfully modified configuration value")); return TRUE; } @@ -3219,18 +3266,18 @@ fu_util_upload_security(FuUtilPrivate *priv, GPtrArray *attrs, GError **error) } if (!priv->assume_yes && !fwupd_remote_get_automatic_security_reports(remote)) { g_autofree gchar *tmp = NULL; - /* TRANSLATORS: ask the user to share, %s is something like: - * "Linux Vendor Firmware Service" */ - tmp = - g_strdup_printf("Upload these anonymous results to the %s to help other users?", - fwupd_remote_get_title(remote)); - - g_print("\n%s [y|N]: ", tmp); - if (!fu_util_prompt_for_boolean(FALSE)) { - g_print("%s [Y|n]: ", - /* TRANSLATORS: stop nagging the user */ - _("Ask again next time?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + if (!fu_console_input_bool(priv->console, + FALSE, + /* TRANSLATORS: ask the user to share, %s is something + * like: "Linux Vendor Firmware Service" */ + _("Upload these anonymous results to the %s to help " + "other users?"), + fwupd_remote_get_title(remote))) { + if (!fu_console_input_bool(priv->console, + TRUE, + "%s", + /* TRANSLATORS: stop nagging the user */ + _("Ask again next time?"))) { if (!fwupd_client_modify_remote(priv->client, fwupd_remote_get_id(remote), "SecurityReportURI", @@ -3308,12 +3355,13 @@ fu_util_upload_security(FuUtilPrivate *priv, GPtrArray *attrs, GError **error) /* ask for permission */ if (!priv->assume_yes && !fwupd_remote_get_automatic_security_reports(remote)) { - fu_util_print_data(_("Target"), fwupd_remote_get_security_report_uri(remote)); - fu_util_print_data(_("Payload"), data); + fu_console_print_kv(priv->console, + _("Target"), + fwupd_remote_get_security_report_uri(remote)); + fu_console_print_kv(priv->console, _("Payload"), data); if (sig != NULL) - fu_util_print_data(_("Signature"), sig); - g_print("%s [Y|n]: ", _("Proceed with upload?")); - if (!fu_util_prompt_for_boolean(TRUE)) { + fu_console_print_kv(priv->console, _("Signature"), sig); + if (!fu_console_input_bool(priv->console, TRUE, "%s", _("Proceed with upload?"))) { g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_PERMISSION_DENIED, @@ -3333,15 +3381,17 @@ fu_util_upload_security(FuUtilPrivate *priv, GPtrArray *attrs, GError **error) if (upload_response == NULL) return FALSE; - /* TRANSLATORS: success, so say thank you to the user */ - g_print("%s\n", "Host Security ID attributes uploaded successfully, thanks!"); + fu_console_print_literal(priv->console, + /* TRANSLATORS: success, so say thank you to the user */ + _("Host Security ID attributes uploaded successfully, thanks!")); /* as this worked, ask if the user want to do this every time */ if (!fwupd_remote_get_automatic_security_reports(remote)) { - g_print("%s [y|N]: ", - /* TRANSLATORS: can we JFDI? */ - _("Automatically upload every time?")); - if (fu_util_prompt_for_boolean(FALSE)) { + if (fu_console_input_bool(priv->console, + FALSE, + "%s", + /* TRANSLATORS: can we JFDI? */ + _("Automatically upload every time?"))) { if (!fwupd_client_modify_remote(priv->client, fwupd_remote_get_id(remote), "AutomaticSecurityReports", @@ -3413,7 +3463,7 @@ fu_util_security_as_json(FuUtilPrivate *priv, } json_builder_end_object(builder); - return fu_util_print_builder(builder, error); + return fu_util_print_builder(priv->console, builder, error); } static gboolean @@ -3488,7 +3538,7 @@ fu_util_sync_bkc(FuUtilPrivate *priv, gchar **values, GError **error) } /* show reboot if needed */ - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -3522,13 +3572,10 @@ fu_util_security_modify_bios_setting(FuUtilPrivate *priv, FwupdSecurityAttr *att _("You should ensure you are comfortable restoring the setting from " "the system firmware setup, as this change may cause the system " "to not boot into Linux or cause other system instability.")); - fu_util_warning_box(title->str, body->str, 80); + fu_console_box(priv->console, title->str, body->str, 80); - /* ask for confirmation */ - g_print("\n%s [y|N]: ", - /* TRANSLATORS: prompt to apply the update */ - _("Perform operation?")); - if (!fu_util_prompt_for_boolean(FALSE)) + /* TRANSLATORS: prompt to apply the update */ + if (!fu_console_input_bool(priv->console, FALSE, "%s", _("Perform operation?"))) return TRUE; g_hash_table_insert(bios_settings, g_strdup(fwupd_security_attr_get_bios_setting_id(attr)), @@ -3614,10 +3661,11 @@ fu_util_security(FuUtilPrivate *priv, gchar **values, GError **error) if (priv->as_json) return fu_util_security_as_json(priv, attrs, events, devices, error); - g_print("%s \033[1m%s\033[0m\n", - /* TRANSLATORS: this is a string like 'HSI:2-U' */ - _("Host Security ID:"), - fwupd_client_get_host_security_id(priv->client)); + fu_console_print(priv->console, + "%s \033[1m%s\033[0m", + /* TRANSLATORS: this is a string like 'HSI:2-U' */ + _("Host Security ID:"), + fwupd_client_get_host_security_id(priv->client)); /* show or hide different elements */ if (priv->show_all) { @@ -3625,20 +3673,20 @@ fu_util_security(FuUtilPrivate *priv, gchar **values, GError **error) flags |= FU_SECURITY_ATTR_TO_STRING_FLAG_SHOW_URLS; } str = fu_util_security_attrs_to_string(attrs, flags); - g_print("%s\n", str); + fu_console_print_literal(priv->console, str); /* events */ if (events != NULL && events->len > 0) { g_autofree gchar *estr = fu_util_security_events_to_string(events, flags); if (estr != NULL) - g_print("%s\n", estr); + fu_console_print_literal(priv->console, estr); } /* known CVEs */ if (devices != NULL && devices->len > 0) { g_autofree gchar *estr = fu_util_security_issues_to_string(devices); if (estr != NULL) - g_print("%s", estr); + fu_console_print_literal(priv->console, estr); } /* host emulation */ @@ -3672,7 +3720,7 @@ fu_util_security(FuUtilPrivate *priv, gchar **values, GError **error) /* reboot is required? */ if (!priv->no_reboot_check && (priv->completion_flags & FWUPD_DEVICE_FLAG_NEEDS_REBOOT) > 0) { - if (!fu_util_prompt_complete(priv->completion_flags, TRUE, error)) + if (!fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error)) return FALSE; } @@ -3720,7 +3768,7 @@ fu_util_private_free(FuUtilPrivate *priv) g_main_loop_unref(priv->loop); g_main_context_unref(priv->main_ctx); g_object_unref(priv->cancellable); - g_object_unref(priv->progressbar); + g_object_unref(priv->console); g_option_context_free(priv->context); g_free(priv); } @@ -3845,7 +3893,7 @@ fu_util_block_firmware(FuUtilPrivate *priv, gchar **values, GError **error) } /* TRANSLATORS: we will not offer this firmware to the user */ - g_print("%s %s\n", _("Blocking firmware:"), csum); + fu_console_print(priv->console, "%s %s", _("Blocking firmware:"), csum); /* remove it from the new list */ csums_new = g_new0(gchar *, g_strv_length(csums) + 2); @@ -3900,7 +3948,7 @@ fu_util_unblock_firmware(FuUtilPrivate *priv, gchar **values, GError **error) } /* TRANSLATORS: we will now offer this firmware to the user */ - g_print("%s %s\n", _("Unblocking firmware:"), csum); + fu_console_print(priv->console, "%s %s", _("Unblocking firmware:"), csum); /* remove it from the new list */ csums_new = g_new0(gchar *, g_strv_length(csums)); @@ -3926,14 +3974,14 @@ fu_util_get_blocked_firmware(FuUtilPrivate *priv, gchar **values, GError **error /* empty list */ if (g_strv_length(csums) == 0) { /* TRANSLATORS: nothing to show */ - g_print("%s\n", _("There are no blocked firmware files")); + fu_console_print_literal(priv->console, _("There are no blocked firmware files")); return TRUE; } /* TRANSLATORS: there follows a list of hashes */ - g_print("%s\n", _("Blocked firmware files:")); + fu_console_print_literal(priv->console, _("Blocked firmware files:")); for (guint i = 0; csums[i] != NULL; i++) { - g_print("%u.\t%s\n", i + 1, csums[i]); + fu_console_print(priv->console, "%u.\t%s", i + 1, csums[i]); } /* success */ @@ -3970,7 +4018,6 @@ fu_util_show_plugin_warnings(FuUtilPrivate *priv) for (guint i = 0; i < 64; i++) { FwupdPluginFlags flag = (guint64)1 << i; const gchar *tmp; - g_autofree gchar *fmt = NULL; g_autofree gchar *url = NULL; g_autoptr(GString) str = g_string_new(NULL); if ((flags & flag) == 0) @@ -3978,17 +4025,15 @@ fu_util_show_plugin_warnings(FuUtilPrivate *priv) tmp = fu_util_plugin_flag_to_string(flag); if (tmp == NULL) continue; - /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_RED); - g_string_append_printf(str, "%s %s\n", fmt, tmp); - + g_string_append_printf(str, "%s\n", tmp); url = g_strdup_printf("https://github.com/fwupd/fwupd/wiki/PluginFlag:%s", fwupd_plugin_flag_to_string(flag)); - g_string_append(str, " "); /* TRANSLATORS: %s is a link to a website */ g_string_append_printf(str, _("See %s for more information."), url); - g_string_append(str, "\n"); - g_printerr("%s", str->str); + fu_console_print_full(priv->console, + FU_CONSOLE_PRINT_FLAG_WARNING, + "%s\n", + str->str); } } @@ -4017,7 +4062,7 @@ fu_util_set_bios_setting(FuUtilPrivate *priv, gchar **input, GError **error) g_strdup_printf(_("Set BIOS setting '%s' using '%s'."), (const gchar *)key, (const gchar *)value); - g_print("\n%s\n", msg); + fu_console_print_literal(priv->console, msg); } } priv->completion_flags |= FWUPD_DEVICE_FLAG_NEEDS_REBOOT; @@ -4027,7 +4072,7 @@ fu_util_set_bios_setting(FuUtilPrivate *priv, gchar **input, GError **error) return TRUE; } - return fu_util_prompt_complete(priv->completion_flags, TRUE, error); + return fu_util_prompt_complete(priv->console, priv->completion_flags, TRUE, error); } static gboolean @@ -4040,13 +4085,13 @@ fu_util_get_bios_setting(FuUtilPrivate *priv, gchar **values, GError **error) if (attrs == NULL) return FALSE; if (priv->as_json) - return fu_util_get_bios_setting_as_json(values, attrs, error); + return fu_util_get_bios_setting_as_json(priv->console, values, attrs, error); for (guint i = 0; i < attrs->len; i++) { FwupdBiosSetting *attr = g_ptr_array_index(attrs, i); if (fu_util_bios_setting_matches_args(attr, values)) { g_autofree gchar *tmp = fu_util_bios_setting_to_string(attr, 0); - g_print("\n%s\n", tmp); + fu_console_print_literal(priv->console, tmp); found = TRUE; } } @@ -4157,9 +4202,9 @@ fu_util_version(FuUtilPrivate *priv, GError **error) /* dump to the screen in the most appropriate format */ if (priv->as_json) - return fu_util_project_versions_as_json(metadata, error); + return fu_util_project_versions_as_json(priv->console, metadata, error); str = fu_util_project_versions_to_string(metadata); - g_print("%s", str); + fu_console_print_literal(priv->console, str); return TRUE; } @@ -4170,7 +4215,7 @@ fu_util_setup_interactive(FuUtilPrivate *priv, GError **error) g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "using --json"); return FALSE; } - return fu_util_setup_interactive_console(error); + return fu_console_setup(priv->console, error); } static void @@ -4180,7 +4225,7 @@ fu_util_cancelled_cb(GCancellable *cancellable, gpointer user_data) if (!g_main_loop_is_running(priv->loop)) return; /* TRANSLATORS: this is from ctrl+c */ - g_print("%s\n", _("Cancelled")); + fu_console_print_literal(priv->console, _("Cancelled")); g_main_loop_quit(priv->loop); } @@ -4197,10 +4242,10 @@ static void fu_util_print_error(FuUtilPrivate *priv, const GError *error) { if (priv->as_json) { - fu_util_print_error_as_json(error); + fu_util_print_error_as_json(priv->console, error); return; } - g_printerr("%s\n", error->message); + fu_console_print_full(priv->console, FU_CONSOLE_PRINT_FLAG_STDERR, "%s\n", error->message); } int @@ -4438,9 +4483,9 @@ main(int argc, char *argv[]) /* create helper object */ priv->main_ctx = g_main_context_new(); priv->loop = g_main_loop_new(priv->main_ctx, FALSE); - priv->progressbar = fu_progressbar_new(); + priv->console = fu_console_new(); priv->post_requests = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref); - fu_progressbar_set_main_context(priv->progressbar, priv->main_ctx); + fu_console_set_main_context(priv->console, priv->main_ctx); /* add commands */ fu_util_cmd_array_add(cmd_array, @@ -4768,7 +4813,7 @@ main(int argc, char *argv[]) } else { is_interactive = TRUE; } - fu_progressbar_set_interactive(priv->progressbar, is_interactive); + fu_console_set_interactive(priv->console, is_interactive); /* get a list of the commands */ priv->context = g_option_context_new(NULL); @@ -4786,36 +4831,36 @@ main(int argc, char *argv[]) g_option_context_add_main_entries(priv->context, options, NULL); ret = g_option_context_parse(priv->context, &argc, &argv, &error); if (!ret) { - /* TRANSLATORS: the user didn't read the man page */ - g_print("%s: %s\n", _("Failed to parse arguments"), error->message); + fu_console_print(priv->console, + "%s: %s", + /* TRANSLATORS: the user didn't read the man page */ + _("Failed to parse arguments"), + error->message); return EXIT_FAILURE; } /* allow disabling SSL strict mode for broken corporate proxies */ if (priv->disable_ssl_strict) { - g_autofree gchar *fmt = NULL; - /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_RED); - g_printerr("%s %s\n", - fmt, - /* TRANSLATORS: try to help */ - _("Ignoring SSL strict checks, " - "to do this automatically in the future " - "export DISABLE_SSL_STRICT in your environment")); + fu_console_print_full(priv->console, + FU_CONSOLE_PRINT_FLAG_WARNING, + "%s\n", + /* TRANSLATORS: try to help */ + _("Ignoring SSL strict checks, " + "to do this automatically in the future " + "export DISABLE_SSL_STRICT in your environment")); (void)g_setenv("DISABLE_SSL_STRICT", "1", TRUE); } /* this doesn't have to be precise (e.g. using the build-year) as we just * want to check the clock is not set to the default of 1970-01-01... */ if (g_date_time_get_year(dt_now) < 2021) { - g_autofree gchar *fmt = NULL; - /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_RED); - g_printerr("%s %s\n", - fmt, - /* TRANSLATORS: try to help */ - _("The system clock has not been set " - "correctly and downloading files may fail.")); + fu_console_print_full( + priv->console, + FU_CONSOLE_PRINT_FLAG_WARNING, + "%s\n", + /* TRANSLATORS: try to help */ + _("The system clock has not been set correctly and downloading " + "files may fail.")); } /* parse filter flags */ @@ -4862,7 +4907,9 @@ main(int argc, char *argv[]) if (is_interactive) { g_autoptr(GError) error_polkit = NULL; if (!fu_polkit_agent_open(&error_polkit)) { - g_printerr("Failed to open polkit agent: %s\n", error_polkit->message); + fu_console_print(priv->console, + "Failed to open polkit agent: %s", + error_polkit->message); } } #endif @@ -4890,8 +4937,10 @@ main(int argc, char *argv[]) /* show a warning if the daemon is tainted */ if (!fwupd_client_connect(priv->client, priv->cancellable, &error)) { #ifdef _WIN32 - /* TRANSLATORS: error message for Windows */ - g_printerr(_("Failed to connect to Windows service, please ensure it's running.")); + fu_console_print_literal( + priv->console, + /* TRANSLATORS: error message for Windows */ + _("Failed to connect to Windows service, please ensure it's running.")); g_debug("%s", error->message); #else /* TRANSLATORS: could not contact the fwupd service over D-Bus */ @@ -4901,14 +4950,12 @@ main(int argc, char *argv[]) return EXIT_FAILURE; } if (fwupd_client_get_tainted(priv->client)) { - g_autofree gchar *fmt = NULL; - /* TRANSLATORS: this is a prefix on the console */ - fmt = fu_util_term_format(_("WARNING:"), FU_UTIL_TERM_COLOR_RED); - g_printerr("%s %s\n", - fmt, - /* TRANSLATORS: the user is SOL for support... */ - _("The daemon has loaded 3rd party code and " - "is no longer supported by the upstream developers!")); + fu_console_print_full(priv->console, + FU_CONSOLE_PRINT_FLAG_WARNING, + "%s\n", + /* TRANSLATORS: the user is SOL for support... */ + _("The daemon has loaded 3rd party code and " + "is no longer supported by the upstream developers!")); } /* just show versions and exit */ @@ -4924,7 +4971,7 @@ main(int argc, char *argv[]) fu_util_show_plugin_warnings(priv); /* show any unsupported warnings */ - fu_util_show_unsupported_warn(); + fu_util_show_unsupported_warning(priv->console); /* we know the runtime daemon version now */ fwupd_client_set_user_agent_for_package(priv->client, g_get_prgname(), PACKAGE_VERSION); @@ -4986,10 +5033,10 @@ main(int argc, char *argv[]) if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_ARGS)) { g_autofree gchar *cmd = g_strdup_printf("%s --help", g_get_prgname()); g_autoptr(GString) str = g_string_new("\n"); - /* TRANSLATORS: error message explaining command on how to get help, + /* TRANSLATORS: explain how to get help, * where $1 is something like 'fwupdmgr --help' */ g_string_append_printf(str, _("Use %s for help"), cmd); - g_printerr("%s\n", str->str); + fu_console_print_literal(priv->console, str->str); } else if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO)) return EXIT_NOTHING_TO_DO; return EXIT_FAILURE; diff --git a/src/meson.build b/src/meson.build index f3ca734ee..e97ee25d3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -80,7 +80,7 @@ endif fwupdutil = library( 'fwupdutil', sources: [ - 'fu-progressbar.c', + 'fu-console.c', 'fu-security-attr-common.c', 'fu-util-bios-setting.c', 'fu-util-common.c',