userui: new option to change VT

Julien Muchembled <[email protected]> Sun, 02 Feb 2014 16:42:56 +0100
Newsgroups gmane.linux.swsusp.devel
Message-ID <[email protected]>
Hello Nigel,

What do you think about the attached patch for tuxonice-userui ?

For example on Debian:
- nothing is done to change VT when hibernation is handled by systemd
- I submitted a patch to pm-utils but it looks like http://bugs.debian.org/732948 will be ignored forever
- I don't know the status of other PM solutions to hibernate

So I think it's safer and simpler to do this inside tuxonice-userui itself.

I used this patch without any issue for more than one month. I recently stopped using pm-utils, in favor of systemd.
I've just noticed that I didn't touch fbsplash_unprepare, but it's probably better to do nothing if the VT will be trashed at exit, so that the user does not see a black screen for a fraction of second.

Apart from that, I am currently adopting packaging of tuxonice-userui on Debian:
http://bugs.debian.org/719529

Regard,
Julien

_______________________________________________
TuxOnIce-devel mailing list
[email protected]
http://lists.tuxonice.net/listinfo/tuxonice-devel
0001-New-option-to-change-VT.patch (text/x-diff, 8 KB)
From d6b9b3a7c069ad6c9b4a8e88ef9901fefc8fafdb Mon Sep 17 00:00:00 2001
From: Julien Muchembled <[email protected]>
Date: Mon, 23 Dec 2013 06:30:06 +0100
Subject: [PATCH] New option to change VT

TOI UI needs its own VT and without such option, it would be required
to work around this in every power management hibernation.
---
 debian/pm-utils.hook            |  2 +-
 fbsplash/cmd.c                  | 11 ++++----
 fbsplash/common.c               |  1 -
 fbsplash/splash.h               |  1 -
 fbsplash/userui_fbsplash_core.c | 22 ----------------
 userui.h                        |  1 +
 userui_core.c                   | 56 +++++++++++++++++++++++++++++++++++++----
 userui_text.c                   |  2 --
 8 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/debian/pm-utils.hook b/debian/pm-utils.hook
index 3de0b24..045cf22 100644
--- a/debian/pm-utils.hook
+++ b/debian/pm-utils.hook
@@ -11,7 +11,7 @@ SYSFS_PATH="/sys/power/tuxonice/user_interface/program"
 
 case $1 in
     hibernate)
-        echo "$TUXONICE_USERUI_PROGRAM" > $SYSFS_PATH
+        echo "$TUXONICE_USERUI_PROGRAM -v63" > $SYSFS_PATH
         ;;
     *) exit $NA
         ;;
diff --git a/fbsplash/cmd.c b/fbsplash/cmd.c
index 2672d69..0a418df 100644
--- a/fbsplash/cmd.c
+++ b/fbsplash/cmd.c
@@ -25,6 +25,7 @@
 #include <errno.h>
 #include <linux/fb.h>
 #include "splash.h"
+#include "../userui.h"
 
 #ifdef CONFIG_FBSPLASH
 #include <linux/console_splash.h>
