dcavalca / rpms / util-linux

Forked from rpms/util-linux 2 years ago
Clone

Blame SOURCES/0152-libsmartcols-add-basic-tools-necessary-for-new-versi.patch

5113bc
From c465ce9765273e8e1227b192e1917826ac4eaaf7 Mon Sep 17 00:00:00 2001
5113bc
From: Karel Zak <kzak@redhat.com>
5113bc
Date: Thu, 31 May 2018 11:13:31 +0200
5113bc
Subject: [PATCH 152/173] libsmartcols: add basic tools necessary for new
5113bc
 version
5113bc
5113bc
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1561350
5113bc
Signed-off-by: Karel Zak <kzak@redhat.com>
5113bc
---
5113bc
 configure.ac          |   3 +
5113bc
 include/carefulputc.h |  96 +++++++++++++++++++++++++++-
5113bc
 include/colors.h      |   5 ++
5113bc
 include/mbsalign.h    |   9 ++-
5113bc
 include/strutils.h    |  13 ++--
5113bc
 include/ttyutils.h    |   1 +
5113bc
 lib/Makemodule.am     |   1 +
5113bc
 lib/color-names.c     |  57 +++++++++++++++++
5113bc
 lib/mbsalign.c        | 172 +++++++++++++++++++++++++++++++++++++++++---------
5113bc
 lib/ttyutils.c        |  52 +++++++++++++++
5113bc
 libfdisk/src/ask.c    |   4 +-
5113bc
 11 files changed, 373 insertions(+), 40 deletions(-)
5113bc
 create mode 100644 lib/color-names.c
5113bc
5113bc
diff --git a/configure.ac b/configure.ac
5113bc
index d561e01d0..8cf317dc0 100644
5113bc
--- a/configure.ac
5113bc
+++ b/configure.ac
5113bc
@@ -133,6 +133,9 @@ AC_SUBST([BSD_WARN_CFLAGS])
5113bc
 dnl libtool-2
5113bc
 LT_INIT
5113bc
 
