Skip to content

Commit

Permalink
Add commands for configuring systemd console-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
silkeh committed Jun 26, 2024
1 parent 8f4566f commit 24e6a66
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 34 deletions.
35 changes: 23 additions & 12 deletions src/bootloaders/systemd-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* This file is part of clr-boot-manager.
*
* Copyright © 2016-2018 Intel Corporation
* Copyright © 2024 Solus Project
*
* clr-boot-manager is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
Expand Down Expand Up @@ -374,6 +375,9 @@ bool sd_class_set_default_kernel(const BootManager *manager, const Kernel *kerne
}

autofree(char) *item_name = NULL;
autofree(char) *console_mode = NULL;
autofree(char) *timeout_s = NULL;
autofree(char) *console_mode_s = NULL;
int timeout = 0;
const char *prefix = NULL;
autofree(char) *old_conf = NULL;
Expand All @@ -392,23 +396,30 @@ bool sd_class_set_default_kernel(const BootManager *manager, const Kernel *kerne
}

timeout = boot_manager_get_timeout_value((BootManager *)manager);
console_mode = boot_manager_get_console_mode((BootManager *)manager);

/* Set the timeout as configured by the user */
if (timeout > 0) {
/* Set the timeout as configured by the user */
item_name = string_printf("timeout %d\ndefault %s-%s-%s-%d.conf\n",
timeout,
prefix,
kernel->meta.ktype,
kernel->meta.version,
kernel->meta.release);
timeout_s = string_printf("timeout %d\n", timeout);
} else {
item_name = string_printf("default %s-%s-%s-%d.conf\n",
prefix,
kernel->meta.ktype,
kernel->meta.version,
kernel->meta.release);
timeout_s = string_printf("");
}

/* Set the console mode as configured by the user */
if (console_mode != NULL) {
console_mode_s = string_printf("console-mode %s\n", console_mode);
} else {
console_mode_s = string_printf("");
}

item_name = string_printf("default %s-%s-%s-%d.conf\n%s%s",
prefix,
kernel->meta.ktype,
kernel->meta.version,
kernel->meta.release,
timeout_s,
console_mode_s);

