From 82664396d6ebfe18c006ed9d55e72794ef147af1 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 8 Feb 2021 20:00:38 +0100 Subject: [PATCH] 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 --- configure.ac | 5 ----- src/conf.c | 3 --- src/finit.c | 5 +++++ src/helpers.c | 57 +++++++++++++++++++++++++++++++++++++++++++-------- src/helpers.h | 3 ++- src/service.c | 4 ++-- 6 files changed, 58 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 11f1ccb8..75724423 100644 --- a/configure.ac +++ b/configure.ac @@ -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])]) diff --git a/src/conf.c b/src/conf.c index 5ed26ab9..4d9c95dc 100644 --- a/src/conf.c +++ b/src/conf.c @@ -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[]) diff --git a/src/finit.c b/src/finit.c index 55e3ff26..1808ae6b 100644 --- a/src/finit.c +++ b/src/finit.c @@ -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. */ diff --git a/src/helpers.c b/src/helpers.c index 92c27fb7..15a6c3a0 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -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; diff --git a/src/helpers.h b/src/helpers.h index 68d6112e..da406985 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -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); diff --git a/src/service.c b/src/service.c index 6eba7a45..d8379f8e 100644 --- a/src/service.c +++ b/src/service.c @@ -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");