5113bc
+dnl check supported linker flags
5113bc
+AX_CHECK_VSCRIPT
5113bc
+
5113bc
 m4_ifndef([PKG_PROG_PKG_CONFIG],
5113bc
   [m4_fatal([Could not locate the pkg-config autoconf
5113bc
     macros. These are usually located in /usr/share/aclocal/pkg.m4.
5113bc
diff --git a/include/carefulputc.h b/include/carefulputc.h
5113bc
index a54498cfd..613d94c1e 100644
5113bc
--- a/include/carefulputc.h
5113bc
+++ b/include/carefulputc.h
5113bc
@@ -26,7 +26,87 @@ static inline int carefulputc(int c, FILE *fp) {
5113bc
 	return (ret < 0) ? EOF : 0;
5113bc
 }
5113bc
 
5113bc
-static inline void fputs_quoted(const char *data, FILE *out)
5113bc
+/*
5113bc
+ * Backported for RHEL7.6 libsmartcols
5113bc
+ */
5113bc
+
5113bc
+/*
5113bc
+ * Requirements enumerated via testing (V8, Firefox, IE11):
5113bc
+ *
5113bc
+ * var charsToEscape = [];
5113bc
+ * for (var i = 0; i < 65535; i += 1) {
5113bc
+ *	try {
5113bc
+ *		JSON.parse('{"sample": "' + String.fromCodePoint(i) + '"}');
5113bc
+ *	} catch (e) {
5113bc
+ *		charsToEscape.push(i);
5113bc
+ *	}
5113bc
+ * }
5113bc
+ */
5113bc
+static inline void fputs_quoted_case_json(const char *data, FILE *out, int dir)
5113bc
+{
5113bc
+	const char *p;
5113bc
+
5113bc
+	fputc('"', out);
5113bc
+	for (p = data; p && *p; p++) {
5113bc
+
5113bc
+		const unsigned char c = (unsigned char) *p;
5113bc
+
5113bc
+		/* From http://www.json.org
5113bc
+		 *
5113bc
+		 * The double-quote and backslashes would break out a string or
5113bc
+		 * init an escape sequence if not escaped.
5113bc
+		 *
5113bc
+		 * Note that single-quotes and forward slashes, while they're
5113bc
+		 * in the JSON spec, don't break double-quoted strings.
5113bc
+		 */
5113bc
+		if (c == '"' || c == '\\') {
5113bc
+			fputc('\\', out);
5113bc
+			fputc(c, out);
5113bc
+			continue;
5113bc
+		}
5113bc
+
5113bc
+		/* All non-control characters OK; do the case swap as required. */
5113bc
+		if (c >= 0x20) {
5113bc
+			fputc(dir ==  1 ? toupper(c) :
5113bc
+			      dir == -1 ? tolower(c) : *p, out);
5113bc
+			continue;
5113bc
+		}
5113bc
+
5113bc
+		/* In addition, all chars under ' ' break Node's/V8/Chrome's, and
5113bc
+		 * Firefox's JSON.parse function
5113bc
+		 */
5113bc
+		switch (c) {
5113bc
+			/* Handle short-hand cases to reduce output size.  C
5113bc
+			 * has most of the same stuff here, so if there's an
5113bc
+			 * "Escape for C" function somewhere in the STL, we
5113bc
+			 * should probably be using it.
5113bc
+			 */
5113bc
+			case '\b':
5113bc
+				fputs("\\b", out);
5113bc
+				break;
5113bc
+			case '\t':
5113bc
+				fputs("\\t", out);
5113bc
+				break;
5113bc
+			case '\n':
5113bc
+				fputs("\\n", out);
5113bc
+				break;
5113bc
+			case '\f':
5113bc
+				fputs("\\f", out);
5113bc
+				break;
5113bc
+			case '\r':
5113bc
+				fputs("\\r", out);
5113bc
+				break;
5113bc
+			default:
5113bc
+				/* Other assorted control characters */
5113bc
+				fprintf(out, "\\u00%02x", c);
5113bc
+				break;
5113bc
+		}
5113bc
+	}
5113bc
+	fputc('"', out);
5113bc
+}
5113bc
+
5113bc
+
5113bc
+static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
5113bc
 {
5113bc
 	const char *p;
5113bc
 
5113bc
@@ -34,16 +114,28 @@ static inline void fputs_quoted(const char *data, FILE *out)
5113bc
 	for (p = data; p && *p; p++) {
5113bc
 		if ((unsigned char) *p == 0x22 ||		/* " */
5113bc
 		    (unsigned char) *p == 0x5c ||		/* \ */
5113bc
+		    (unsigned char) *p == 0x60 ||		/* ` */
5113bc
+		    (unsigned char) *p == 0x24 ||		/* $ */
5113bc
 		    !isprint((unsigned char) *p) ||
5113bc
 		    iscntrl((unsigned char) *p)) {
5113bc
 
5113bc
 			fprintf(out, "\\x%02x", (unsigned char) *p);
5113bc
 		} else
5113bc
-			fputc(*p, out);
5113bc
+			fputc(dir ==  1 ? toupper(*p) :
5113bc
+			      dir == -1 ? tolower(*p) :
5113bc
+			      *p, out);
5113bc
 	}
5113bc
 	fputc('"', out);
5113bc
 }
5113bc
 
5113bc
+#define fputs_quoted(_d, _o)		fputs_quoted_case(_d, _o, 0)
5113bc
+#define fputs_quoted_upper(_d, _o)	fputs_quoted_case(_d, _o, 1)
5113bc
+#define fputs_quoted_lower(_d, _o)	fputs_quoted_case(_d, _o, -1)
5113bc
+
5113bc
+#define fputs_quoted_json(_d, _o)       fputs_quoted_case_json(_d, _o, 0)
5113bc
+#define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1)
5113bc
+#define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1)
5113bc
+
5113bc
 static inline void fputs_nonblank(const char *data, FILE *out)
5113bc
 {
5113bc
 	const char *p;
5113bc
diff --git a/include/colors.h b/include/colors.h
5113bc
index dd77bf6df..39c0edf46 100644
5113bc
--- a/include/colors.h
5113bc
+++ b/include/colors.h
5113bc
@@ -38,6 +38,11 @@
5113bc
 
5113bc
 #define UL_COLOR_WHITE		"\033[1;37m"
5113bc
 
5113bc
+/* maximal length of human readable name of ESC seq. */
5113bc
+#define UL_COLORNAME_MAXSZ      32
5113bc
+
5113bc
+extern const char *color_sequence_from_colorname(const char *str);
5113bc
+
5113bc
 /* Initialize the global variable OUT_IS_TERM */
5113bc
 extern int colors_init(void);
5113bc
 
5113bc
diff --git a/include/mbsalign.h b/include/mbsalign.h
5113bc
index 5eaf606e5..0c28e6f69 100644
5113bc
--- a/include/mbsalign.h
5113bc
+++ b/include/mbsalign.h
5113bc
@@ -46,11 +46,18 @@ extern size_t mbsalign (const char *src, char *dest,
5113bc
 			size_t dest_size,  size_t *width,
5113bc
 			mbs_align_t align, int flags);
5113bc
 
5113bc
+extern size_t mbsalign_with_padding (const char *src, char *dest, size_t dest_size,
5113bc
+	               size_t *width, mbs_align_t align, int flags,
5113bc
+		       int padchar);
5113bc
+
5113bc
 extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz);
5113bc
 extern size_t mbs_safe_width(const char *s);
5113bc
 
5113bc
 extern char *mbs_safe_encode(const char *s, size_t *width);
5113bc
-extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf);
5113bc
+extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars);
5113bc
 extern size_t mbs_safe_encode_size(size_t bytes);
5113bc
 
5113bc
+extern char *mbs_invalid_encode(const char *s, size_t *width);
5113bc
+extern char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf);
5113bc
+
5113bc
 #endif /* UTIL_LINUX_MBSALIGN_H */
5113bc
diff --git a/include/strutils.h b/include/strutils.h
5113bc
index 1f028e4ed..822fb7d49 100644
5113bc
--- a/include/strutils.h
5113bc
+++ b/include/strutils.h
5113bc
@@ -6,6 +6,7 @@
5113bc
 #include <string.h>
5113bc
 #include <sys/types.h>
5113bc
 #include <stdio.h>
5113bc
+#include <errno.h>
5113bc
 
5113bc
 /* default strtoxx_or_err() exit code */
5113bc
 #ifndef STRTOXX_EXIT_CODE
5113bc
@@ -57,20 +58,24 @@ static inline void xstrncpy(char *dest, const char *src, size_t n)
5113bc
 	dest[n-1] = 0;
5113bc
 }
