chiark / gitweb /
main: switch to primary console vt on crash
authorLennart Poettering <lennart@poettering.net>
Sat, 10 Apr 2010 21:36:43 +0000 (23:36 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 10 Apr 2010 21:36:43 +0000 (23:36 +0200)
main.c
util.c
util.h

diff --git a/main.c b/main.c
index 5f0aeba85752c09293120fccd3e2da72f41f9322..68a90210839f127748f29d465d35966cf7d79185 100644 (file)
--- a/main.c
+++ b/main.c
@@ -48,7 +48,8 @@ static char *default_unit = NULL;
 static ManagerRunningAs running_as = _MANAGER_RUNNING_AS_INVALID;
 
 static bool dump_core = true;
-static bool crash_shell = true;
+static bool crash_shell = false;
+static int crash_chvt = -1;
 
 _noreturn static void freeze(void) {
         for (;;)
@@ -102,6 +103,9 @@ _noreturn static void crash(int sig) {
                 }
         }
 
+        if (crash_chvt)
+                chvt(crash_chvt);
+
         if (crash_shell) {
                 log_info("Executing crash shell in 10s...");
                 sleep(10);
@@ -170,7 +174,7 @@ static int parse_proc_cmdline_word(const char *word) {
                 int r;
 
                 if ((r = parse_boolean(word + 18)) < 0)
-                        log_warning("Failed to parse dump core switch %s, Ignoring", word + 18);
+                        log_warning("Failed to parse dump core switch %s, Ignoring.", word + 18);
                 else
                         dump_core = r;
 
@@ -178,10 +182,18 @@ static int parse_proc_cmdline_word(const char *word) {
                 int r;
 
                 if ((r = parse_boolean(word + 20)) < 0)
-                        log_warning("Failed to parse crash shell switch %s, Ignoring", word + 20);
+                        log_warning("Failed to parse crash shell switch %s, Ignoring.", word + 20);
                 else
                         crash_shell = r;
 
+        } else if (startswith(word, "systemd.crash_chvt=")) {
+                int k;
+
+                if (safe_atoi(word + 19, &k) < 0)
+                        log_warning("Failed to parse crash chvt switch %s, Ignoring.", word + 19);
+                else
+                        crash_chvt = k;
+
         } else if (startswith(word, "systemd.")) {
 
                 log_warning("Unknown kernel switch %s. Ignoring.", word);
@@ -192,6 +204,7 @@ static int parse_proc_cmdline_word(const char *word) {
                 log_info("systemd.log_level=LEVEL                  Log level");
                 log_info("systemd.dump_core=0|1                    Dump core on crash");
                 log_info("systemd.crash_shell=0|1                  On crash run shell");
+                log_info("systemd.crash_chvt=N                     Change to VT #N on crash");
 
         } else {
                 unsigned i;
diff --git a/util.c b/util.c
index f3161bd7f3e888b4a4b34e8ded2b1a4fde652f13..f9eae6bba1e8818b7d56c8174664f33626975c7c 100644 (file)
--- a/util.c
+++ b/util.c
@@ -34,6 +34,9 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
+#include <sys/ioctl.h>
+#include <linux/vt.h>
+#include <linux/tiocl.h>
 
 #include "macro.h"
 #include "util.h"
@@ -1294,6 +1297,31 @@ bool fstype_is_network(const char *fstype) {
         return false;
 }
 
+int chvt(int vt) {
+        int fd, r = 0;
+
+        if ((fd = open("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
+                return -errno;
+
+        if (vt < 0) {
+                int tiocl[2] = {
+                        TIOCL_GETKMSGREDIRECT,
+                        0
+                };
+
+                if (ioctl(fd, TIOCLINUX, tiocl) < 0)
+                        return -errno;
+
+                vt = tiocl[0] <= 0 ? 1 : tiocl[0];
+        }
+
+        if (ioctl(fd, VT_ACTIVATE, vt) < 0)
+                r = -errno;
+
+        close_nointr(r);
+        return r;
+}
+
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
diff --git a/util.h b/util.h
index a716d8a57eaa4e69d720d95afd276b856d2b81b8..ba27b5aae01b55cddd4073b6ef112bd308db6ca0 100644 (file)
--- a/util.h
+++ b/util.h
@@ -198,6 +198,8 @@ int close_all_fds(const int except[], unsigned n_except);
 
 bool fstype_is_network(const char *fstype);
 
+int chvt(int vt);
+
 extern char * __progname;
 
 const char *ioprio_class_to_string(int i);