Skip to contentSkip to conversation

Bug#528357: /usr/bin/showconsolefont: produces garbage

kbd Michael Schutte 1 participant 2 messages May 16, 2009 – May 18, 2009 3 messages not in the archive

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 20090516155022.GA10925@graeme

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw

Hi Alexey,

Somewhere between 2.6.26 and 2.6.29, a change in the Linux kernel has caused showconsolefont to print garbage instead of spaces. A Debian user has provided these two screenshots in his bug report [1]:

    http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=15;filename=showconsolefont-lenny.png;att=1;bug=528357	
    http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=showconsolefont-garbage.png;att=1;bug=528357

[1] http://bugs.debian.org/528357

This happens only when the console is in Unicode mode, which makes it quite clear that the space character becomes something different in each unimap showconsolefont switches to. And indeed, if "\xef\x80\xa0" (which is the UTF-8 representation of U+F020, a straight-to-font space) is used instead of " ", everything is fine again for Unicode consoles; but, not surprisingly, this produces rubbish in XLATE mode.

One way to solve this would be to check which mode the VT is in and then using the appropriate way to print spaces. Another idea is forcibly switching the console to Unicode mode, dumping the font using UTF-8 characters, and then reverting the mode change if necessary, but that would involve a near-complete rewrite of showconsolefont.c. There might be better solutions, but I don’t even know which commit from linux-2.6.git introduces these problems.

Perhaps I’m also missing something obvious. Any comments?

All the best,

Signature · 1 line
Michael Schutte <[email protected]>
#4 lore raw

tag 528357 + patch
thanks

Quoted 2 lines · Michael Schutte

One way to solve this would be to check which mode the VT is in and then using the appropriate way to print spaces.

The attached patch uses this approach.

Signature · 1 line
Michael Schutte <[email protected]>

From 8c30fa09c9738b6b3605d94d681cee5e5ca2b371 Mon Sep 17 00:00:00 2001
From: Michael Schutte <[email protected]>
Date: Mon, 18 May 2009 19:47:00 +0200
Subject: [PATCH] showconsolefont: Print adequate space chars
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

Figure out whether the console is in Unicode or XLATE mode to decide whether to use a direct-to-font (U+F020) or a simple ASCII space character, respectively. This avoids showconsolefont’s output becoming a mess, cf. <http://bugs.debian.org/528357>.

---
 src/showconsolefont.c |   24 +++++++++++++++++-------
 1 files changed, 17 insertions(+), 7 deletions(-)
src/showconsolefont.c +17 -7
index c0b58d6..733e634 100644
@@ -116,7 +116,8 @@ usage(void) {
 int
 main (int argc, char **argv) {
 	int c, n, cols, rows, nr, i, j, k;
-	char *sep, *console = NULL;
+	int mode;
+	char *space, *sep, *console = NULL;
 	int list[64], lth, info = 0, verbose = 0;
 
 	set_progname(argv[0]);
@@ -148,6 +149,17 @@ main (int argc, char **argv) {
 	if (optind != argc)
 		usage();
 
+	fd = getfd(console);
+
+	if (ioctl(fd, KDGKBMODE, &mode)) {
+		perror("KDGKBMODE");
+		leave(1);
+	}
+	if (mode == K_UNICODE)
+		space = "\xef\x80\xa0";	/* U+F020 (direct-to-font space) */
+	else
+		space = " ";
+
         if (info) {
 	    nr = rows = cols = 0;
 	    n = getfont(fd, NULL, &nr, &rows, &cols);
@@ -164,8 +176,6 @@ main (int argc, char **argv) {
 	    leave(0);
 	  }
 
-	fd = getfd(console);
-
 	settrivialscreenmap();
 	getoldunicodemap();
 
@@ -175,7 +185,7 @@ main (int argc, char **argv) {
 	cols = ((n > 256) ? 32 : 16);
 	nr = 64/cols;
 	rows = (n+cols-1)/cols;
-	sep = ((cols == 16) ? "  " : " ");
+	sep = ((cols == 16) ? "%1$s%1$s" : "%1$s");
 
 	for (i=0; i<rows; i++) {
 		if (i % nr == 0) {
@@ -185,12 +195,12 @@ main (int argc, char **argv) {
 					list[lth++] = k+j*rows;
 			setnewunicodemap(list, lth);
 		}
-		printf("    ");
+		printf("%1$s%1$s%1$s%1$s", space);
 		for(j=0; j < cols && i+j*rows < n; j++) {
 			putchar(BASE + (i%nr)*cols+j);
-			printf("%s", sep);
+			printf(sep, space);
 			if (j%8 == 7)
-				printf("%s", sep);
+				printf(sep, space);
 		}
 		putchar('\n');
 		if (i%8 == 7)
Signature · 1 line
1.6.2.4