5113bc
 
5113bc
-static inline char *strdup_to_offset(void *stru, size_t offset, const char *str)
5113bc
+static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
5113bc
 {
5113bc
 	char *n = NULL;
5113bc
-	char **o = (char **) ((char *) stru + offset);
5113bc
+	char **o;
5113bc
 
5113bc
+	if (!stru)
5113bc
+		return -EINVAL;
5113bc
+
5113bc
+	o = (char **) ((char *) stru + offset);
5113bc
 	if (str) {
5113bc
 		n = strdup(str);
5113bc
 		if (!n)
5113bc
-			return NULL;
5113bc
+			return -ENOMEM;
5113bc
 	}
5113bc
 
5113bc
 	free(*o);
5113bc
 	*o = n;
5113bc
-	return n;
5113bc
+	return 0;
5113bc
 }
5113bc
 
5113bc
 #define strdup_to_struct_member(_s, _m, _str) \
5113bc
diff --git a/include/ttyutils.h b/include/ttyutils.h
5113bc
index 13495ba96..47fe34472 100644
5113bc
--- a/include/ttyutils.h
5113bc
+++ b/include/ttyutils.h
5113bc
@@ -47,6 +47,7 @@ struct chardata {
5113bc
 	        (ptr)->capslock = 0;         \
5113bc
 	} while (0)
5113bc
 
5113bc
+extern int get_terminal_dimension(int *cols, int *lines);
5113bc
 extern int get_terminal_width(void);
5113bc
 extern int get_terminal_name(int fd, const char **path, const char **name,
5113bc
 			     const char **number);
5113bc
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
5113bc
index acae27afb..714233c40 100644
5113bc
--- a/lib/Makemodule.am
5113bc
+++ b/lib/Makemodule.am
5113bc
@@ -6,6 +6,7 @@ libcommon_la_SOURCES = \
5113bc
 	lib/blkdev.c \
5113bc
 	lib/canonicalize.c \
5113bc
 	lib/colors.c \
5113bc
+	lib/color-names.c \
5113bc
 	lib/crc32.c \
5113bc
 	lib/env.c \
5113bc
 	lib/idcache.c \
