Show the shutdown sequence on the active virtual terminal
authorMichel Stam <m.stam@fugro.nl>
Mon, 13 Oct 2014 14:14:35 +0000 (16:14 +0200)
committerJohn Crispin <blogic@openwrt.org>
Sun, 12 Oct 2014 11:24:11 +0000 (13:24 +0200)
procd by default writes to /dev/console. When rebooting, this means that the
terminal on which the reboot sequence was started will not see what is going
on. This patch fixes that by reopening stdin, stdout and stderr to the console
device specified on the commandline, /dev/tty0 or /dev/console upon reboot.

Also, due to (probably) pivot-root, /proc/1/fd shows 1-3 pointing to
/console. This patch also fixes that.

Signed-off-by: Michel Stam <m.stam@fugro.nl>
state.c

diff --git a/state.c b/state.c
index 41e4471..7f0ec50 100644 (file)
--- a/state.c
+++ b/state.c
@@ -12,7 +12,9 @@
  * GNU General Public License for more details.
  */
 
+#include <fcntl.h>
 #include <sys/reboot.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -23,6 +25,7 @@
 #include "plug/hotplug.h"
 #include "watchdog.h"
 #include "service/service.h"
+#include "utils/utils.h"
 
 enum {
        STATE_NONE = 0,
@@ -38,6 +41,52 @@ enum {
 static int state = STATE_NONE;
 static int reboot_event;
 
+static void set_stdio(const char* tty)
+{
+       chdir("/dev");
+       freopen(tty, "r", stdin);
+       freopen(tty, "w", stdout);
+       freopen(tty, "w", stderr);
+       chdir("/");
+       fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK);
+}
+
+static void set_console(void)
+{
+       const char* tty;
+       char* split;
+       char line[ 20 ];
+       const char* try[] = { "tty0", "console", NULL }; /* Try the most common outputs */
+       int f, i = 0;
+
+       tty = get_cmdline_val("console",line,sizeof(line));
+       if (tty != NULL) {
+               split = strchr(tty, ',');
+               if ( split != NULL )
+                       *split = '\0';
+       } else {
+               // Try a default
+               tty=try[i];
+               i++;
+       }
+
+       chdir("/dev");
+       while (tty!=NULL) {
+               f = open(tty, O_RDONLY);
+               if (f >= 0) {
+                       close(f);
+                       break;
+               }
+
+               tty=try[i];
+               i++;
+       }
+       chdir("/");
+
+       if (tty != NULL)
+               set_stdio(tty);
+}
+
 static void state_enter(void)
 {
        char ubus_cmd[] = "/sbin/ubusd";
@@ -53,6 +102,7 @@ static void state_enter(void)
        case STATE_UBUS:
                // try to reopen incase the wdt was not available before coldplug
                watchdog_init(0);
+               set_stdio("console");
                LOG("- ubus -\n");
                procd_connect_ubus();
                service_init();
@@ -73,6 +123,8 @@ static void state_enter(void)
                break;
 
        case STATE_SHUTDOWN:
+               /* Redirect output to the console for the users' benefit */
+               set_console();
                LOG("- shutdown -\n");
                procd_inittab_run("shutdown");
                sync();