@@ -32,7 +33,7 @@
 void cmd_setstate(unsigned int state, unsigned char origin)
 {
 	struct fb_splash_iowrapper wrapper = {
-		.vc = arg_vc,
+		.vc = suspend_vt,
 		.origin = origin,
 		.data = &state,
 	};
@@ -46,7 +47,7 @@ void cmd_setstate(unsigned int state, unsigned char origin)
 void cmd_setpic(struct fb_image *img, unsigned char origin)
 {
 	struct fb_splash_iowrapper wrapper = {
-		.vc = arg_vc,
+		.vc = suspend_vt,
 		.origin = origin,
 		.data = img,
 	};
@@ -60,7 +61,7 @@ void cmd_setcfg(unsigned char origin)
 {
 	struct vc_splash vc_cfg;
 	struct fb_splash_iowrapper wrapper = {
-		.vc = arg_vc,
+		.vc = suspend_vt,
 		.origin = origin,
 		.data = &vc_cfg,
 	};
@@ -82,7 +83,7 @@ void cmd_getcfg()
 {
 	struct vc_splash vc_cfg;
 	struct fb_splash_iowrapper wrapper = {
-		.vc = arg_vc,
+		.vc = suspend_vt,
 		.origin = FB_SPLASH_IO_ORIG_USER,
 		.data = &vc_cfg,
 	};
@@ -97,7 +98,7 @@ void cmd_getcfg()
 		strcpy(vc_cfg.theme, "<none>");
 	} 
 		
-	printf("Splash config on console %d:\n", arg_vc);
+	printf("Splash config on console %d:\n", suspend_vt);
 	printf("tx:       %d\n", vc_cfg.tx);
 	printf("ty:	  %d\n", vc_cfg.ty);
 	printf("twidth:	  %d\n", vc_cfg.twidth);
diff --git a/fbsplash/common.c b/fbsplash/common.c
index 4450192..f0dd1d6 100644
--- a/fbsplash/common.c
+++ b/fbsplash/common.c
@@ -38,7 +38,6 @@ char *config_file = NULL;
 
 enum TASK arg_task = none; 
 int arg_fb = 0;
-int arg_vc = 0;
 char arg_mode = 'v';
 char *arg_theme = NULL;
 u16 arg_progress = 0;
diff --git a/fbsplash/splash.h b/fbsplash/splash.h
index 4b37ff1..bd0d100 100644
--- a/fbsplash/splash.h
+++ b/fbsplash/splash.h
@@ -265,7 +265,6 @@ extern struct fb_fix_screeninfo   fb_fix;
 extern enum ENDIANESS endianess;
 extern enum TASK arg_task;
 extern int arg_fb;
-extern int arg_vc;
 extern char *arg_theme;
 extern char arg_mode;
 extern u16 arg_progress;
diff --git a/fbsplash/userui_fbsplash_core.c b/fbsplash/userui_fbsplash_core.c
index d1ff32d..e294a77 100644
--- a/fbsplash/userui_fbsplash_core.c
+++ b/fbsplash/userui_fbsplash_core.c
@@ -68,27 +68,6 @@ static void silent_off() {
 	show_cursor();
 }
 
-static int get_active_vt() {
-	int vt, fd;
-	struct vt_stat vt_stat;
-
-	vt = 62; /* default */
-
-	if ((fd = open("/dev/tty0", O_RDONLY)) == -1)
-		goto out;
-
-	if (ioctl(fd, VT_GETSTATE, &vt_stat) == -1)
-		goto out;
-
-	vt = vt_stat.v_active - 1;
-
-out:
-	if (fd >= 0)
-		close(fd);
-
-	return vt;
-}
-
 static int fbsplash_load() {
 	fb_fd = -1;
 	last_pos = 0;
@@ -104,7 +83,6 @@ static int fbsplash_load() {
 		return 1;
 	}
 
-	arg_vc = get_active_vt();
 	arg_mode = 's';
 
 	/* Read theme config file */
diff --git a/userui.h b/userui.h
index ca59826..920f704 100644
--- a/userui.h
+++ b/userui.h
@@ -53,6 +53,7 @@ void printk(char *msg, ...);
 
 extern char software_suspend_version[32];
 extern int can_use_escape;
+extern int suspend_vt;
 extern volatile __uint32_t console_loglevel;
 extern volatile __uint32_t suspend_action;
 extern volatile __uint32_t suspend_debug;
diff --git a/userui_core.c b/userui_core.c
index 74d7aa6..5e3f713 100644
--- a/userui_core.c
+++ b/userui_core.c
@@ -96,6 +96,8 @@ static void might_switch_ops(void)
 }
 
 static int netlink_socket_num = 0;
+static int saved_vt = 0;
+int suspend_vt = 0;
 
 static char* descriptions[] = {
 	"General",
@@ -373,7 +375,7 @@ int common_keypress_handler(int key)
 }
 
 static void handle_params(int argc, char **argv) {
-	static char global_optstring[] = "htc:fu";
+	static char global_optstring[] = "htc:fuv:";
 	static struct option global_longopts[] = {
 		{"help", 0, 0, 'h'},
 		{"test", 0, 0, 't'},
@@ -382,6 +384,7 @@ static void handle_params(int argc, char **argv) {
 #ifdef USE_USPLASH
 		{"usplash", 0, 0, 'u'},
 #endif
+		{"chvt", 1, 0, 'v'},
 		{NULL, 0, 0, 0},
 	};
 
@@ -437,6 +440,9 @@ static void handle_params(int argc, char **argv) {
 			case 't':
 				test_run++;
 				break;
+			case 'v':
+				suspend_vt = atoi(optarg);
+				break;
 			case 'h':
 				fprintf(stderr,
 "Usage: %s [options]\n"
@@ -445,6 +451,9 @@ static void handle_params(int argc, char **argv) {
 "     Specifying -t once will give an demo of this module.\n"
 "     Specifying -t twice will make the demo run as fast as it can.\n"
 "     (useful for performance testing).\n"
+"  -v, --chvt=N\n"
+"     Makes /dev/ttyN the foreground terminal before doing anything else\n"
+"     and restore previous VT at the end.\n"
 #ifdef USE_USPLASH
 "  -u\n"
 "     Use usersplash interface by default.\n"
@@ -603,6 +612,27 @@ static void enforce_lifesavers() {
 	setrlimit(RLIMIT_CORE, &r);
 }
 
+static int chvt(int vt) {
+	return ioctl(console_fd, VT_ACTIVATE, vt)
+	    || ioctl(console_fd, VT_WAITACTIVE, vt)
+	    || close(console_fd)
+	    || (console_fd = open("/dev/console", O_RDWR)) == -1;
+}
+
+static void restore_vt() {
+	struct rlimit r;
+	r.rlim_cur = r.rlim_max = console_fd + 1;
+	setrlimit(RLIMIT_NOFILE, &r);
+	close(STDOUT_FILENO);
+	close(STDERR_FILENO);
+	/* It does not matter whether other files are still opened or not.
+	 * RLIMIT_NOFILE only prevents files from being opened with a fd greater
+	 * or equal than the limit. chvt should reopen console with fd=0
+	 */
+	chvt(saved_vt);
+	ioctl(console_fd, VT_DISALLOCATE, suspend_vt);
+}
+
 static void restore_console() {
 	int result;
 	ioctl(console_fd, KDSKBMODE, K_XLATE);
@@ -726,14 +756,30 @@ static void setup_signal_handlers() {
 }
 
 static void open_console() {
+	struct vt_stat vtstat;
+
 	if ((console_fd = open("/dev/console", O_RDWR)) == -1)
 		bail_err("open(\"/dev/console\", O_RDWR)");
 
-	if (dup2(console_fd, STDIN_FILENO) == -1)
-		bail_err("dup2(fd, STDIN_FILENO)");
-	if (!test_run && dup2(console_fd, STDOUT_FILENO) == -1)
+	if (ioctl(console_fd, VT_GETSTATE, &vtstat))
+		bail_err("VT_GETSTATE");
+	if (!suspend_vt)
+		suspend_vt = vtstat.v_active;
+	else if (suspend_vt != vtstat.v_active) {
+		if (chvt(suspend_vt))
+			bail_err("failed to change VT");
+		saved_vt = vtstat.v_active;
+		atexit(restore_vt);
+	}
+
+	if (console_fd != STDIN_FILENO) {
+		if (dup2(console_fd, STDIN_FILENO) == -1 || close(console_fd))
+			bail_err("dup2(fd, STDIN_FILENO)");
+		console_fd = STDIN_FILENO;
+	}
+	if (dup2(console_fd, STDOUT_FILENO) == -1)
 		bail_err("dup2(fd, STDOUT_FILENO)");
-	if (!test_run && dup2(console_fd, STDERR_FILENO) == -1)
+	if (dup2(console_fd, STDERR_FILENO) == -1)
 		bail_err("dup2(fd, STDERR_FILENO)");
 }
 
diff --git a/userui_text.c b/userui_text.c
index 0b9ff2a..5502f4b 100644
--- a/userui_text.c
+++ b/userui_text.c
@@ -362,8 +362,6 @@ static void text_cleanup()
 		close(vcsa_fd);
 
 	ioctl(STDOUT_FILENO, TCSETSF, (long)&termios);
-
-	/* chvt back? */
 }
 
 static void text_redraw()
-- 
1.8.5.2.988.g9b015e5.dirty
signature.asc (application/pgp-signature, 836 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iQIcBAEBCAAGBQJS7meFAAoJEEwjvlkacWMkZYAP/RMvPdJAnHDBuRZTEcEvpjjL
/qtFFVZFjp5h6Av1x2NkSZT09FIxD8hnHOl89sa8x6c+roes3uLenyD4DE5xu7qB
3DNtICiTF5OKeyES3ZKzE0hW+4iFdgXt/qGV+/ExNSOpV7IZwxy3sd2GmfH1LiU7
mHaEH7fCwB1Mviu4/gLYLNwQKPYJSb/65pZl3U1GbmJH5w8+o9Y6/PPpLfvfwTK2
usbCGKBDWGyZZ8iEPG0Fo59/W8imWpkHYFgGg1En4Wv9VZX9y4EcIpppK/E4Sves
qe+L1IR6R/ZReYjykWUxy+JVa8aw0coYS02g0EOzVwqCWGcMiQ+kxKcXZK4cDU9G
u4Iyq8KiKFB1YPnxFpUUShH8+p2gpKsHOmN2nLZLAK4DtfEHo06ej5H3Bql02XY/
E2dQahSOGkv09dv2ttEBsMqKemsSgnhMKB0Fxukcd5Wq+AG83ZtpjFe7QOxV4NFx
EPKtHuQaspWTtboXWXl5UZtDA6F6W/smLAD3561rPp3vVbwpdn6+r1gzlUmZv93b
2r4d7hsjdf/UhrnAJtw96JXxXh3OFXTfNRsLbIUGLY560PYDXHhCbXYnW3go4+AI
SHxEs60goIMhVPEyzKowJjxQdiVU60CI9qqfGfHktC8xp+6E/xMcNbznFJeIEdzY
QEtRnuTL5BQ018eFATwr
=MwBS
-----END PGP SIGNATURE-----