5113bc
diff --git a/lib/color-names.c b/lib/color-names.c
5113bc
new file mode 100644
5113bc
index 000000000..cf37670a9
5113bc
--- /dev/null
5113bc
+++ b/lib/color-names.c
5113bc
@@ -0,0 +1,57 @@
5113bc
+
5113bc
+#include "c.h"
5113bc
+#include "colors.h"
5113bc
+
5113bc
+struct ul_color_name {
5113bc
+	const char *name;
5113bc
+	const char *seq;
5113bc
+};
5113bc
+
5113bc
+/*
5113bc
+ * qsort/bsearch buddy
5113bc
+ */
5113bc
+static int cmp_color_name(const void *a0, const void *b0)
5113bc
+{
5113bc
+	struct ul_color_name	*a = (struct ul_color_name *) a0,
5113bc
+				*b = (struct ul_color_name *) b0;
5113bc
+	return strcmp(a->name, b->name);
5113bc
+}
5113bc
+
5113bc
+/*
5113bc
+ * Maintains human readable color names
5113bc
+ */
5113bc
+const char *color_sequence_from_colorname(const char *str)
5113bc
+{
5113bc
+	static const struct ul_color_name basic_schemes[] = {
5113bc
+		{ "black",	UL_COLOR_BLACK           },
5113bc
+		{ "blink",      UL_COLOR_BLINK           },
5113bc
+		{ "blue",	UL_COLOR_BLUE            },
5113bc
+		{ "bold",       UL_COLOR_BOLD		 },
5113bc
+		{ "brown",	UL_COLOR_BROWN           },
5113bc
+		{ "cyan",	UL_COLOR_CYAN            },
5113bc
+		{ "darkgray",	UL_COLOR_DARK_GRAY       },
5113bc
+		{ "gray",	UL_COLOR_GRAY            },
5113bc
+		{ "green",	UL_COLOR_GREEN           },
5113bc
+		{ "halfbright", UL_COLOR_HALFBRIGHT	 },
5113bc
+		{ "lightblue",	UL_COLOR_BOLD_BLUE       },
5113bc
+		{ "lightcyan",	UL_COLOR_BOLD_CYAN       },
5113bc
+		{ "lightgray,",	UL_COLOR_GRAY            },
5113bc
+		{ "lightgreen", UL_COLOR_BOLD_GREEN      },
5113bc
+		{ "lightmagenta", UL_COLOR_BOLD_MAGENTA  },
5113bc
+		{ "lightred",	UL_COLOR_BOLD_RED        },
5113bc
+		{ "magenta",	UL_COLOR_MAGENTA         },
5113bc
+		{ "red",	UL_COLOR_RED             },
5113bc
+		{ "reset",      UL_COLOR_RESET,          },
5113bc
+		{ "reverse",    UL_COLOR_REVERSE         },
5113bc
+		{ "yellow",	UL_COLOR_BOLD_YELLOW     },
5113bc
+	};
5113bc
+	struct ul_color_name key = { .name = (char *) str }, *res;
5113bc
+
5113bc
+	if (!str)
5113bc
+		return NULL;
5113bc
+
5113bc
+	res = bsearch(&key, basic_schemes, ARRAY_SIZE(basic_schemes),
5113bc
+				sizeof(struct ul_color_name),
5113bc
+				cmp_color_name);
5113bc
+	return res ? res->seq : NULL;
5113bc
+}
5113bc
diff --git a/lib/mbsalign.c b/lib/mbsalign.c
5113bc
index b307d19f7..8fdab9ee9 100644
5113bc
--- a/lib/mbsalign.c
5113bc
+++ b/lib/mbsalign.c
5113bc
@@ -27,9 +27,9 @@
5113bc
 
5113bc
 #include "c.h"
5113bc
 #include "mbsalign.h"
5113bc
+#include "strutils.h"
5113bc
 #include "widechar.h"
5113bc
 
5113bc
-#ifdef HAVE_WIDECHAR
5113bc
 /* Replace non printable chars.
5113bc
    Note \t and \n etc. are non printable.
5113bc
    Return 1 if replacement made, 0 otherwise.  */
5113bc
@@ -43,17 +43,19 @@
5113bc
  */
5113bc
 size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz)
