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