[PATCH 1/1 v3] paint visual host key with unicode box-drawing characters
Christian Hesse
mail at eworm.de
Thu Jul 9 18:34:04 AEST 2015
Signed-off-by: Christian Hesse <mail at eworm.de>
---
configure.ac | 11 ++++++
defines.h | 5 +++
log.c | 3 +-
sshkey.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
4 files changed, 106 insertions(+), 21 deletions(-)
diff --git a/configure.ac b/configure.ac
index bb0095f..7e3965f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -383,6 +383,8 @@ AC_CHECK_HEADERS([ \
inttypes.h \
limits.h \
locale.h \
+ iconv.h \
+ langinfo.h \
login.h \
maillock.h \
ndir.h \
@@ -4641,6 +4643,15 @@ AC_ARG_ENABLE([pututxline],
fi
]
)
+AC_ARG_ENABLE([unicode],
+ [ --disable-unicode disable use of unicode [no]],
+ [
+ if test "x$enableval" = "xno" ; then
+ AC_DEFINE([DISABLE_UNICODE], [1],
+ [Define if you don't want to use unicode])
+ fi
+ ]
+)
AC_ARG_WITH([lastlog],
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
[
diff --git a/defines.h b/defines.h
index fa0ccba..7ea69cc 100644
--- a/defines.h
+++ b/defines.h
@@ -850,4 +850,9 @@ struct winsize {
# endif /* gcc version */
#endif /* __predict_true */
+#if defined(HAVE_LOCALE_H) && defined(HAVE_ICONV_H) && \
+ defined(HAVE_LANGINFO_H) && !defined(DISABLE_UNICODE)
+# define USE_UNICODE
+#endif
+
#endif /* _DEFINES_H */
diff --git a/log.c b/log.c
index 32e1d2e..7463617 100644
--- a/log.c
+++ b/log.c
@@ -444,8 +444,9 @@ 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));
+ (void)write(log_stderr_fd, "\r\n", 2);
} else {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
diff --git a/sshkey.c b/sshkey.c
index cfe5980..554087f 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -44,6 +44,12 @@
#include <stdio.h>
#include <string.h>
#include <resolv.h>
+#ifdef USE_UNICODE
+#include <locale.h>
+#include <unistd.h>
+#include <iconv.h>
+#include <langinfo.h>
+#endif /* USE_UNICODE */
#ifdef HAVE_UTIL_H
#include <util.h>
#endif /* HAVE_UTIL_H */
@@ -1088,17 +1094,75 @@ 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.
*/
+ 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 USE_UNICODE
+ iconv_t cd;
+ /* unicode character codes for box drawing
+ * http://unicode.org/charts/PDF/U2500.pdf */
+ uint32_t border_unicode[] = {
+ 0x250c, /* ┌ upper left */
+ 0x2500, /* ─ horizontal */
+ 0x2524, /* ┤ left of title/hash */
+ 0x251c, /* ├ right of title/hash */
+ 0x2510, /* ┐ upper right */
+ 0x2502, /* │ vertical */
+ 0x2514, /* └ lower left */
+ 0x2518 /* ┘ lower right */ };
+ /* border_buffer is array of array of char
+ * we use this to have statically allocated buffer */
+ char border_buffer[8][5];
+ /* border_encoded is array of pointer to char */
+ char *border_encoded[8];
+
+ if (isatty(fileno(stdout)) == 1) {
+ /* initialize locale */
+ setlocale(LC_ALL, "");
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ cd = iconv_open(nl_langinfo(CODESET), "UTF32LE");
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ cd = iconv_open(nl_langinfo(CODESET), "UTF32BE");
+#else
+#error Unknown __BYTE_ORDER
+#endif
+
+ /* encode the border elements */
+ for (int i = 0; i < 8; i++) {
+ size_t in_size = sizeof(uint32_t);;
+ size_t out_size = sizeof(border_buffer[i]);
+ char *input = (char *) &border_unicode[i];
+ char *output = border_buffer[i];
+
+ memset(border_buffer[i], 0, out_size);
+ iconv(cd, &input, &in_size, &output, &out_size);
+
+ /* if iconv() was successful we have a string with non-zero length
+ * fall back to ascii otherwise */
+ if (border_buffer[i][0] != 0)
+ border_encoded[i] = border_buffer[i];
+ else
+ border_encoded[i] = border_ascii[i];
+ }
+
+ iconv_close(cd);
+
+ border = border_encoded;
+ } else
+#endif /* USE_UNICODE */
+ border = border_ascii;
+
/* initialize field */
memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
x = FLDSIZE_X / 2;
@@ -1132,47 +1196,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