5113bc
 {
5113bc
-	mbstate_t st;
5113bc
 	const char *p = buf, *last = buf;
5113bc
 	size_t width = 0, bytes = 0;
5113bc
 
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
+	mbstate_t st;
5113bc
 	memset(&st, 0, sizeof(st));
5113bc
-
5113bc
+#endif
5113bc
 	if (p && *p && bufsz)
5113bc
 		last = p + (bufsz - 1);
5113bc
 
5113bc
 	while (p && *p && p <= last) {
5113bc
-		if (iscntrl((unsigned char) *p)) {
5113bc
+		if ((p < last && *p == '\\' && *(p + 1) == 'x')
5113bc
+		    || iscntrl((unsigned char) *p)) {
5113bc
 			width += 4, bytes += 4;		/* *p encoded to \x?? */
5113bc
 			p++;
5113bc
 		}
5113bc
@@ -106,28 +108,36 @@ size_t mbs_safe_width(const char *s)
5113bc
 
5113bc
 /*
5113bc
  * Copy @s to @buf and replace control and non-printable chars with
5113bc
- * \x?? hex sequence. The @width returns number of cells.
5113bc
+ * \x?? hex sequence. The @width returns number of cells. The @safechars
5113bc
+ * are not encoded.
5113bc
  *
5113bc
  * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
5113bc
  * bytes.
5113bc
  */
5113bc
-char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
5113bc
+char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars)
5113bc
 {
5113bc
-	mbstate_t st;
5113bc
 	const char *p = s;
5113bc
 	char *r;
5113bc
 	size_t sz = s ? strlen(s) : 0;
5113bc
 
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
+	mbstate_t st;
5113bc
+	memset(&st, 0, sizeof(st));
5113bc
+#endif
5113bc
 	if (!sz || !buf)
5113bc
 		return NULL;
5113bc
 
5113bc
-	memset(&st, 0, sizeof(st));
5113bc
-
5113bc
 	r = buf;
5113bc
 	*width = 0;
5113bc
 
5113bc
 	while (p && *p) {
5113bc
-		if (iscntrl((unsigned char) *p)) {
5113bc
+		if (safechars && strchr(safechars, *p)) {
5113bc
+			*r++ = *p++;
5113bc
+			continue;
5113bc
+		}
5113bc
+
5113bc
+		if ((*p == '\\' && *(p + 1) == 'x')
5113bc
+		    || iscntrl((unsigned char) *p)) {
5113bc
 			sprintf(r, "\\x%02x", (unsigned char) *p);
5113bc
 			r += 4;
5113bc
 			*width += 4;
5113bc
@@ -152,13 +162,13 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
5113bc
 					r += 4;
5113bc
 					*width += 4;
5113bc
 				} else {
5113bc
-					width++;
5113bc
+					(*width)++;
5113bc
 					*r++ = *p;
5113bc
 				}
5113bc
 			} else if (!iswprint(wc)) {
5113bc
 				size_t i;
5113bc
 				for (i = 0; i < len; i++) {
5113bc
-					sprintf(r, "\\x%02x", (unsigned char) *p);
5113bc
+					sprintf(r, "\\x%02x", (unsigned char) p[i]);
5113bc
 					r += 4;
5113bc
 					*width += 4;
5113bc
 				}
5113bc
@@ -177,13 +187,76 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
5113bc
 			*width += 4;
5113bc
 		} else {
5113bc
 			*r++ = *p++;
5113bc
-			*width++;
5113bc
+			(*width)++;
5113bc
 		}
5113bc
 #endif
5113bc
 	}
5113bc
 
5113bc
 	*r = '\0';
5113bc
+	return buf;
5113bc
+}
5113bc
 
5113bc
+/*
5113bc
+ * Copy @s to @buf and replace broken sequences to \x?? hex sequence. The
5113bc
+ * @width returns number of cells. The @safechars are not encoded.
5113bc
+ *
5113bc
+ * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
5113bc
+ * bytes.
5113bc
+ */
5113bc
+char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf)
5113bc
+{
5113bc
+	const char *p = s;
5113bc
+	char *r;
5113bc
+	size_t sz = s ? strlen(s) : 0;
5113bc
+
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
+	mbstate_t st;
5113bc
+	memset(&st, 0, sizeof(st));
5113bc
+#endif
5113bc
+	if (!sz || !buf)
5113bc
+		return NULL;
5113bc
+
5113bc
+	r = buf;
5113bc
+	*width = 0;
5113bc
+
5113bc
+	while (p && *p) {
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
+		wchar_t wc;
5113bc
+		size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
5113bc
+#else
5113bc
+		size_t len = 1;
5113bc
+#endif
5113bc
+
5113bc
+		if (len == 0)
5113bc
+			break;		/* end of string */
5113bc
+
5113bc
+		if (len == (size_t) -1 || len == (size_t) -2) {
5113bc
+			len = 1;
5113bc
+			/*
5113bc
+			 * Not valid multibyte sequence -- maybe it's
5113bc
+			 * printable char according to the current locales.
5113bc
+			 */
5113bc
+			if (!isprint((unsigned char) *p)) {
5113bc
+				sprintf(r, "\\x%02x", (unsigned char) *p);
5113bc
+				r += 4;
5113bc
+				*width += 4;
5113bc
+			} else {
5113bc
+				(*width)++;
5113bc
+				*r++ = *p;
5113bc
+			}
5113bc
+		} else if (*p == '\\' && *(p + 1) == 'x') {
5113bc
+			sprintf(r, "\\x%02x", (unsigned char) *p);
5113bc
+			r += 4;
5113bc
+			*width += 4;
5113bc
+		} else {
5113bc
+			memcpy(r, p, len);
5113bc
+			r += len;
5113bc
+			*width += wcwidth(wc);
5113bc
+		}
5113bc
+		p += len;
5113bc
+	}
5113bc
+
5113bc
+	*r = '\0';
5113bc
 	return buf;
5113bc
 }
5113bc
 
5113bc
@@ -199,17 +272,39 @@ size_t mbs_safe_encode_size(size_t bytes)
5113bc
 char *mbs_safe_encode(const char *s, size_t *width)
5113bc
 {
5113bc
 	size_t sz = s ? strlen(s) : 0;
5113bc
-	char *buf;
5113bc
+	char *buf, *ret = NULL;
5113bc
 
5113bc
 	if (!sz)
5113bc
 		return NULL;
5113bc
 	buf = malloc(mbs_safe_encode_size(sz));
5113bc
-	if (!buf)
5113bc
-		return NULL;
5113bc
+	if (buf)
5113bc
+		ret = mbs_safe_encode_to_buffer(s, width, buf, NULL);
5113bc
+	if (!ret)
5113bc
+		free(buf);
5113bc
+	return ret;
5113bc
+}
5113bc
 
5113bc
-	return mbs_safe_encode_to_buffer(s, width, buf);
5113bc
+/*
5113bc
+ * Returns allocated string where all broken widechars chars are
5113bc
+ * replaced with \x?? hex sequence.
5113bc
+ */
5113bc
+char *mbs_invalid_encode(const char *s, size_t *width)
5113bc
+{
5113bc
+	size_t sz = s ? strlen(s) : 0;
5113bc
+	char *buf, *ret = NULL;
5113bc
+
5113bc
+	if (!sz)
5113bc
+		return NULL;
5113bc
+	buf = malloc(mbs_safe_encode_size(sz));
5113bc
+	if (buf)
5113bc
+		ret = mbs_invalid_encode_to_buffer(s, width, buf);
5113bc
+	if (!ret)
5113bc
+		free(buf);
5113bc
+	return ret;
5113bc
 }
5113bc
 
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
+
5113bc
 static bool
5113bc
 wc_ensure_printable (wchar_t *wchars)
5113bc
 {
5113bc
@@ -246,6 +341,7 @@ wc_truncate (wchar_t *wc, size_t width)
5113bc
         }
5113bc
       if (cells + next_cells > width)
5113bc
         break;
5113bc
+
5113bc
       cells += next_cells;
5113bc
       wc++;
5113bc
     }