write_config:
if (file_get_text(sd_class_config.loader_config, &old_conf)) {
if (streq(old_conf, item_name)) {
Expand Down
15 changes: 15 additions & 0 deletions src/bootman/bootman.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* This file is part of clr-boot-manager.
*
* Copyright © 2016-2018 Intel Corporation
* Copyright © 2024 Solus Project
*
* clr-boot-manager is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
Expand Down Expand Up @@ -344,6 +345,20 @@ bool boot_manager_is_update_efi_vars(BootManager *self);
*/
int boot_manager_get_timeout_value(BootManager *manager);

/**
* Determine the console mode based on the contents of
* SYSCONFDIR/console_mode
*/
char *boot_manager_get_console_mode(BootManager *manager);

/**
* Determine the console mode based on the contents of
* SYSCONFDIR/console_mode
*
* @param mode console mode for systemd-boot. See `man loader.conf` for valid values
*/
bool boot_manager_set_console_mode(BootManager *manager, const char *mode);

/**
* Determine the default kernel for the given type if it is in the set
* This does not create a new instance, simply a pointer to the existing
Expand Down
79 changes: 59 additions & 20 deletions src/bootman/timeout.c → src/bootman/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* This file is part of clr-boot-manager.
*
* Copyright © 2016-2018 Intel Corporation
* Copyright © 2024 Solus Project
*
* clr-boot-manager is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
Expand All @@ -11,6 +12,7 @@

#define _GNU_SOURCE

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
Expand All @@ -21,26 +23,25 @@
#include "log.h"
#include "nica/files.h"

bool boot_manager_set_timeout_value(BootManager *self, int timeout)
static bool write_sysconf_file(BootManager *self, const char *filename, const char *contents)
{
assert(self != NULL);
assert(self->sysconfig != NULL);

autofree(FILE) *fp = NULL;
autofree(char) *path = NULL;
autofree(char) *dir = NULL;

if (!self || !self->sysconfig) {
return false;
}

dir = string_printf("%s%s", self->sysconfig->prefix, KERNEL_CONF_DIRECTORY);

if (!nc_mkdir_p(dir, 00755)) {
LOG_ERROR("Failed to create directory %s: %s", dir, strerror(errno));
return false;
}

path = string_printf("%s%s/timeout", self->sysconfig->prefix, KERNEL_CONF_DIRECTORY);
path = string_printf("%s%s/%s", self->sysconfig->prefix, KERNEL_CONF_DIRECTORY, filename);

if (timeout <= 0) {
if (contents == NULL) {
/* Nothing to be done here. */
if (!nc_file_exists(path)) {
return true;
Expand All @@ -58,42 +59,80 @@ bool boot_manager_set_timeout_value(BootManager *self, int timeout)
return false;
}

if (fprintf(fp, "%d\n", timeout) < 0) {
if (fprintf(fp, "%s\n", contents) < 0) {
LOG_FATAL("Unable to set new timeout: %s", strerror(errno));
return false;
}
return true;
}

int boot_manager_get_timeout_value(BootManager *self)
bool boot_manager_set_timeout_value(BootManager *self, int timeout)
{
autofree(FILE) *fp = NULL;
autofree(char) *path = NULL;
int t_val;

if (!self || !self->sysconfig) {
return false;
if (timeout <= 0) {
return write_sysconf_file(self, "timeout", NULL);
}

path = string_printf("%s%s/timeout", self->sysconfig->prefix, KERNEL_CONF_DIRECTORY);
autofree(char) *timeout_s = string_printf("%d", timeout);

return write_sysconf_file(self, "timeout", timeout_s);
}

/* Default timeout being -1, i.e. don't use one */
bool boot_manager_set_console_mode(BootManager *self, const char *mode)
{
return write_sysconf_file(self, "console_mode", mode);
}

static char *read_sysconf_value(BootManager *self, const char *filename)
{
assert(self != NULL);
assert(self->sysconfig != NULL);

autofree(FILE) *fp = NULL;
autofree(char) *path = NULL;
autofree(char) *line = NULL;
size_t size = 0;

path = string_printf("%s%s/%s", self->sysconfig->prefix, KERNEL_CONF_DIRECTORY, filename);
if (!nc_file_exists(path)) {
return -1;
return NULL;
}

fp = fopen(path, "r");
if (!fp) {
LOG_FATAL("Unable to open %s for reading: %s", path, strerror(errno));
return NULL;
}

__ssize_t n = getline(&line, &size, fp);
if (n < 0) {
LOG_ERROR("Failed to parse config file %s, using defaults", path);
return NULL;
}

line[strcspn(line, "\n")] = '\0';

return strndup(line, (size_t)n);
}

int boot_manager_get_timeout_value(BootManager *self)
{
autofree(char) *value = read_sysconf_value(self, "timeout");
if (value == NULL) {
return -1;
}

if (fscanf(fp, "%d\n", &t_val) != 1) {
int timeout = atoi(value);
if (timeout <= 0) {
LOG_ERROR("Failed to parse config file, defaulting to no timeout");
return -1;
}

return t_val;
return timeout;
}

char *boot_manager_get_console_mode(BootManager *self)
{
return read_sysconf_value(self, "console_mode");
}

/*
Expand Down
46 changes: 45 additions & 1 deletion src/cli/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* This file is part of clr-boot-manager.
*
* Copyright © 2016-2018 Intel Corporation
* Copyright © 2024 Solus Project
*
* clr-boot-manager is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
Expand All @@ -20,6 +21,7 @@

#include "ops/report_booted.h"
#include "ops/timeout.h"
#include "ops/console_mode.h"
#include "ops/update.h"
#include "ops/kernels.h"
#include "ops/mount.h"
Expand All @@ -29,6 +31,8 @@ static SubCommand cmd_help;
static SubCommand cmd_version;
static SubCommand cmd_set_timeout;
static SubCommand cmd_get_timeout;
static SubCommand cmd_set_console_mode;
static SubCommand cmd_get_console_mode;
static SubCommand cmd_report_booted;
static SubCommand cmd_list_kernels;
static SubCommand cmd_set_kernel;
Expand Down Expand Up @@ -71,7 +75,7 @@ static bool print_usage(int argc, char **argv)

nc_hashmap_iter_init(g_commands, &iter);
while (nc_hashmap_iter_next(&iter, (void **)&id, (void **)&command)) {
fprintf(stdout, "%15s - %s\n", id, command->blurb);
fprintf(stdout, "%16s - %s\n", id, command->blurb);
}

cli_print_default_args_help();
Expand Down Expand Up @@ -168,6 +172,46 @@ to forcibly delay the system boot for a specified number of seconds.",
return EXIT_FAILURE;
}

/* Set the console mode */
cmd_set_console_mode = (SubCommand){
.name = "set-console-mode",
.blurb = "Set the console mode to be used by the bootloader",
.help = "Set the default console mode to be used by" PACKAGE_NAME
" when using\n\
the \"update\" command.\n\
This value will be used when next configuring the bootloader, and is used\n\
to configure the console mode.\n\
See `console-mode` in `man loader.conf` for possible values.",
.callback = cbm_command_set_console_mode,
.usage = " [--path=/path/to/filesystem/root]",
.requires_root = true,
};

if (!nc_hashmap_put(commands, cmd_set_console_mode.name, &cmd_set_console_mode)) {
DECLARE_OOM();
return EXIT_FAILURE;
}

/* Get the console mode */
cmd_get_console_mode = (SubCommand){
.name = "get-console-mode",
.blurb = "Get the console mode to be used by the bootloader",
.help = "Get the default console mode to be used by" PACKAGE_NAME
" when using\n\
the \"update\" command.\n\
This value will be used when next configuring the bootloader, and is used\n\
to configure the console mode.\n\
See `console-mode` in `man loader.conf` for possible values.",
.callback = cbm_command_get_console_mode,
.usage = " [--path=/path/to/filesystem/root]",
.requires_root = true,
};

if (!nc_hashmap_put(commands, cmd_get_console_mode.name, &cmd_get_console_mode)) {
DECLARE_OOM();
return EXIT_FAILURE;
}

/* Report the system as successfully booted */
cmd_report_booted =
(SubCommand){.name = "report-booted",
Expand Down
Loading

0 comments on commit 24e6a66

Please sign in to comment.