Linux console tools development discussion
 help / color / mirror / Atom feed
From: Balint Reczey <balint@balintreczey.hu>
To: kbd@lists.altlinux.org
Subject: [kbd] [PATCH] kbd_mode: Add -f option and deny dangerous mode switches without it
Date: Tue, 23 Apr 2019 17:38:07 +0200
Message-ID: <5cc19b8a.1c69fb81.6f70f.d8f0@mx.google.com> (raw)

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



             reply	other threads:[~2019-04-23 15:38 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-23 15:38 Balint Reczey [this message]
2019-05-08  9:19 ` Alexey Gladkov
2019-06-12 13:05   ` Bálint Réczey
2019-06-17  8:40     ` Alexey Gladkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5cc19b8a.1c69fb81.6f70f.d8f0@mx.google.com \
    --to=balint@balintreczey.hu \
    --cc=kbd@lists.altlinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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