5113bc
@@ -273,7 +369,7 @@ rpl_wcswidth (const wchar_t *s, size_t n)
5113bc
 
5113bc
   return ret;
5113bc
 }
5113bc
-#endif
5113bc
+#endif /* HAVE_WIDECHAR */
5113bc
 
5113bc
 /* Truncate multi-byte string to @width and returns number of
5113bc
  * bytes of the new string @str, and in @width returns number
5113bc
@@ -290,7 +386,7 @@ mbs_truncate(char *str, size_t *width)
5113bc
 	if (sz == (ssize_t) -1)
5113bc
 		goto done;
5113bc
 
5113bc
-	wcs = malloc((sz + 1) * sizeof(wchar_t));
5113bc
+	wcs = calloc(1, (sz + 1) * sizeof(wchar_t));
5113bc
 	if (!wcs)
5113bc
 		goto done;
5113bc
 
5113bc
@@ -301,7 +397,7 @@ mbs_truncate(char *str, size_t *width)
5113bc
 done:
5113bc
 	free(wcs);
5113bc
 #else
5113bc
-	if (*width < bytes)
5113bc
+	if (bytes >= 0 && *width < (size_t) bytes)
5113bc
 		bytes = *width;
5113bc
 #endif
5113bc
 	if (bytes >= 0)
5113bc
@@ -315,16 +411,23 @@ done:
5113bc
    A pointer to the terminating NUL is returned.  */
