Refactor 3e8d63c: use consoles from /sys/class/tty/console/active

As documented in the kernel docs and systemd[1], the default system
console is the first listed in /sys/class/tty/console/active, which
is the reverse order of console= given on the kernel cmdline.

Some distros don't have console= on their default command line in
their bootloader, e.g. Alpine Linux, some multiple, e.g Buildroot.
Instead of relying on the value given at configure time we probe
sysfs and open all (at most three) consoles listed.  This way we
at least get the default console for our progress output.

- drop old --with-console from configure script
- drop /proc/cmdline fishing in favor of sysfs
- replace CONSOLE from configure with new console()

[1]: http://0pointer.de/blog/projects/serial-console.html

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2021-02-08 20:09:49 +01:00
parent 3fb700c17d
commit 82664396d6
6 changed files with 58 additions and 19 deletions
-5
View File
@@ -218,11 +218,6 @@ AS_IF([test "x$with_heading" != "xno"], [
heading="$PACKAGE_NAME v$PACKAGE_VERSION"])])
AC_DEFINE_UNQUOTED(INIT_HEADING, "$heading", [Displayed by Finit at boot])
AS_IF([test "x$with_console" != "xno"], [
AS_IF([test "x$console" = "xyes"], [
console=/dev/console])])
AC_DEFINE_UNQUOTED(CONSOLE, "$console", [Default console to use])
AS_IF([test "x$with_hostname" != "xno"], [
AS_IF([test "x$hostname" = "xyes"], [
hostname=noname])])
-3
View File
@@ -89,9 +89,6 @@ static void parse_arg(char *arg, int *dbg)
if (string_compare(arg, "splash"))
splash = 1;
if (string_match(arg, "console="))
add_console(arg);
}
void conf_parse_cmdline(int argc, char *argv[])
+5
View File
@@ -386,6 +386,11 @@ int main(int argc, char *argv[])
*/
conf_parse_cmdline(argc, argv);
/*
* Figure out system console(s)
*/
console_init();
/*
* Initalize event context.
*/
+49 -8
View File
@@ -69,43 +69,84 @@ static const char *color[] = STATUS_CLASS;
/*
* System consoles, can be given multiple times on the kernel cmdline.
* We support only three currently.
* We support only three currently. If none are given on the cmdline
* we probe /sys/class/tty/console/active and use the first (default).
*/
#define MAX_CONS 3
static char *consoles[MAX_CONS];
static int fds[MAX_CONS];
static int num_cons = 0;
/*
* System default console is always the first
*/
char *console(void)
{
return consoles[0];
}
void add_console(char *str)
static void add_console(char *cons)
{
char *cons, *ptr;
char path[80];
char *ptr;
int i;
if (num_cons == NELEMS(fds)) {
_e("too many consoles, max %d supported", NELEMS(fds));
return;
}
cons = strchr(str, '=');
if (!cons)
return;
cons++;
/* drop any options */
ptr = strchr(cons, ',');
if (ptr)
*ptr = 0;
snprintf(path, sizeof(path), "/dev/%s", cons);
/* check for and skip duplicates */
for (i = 0; i < num_cons; i++) {
if (string_compare(path, consoles[i]))
return;
}
/* this requires we have /dev mounted && a device there */
fds[num_cons] = open(path, O_WRONLY);
if (fds[num_cons] < 0) {
_pe("Failed opening console %s", path);
return;
}
consoles[num_cons] = strdup(path);
num_cons++;
}
void console_init(void)
{
char *cons, *ptr, *tok;
char buf[512];
FILE *fp;
fp = fopen("/sys/class/tty/console/active", "r");
if (!fp) {
fallback:
_d("Using fallback /dev/console");
add_console("/dev/console");
return;
}
ptr = fgets(buf, sizeof(buf), fp);
fclose(fp);
if (!ptr)
goto fallback;
cons = chomp(ptr);
_d("Using these system consoles: %s", cons);
while ((tok = strtok(cons, " \t"))) {
cons = NULL;
add_console(tok);
}
}
ssize_t cprintf(const char *fmt, ...)
{
const size_t len = strlen(fmt) * 2;
+2 -1
View File
@@ -50,7 +50,8 @@ void endfsent (void);
struct fstab *getfsent (void);
#endif /* HAVE_GETFSENT */
void add_console (char *str);
char *console (void);
void console_init (void);
ssize_t cprintf (const char *fmt, ...);
char *strip_line (char *line);
+2 -2
View File
@@ -265,11 +265,11 @@ static int redirect(svc_t *svc)
if (svc->log.null)
return fredirect("/dev/null");
if (svc->log.console)
return fredirect(CONSOLE);
return fredirect(console());
return lredirect(svc);
} else if (log_is_debug())
return fredirect(CONSOLE);
return fredirect(console());
#ifdef REDIRECT_OUTPUT
else
return fredirect("/dev/null");