[PATCH v2 1/1] paint visual host key with unicode box-drawing characters

Christian Hesse list at eworm.de
Mon Jul 6 23:18:29 AEST 2015


From: Christian Hesse <mail at eworm.de>

Signed-off-by: Christian Hesse <mail at eworm.de>
---
 log.c    |  2 +-
 sshkey.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/log.c b/log.c
index 32e1d2e..90c1232 100644
--- a/log.c
+++ b/log.c
@@ -444,7 +444,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
 		tmp_handler(level, fmtbuf, log_handler_ctx);
 		log_handler = tmp_handler;
 	} else if (log_on_stderr) {
-		snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
+		/* we want unicode multi byte characters, so do not use fmtbuf here */
 		(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
 	} else {
 #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
diff --git a/sshkey.c b/sshkey.c
index cfe5980..326bc29 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -44,6 +44,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <resolv.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif /* HAVE_LOCALE_H */
 #ifdef HAVE_UTIL_H
 #include <util.h>
 #endif /* HAVE_UTIL_H */
@@ -1088,17 +1091,47 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
 	 * Chars to be used after each other every time the worm
 	 * intersects with itself.  Matter of taste.
 	 */
+#ifdef HAVE_LOCALE_H
+	char    *locale;
+	char    *border_utf8[] = {
+			"\342\224\217", /* ┏ upper left */
+			"\342\224\201", /* ━ horizontal */
+			"\342\224\253", /* ┫ left of title/hash */
+			"\342\224\243", /* ┣ right of title/hash */
+			"\342\224\223", /* ┓ upper right */
+			"\342\224\203", /* ┃ vertical */
+			"\342\224\227", /* ┗ lower left */
+			"\342\224\233"  /* ┛ lower right */ };
+#endif
+	char    *border_ascii[] = { "+", "-", "[", "]", "+", "|", "+", "+" };
+	char   **border;
 	char	*augmentation_string = " .o+=*BOX@%&#/^SE";
-	char	*retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
+	char	*retval, *p, title[FLDSIZE_X - 2], hash[FLDSIZE_X - 2];
 	u_char	 field[FLDSIZE_X][FLDSIZE_Y];
 	size_t	 i, tlen, hlen;
 	u_int	 b;
 	int	 x, y, r;
 	size_t	 len = strlen(augmentation_string) - 1;
 
-	if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
+	if ((retval = malloc((FLDSIZE_X + 7) * FLDSIZE_Y + FLDSIZE_X * 3 * 2)) == NULL)
 		return NULL;
 
+#ifdef HAVE_LOCALE_H
+	/* initialize locale */
+	setlocale(LC_ALL, "");
+
+	/* get locale for LC_CTYPE and decide about characters to use */
+	locale = setlocale(LC_CTYPE, NULL);
+	if (locale != NULL && *locale != 0 &&
+			(strstr(locale, "UTF-8") ||
+			 strstr(locale, "utf-8") ||
+			 strstr(locale, "UTF8")  ||
+			 strstr(locale, "utf8")))
+		border = border_utf8;
+	else
+#endif
+		border = border_ascii;
+
 	/* initialize field */
 	memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
 	x = FLDSIZE_X / 2;
@@ -1132,47 +1165,51 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
 	field[x][y] = len;
 
 	/* assemble title */
-	r = snprintf(title, sizeof(title), "[%s %u]",
+	r = snprintf(title, sizeof(title), "%s %u",
 		sshkey_type(k), sshkey_size(k));
-	/* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
+	/* If "type size" won't fit, then try "type"; fits "ED25519-CERT" */
 	if (r < 0 || r > (int)sizeof(title))
-		r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
+		r = snprintf(title, sizeof(title), "%s", sshkey_type(k));
 	tlen = (r <= 0) ? 0 : strlen(title);
 
 	/* assemble hash ID. */
-	r = snprintf(hash, sizeof(hash), "[%s]", alg);
+	r = snprintf(hash, sizeof(hash), "%s", alg);
 	hlen = (r <= 0) ? 0 : strlen(hash);
 
 	/* output upper border */
 	p = retval;
-	*p++ = '+';
-	for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
-		*p++ = '-';
+	p += sprintf(p, "%s", border[0]);
+	for (i = 0; i < (FLDSIZE_X - tlen - 2) / 2; i++)
+		p += sprintf(p, "%s", border[1]);
+	p += sprintf(p, "%s", border[2]);
 	memcpy(p, title, tlen);
 	p += tlen;
-	for (i += tlen; i < FLDSIZE_X; i++)
-		*p++ = '-';
-	*p++ = '+';
+	p += sprintf(p, "%s", border[3]);
+	for (i += tlen + 2; i < FLDSIZE_X; i++)
+		p += sprintf(p, "%s", border[1]);
+	p += sprintf(p, "%s", border[4]);
 	*p++ = '\n';
 
 	/* output content */
 	for (y = 0; y < FLDSIZE_Y; y++) {
-		*p++ = '|';
+		p += sprintf(p, "%s", border[5]);
 		for (x = 0; x < FLDSIZE_X; x++)
 			*p++ = augmentation_string[MIN(field[x][y], len)];
-		*p++ = '|';
+		p += sprintf(p, "%s", border[5]);
 		*p++ = '\n';
 	}
 
 	/* output lower border */
-	*p++ = '+';
-	for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
-		*p++ = '-';
+	p += sprintf(p, "%s", border[6]);
+	for (i = 0; i < (FLDSIZE_X - hlen - 2) / 2; i++)
+		p += sprintf(p, "%s", border[1]);
+	p += sprintf(p, "%s", border[2]);
 	memcpy(p, hash, hlen);
 	p += hlen;
-	for (i += hlen; i < FLDSIZE_X; i++)
-		*p++ = '-';
-	*p++ = '+';
+	p += sprintf(p, "%s", border[3]);
+	for (i += hlen + 2; i < FLDSIZE_X; i++)
+		p += sprintf(p, "%s", border[1]);
+	p += sprintf(p, "%s", border[7]);
 
 	return retval;
 }
-- 
2.4.5



More information about the openssh-unix-dev mailing list