5113bc
 
5113bc
 static char*
5113bc
-mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces)
5113bc
+mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces, int padchar)
5113bc
 {
5113bc
   /* FIXME: Should we pad with "figure space" (\u2007)
5113bc
      if non ascii data present?  */
5113bc
-  while (n_spaces-- && (dest < dest_end))
5113bc
-    *dest++ = ' ';
5113bc
+  for (/* nothing */; n_spaces && (dest < dest_end); n_spaces--)
5113bc
+    *dest++ = padchar;
5113bc
   *dest = '\0';
5113bc
   return dest;
5113bc
 }
5113bc
 
5113bc
+size_t
5113bc
+mbsalign (const char *src, char *dest, size_t dest_size,
5113bc
+          size_t *width, mbs_align_t align, int flags)
5113bc
+{
5113bc
+	return mbsalign_with_padding(src, dest, dest_size, width, align, flags, ' ');
5113bc
+}
5113bc
+
5113bc
 /* Align a string, SRC, in a field of *WIDTH columns, handling multi-byte
5113bc
    characters; write the result into the DEST_SIZE-byte buffer, DEST.
5113bc
    ALIGNMENT specifies whether to left- or right-justify or to center.
5113bc
@@ -339,8 +442,14 @@ mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces)
5113bc
    Update *WIDTH to indicate how many columns were used before padding.  */
5113bc
 
5113bc
 size_t
