diff options
-rw-r--r-- | main.c | 19 | ||||
-rw-r--r-- | util.c | 28 | ||||
-rw-r--r-- | util.h | 2 |
3 files changed, 46 insertions, 3 deletions
@@ -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; @@ -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", @@ -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); |