Linux console tools development discussion
 help / color / mirror / Atom feed
* [kbd] [PATCH] kbd_mode: Add -f option and deny dangerous mode switches without it
@ 2019-04-23 15:38 Balint Reczey
  2019-05-08  9:19 ` Alexey Gladkov
  0 siblings, 1 reply; 4+ messages in thread
From: Balint Reczey @ 2019-04-23 15:38 UTC (permalink / raw)
  To: kbd

kbd_mode(1) already had a warning but kbd_mode still performed all
mode changes even when they made keyboards unusable.

The added flag let's the callers try safe changes or force the risky
ones. This change may break scripts but the broken scripts most likely
made the keyboard unusable and should be updated.

Original bug report at:
https://bugs.launchpad.net/ubuntu/+source/kbd/+bug/520546

Signed-off-by: Balint Reczey <balint.reczey@canonical.com>
---
 docs/man/man1/kbd_mode.1 |  8 +++--
 src/kbd_mode.c           | 65 ++++++++++++++++++++++++++++------------
 2 files changed, 52 insertions(+), 21 deletions(-)

diff --git a/docs/man/man1/kbd_mode.1 b/docs/man/man1/kbd_mode.1
index 960b36c..f605c02 100644
--- a/docs/man/man1/kbd_mode.1
+++ b/docs/man/man1/kbd_mode.1
@@ -7,6 +7,8 @@ kbd_mode \- report or set the keyboard mode
 [
 .I -a | -u | -k | -s 
 ] [
+.I -f
+] [
 .I -C CONSOLE
 ]
 .SH DESCRIPTION
@@ -36,11 +38,13 @@ kbd_mode operates on the console specified by the "\-C" option; if there
 is none, the console associated with stdin is used.
 
 Warning: changing the keyboard mode, other than between ASCII and
-Unicode, will probably make your keyboard unusable.
+Unicode, will probably make your keyboard unusable. Set the "\-f" option
+to force such changes.
 This command is only meant for use (say via remote login)
 when some program left your keyboard in the wrong state.
 Note that in some obsolete versions of this program the "\-u"
-option was a synonym for "\-s".
+option was a synonym for "\-s" and older versions of this program may
+not recognize the "\-f" option.
 .SH "SEE ALSO"
 .BR loadkeys (1)
 
diff --git a/src/kbd_mode.c b/src/kbd_mode.c
index 5d291b7..956ea51 100644
--- a/src/kbd_mode.c
+++ b/src/kbd_mode.c
@@ -20,13 +20,34 @@
 static void __attribute__((noreturn))
 usage(void)
 {
-	fprintf(stderr, _("usage: kbd_mode [-a|-u|-k|-s] [-C device]\n"));
+	fprintf(stderr, _("usage: kbd_mode [-a|-u|-k|-s] [-f] [-C device]\n"));
 	exit(EXIT_FAILURE);
 }
 
+static void
+fprint_mode(FILE *stream, int  mode)
+{
+	switch (mode) {
+		case K_RAW:
+			fprintf(stream, _("The keyboard is in raw (scancode) mode\n"));
+			break;
+		case K_MEDIUMRAW:
+			fprintf(stream, _("The keyboard is in mediumraw (keycode) mode\n"));
+			break;
+		case K_XLATE:
+			fprintf(stream, _("The keyboard is in the default (ASCII) mode\n"));
+			break;
+		case K_UNICODE:
+			fprintf(stream, _("The keyboard is in Unicode (UTF-8) mode\n"));
+			break;
+		default:
+			fprintf(stream, _("The keyboard is in some unknown mode\n"));
+        }
+}
+
 int main(int argc, char *argv[])
 {
-	int fd, mode, c, n = 0;
+	int fd, mode, orig_mode, c, n = 0, force = 0;
 	char *console = NULL;
 
 	set_progname(argv[0]);
@@ -38,7 +59,7 @@ int main(int argc, char *argv[])
 	if (argc == 2 && !strcmp(argv[1], "-V"))
 		print_version_and_exit();
 
-	while ((c = getopt(argc, argv, "auskC:")) != EOF) {
+	while ((c = getopt(argc, argv, "auskfC:")) != EOF) {
 		switch (c) {
 			case 'a':
 				if (n > 0)
@@ -64,6 +85,9 @@ int main(int argc, char *argv[])
 				mode = K_MEDIUMRAW;
 				n++;
 				break;
+			case 'f':
+				force = 1;
+				break;
 			case 'C':
 				if (!optarg || !optarg[0])
 					usage();
@@ -82,25 +106,28 @@ int main(int argc, char *argv[])
 		if (ioctl(fd, KDGKBMODE, &mode)) {
 			kbd_error(EXIT_FAILURE, errno, "ioctl KDGKBMODE");
 		}
-		switch (mode) {
-			case K_RAW:
-				printf(_("The keyboard is in raw (scancode) mode\n"));
-				break;
-			case K_MEDIUMRAW:
-				printf(_("The keyboard is in mediumraw (keycode) mode\n"));
-				break;
-			case K_XLATE:
-				printf(_("The keyboard is in the default (ASCII) mode\n"));
-				break;
-			case K_UNICODE:
-				printf(_("The keyboard is in Unicode (UTF-8) mode\n"));
-				break;
-			default:
-				printf(_("The keyboard is in some unknown mode\n"));
-		}
+		fprint_mode(stdout, mode);
 		return EXIT_SUCCESS;
 	}
 
+	if (force == 0) {
+		/* only perform safe mode switches */
+		if (ioctl(fd, KDGKBMODE, &orig_mode)) {
+			kbd_error(EXIT_FAILURE, errno, "ioctl KDGKBMODE");
+		}
+
+		if (mode == orig_mode) {
+			/* skip mode change */
+			return EXIT_SUCCESS;
+		}
+
+		if ((mode == K_XLATE && orig_mode != K_UNICODE) || (mode == K_UNICODE && orig_mode != K_XLATE)) {
+			fprint_mode(stderr, orig_mode);
+			fprintf(stderr, _("Changing to the requested mode may make "
+				"your keyboard unusable, please use -f to force the change.\n"));
+			return EXIT_FAILURE;
+		}
+	}
 	if (ioctl(fd, KDSKBMODE, mode)) {
 		kbd_error(EXIT_FAILURE, errno, "ioctl KDSKBMODE");
 	}
-- 
2.17.1



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-06-17  8:40 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-23 15:38 [kbd] [PATCH] kbd_mode: Add -f option and deny dangerous mode switches without it Balint Reczey
2019-05-08  9:19 ` Alexey Gladkov
2019-06-12 13:05   ` Bálint Réczey
2019-06-17  8:40     ` Alexey Gladkov

Linux console tools development discussion

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/kbd/0 kbd/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 kbd kbd/ http://lore.altlinux.org/kbd \
		kbd@lists.altlinux.org kbd@lists.altlinux.ru kbd@lists.altlinux.com
	public-inbox-index kbd

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.kbd


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git