5113bc
-mbsalign (const char *src, char *dest, size_t dest_size,
5113bc
-          size_t *width, mbs_align_t align, int flags)
5113bc
+mbsalign_with_padding (const char *src, char *dest, size_t dest_size,
5113bc
+	               size_t *width, mbs_align_t align,
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
+		       int flags,
5113bc
+#else
5113bc
+		       int flags __attribute__((__unused__)),
5113bc
+#endif
5113bc
+		       int padchar)
5113bc
 {
5113bc
   size_t ret = -1;
5113bc
   size_t src_size = strlen (src) + 1;
5113bc
@@ -350,10 +459,11 @@ mbsalign (const char *src, char *dest, size_t dest_size,
5113bc
   size_t n_cols = src_size - 1;
5113bc
   size_t n_used_bytes = n_cols; /* Not including NUL */
5113bc
   size_t n_spaces = 0, space_left;
5113bc
+
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
   bool conversion = false;
5113bc
   bool wc_enabled = false;
5113bc
 
5113bc
-#ifdef HAVE_WIDECHAR
5113bc
   /* In multi-byte locales convert to wide characters
5113bc
      to allow easy truncation. Also determine number
5113bc
      of screen columns used.  */
5113bc
@@ -407,9 +517,9 @@ mbsalign (const char *src, char *dest, size_t dest_size,
5113bc
         n_cols = wc_truncate (str_wc, *width);
5113bc
         n_used_bytes = wcstombs (newstr, str_wc, src_size);
5113bc
     }
5113bc
-#endif
5113bc
 
5113bc
 mbsalign_unibyte:
5113bc
+#endif
5113bc
 
5113bc
   if (n_cols > *width) /* Unibyte truncation required.  */
5113bc
     {
5113bc
@@ -451,14 +561,14 @@ mbsalign_unibyte:
5113bc
 	  abort();
5113bc
         }
5113bc
 
5113bc
-      dest = mbs_align_pad (dest, dest_end, start_spaces);
5113bc
+      dest = mbs_align_pad (dest, dest_end, start_spaces, padchar);
5113bc
       space_left = dest_end - dest;
5113bc
       dest = mempcpy (dest, str_to_print, min (n_used_bytes, space_left));
5113bc
-      mbs_align_pad (dest, dest_end, end_spaces);
5113bc
+      mbs_align_pad (dest, dest_end, end_spaces, padchar);
5113bc
     }
5113bc
-
5113bc
+#ifdef HAVE_WIDECHAR
5113bc
 mbsalign_cleanup:
5113bc
-
5113bc
+#endif
5113bc
   free (str_wc);
5113bc
   free (newstr);
5113bc
 
5113bc
diff --git a/lib/ttyutils.c b/lib/ttyutils.c
5113bc
index ea551e26c..91497e763 100644
5113bc
--- a/lib/ttyutils.c
5113bc
+++ b/lib/ttyutils.c
5113bc
@@ -9,6 +9,58 @@
5113bc
 #include "c.h"
5113bc
 #include "ttyutils.h"
5113bc
 
5113bc
+/*
5113bc
+ * Backported for RHEL7.6 libsmartcols
5113bc
+ */
5113bc
+static int get_env_int(const char *name)
5113bc
+{
5113bc
+	const char *cp = getenv(name);
5113bc
+
5113bc
+	if (cp) {
5113bc
+		char *end = NULL;
5113bc
+		long x;
5113bc
+
5113bc
+		errno = 0;
5113bc
+		x = strtol(cp, &end, 10);
5113bc
+
5113bc
+		if (errno == 0 && end && *end == '\0' && end > cp &&
5113bc
+		    x > 0 && x <= INT_MAX)
5113bc
+			return x;
5113bc
+	}
5113bc
+
5113bc
+	return -1;
5113bc
+}
5113bc
+
5113bc
+int get_terminal_dimension(int *cols, int *lines)
5113bc
+{
5113bc
+	int c = 0, l = 0;
5113bc
+
5113bc
+#if defined(TIOCGWINSZ)
5113bc
+	struct winsize	w_win;
5113bc
+	if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w_win) == 0) {
5113bc
+		c = w_win.ws_col;
5113bc
+		l = w_win.ws_row;
5113bc
+	}
5113bc
+#elif defined(TIOCGSIZE)
5113bc
+	struct ttysize	t_win;
5113bc
+	if (ioctl (STDOUT_FILENO, TIOCGSIZE, &t_win) == 0) {
5113bc
+		c = t_win.ts_cols;
5113bc
+		l = t_win.ts_lines;
5113bc
+	}
5113bc
+#endif
5113bc
+
5113bc
+	if (cols && c <= 0)
5113bc
+		c = get_env_int("COLUMNS");
5113bc
+	if (lines && l <= 0)
5113bc
+		l = get_env_int("LINES");
5113bc
+
5113bc
+	if (cols)
5113bc
+		*cols = c;
5113bc
+	if (lines)
5113bc
+		*lines = l;
5113bc
+	return 0;
5113bc
+}
5113bc
+
5113bc
 int get_terminal_width(void)
5113bc
 {
5113bc
 #ifdef TIOCGSIZE
5113bc
diff --git a/libfdisk/src/ask.c b/libfdisk/src/ask.c
5113bc
index cdb4d0124..a10f3dc82 100644
5113bc
--- a/libfdisk/src/ask.c
5113bc
+++ b/libfdisk/src/ask.c
5113bc
@@ -42,7 +42,7 @@ const char *fdisk_ask_get_query(struct fdisk_ask *ask)
5113bc
 int fdisk_ask_set_query(struct fdisk_ask *ask, const char *str)
5113bc
 {
5113bc
 	assert(ask);
5113bc
-	return !strdup_to_struct_member(ask, query, str) ? -ENOMEM : 0;
5113bc
+	return strdup_to_struct_member(ask, query, str);
5113bc
 }
5113bc
 
5113bc
 int fdisk_ask_get_type(struct fdisk_ask *ask)
5113bc
@@ -90,7 +90,7 @@ const char *fdisk_ask_number_get_range(struct fdisk_ask *ask)
5113bc
 int fdisk_ask_number_set_range(struct fdisk_ask *ask, const char *range)
5113bc
 {
5113bc
 	assert(ask);
5113bc
-	return !strdup_to_struct_member(ask, data.num.range, range) ? -ENOMEM : 0;
5113bc
+	return strdup_to_struct_member(ask, data.num.range, range);
5113bc
 }
5113bc
 
5113bc
 uint64_t fdisk_ask_number_get_default(struct fdisk_ask *ask)
5113bc
-- 
5113bc
2.14.4
5113bc