From 9bf4499dd7c72db7636555ec386804540a3266fe Mon Sep 17 00:00:00 2001
From: Audun-Marius Gangstø <audun@gangsto.org>
Date: Sat, 21 Nov 2020 12:26:39 +0100
Subject: lineedit: fix unicode characters in prompt
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

function                                             old     new   delta
parse_and_put_prompt                                 779     823     +44

Signed-off-by: Audun-Marius Gangstø <audun@gangsto.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index e40a72064..a3b798e3f 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2029,10 +2029,17 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 			if (c == '\n')
 				cmdedit_prmt_len = 0;
 			else if (flg_not_length != ']') {
-#if 0 /*ENABLE_UNICODE_SUPPORT*/
-/* Won't work, pbuf is one BYTE string here instead of an one Unicode char string. */
-/* FIXME */
-				cmdedit_prmt_len += unicode_strwidth(pbuf);
+#if ENABLE_UNICODE_SUPPORT
+				if (n == 1) {
+					/* Only count single-byte characters and the first of multi-byte characters */
+					if ((unsigned char)*pbuf < 0x80  /* single byte character */
+					 || (unsigned char)*pbuf >= 0xc0 /* first of multi-byte characters */
+					) {
+						cmdedit_prmt_len += n;
+					}
+				} else {
+					cmdedit_prmt_len += unicode_strwidth(pbuf);
+				}
 #else
 				cmdedit_prmt_len += n;
 #endif
-- 
cgit v1.2.3-55-g6feb


From 12aa68d10fdcc5bd2d9385506d11aed3a0c2eaf1 Mon Sep 17 00:00:00 2001
From: Jan Klötzke <jan@kloetzke.net>
Date: Mon, 16 Dec 2019 22:56:49 +0100
Subject: libbb: set netlink socket revbuf size before binding
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

As soon as the socket is bound it will receive messages. Make sure the
recieve buffer size is increased before the first message is received.

Signed-off-by: Jan Klötzke <jan@kloetzke.net>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/xconnect.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

(limited to 'libbb')

diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index e9a2470e4..5dd9cfd28 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -422,17 +422,14 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf)
 	struct sockaddr_nl sa;
 	int fd;
 
-	memset(&sa, 0, sizeof(sa));
-	sa.nl_family = AF_NETLINK;
-	sa.nl_pid = getpid();
-	sa.nl_groups = grp;
 	fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto);
-	xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
-	close_on_exec_on(fd);
 
+	/* Set receive buffer size before binding the socket
+	 * We want to have enough space before we start receiving messages.
+	 */
 	if (rcvbuf != 0) {
-		// SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
-		setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF,      rcvbuf);
+		setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf);
+		/* SO_RCVBUFFORCE (root only) can go above net.core.rmem_max */
 		setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf);
 # if 0
 		{
@@ -444,6 +441,13 @@ int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf)
 # endif
 	}
 
+	memset(&sa, 0, sizeof(sa));
+	sa.nl_family = AF_NETLINK;
+	sa.nl_pid = getpid();
+	sa.nl_groups = grp;
+	xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
+	close_on_exec_on(fd);
+
 	return fd;
 }
 #endif
-- 
cgit v1.2.3-55-g6feb


From 20900489a1fff2a563999d90e24239206f202b21 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 25 Nov 2020 22:47:00 +0100
Subject: base32: new applet

function                                             old     new   delta
baseNUM_main                                           -     568    +568
decode_base32                                          -     275    +275
bb_uuenc_tbl_base32                                    -      34     +34
read_base64                                          218     236     +18
applet_names                                        2732    2739      +7
applet_main                                         1580    1584      +4
packed_usage                                       33480   33478      -2
base64_main                                          208       -    -208
------------------------------------------------------------------------------
(add/remove: 3/1 grow/shrink: 3/1 up/down: 906/-210)          Total: 696 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 coreutils/uudecode.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++-----
 include/libbb.h      |   3 ++
 libbb/uuencode.c     |  84 ++++++++++++++++++++++++++++++++++--
 3 files changed, 192 insertions(+), 13 deletions(-)

(limited to 'libbb')

diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c
index 5b2edd649..e4fb0d48b 100644
--- a/coreutils/uudecode.c
+++ b/coreutils/uudecode.c
@@ -168,9 +168,11 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv)
 }
 #endif
 
-//applet:IF_BASE64(APPLET(base64, BB_DIR_BIN, BB_SUID_DROP))
-
-//kbuild:lib-$(CONFIG_BASE64) += uudecode.o
+//config:config BASE32
+//config:	bool "base32 (4.9 kb)"
+//config:	default y
+//config:	help
+//config:	Base32 encode and decode
 
 //config:config BASE64
 //config:	bool "base64 (4.9 kb)"
@@ -178,6 +180,14 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv)
 //config:	help
 //config:	Base64 encode and decode
 
+//usage:#define base32_trivial_usage
+//usage:	"[-d] [FILE]"
+//usage:#define base32_full_usage "\n\n"
+//usage:       "Base32 encode or decode FILE to standard output"
+//usage:     "\n	-d	Decode data"
+////usage:     "\n	-w COL	Wrap lines at COL (default 76, 0 disables)"
+////usage:     "\n	-i	When decoding, ignore non-alphabet characters"
+
 //usage:#define base64_trivial_usage
 //usage:	"[-d] [FILE]"
 //usage:#define base64_full_usage "\n\n"
@@ -186,9 +196,77 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv)
 ////usage:     "\n	-w COL	Wrap lines at COL (default 76, 0 disables)"
 ////usage:     "\n	-i	When decoding, ignore non-alphabet characters"
 
-#if ENABLE_BASE64
-int base64_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int base64_main(int argc UNUSED_PARAM, char **argv)
+//                 APPLET_ODDNAME:name    main     location    suid_type     help
+//applet:IF_BASE32(APPLET_ODDNAME(base32, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base32))
+//applet:IF_BASE64(APPLET_ODDNAME(base64, baseNUM, BB_DIR_BIN, BB_SUID_DROP, base64))
+
+//kbuild:lib-$(CONFIG_BASE64) += uudecode.o
+//kbuild:lib-$(CONFIG_BASE32) += uudecode.o
+
+#if ENABLE_BASE32 || ENABLE_BASE64
+
+# if ENABLE_BASE32
+static void bb_b32encode(char *p, const void *src, int length)
+{
+#define tbl bb_uuenc_tbl_base32
+	const unsigned char *s = src;
+
+	/* Transform 5x8 bits to 8x5 bits */
+	while (length > 0) {
+		unsigned cur, next;
+
+		length--;
+		cur = *s++;
+		*p++ = tbl[cur >> 3];			// xxxxx--- -------- -------- -------- --------
+		cur &= 7;
+
+		next = 0;
+		if (--length >= 0)
+			next = *s++;
+		*p++ = tbl[(cur << 2) + (next >> 6)];	// -----xxx xx------ -------- -------- --------
+		cur = next & 0x3f;
+
+		*p++ = tbl[cur >> 1];			// -------- --xxxxx- -------- -------- --------
+		cur &= 1;
+
+		next = 0;
+		if (--length >= 0)
+			next = *s++;
+		*p++ = tbl[(cur << 4) + (next >> 4)];	// -------- -------x xxxx---- -------- --------
+		cur = next & 0xf;
+
+		next = 0;
+		if (--length >= 0)
+			next = *s++;
+		*p++ = tbl[(cur << 1) + (next >> 7)];	// -------- -------- ----xxxx x------- --------
+		cur = next & 0x7f;
+
+		*p++ = tbl[cur >> 2];			// -------- -------- -------- -xxxxx-- --------
+		cur &= 3;
+
+		next = 0;
+		if (--length >= 0)
+			next = *s++;
+		*p++ = tbl[(cur << 3) + (next >> 5)];	// -------- -------- -------- ------xx xxx-----
+		cur = next & 0x1f;
+
+		*p++ = tbl[cur];			// -------- -------- -------- -------- ---xxxxx
+	}
+#undef tbl
+	/* Zero-terminate */
+	*p = '\0';
+	/* Pad as necessary */
+	length = ((-length) * 3) >> 1; /* -4 => 6 pad chars, -3 => 4, -2 => 3, -1 => 1 */
+	while (length--) {
+		*--p = '=';
+	}
+}
+# else
+void bb_b32encode(char *p, const void *src, int length); /* undefined */
+# endif
+
+int baseNUM_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int baseNUM_main(int argc UNUSED_PARAM, char **argv)
 {
 	FILE *src_stream;
 	unsigned opts;
@@ -200,7 +278,10 @@ int base64_main(int argc UNUSED_PARAM, char **argv)
 		*--argv = (char*)"-";
 	src_stream = xfopen_stdin(argv[0]);
 	if (opts) {
-		read_base64(src_stream, stdout, /*flags:*/ (unsigned char)EOF);
+		int flags = (unsigned char)EOF;
+		if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3'))
+			flags = ((unsigned char)EOF) | BASE64_32;
+		read_base64(src_stream, stdout, flags);
 	} else {
 		enum {
 			SRC_BUF_SIZE = 76 / 4 * 3, /* this *MUST* be a multiple of 3 */
@@ -210,14 +291,31 @@ int base64_main(int argc UNUSED_PARAM, char **argv)
 		char dst_buf[DST_BUF_SIZE + 1];
 		int src_fd = fileno(src_stream);
 		while (1) {
-			size_t size = full_read(src_fd, src_buf, SRC_BUF_SIZE);
+			size_t size;
+			if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3'))
+				size = 72 / 8 * 5;
+//FIXME: wrong, default width of base32 is not 72, but 76 chars
+//(not a multiple of 8 - requires adding wrapping logic)
+//when this is fixed, can implement -w COL too
+			else
+				size = SRC_BUF_SIZE;
+
+			size = full_read(src_fd, src_buf, size);
 			if (!size)
 				break;
 			if ((ssize_t)size < 0)
 				bb_simple_perror_msg_and_die(bb_msg_read_error);
+
 			/* Encode the buffer we just read in */
-			bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
-			xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3));
+			if (ENABLE_BASE32 && (!ENABLE_BASE64 || applet_name[4] == '3')) {
+				bb_b32encode(dst_buf, src_buf, size);
+				size = 8 * ((size + 4) / 5);
+			} else {
+				bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
+				size = 4 * ((size + 2) / 3);
+			}
+
+			xwrite(STDOUT_FILENO, dst_buf, size);
 			bb_putchar('\n');
 			fflush(stdout);
 		}
diff --git a/include/libbb.h b/include/libbb.h
index 1b7c0b83a..ef4a34f07 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2026,14 +2026,17 @@ char *percent_decode_in_place(char *str, int strict) FAST_FUNC;
 
 
 extern const char bb_uuenc_tbl_base64[] ALIGN1;
+extern const char bb_uuenc_tbl_base32[] ALIGN1;
 extern const char bb_uuenc_tbl_std[] ALIGN1;
 void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
 enum {
 	BASE64_FLAG_UU_STOP = 0x100,
+	BASE64_32           = 0x200, /* base32 */
 	/* Sign-extends to a value which never matches fgetc result: */
 	BASE64_FLAG_NO_STOP_CHAR = 0x80,
 };
 const char *decode_base64(char **pp_dst, const char *src) FAST_FUNC;
+const char *decode_base32(char **pp_dst, const char *src) FAST_FUNC;
 void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC;
 
 typedef struct md5_ctx_t {
diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index d36b34f63..b4ee20c20 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -8,7 +8,8 @@
  */
 #include "libbb.h"
 
-/* Conversion table.  for base 64 */
+/* Conversion tables */
+/* for base 64 */
 const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = {
 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
@@ -21,7 +22,16 @@ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = {
 	'=' /* termination character */,
 	'\0' /* needed for uudecode.c only */
 };
-
+#if ENABLE_BASE32
+const char bb_uuenc_tbl_base32[33 + 1] ALIGN1 = {
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+	'Y', 'Z', '2', '3', '4', '5', '6', '7',
+	'=',
+	'\0'
+};
+#endif
 const char bb_uuenc_tbl_std[65] ALIGN1 = {
 	'`', '!', '"', '#', '$', '%', '&', '\'',
 	'(', ')', '*', '+', ',', '-', '.', '/',
@@ -153,6 +163,68 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 	return src_tail;
 }
 
+#if ENABLE_BASE32
+const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
+{
+	char *dst = *pp_dst;
+	const char *src_tail;
+
+	while (1) {
+		unsigned char five_bit[8];
+		int count = 0;
+
+		/* Fetch up to eight 5-bit values */
+		src_tail = src;
+		while (count < 8) {
+			char *table_ptr;
+			int ch;
+
+			/* Get next _valid_ character.
+			 * bb_uuenc_tbl_base32[] contains this string:
+			 *  0         1         2         3
+			 *  01234567890123456789012345678901
+			 * "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
+			 */
+			do {
+				ch = *src;
+				if (ch == '\0') {
+					if (count == 0) {
+						src_tail = src;
+					}
+					goto ret;
+				}
+				src++;
+				table_ptr = strchr(bb_uuenc_tbl_base32, toupper(ch));
+			} while (!table_ptr);
+
+			/* Convert encoded character to decimal */
+			ch = table_ptr - bb_uuenc_tbl_base32;
+
+			/* ch is 32 if char was '=', otherwise 0..31 */
+			if (ch == 32)
+				break;
+			five_bit[count] = ch;
+			count++;
+		}
+
+		/* Transform 5-bit values to 8-bit ones */
+		if (count > 1)                                        // xxxxx xxx-- ----- ----- ----- ----- ----- -----
+			*dst++ = five_bit[0] << 3 | five_bit[1] >> 2;
+		if (count > 3)                                        // ----- ---xx xxxxx x---- ----- ----- ----- -----
+			*dst++ = five_bit[1] << 6 | five_bit[2] << 1 | five_bit[3] >> 4;
+		if (count > 4)                                        // ----- ----- ----- -xxxx xxxx- ----- ----- -----
+			*dst++ = five_bit[3] << 4 | five_bit[4] >> 1;
+		if (count > 6)                                        // ----- ----- ----- ----- ----x xxxxx xx--- -----
+			*dst++ = five_bit[4] << 7 | five_bit[5] << 2 | five_bit[6] >> 3;
+		if (count > 7)                                        // ----- ----- ----- ----- ----- ----- --xxx xxxxx
+			*dst++ = five_bit[6] << 5 | five_bit[7];
+	} /* while (1) */
+ ret:
+	*pp_dst = dst;
+	return src_tail;
+}
+#endif
+
 /*
  * Decode base64 encoded stream.
  * Can stop on EOF, specified char, or on uuencode-style "====" line:
@@ -163,6 +235,7 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 /* Note that EOF _can_ be passed as exit_char too */
 #define exit_char    ((int)(signed char)flags)
 #define uu_style_end (flags & BASE64_FLAG_UU_STOP)
+#define base32       (flags & BASE64_32)
 
 	/* uuencoded files have 61 byte lines. Use 64 byte buffer
 	 * to process line at a time.
@@ -204,7 +277,12 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 			return;
 
 		out_tail = out_buf;
-		in_tail = decode_base64(&out_tail, in_buf);
+#if ENABLE_BASE32
+		if (base32)
+			in_tail = decode_base32(&out_tail, in_buf);
+		else
+#endif
+			in_tail = decode_base64(&out_tail, in_buf);
 
 		fwrite(out_buf, (out_tail - out_buf), 1, dst_stream);
 
-- 
cgit v1.2.3-55-g6feb


From 170b8628fabff2d81606cac052a35f8cf91cc7b2 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 27 Nov 2020 20:44:55 +0100
Subject: libbb: smaller and faster decode_base64()

function                                             old     new   delta
decode_base64                                        195     180     -15

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/uuencode.c   | 100 +++++++++++++++++++----------------------------------
 networking/httpd.c |  37 --------------------
 2 files changed, 36 insertions(+), 101 deletions(-)

(limited to 'libbb')

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index b4ee20c20..2e9edb219 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -82,7 +82,7 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl
 }
 
 /*
- * Decode base64 encoded string. Stops on '\0'.
+ * Decode base64 encoded string. Stops on NUL after terminating "=" or "==".
  *
  * Returns: pointer to the undecoded part of source.
  * If points to '\0', then the source was fully decoded.
@@ -91,76 +91,48 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl
 const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 {
 	char *dst = *pp_dst;
-	const char *src_tail;
-
-	while (1) {
-		unsigned char six_bit[4];
-		int count = 0;
+	unsigned ch = 0;
+	int i = 0;
 
-		/* Fetch up to four 6-bit values */
-		src_tail = src;
-		while (count < 4) {
-			char *table_ptr;
-			int ch;
+	while (*src) {
+		int t = (unsigned char)*src++;
 
-			/* Get next _valid_ character.
-			 * bb_uuenc_tbl_base64[] contains this string:
-			 *  0         1         2         3         4         5         6
-			 *  01234567890123456789012345678901234567890123456789012345678901234
-			 * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
-			 */
-			do {
-				ch = *src;
-				if (ch == '\0') {
-					if (count == 0) {
-						/* Example:
-						 * If we decode "QUJD <NUL>", we want
-						 * to return ptr to NUL, not to ' ',
-						 * because we did fully decode
-						 * the string (to "ABC").
-						 */
-						src_tail = src;
-					}
-					goto ret;
-				}
-				src++;
-				table_ptr = strchr(bb_uuenc_tbl_base64, ch);
+		/* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */
+		if (t >= '0' && t <= '9')
+			t = t - '0' + 52;
+		else if (t >= 'A' && t <= 'Z')
+			t = t - 'A';
+		else if (t >= 'a' && t <= 'z')
+			t = t - 'a' + 26;
+		else if (t == '+')
+			t = 62;
+		else if (t == '/')
+			t = 63;
+		else if (t == '=' && (i == 3 || (i == 2 && *src == '=')))
+			/* the above disallows "==AA", "A===", "AA=A" etc */
+			t = 0x1000000;
+		else
 //TODO: add BASE64_FLAG_foo to die on bad char?
-			} while (!table_ptr);
-
-			/* Convert encoded character to decimal */
-			ch = table_ptr - bb_uuenc_tbl_base64;
+			continue;
 
-			/* ch is 64 if char was '=', otherwise 0..63 */
-			if (ch == 64)
+		ch = (ch << 6) | t;
+		if (++i == 4) {
+			*dst++ = (char) (ch >> 16);
+			*dst++ = (char) (ch >> 8);
+			*dst++ = (char) ch;
+			i = 0;
+			if (ch & 0x1000000) { /* was last input char '='? */
+				dst--;
+				if (ch & (0x1000000 << 6)) /* was it "=="? */
+					dst--;
 				break;
-			six_bit[count] = ch;
-			count++;
+			}
+			ch = 0;
 		}
-
-		/* Transform 6-bit values to 8-bit ones.
-		 * count can be < 4 when we decode the tail:
-		 * "eQ==" -> "y", not "y NUL NUL".
-		 * Note that (count > 1) is always true,
-		 * "x===" encoding is not valid:
-		 * even a single zero byte encodes as "AA==".
-		 * However, with current logic we come here with count == 1
-		 * when we decode "==" tail.
-		 */
-		if (count > 1)
-			*dst++ = six_bit[0] << 2 | six_bit[1] >> 4;
-		if (count > 2)
-			*dst++ = six_bit[1] << 4 | six_bit[2] >> 2;
-		if (count > 3)
-			*dst++ = six_bit[2] << 6 | six_bit[3];
-		/* Note that if we decode "AA==" and ate first '=',
-		 * we just decoded one char (count == 2) and now we'll
-		 * do the loop once more to decode second '='.
-		 */
-	} /* while (1) */
- ret:
+	}
 	*pp_dst = dst;
-	return src_tail;
+	/* i should be zero here if full 4-char block was decoded */
+	return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
 }
 
 #if ENABLE_BASE32
diff --git a/networking/httpd.c b/networking/httpd.c
index 961f8cab4..4ffd89c48 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1017,46 +1017,9 @@ static char *encodeString(const char *string)
  */
 static void decodeBase64(char *Data)
 {
-# if ENABLE_BASE64 || ENABLE_UUDECODE
-	/* Call decode_base64() from uuencode.c */
 	char *eptr = Data;
 	decode_base64(&eptr, Data);
 	*eptr = '\0';
-# else
-	const unsigned char *in = (const unsigned char *)Data;
-	/* The decoded size will be at most 3/4 the size of the encoded */
-	unsigned ch = 0;
-	int i = 0;
-
-	while (*in) {
-		int t = *in++;
-
-		if (t >= '0' && t <= '9')
-			t = t - '0' + 52;
-		else if (t >= 'A' && t <= 'Z')
-			t = t - 'A';
-		else if (t >= 'a' && t <= 'z')
-			t = t - 'a' + 26;
-		else if (t == '+')
-			t = 62;
-		else if (t == '/')
-			t = 63;
-		else if (t == '=')
-			t = 0;
-		else
-			continue;
-
-		ch = (ch << 6) | t;
-		i++;
-		if (i == 4) {
-			*Data++ = (char) (ch >> 16);
-			*Data++ = (char) (ch >> 8);
-			*Data++ = (char) ch;
-			i = 0;
-		}
-	}
-	*Data = '\0';
-# endif
 }
 #endif
 
-- 
cgit v1.2.3-55-g6feb


From 2cd37d65e221f7267e97360d21f55a2318b25355 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 27 Nov 2020 21:25:34 +0100
Subject: libbb: faster and smaller decode_base32()

function                                             old     new   delta
decode_base32                                        275     224     -51

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/uuencode.c | 84 +++++++++++++++++++++++---------------------------------
 1 file changed, 34 insertions(+), 50 deletions(-)

(limited to 'libbb')

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 2e9edb219..7c7f1cf1c 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -82,7 +82,7 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl
 }
 
 /*
- * Decode base64 encoded string. Stops on NUL after terminating "=" or "==".
+ * Decode base64 encoded string.
  *
  * Returns: pointer to the undecoded part of source.
  * If points to '\0', then the source was fully decoded.
@@ -139,61 +139,45 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 {
 	char *dst = *pp_dst;
-	const char *src_tail;
-
-	while (1) {
-		unsigned char five_bit[8];
-		int count = 0;
-
-		/* Fetch up to eight 5-bit values */
-		src_tail = src;
-		while (count < 8) {
-			char *table_ptr;
-			int ch;
+	uint64_t ch = 0;
+	int i = 0;
 
-			/* Get next _valid_ character.
-			 * bb_uuenc_tbl_base32[] contains this string:
-			 *  0         1         2         3
-			 *  01234567890123456789012345678901
-			 * "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
-			 */
-			do {
-				ch = *src;
-				if (ch == '\0') {
-					if (count == 0) {
-						src_tail = src;
-					}
-					goto ret;
-				}
-				src++;
-				table_ptr = strchr(bb_uuenc_tbl_base32, toupper(ch));
-			} while (!table_ptr);
+	while (*src) {
+		int t = (unsigned char)*src++;
 
-			/* Convert encoded character to decimal */
-			ch = table_ptr - bb_uuenc_tbl_base32;
+		/* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
+		if (t >= '2' && t <= '7')
+			t = t - '2' + 26;
+		else if ((t|0x20) >= 'a' && (t|0x20) <= 'z')
+			t = (t|0x20) - 'a';
+		else if (t == '=' && i > 1)
+			t = 0;
+		else
+//TODO: add BASE64_FLAG_foo to die on bad char?
+			continue;
 
-			/* ch is 32 if char was '=', otherwise 0..31 */
-			if (ch == 32)
+		ch = (ch << 5) | t;
+		if (++i == 8) {
+			*dst++ = (char) (ch >> 32);
+			*dst++ = (char) (ch >> 24);
+			*dst++ = (char) (ch >> 16);
+			*dst++ = (char) (ch >> 8);
+			*dst++ = (char) ch;
+			if (t == 0 && src[-1] == '=') { /* was last input char '='? */
+				const char *s = src;
+				while (*--s == '=' && --i != 0)
+					continue;
+				i = 8 - i; /* count of =, must be 1, 3, 4 or 6 */
+				dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
+				i = 0;
 				break;
-			five_bit[count] = ch;
-			count++;
+			}
+			i = 0;
 		}
-
-		/* Transform 5-bit values to 8-bit ones */
-		if (count > 1)                                        // xxxxx xxx-- ----- ----- ----- ----- ----- -----
-			*dst++ = five_bit[0] << 3 | five_bit[1] >> 2;
-		if (count > 3)                                        // ----- ---xx xxxxx x---- ----- ----- ----- -----
-			*dst++ = five_bit[1] << 6 | five_bit[2] << 1 | five_bit[3] >> 4;
-		if (count > 4)                                        // ----- ----- ----- -xxxx xxxx- ----- ----- -----
-			*dst++ = five_bit[3] << 4 | five_bit[4] >> 1;
-		if (count > 6)                                        // ----- ----- ----- ----- ----x xxxxx xx--- -----
-			*dst++ = five_bit[4] << 7 | five_bit[5] << 2 | five_bit[6] >> 3;
-		if (count > 7)                                        // ----- ----- ----- ----- ----- ----- --xxx xxxxx
-			*dst++ = five_bit[6] << 5 | five_bit[7];
-	} /* while (1) */
- ret:
+	}
 	*pp_dst = dst;
-	return src_tail;
+	/* i should be zero here if full 8-char block was decoded */
+	return src - i;
 }
 #endif
 
-- 
cgit v1.2.3-55-g6feb


From 7467e905e558228aab992f85406382518f2e1666 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 28 Nov 2020 09:50:14 +0100
Subject: base32/64: code shrink

function                                             old     new   delta
decode_base64                                        180     178      -2
decode_base32                                        224     217      -7
read_base64                                          236     222     -14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-23)             Total: -23 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/uuencode.c | 75 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 43 insertions(+), 32 deletions(-)

(limited to 'libbb')

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 7c7f1cf1c..0e6fc8a3c 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -93,9 +93,10 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 	char *dst = *pp_dst;
 	unsigned ch = 0;
 	int i = 0;
+	int t;
 
-	while (*src) {
-		int t = (unsigned char)*src++;
+	while ((t = (unsigned char)*src) != '\0') {
+		src++;
 
 		/* "if" forest is faster than strchr(bb_uuenc_tbl_base64, t) */
 		if (t >= '0' && t <= '9')
@@ -131,7 +132,7 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 		}
 	}
 	*pp_dst = dst;
-	/* i should be zero here if full 4-char block was decoded */
+	/* i is zero here if full 4-char block was decoded */
 	return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
 }
 
@@ -141,9 +142,10 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 	char *dst = *pp_dst;
 	uint64_t ch = 0;
 	int i = 0;
+	int t;
 
-	while (*src) {
-		int t = (unsigned char)*src++;
+	while ((t = (unsigned char)*src) != '\0') {
+		src++;
 
 		/* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
 		if (t >= '2' && t <= '7')
@@ -156,27 +158,35 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 //TODO: add BASE64_FLAG_foo to die on bad char?
 			continue;
 
-		ch = (ch << 5) | t;
+		ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */
 		if (++i == 8) {
+			/* testcase:
+			 * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d
+			 * IOW, decoding of
+			 * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI==
+			 * ====
+			 * should correctly stitch together the tail.
+			 */
+			if (t == 0) {
+				const char *s = src;
+				while (*--s == '=')
+					t--;
+			}
 			*dst++ = (char) (ch >> 32);
 			*dst++ = (char) (ch >> 24);
 			*dst++ = (char) (ch >> 16);
 			*dst++ = (char) (ch >> 8);
 			*dst++ = (char) ch;
-			if (t == 0 && src[-1] == '=') { /* was last input char '='? */
-				const char *s = src;
-				while (*--s == '=' && --i != 0)
-					continue;
-				i = 8 - i; /* count of =, must be 1, 3, 4 or 6 */
-				dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
-				i = 0;
-				break;
-			}
 			i = 0;
+			if (t < 0) /* was last input char '='? */
+				break;
 		}
 	}
+	if (t < 0) /* was last input char '='? */
+		/* -t is the count of =, must be 1, 3, 4 or 6 */
+		dst -= (-t + 1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
 	*pp_dst = dst;
-	/* i should be zero here if full 8-char block was decoded */
+	/* i is zero here if full 8-char block was decoded */
 	return src - i;
 }
 #endif
@@ -193,19 +203,20 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 #define uu_style_end (flags & BASE64_FLAG_UU_STOP)
 #define base32       (flags & BASE64_32)
 
-	/* uuencoded files have 61 byte lines. Use 64 byte buffer
-	 * to process line at a time.
+	/* uuencoded files have 61 byte lines.
+	 * base32/64 have 76 byte lines by default.
+	 * Use 80 byte buffer to process one line at a time.
 	 */
-	enum { BUFFER_SIZE = 64 };
-
-	char in_buf[BUFFER_SIZE + 2];
-	char out_buf[BUFFER_SIZE / 4 * 3 + 2];
-	char *out_tail;
-	const char *in_tail;
+	enum { BUFFER_SIZE = 80 };
+	/* decoded data is shorter than input, can use single buffer for both */
+	char buf[BUFFER_SIZE + 2];
 	int term_seen = 0;
 	int in_count = 0;
 
 	while (1) {
+		char *out_tail;
+		const char *in_tail;
+
 		while (in_count < BUFFER_SIZE) {
 			int ch = fgetc(src_stream);
 			if (ch == exit_char) {
@@ -224,23 +235,23 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 			 */
 			if (ch <= ' ')
 				break;
-			in_buf[in_count++] = ch;
+			buf[in_count++] = ch;
 		}
-		in_buf[in_count] = '\0';
+		buf[in_count] = '\0';
 
 		/* Did we encounter "====" line? */
-		if (uu_style_end && strcmp(in_buf, "====") == 0)
+		if (uu_style_end && strcmp(buf, "====") == 0)
 			return;
 
-		out_tail = out_buf;
+		out_tail = buf;
 #if ENABLE_BASE32
 		if (base32)
-			in_tail = decode_base32(&out_tail, in_buf);
+			in_tail = decode_base32(&out_tail, buf);
 		else
 #endif
-			in_tail = decode_base64(&out_tail, in_buf);
+			in_tail = decode_base64(&out_tail, buf);
 
-		fwrite(out_buf, (out_tail - out_buf), 1, dst_stream);
+		fwrite(buf, (out_tail - buf), 1, dst_stream);
 
 		if (term_seen) {
 			/* Did we consume ALL characters? */
@@ -252,6 +263,6 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 
 		/* It was partial decode */
 		in_count = strlen(in_tail);
-		memmove(in_buf, in_tail, in_count);
+		memmove(buf, in_tail, in_count);
 	}
 }
-- 
cgit v1.2.3-55-g6feb


From f140b49f5f631b09acf7811933d843fe17f06343 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 28 Nov 2020 12:33:50 +0100
Subject: base32/64: code shrink

function                                             old     new   delta
decode_base64                                        178     173      -5
decode_base32                                        217     186     -31
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-36)             Total: -36 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/uuencode.c | 66 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 37 insertions(+), 29 deletions(-)

(limited to 'libbb')

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 0e6fc8a3c..6205af261 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -92,8 +92,8 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 {
 	char *dst = *pp_dst;
 	unsigned ch = 0;
+	unsigned t;
 	int i = 0;
-	int t;
 
 	while ((t = (unsigned char)*src) != '\0') {
 		src++;
@@ -117,11 +117,11 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 			continue;
 
 		ch = (ch << 6) | t;
-		if (++i == 4) {
+		i = (i + 1) & 3;
+		if (i == 0) {
 			*dst++ = (char) (ch >> 16);
 			*dst++ = (char) (ch >> 8);
 			*dst++ = (char) ch;
-			i = 0;
 			if (ch & 0x1000000) { /* was last input char '='? */
 				dst--;
 				if (ch & (0x1000000 << 6)) /* was it "=="? */
@@ -140,9 +140,9 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 {
 	char *dst = *pp_dst;
-	uint64_t ch = 0;
+	int64_t ch = 0;
+	unsigned t;
 	int i = 0;
-	int t;
 
 	while ((t = (unsigned char)*src) != '\0') {
 		src++;
@@ -150,44 +150,52 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 		/* "if" forest is faster than strchr(bb_uuenc_tbl_base32, t) */
 		if (t >= '2' && t <= '7')
 			t = t - '2' + 26;
-		else if ((t|0x20) >= 'a' && (t|0x20) <= 'z')
-			t = (t|0x20) - 'a';
 		else if (t == '=' && i > 1)
 			t = 0;
-		else
+		else {
+			t = (t | 0x20) - 'a';
+			if (t > 25)
 //TODO: add BASE64_FLAG_foo to die on bad char?
-			continue;
+				continue;
+		}
 
-		ch = (ch << 5) | (unsigned)t; /* cast prevents pointless sign-extension of t */
-		if (++i == 8) {
-			/* testcase:
-			 * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d
-			 * IOW, decoding of
-			 * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI==
-			 * ====
-			 * should correctly stitch together the tail.
-			 */
-			if (t == 0) {
-				const char *s = src;
-				while (*--s == '=')
-					t--;
-			}
+		ch = (ch << 5) | t;
+		i = (i + 1) & 7;
+		if (i == 0) {
 			*dst++ = (char) (ch >> 32);
+			if (src[-1] == '=') /* was last input char '='? */
+				goto tail;
 			*dst++ = (char) (ch >> 24);
 			*dst++ = (char) (ch >> 16);
 			*dst++ = (char) (ch >> 8);
 			*dst++ = (char) ch;
-			i = 0;
-			if (t < 0) /* was last input char '='? */
-				break;
 		}
 	}
-	if (t < 0) /* was last input char '='? */
-		/* -t is the count of =, must be 1, 3, 4 or 6 */
-		dst -= (-t + 1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
 	*pp_dst = dst;
 	/* i is zero here if full 8-char block was decoded */
 	return src - i;
+ tail:
+	{
+		const char *s = src;
+		while (*--s == '=')
+			i++;
+		/* Why duplicate the below code? Testcase:
+		 * echo ' 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18' | base32 | base32 -d
+		 * IOW, decoding of
+		 * EAYSAMRAGMQDIIBVEA3CANZAHAQDSIBRGAQDCMJAGEZCAMJTEAYTIIBRGUQDCNRAGE3SAMJYBI==
+		 * ====
+		 * must correctly stitch together the tail, must not overwrite
+		 * the tail before it is analyzed! (we can be decoding in-place)
+		 * Else testcase fails, prints trailing extra NUL bytes.
+		 */
+		*dst++ = (char) (ch >> 24);
+		*dst++ = (char) (ch >> 16);
+		*dst++ = (char) (ch >> 8);
+		*dst++ = (char) ch;
+		dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
+	}
+	*pp_dst = dst;
+	return src;
 }
 #endif
 
-- 
cgit v1.2.3-55-g6feb


From fc6faac84e978c9482106f53e711ab971a0ce188 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 28 Nov 2020 12:48:34 +0100
Subject: libbb: trim base32/64 tables

function                                             old     new   delta
bb_uuenc_tbl_base64                                   66      65      -1
bb_uuenc_tbl_base32                                   34      32      -2

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/uuencode.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

(limited to 'libbb')

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 6205af261..139c60bd5 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -9,8 +9,17 @@
 #include "libbb.h"
 
 /* Conversion tables */
+#if ENABLE_BASE32
+const char bb_uuenc_tbl_base32[] ALIGN1 = {
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+	'Y', 'Z', '2', '3', '4', '5', '6', '7',
+	/* unused: '=', */
+};
+#endif
 /* for base 64 */
-const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = {
+const char bb_uuenc_tbl_base64[] ALIGN1 = {
 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
 	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
 	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
@@ -20,19 +29,8 @@ const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = {
 	'w', 'x', 'y', 'z', '0', '1', '2', '3',
 	'4', '5', '6', '7', '8', '9', '+', '/',
 	'=' /* termination character */,
-	'\0' /* needed for uudecode.c only */
 };
-#if ENABLE_BASE32
-const char bb_uuenc_tbl_base32[33 + 1] ALIGN1 = {
-	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-	'Y', 'Z', '2', '3', '4', '5', '6', '7',
-	'=',
-	'\0'
-};
-#endif
-const char bb_uuenc_tbl_std[65] ALIGN1 = {
+const char bb_uuenc_tbl_std[] ALIGN1 = {
 	'`', '!', '"', '#', '$', '%', '&', '\'',
 	'(', ')', '*', '+', ',', '-', '.', '/',
 	'0', '1', '2', '3', '4', '5', '6', '7',
-- 
cgit v1.2.3-55-g6feb


From 885121e25db2ec9a8191a406085d91790a133d20 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 28 Nov 2020 13:26:44 +0100
Subject: libbb: change decode_base32/64 API to return the end of _dst_, not
 _src_.

function                                             old     new   delta
decode_base64                                        173     178      +5
read_base64                                          222     220      -2
decode_base32                                        186     182      -4
handle_incoming_and_exit                            2263    2239     -24
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 5/-30)             Total: -25 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h    |  4 ++--
 libbb/uuencode.c   | 29 +++++++++++++++--------------
 networking/httpd.c |  6 ++----
 3 files changed, 19 insertions(+), 20 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index ef4a34f07..e56fff3e8 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2035,8 +2035,8 @@ enum {
 	/* Sign-extends to a value which never matches fgetc result: */
 	BASE64_FLAG_NO_STOP_CHAR = 0x80,
 };
-const char *decode_base64(char **pp_dst, const char *src) FAST_FUNC;
-const char *decode_base32(char **pp_dst, const char *src) FAST_FUNC;
+char *decode_base64(char *dst, const char **pp_src) FAST_FUNC;
+char *decode_base32(char *dst, const char **pp_src) FAST_FUNC;
 void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC;
 
 typedef struct md5_ctx_t {
diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 139c60bd5..6e63bfc6a 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -86,9 +86,9 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl
  * If points to '\0', then the source was fully decoded.
  * (*pp_dst): advanced past the last written byte.
  */
-const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
+char* FAST_FUNC decode_base64(char *dst, const char **pp_src)
 {
-	char *dst = *pp_dst;
+	const char *src = pp_src ? *pp_src : dst; /* for httpd.c, support NULL 2nd param */
 	unsigned ch = 0;
 	unsigned t;
 	int i = 0;
@@ -129,16 +129,17 @@ const char* FAST_FUNC decode_base64(char **pp_dst, const char *src)
 			ch = 0;
 		}
 	}
-	*pp_dst = dst;
 	/* i is zero here if full 4-char block was decoded */
-	return src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
+	if (pp_src)
+		*pp_src = src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
+	return dst;
 }
 
 #if ENABLE_BASE32
-const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
+char* FAST_FUNC decode_base32(char *dst, const char **pp_src)
 {
-	char *dst = *pp_dst;
-	int64_t ch = 0;
+	const char *src = *pp_src;
+	uint64_t ch = 0;
 	unsigned t;
 	int i = 0;
 
@@ -169,9 +170,9 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 			*dst++ = (char) ch;
 		}
 	}
-	*pp_dst = dst;
 	/* i is zero here if full 8-char block was decoded */
-	return src - i;
+	*pp_src = src - i;
+	return dst;
  tail:
 	{
 		const char *s = src;
@@ -192,8 +193,8 @@ const char* FAST_FUNC decode_base32(char **pp_dst, const char *src)
 		*dst++ = (char) ch;
 		dst -= (i+1) * 2 / 3; /* discard last 1, 2, 3 or 4 bytes */
 	}
-	*pp_dst = dst;
-	return src;
+	*pp_src = src;
+	return dst;
 }
 #endif
 
@@ -249,13 +250,13 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 		if (uu_style_end && strcmp(buf, "====") == 0)
 			return;
 
-		out_tail = buf;
+		in_tail = buf;
 #if ENABLE_BASE32
 		if (base32)
-			in_tail = decode_base32(&out_tail, buf);
+			out_tail = decode_base32(buf, &in_tail);
 		else
 #endif
-			in_tail = decode_base64(&out_tail, buf);
+			out_tail = decode_base64(buf, &in_tail);
 
 		fwrite(buf, (out_tail - buf), 1, dst_stream);
 
diff --git a/networking/httpd.c b/networking/httpd.c
index 4ffd89c48..4346141ee 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1015,11 +1015,9 @@ static char *encodeString(const char *string)
  * Parameter: a pointer to a base64 encoded string.
  * Decoded data is stored in-place.
  */
-static void decodeBase64(char *Data)
+static void decodeBase64(char *data)
 {
-	char *eptr = Data;
-	decode_base64(&eptr, Data);
-	*eptr = '\0';
+	decode_base64(data, NULL)[0] = '\0';
 }
 #endif
 
-- 
cgit v1.2.3-55-g6feb


From ae04ce82cf4352c0d0ecd993b586c10b6b8f80af Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 28 Nov 2020 13:39:05 +0100
Subject: base32/64: "truncated base64 input" -> "truncated input"

   text	   data	    bss	    dec	    hex	filename
1021739	    559	   5052	1027350	  fad16	busybox_old
1021732	    559	   5052	1027343	  fad0f	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/uuencode.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'libbb')

diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 6e63bfc6a..21af7a8c9 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -28,7 +28,7 @@ const char bb_uuenc_tbl_base64[] ALIGN1 = {
 	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
 	'w', 'x', 'y', 'z', '0', '1', '2', '3',
 	'4', '5', '6', '7', '8', '9', '+', '/',
-	'=' /* termination character */,
+	'=' /* termination character */
 };
 const char bb_uuenc_tbl_std[] ALIGN1 = {
 	'`', '!', '"', '#', '$', '%', '&', '\'',
@@ -38,7 +38,7 @@ const char bb_uuenc_tbl_std[] ALIGN1 = {
 	'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
 	'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
 	'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
-	'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
+	'X', 'Y', 'Z', '[', '\\',']', '^', '_',
 	'`' /* termination character */
 };
 
@@ -82,9 +82,10 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl
 /*
  * Decode base64 encoded string.
  *
- * Returns: pointer to the undecoded part of source.
+ * Returns: pointer past the last written output byte,
+ * the result is not NUL-terminated.
+ * (*pp_src) is advanced past the last read byte.
  * If points to '\0', then the source was fully decoded.
- * (*pp_dst): advanced past the last written byte.
  */
 char* FAST_FUNC decode_base64(char *dst, const char **pp_src)
 {
@@ -131,7 +132,7 @@ char* FAST_FUNC decode_base64(char *dst, const char **pp_src)
 	}
 	/* i is zero here if full 4-char block was decoded */
 	if (pp_src)
-		*pp_src = src - i; /* -i rejects truncations: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
+		*pp_src = src - i; /* -i signals truncation: e.g. "MQ" and "MQ=" (correct encoding is "MQ==" -> "1") */
 	return dst;
 }
 
@@ -265,7 +266,7 @@ void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
 			if (*in_tail == '\0')
 				return;
 			/* No */
-			bb_simple_error_msg_and_die("truncated base64 input");
+			bb_simple_error_msg_and_die("truncated input");
 		}
 
 		/* It was partial decode */
-- 
cgit v1.2.3-55-g6feb


From 32a8f70ac1caa4037b63747c0c0a5086953ea668 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sat, 28 Nov 2020 23:21:13 +0100
Subject: libbb: in @SECONDS date format, use 64-bit time if libc allows

function                                             old     new   delta
packed_usage                                       33472   33486     +14
parse_datestr                                        919     916      -3

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 coreutils/date.c | 1 +
 libbb/time.c     | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/coreutils/date.c b/coreutils/date.c
index dfc1c7663..7061f1719 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -111,6 +111,7 @@
 //usage:	)
 //usage:     "\n"
 //usage:     "\nRecognized TIME formats:"
+//usage:     "\n	@seconds_since_1970"
 //usage:     "\n	hh:mm[:ss]"
 //usage:     "\n	[YYYY.]MM.DD-hh:mm[:ss]"
 //usage:     "\n	YYYY-MM-DD hh:mm[:ss]"
diff --git a/libbb/time.c b/libbb/time.c
index e66a9cba8..86b88a414 100644
--- a/libbb/time.c
+++ b/libbb/time.c
@@ -90,7 +90,11 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
 		ptm->tm_mon -= 1; /* Adjust month from 1-12 to 0-11 */
 	} else
 	if (date_str[0] == '@') {
-		time_t t = bb_strtol(date_str + 1, NULL, 10);
+		time_t t;
+		if (sizeof(t) <= sizeof(long))
+			t = bb_strtol(date_str + 1, NULL, 10);
+		else /* time_t is 64 bits but longs are smaller */
+			t = bb_strtoll(date_str + 1, NULL, 10);
 		if (!errno) {
 			struct tm *lt = localtime(&t);
 			if (lt) {
-- 
cgit v1.2.3-55-g6feb


From 87bd558f3f0452ed62f2686472e03a1be4a6e36d Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sun, 29 Nov 2020 11:32:48 +0100
Subject: libbb: bb_do_delay(3) -> pause_after_failed_login(), and stop looping
 there

function                                             old     new   delta
pause_after_failed_login                               -       9      +9
vlock_main                                           358     353      -5
sulogin_main                                         252     247      -5
su_main                                              484     479      -5
passwd_main                                          936     931      -5
login_main                                           967     962      -5
bb_do_delay                                           68       -     -68
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 0/5 up/down: 9/-93)             Total: -84 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h      |  7 ++++---
 libbb/bb_do_delay.c  | 22 ++++++++++++++++------
 loginutils/login.c   |  2 +-
 loginutils/passwd.c  |  2 +-
 loginutils/su.c      |  2 +-
 loginutils/sulogin.c |  2 +-
 loginutils/vlock.c   |  2 +-
 networking/pscan.c   |  2 +-
 8 files changed, 26 insertions(+), 15 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index e56fff3e8..6b822016e 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1604,9 +1604,10 @@ char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC;
 #ifndef LOGIN_FAIL_DELAY
 #define LOGIN_FAIL_DELAY 3
 #endif
-extern void bb_do_delay(int seconds) FAST_FUNC;
-extern void change_identity(const struct passwd *pw) FAST_FUNC;
-extern void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
+void pause_after_failed_login(void) FAST_FUNC;
+void bb_do_delay(int seconds) FAST_FUNC;
+void change_identity(const struct passwd *pw) FAST_FUNC;
+void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
 
 /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL.
  * Note that getpwuid result might need xstrdup'ing
diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c
index 65541704b..29343305d 100644
--- a/libbb/bb_do_delay.c
+++ b/libbb/bb_do_delay.c
@@ -8,13 +8,23 @@
  */
 #include "libbb.h"
 
-void FAST_FUNC bb_do_delay(int seconds)
+/* void FAST_FUNC bb_do_delay(int seconds) { ... } - no users yet */
+
+#ifndef LOGIN_FAIL_DELAY
+#define LOGIN_FAIL_DELAY 3
+#endif
+void FAST_FUNC pause_after_failed_login(void)
 {
-	time_t start, now;
+#if 0 /* over-engineered madness */
+	time_t end, diff;
 
-	start = time(NULL);
+	end = time(NULL) + LOGIN_FAIL_DELAY;
+	diff = LOGIN_FAIL_DELAY;
 	do {
-		sleep(seconds);
-		now = time(NULL);
-	} while ((now - start) < seconds);
+		sleep(diff);
+		diff = end - time(NULL);
+	} while (diff > 0);
+#else
+	sleep(LOGIN_FAIL_DELAY);
+#endif
 }
diff --git a/loginutils/login.c b/loginutils/login.c
index 3531d1424..c3a835180 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -505,7 +505,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 #endif /* ENABLE_PAM */
  auth_failed:
 		opt &= ~LOGIN_OPT_f;
-		bb_do_delay(LOGIN_FAIL_DELAY);
+		pause_after_failed_login();
 		/* TODO: doesn't sound like correct English phrase to me */
 		puts("Login incorrect");
 		if (++count == 3) {
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 6c643d3d0..770acf58a 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -57,7 +57,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, const char *algo
 		encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */
 		if (strcmp(encrypted, pw->pw_passwd) != 0) {
 			syslog(LOG_WARNING, "incorrect password for %s", pw->pw_name);
-			bb_do_delay(LOGIN_FAIL_DELAY);
+			pause_after_failed_login();
 			puts("Incorrect password");
 			goto err_ret;
 		}
diff --git a/loginutils/su.c b/loginutils/su.c
index 7c1fc69c5..6f91039f9 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -146,7 +146,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
 		if (ENABLE_FEATURE_SU_SYSLOG)
 			syslog(LOG_NOTICE, "%c %s %s:%s",
 				'-', tty, old_user, opt_username);
-		bb_do_delay(LOGIN_FAIL_DELAY);
+		pause_after_failed_login();
 		bb_simple_error_msg_and_die("incorrect password");
 	}
 
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index 099085340..48dafd186 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -74,7 +74,7 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
 		if (r > 0) {
 			break;
 		}
-		bb_do_delay(LOGIN_FAIL_DELAY);
+		pause_after_failed_login();
 		bb_simple_info_msg("Login incorrect");
 	}
 
diff --git a/loginutils/vlock.c b/loginutils/vlock.c
index 9e319fe61..334b7d2ad 100644
--- a/loginutils/vlock.c
+++ b/loginutils/vlock.c
@@ -120,7 +120,7 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
 		if (ask_and_check_password(pw) > 0) {
 			break;
 		}
-		bb_do_delay(LOGIN_FAIL_DELAY);
+		pause_after_failed_login();
 		puts("Incorrect password");
 	}
 
diff --git a/networking/pscan.c b/networking/pscan.c
index 2715ef2df..e114e55d2 100644
--- a/networking/pscan.c
+++ b/networking/pscan.c
@@ -139,7 +139,7 @@ int pscan_main(int argc UNUSED_PARAM, char **argv)
 			 * We check rtt BEFORE we usleep, otherwise
 			 * on localhost we'll have no writes done (!)
 			 * before we exceed (rather small) rtt */
-			usleep(rtt_4/8);
+			usleep(rtt_4 / 8);
  open:
 			diff = MONOTONIC_US() - start;
 			DMSG("write to port %u @%u", port, diff - start);
-- 
cgit v1.2.3-55-g6feb


From ec16c030bd5527137f95a1c30e6a1f3c9054dcf7 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sun, 29 Nov 2020 11:37:34 +0100
Subject: libbb: introduce and use sleep1()

function                                             old     new   delta
sleep1                                                 -       9      +9
run_shutdown_and_kill_processes                       97      95      -2
restore_state_and_exit                               116     114      -2
reread_partition_table                                67      65      -2
flush_buffer_cache                                    80      78      -2
chat_main                                           1302    1300      -2
timeout_main                                         310     307      -3
telnet_main                                         1235    1232      -3
stop_handler                                          86      83      -3
process_action                                      1078    1075      -3
nbdclient_main                                      1185    1182      -3
init_main                                            789     786      -3
getty_main                                          1541    1538      -3
do_time                                              410     407      -3
runsv_main                                          1682    1677      -5
pause_and_low_level_reboot                            59      54      -5
inetd_main                                          1917    1911      -6
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/16 up/down: 9/-50)            Total: -41 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 coreutils/timeout.c     |  2 +-
 e2fsprogs/fsck.c        |  2 +-
 include/libbb.h         |  4 +---
 init/halt.c             |  4 ++--
 init/init.c             | 12 ++++++------
 libbb/bb_do_delay.c     |  6 ++++++
 loginutils/getty.c      |  2 +-
 miscutils/chat.c        |  2 +-
 miscutils/hdparm.c      |  4 ++--
 networking/ifplugd.c    |  2 +-
 networking/inetd.c      |  4 ++--
 networking/nbd-client.c |  2 +-
 networking/nc_bloaty.c  |  2 +-
 networking/slattach.c   |  2 +-
 networking/telnet.c     |  2 +-
 runit/runsv.c           |  4 ++--
 sysklogd/logread.c      |  2 +-
 util-linux/fdisk.c      |  2 +-
 util-linux/mdev.c       |  2 +-
 19 files changed, 33 insertions(+), 29 deletions(-)

(limited to 'libbb')

diff --git a/coreutils/timeout.c b/coreutils/timeout.c
index 8b7bc2eaa..2a628b71d 100644
--- a/coreutils/timeout.c
+++ b/coreutils/timeout.c
@@ -105,7 +105,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv)
  grandchild:
 		/* Just sleep(HUGE_NUM); kill(parent) may kill wrong process! */
 		while (1) {
-			sleep(1);
+			sleep1();
 			if (--timeout <= 0)
 				break;
 			if (kill(parent, 0)) {
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c
index fc53a9043..96c1e51e0 100644
--- a/e2fsprogs/fsck.c
+++ b/e2fsprogs/fsck.c
@@ -480,7 +480,7 @@ static int wait_one(int flags)
 			 * time to set up the signal handler
 			 */
 			if (inst2->start_time >= time(NULL) - 1)
-				sleep(1);
+				sleep1();
 			kill(inst2->pid, SIGUSR1);
 			inst2->flags |= FLAG_PROGRESS;
 			break;
diff --git a/include/libbb.h b/include/libbb.h
index 6b822016e..9fa0ce90d 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1601,11 +1601,9 @@ char *bb_simplify_path(const char *path) FAST_FUNC;
 /* Returns ptr to NUL */
 char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC;
 
-#ifndef LOGIN_FAIL_DELAY
-#define LOGIN_FAIL_DELAY 3
-#endif
 void pause_after_failed_login(void) FAST_FUNC;
 void bb_do_delay(int seconds) FAST_FUNC;
+void sleep1(void) FAST_FUNC;
 void change_identity(const struct passwd *pw) FAST_FUNC;
 void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
 
diff --git a/init/halt.c b/init/halt.c
index 785c38130..2070eaa4d 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -144,14 +144,14 @@ static int init_was_not_there(void)
 	 */
 #if 0
 	while (kill(1, 0) != 0 && --cnt >= 0)
-		sleep(1);
+		sleep1();
 #endif
 	/* ... so let's wait for some evidence a usual startup event,
 	 * mounting of /proc, happened. By that time init should be ready
 	 * for signals.
 	 */
 	while (access("/proc/meminfo", F_OK) != 0 && --cnt >= 0)
-		sleep(1);
+		sleep1();
 
 	/* Does it look like init wasn't there? */
 	return (cnt != initial - 1);
diff --git a/init/init.c b/init/init.c
index 28775a65c..efab5dcb4 100644
--- a/init/init.c
+++ b/init/init.c
@@ -736,7 +736,7 @@ static void pause_and_low_level_reboot(unsigned magic)
 	pid_t pid;
 
 	/* Allow time for last message to reach serial console, etc */
-	sleep(1);
+	sleep1();
 
 	/* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
 	 * in linux/kernel/sys.c, which can cause the machine to panic when
@@ -751,7 +751,7 @@ static void pause_and_low_level_reboot(unsigned magic)
 	 * we would eternally sleep here - not what we want.
 	 */
 	waitpid(pid, NULL, 0);
-	sleep(1); /* paranoia */
+	sleep1(); /* paranoia */
 	_exit(EXIT_SUCCESS);
 }
 
@@ -768,12 +768,12 @@ static void run_shutdown_and_kill_processes(void)
 	kill(-1, SIGTERM);
 	message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
 	sync();
-	sleep(1);
+	sleep1();
 
 	kill(-1, SIGKILL);
 	message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
 	sync();
-	/*sleep(1); - callers take care about making a pause */
+	/*sleep1(); - callers take care about making a pause */
 }
 
 /* Signal handling by init:
@@ -904,7 +904,7 @@ static void stop_handler(int sig UNUSED_PARAM)
 		wpid = wait_any_nohang(NULL);
 		mark_terminated(wpid);
 		if (wpid <= 0) /* no processes exited? sleep a bit */
-			sleep(1);
+			sleep1();
 	}
 
 	signal(SIGCONT, SIG_DFL);
@@ -1209,7 +1209,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
 		}
 
 		/* Don't consume all CPU time - sleep a bit */
-		sleep(1);
+		sleep1();
 	} /* while (1) */
 }
 
diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c
index 29343305d..3a86dc2ae 100644
--- a/libbb/bb_do_delay.c
+++ b/libbb/bb_do_delay.c
@@ -28,3 +28,9 @@ void FAST_FUNC pause_after_failed_login(void)
 	sleep(LOGIN_FAIL_DELAY);
 #endif
 }
+
+void FAST_FUNC sleep1(void)
+{
+	sleep(1);
+}
+
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 7393a3d1c..99af72f68 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -434,7 +434,7 @@ static void auto_baud(void)
 	 * Wait for a while, then read everything the modem has said so far and
 	 * try to extract the speed of the dial-in call.
 	 */
-	sleep(1);
+	sleep1();
 	nread = safe_read(STDIN_FILENO, G.line_buf, sizeof(G.line_buf) - 1);
 	if (nread > 0) {
 		int speed;
diff --git a/miscutils/chat.c b/miscutils/chat.c
index a04565063..a7faaf284 100644
--- a/miscutils/chat.c
+++ b/miscutils/chat.c
@@ -473,7 +473,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
 					if ('\\' == c) {
 						c = *++buf;
 						if ('d' == c) {
-							sleep(1);
+							sleep1();
 							len--;
 							continue;
 						}
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index d25a2466e..431a0ad96 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -1436,7 +1436,7 @@ static void flush_buffer_cache(/*int fd*/ void)
 	fsync(fd);				/* flush buffers */
 	ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */
 #ifdef HDIO_DRIVE_CMD
-	sleep(1);
+	sleep1();
 	if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) {	/* await completion */
 		if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
 			bb_simple_perror_msg("HDIO_DRIVE_CMD");
@@ -1511,7 +1511,7 @@ static void do_time(int cache /*,int fd*/)
 	 * NB: *small* delay. User is expected to have a clue and to not run
 	 * heavy io in parallel with measurements. */
 	sync();
-	sleep(1);
+	sleep1();
 	if (cache) { /* Time cache */
 		seek_to_zero();
 		read_big_block(buf);
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 0d17b7d8c..60916eae6 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -735,7 +735,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
 					delay_time += G.delay_down;
 #if 0  /* if you are back in 1970... */
 				if (delay_time == 0) {
-					sleep(1);
+					sleep1();
 					delay_time = 1;
 				}
 #endif
diff --git a/networking/inetd.c b/networking/inetd.c
index 3cd2b11f0..44b1ac700 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1305,7 +1305,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 		if (ready_fd_cnt < 0) {
 			if (errno != EINTR) {
 				bb_simple_perror_msg("select");
-				sleep(1);
+				sleep1();
 			}
 			continue;
 		}
@@ -1406,7 +1406,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv)
 
 				if (pid < 0) { /* fork error */
 					bb_simple_perror_msg("vfork"+1);
-					sleep(1);
+					sleep1();
 					restore_sigmask(&omask);
 					maybe_close(new_udp_fd);
 					maybe_close(accepted_fd);
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index 3db3b46f9..755b42ccd 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -270,7 +270,7 @@ int nbdclient_main(int argc, char **argv)
 						close(fd);
 					break;
 				}
-				sleep(1);
+				sleep1();
 			}
 			open(device, O_RDONLY);
 			return 0;
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c
index 88eda6b28..25b95246f 100644
--- a/networking/nc_bloaty.c
+++ b/networking/nc_bloaty.c
@@ -196,7 +196,7 @@ enum {
 /* Debug: squirt whatever message and sleep a bit so we can see it go by. */
 /* Beware: writes to stdOUT... */
 #if 0
-#define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep(1); } while (0)
+#define Debug(...) do { printf(__VA_ARGS__); printf("\n"); fflush_all(); sleep1(); } while (0)
 #else
 #define Debug(...) do { } while (0)
 #endif
diff --git a/networking/slattach.c b/networking/slattach.c
index 51fbc1f49..6d2a252fc 100644
--- a/networking/slattach.c
+++ b/networking/slattach.c
@@ -76,7 +76,7 @@ static void restore_state_and_exit(int exitcode)
 	cfsetispeed(&state, B0);
 	cfsetospeed(&state, B0);
 	exitcode |= tcsetattr_serial_or_warn(&state);
-	sleep(1);
+	sleep1();
 
 	/* Restore line status */
 	if (tcsetattr_serial_or_warn(&G.saved_state))
diff --git a/networking/telnet.c b/networking/telnet.c
index 9fc85050b..19a414b30 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -673,7 +673,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv)
 			if (bb_got_signal)
 				con_escape();
 			else
-				sleep(1);
+				sleep1();
 			continue;
 		}
 
diff --git a/runit/runsv.c b/runit/runsv.c
index 36d85101e..7e22862cd 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -651,7 +651,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv)
 				gettimeofday_ns(&svd[0].start);
 				update_status(&svd[0]);
 				if (LESS(svd[0].start.tv_sec, deadline))
-					sleep(1);
+					sleep1();
 			}
 			if (haslog) {
 				if (child == svd[1].pid) {
@@ -664,7 +664,7 @@ int runsv_main(int argc UNUSED_PARAM, char **argv)
 					gettimeofday_ns(&svd[1].start);
 					update_status(&svd[1]);
 					if (LESS(svd[1].start.tv_sec, deadline))
-						sleep(1);
+						sleep1();
 				}
 			}
 		} /* for (;;) */
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
index 1e1f1347f..b52dc9cac 100644
--- a/sysklogd/logread.c
+++ b/sysklogd/logread.c
@@ -180,7 +180,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv)
 			if (cur == shbuf_tail) {
 				sem_up(log_semid);
 				fflush_all();
-				sleep(1); /* TODO: replace me with a sleep_on */
+				sleep1(); /* TODO: replace me with a sleep_on */
 				continue;
 			}
 		}
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index 0fb2e3e17..0df3ebf7d 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -2667,7 +2667,7 @@ reread_partition_table(int leave)
 	/* Users with slow external USB disks on a 320MHz ARM system (year 2011)
 	 * report that sleep is needed, otherwise BLKRRPART may fail with -EIO:
 	 */
-	sleep(1);
+	sleep1();
 	i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
 			"WARNING: rereading partition table "
 			"failed, kernel still uses old table");
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 9a8c14456..ebf83d1a3 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -920,7 +920,7 @@ static void load_firmware(const char *firmware, const char *sysfs_path)
 		loading_fd = open("loading", O_WRONLY);
 		if (loading_fd >= 0)
 			goto loading;
-		sleep(1);
+		sleep1();
 	}
 	goto out;
 
-- 
cgit v1.2.3-55-g6feb


From 6a55b4e403979ba299261816a7ec1bb55bbf3f2b Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sun, 29 Nov 2020 12:40:25 +0100
Subject: libbb: introduce and use msleep()

function                                             old     new   delta
msleep                                                 -      45     +45
watchdog_main                                        271     266      -5
common_traceroute_main                              3546    3530     -16
beep_main                                            277     248     -29
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/3 up/down: 45/-50)             Total: -5 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h         |  3 ++-
 libbb/bb_do_delay.c     | 15 ++++++++++++++-
 miscutils/beep.c        |  4 ++--
 miscutils/watchdog.c    |  2 +-
 networking/traceroute.c |  2 +-
 5 files changed, 20 insertions(+), 6 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index 9fa0ce90d..18dc9f935 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1602,7 +1602,8 @@ char *bb_simplify_path(const char *path) FAST_FUNC;
 char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC;
 
 void pause_after_failed_login(void) FAST_FUNC;
-void bb_do_delay(int seconds) FAST_FUNC;
+void bb_do_delay(unsigned seconds) FAST_FUNC;
+void msleep(unsigned ms) FAST_FUNC;
 void sleep1(void) FAST_FUNC;
 void change_identity(const struct passwd *pw) FAST_FUNC;
 void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c
index 3a86dc2ae..3dbf032db 100644
--- a/libbb/bb_do_delay.c
+++ b/libbb/bb_do_delay.c
@@ -8,7 +8,7 @@
  */
 #include "libbb.h"
 
-/* void FAST_FUNC bb_do_delay(int seconds) { ... } - no users yet */
+/* void FAST_FUNC bb_do_delay(unsigned seconds) { ... } - no users yet */
 
 #ifndef LOGIN_FAIL_DELAY
 #define LOGIN_FAIL_DELAY 3
@@ -34,3 +34,16 @@ void FAST_FUNC sleep1(void)
 	sleep(1);
 }
 
+void FAST_FUNC msleep(unsigned ms)
+{
+	/* 1. usleep(n) is not guaranteed by standards to accept n >= 1000000
+	 * 2. multiplication in usleep(ms * 1000) can overflow if ms > 4294967
+	 *    (sleep of ~71.5 minutes)
+	 * Let's play safe and loop:
+	 */
+	while (ms > 500) {
+		usleep(500000);
+		ms -= 500;
+	}
+	usleep(ms * 1000);
+}
diff --git a/miscutils/beep.c b/miscutils/beep.c
index 1669332fd..7c60aed08 100644
--- a/miscutils/beep.c
+++ b/miscutils/beep.c
@@ -114,10 +114,10 @@ int beep_main(int argc, char **argv)
 		while (rep) {
 //bb_error_msg("rep[%d] freq=%d, length=%d, delay=%d", rep, freq, length, delay);
 			xioctl(speaker, KIOCSOUND, (void*)(uintptr_t)tickrate_div_freq);
-			usleep(1000 * length);
+			msleep(length);
 			ioctl(speaker, KIOCSOUND, (void*)0);
 			if (--rep)
-				usleep(1000 * delay);
+				msleep(delay);
 		}
 	}
 
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c
index 8c8d7217f..971b777a3 100644
--- a/miscutils/watchdog.c
+++ b/miscutils/watchdog.c
@@ -143,7 +143,7 @@ int watchdog_main(int argc UNUSED_PARAM, char **argv)
 		 * as the counter value is undefined at this point -- PFM
 		 */
 		write(3, "", 1); /* write zero byte */
-		usleep(stimer_duration * 1000L);
+		msleep(stimer_duration);
 	}
 	return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */
 }
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 1c4dc3e4a..34d2a09dd 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -1071,7 +1071,7 @@ common_traceroute_main(int op, char **argv)
 
 			fflush_all();
 			if (probe != 0 && pausemsecs > 0)
-				usleep(pausemsecs * 1000);
+				msleep(pausemsecs);
 
 			send_probe(++seq, ttl);
 			t2 = t1 = monotonic_us();
-- 
cgit v1.2.3-55-g6feb


From eb773054e47a30c78a82ed80ad4da7abe9bfb09b Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Sun, 29 Nov 2020 14:24:14 +0100
Subject: libbb: code shrink

function                                             old     new   delta
generate_uuid                                        124     103     -21

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/xfuncs_printf.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

(limited to 'libbb')

diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index f1cf7aeed..fcc798662 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -633,14 +633,11 @@ void FAST_FUNC generate_uuid(uint8_t *buf)
 	pid_t pid;
 	int i;
 
-	i = open("/dev/urandom", O_RDONLY);
-	if (i >= 0) {
-		read(i, buf, 16);
-		close(i);
-	}
+	open_read_close("/dev/urandom", buf, 16);
 	/* Paranoia. /dev/urandom may be missing.
 	 * rand() is guaranteed to generate at least [0, 2^15) range,
-	 * but lowest bits in some libc are not so "random".  */
+	 * but lowest bits in some libc are not so "random".
+	 */
 	srand(monotonic_us()); /* pulls in printf */
 	pid = getpid();
 	while (1) {
-- 
cgit v1.2.3-55-g6feb


From 33e955ab91d2f76bd8ea6e12fce215d863f4d7d7 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 30 Nov 2020 11:18:00 +0100
Subject: unicode: fix handling of short 1-4 char tables

function                                             old     new   delta
in_uint16_table                                       92     107     +15

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/time.c    | 1 -
 libbb/unicode.c | 6 ++++--
 2 files changed, 4 insertions(+), 3 deletions(-)

(limited to 'libbb')

diff --git a/libbb/time.c b/libbb/time.c
index 86b88a414..74a69eefb 100644
--- a/libbb/time.c
+++ b/libbb/time.c
@@ -250,7 +250,6 @@ char* FAST_FUNC strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp)
 
 #if ENABLE_MONOTONIC_SYSCALL
 
-#include <sys/syscall.h>
 /* Old glibc (< 2.3.4) does not provide this constant. We use syscall
  * directly so this definition is safe. */
 #ifndef CLOCK_MONOTONIC
diff --git a/libbb/unicode.c b/libbb/unicode.c
index 79481f159..bfeaef895 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -306,8 +306,10 @@ static int in_uint16_table(unsigned ucs, const uint16_t *table, unsigned max)
 	unsigned first, last;
 
 	first = table[0] >> 2;
-	last = first + (table[0] & 3);
-	if (ucs < first || ucs > last)
+	if (ucs < first)
+		return 0;
+	last = (table[max] >> 2) + (table[max] & 3);
+	if (ucs > last)
 		return 0;
 
 	min = 0;
-- 
cgit v1.2.3-55-g6feb


From 2fba2f5bb99145eaa1635fe5a162426158d56a2c Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 30 Nov 2020 11:30:17 +0100
Subject: unicode: relax array alignment for tables

   text	   data	    bss	    dec	    hex	filename
1022075	    559	   5052	1027686	  fae66	busybox_old
1021988	    559	   5052	1027599	  fae0f	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/unicode.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'libbb')

diff --git a/libbb/unicode.c b/libbb/unicode.c
index bfeaef895..e98cbbf35 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -25,7 +25,7 @@ uint8_t unicode_status;
 
 void FAST_FUNC reinit_unicode(const char *LANG)
 {
-	static const char unicode_0x394[] = { 0xce, 0x94, 0 };
+	static const char unicode_0x394[] ALIGN1 = { 0xce, 0x94, 0 };
 	size_t width;
 
 	/* We pass "" instead of "C" because some libc's have
@@ -589,12 +589,12 @@ int FAST_FUNC wcwidth(unsigned ucs)
 		BIG_(0xFE20, 0xFE23) \
 		BIG_(0xFEFF, 0xFEFF) \
 		BIG_(0xFFF9, 0xFFFB)
-	static const struct interval combining[] = { ARRAY };
+	static const struct interval combining[] ALIGN4 = { ARRAY };
 #  undef BIG_
 #  undef PAIR
 #  define BIG_(a,b)
 #  define PAIR(a,b) (a << 2) | (b-a),
-	static const uint16_t combining1[] = { ARRAY };
+	static const uint16_t combining1[] ALIGN2 = { ARRAY };
 #  undef BIG_
 #  undef PAIR
 #  define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1];
@@ -648,7 +648,7 @@ int FAST_FUNC wcwidth(unsigned ucs)
 #   if CONFIG_LAST_SUPPORTED_WCHAR >= 0x10000
 	if (ucs >= 0x10000) {
 		/* Combining chars in Supplementary Multilingual Plane 0x1xxxx */
-		static const struct interval combining0x10000[] = {
+		static const struct interval combining0x10000[] ALIGN4 = {
 			{ 0x0A01, 0x0A03 }, { 0x0A05, 0x0A06 }, { 0x0A0C, 0x0A0F },
 			{ 0x0A38, 0x0A3A }, { 0x0A3F, 0x0A3F }, { 0xD167, 0xD169 },
 			{ 0xD173, 0xD182 }, { 0xD185, 0xD18B }, { 0xD1AA, 0xD1AD },
@@ -759,12 +759,12 @@ int FAST_FUNC unicode_bidi_isrtl(wint_t wc)
 		{0x10E7F, 0x10FFF},
 		{0x1E800, 0x1EFFF}
 		*/
-	static const struct interval rtl_b[] = { ARRAY };
+	static const struct interval rtl_b[] ALIGN4 = { ARRAY };
 #  undef BIG_
 #  undef PAIR
 #  define BIG_(a,b)
 #  define PAIR(a,b) (a << 2) | (b-a),
-	static const uint16_t rtl_p[] = { ARRAY };
+	static const uint16_t rtl_p[] ALIGN2 = { ARRAY };
 #  undef BIG_
 #  undef PAIR
 #  define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1];
@@ -963,12 +963,12 @@ int FAST_FUNC unicode_bidi_is_neutral_wchar(wint_t wc)
 		{0x1F030, 0x1F093},
 		{0x1F100, 0x1F10A}
 		*/
-	static const struct interval neutral_b[] = { ARRAY };
+	static const struct interval neutral_b[] ALIGN4 = { ARRAY };
 #  undef BIG_
 #  undef PAIR
 #  define BIG_(a,b)
 #  define PAIR(a,b) (a << 2) | (b-a),
-	static const uint16_t neutral_p[] = { ARRAY };
+	static const uint16_t neutral_p[] ALIGN2 = { ARRAY };
 #  undef BIG_
 #  undef PAIR
 #  define BIG_(a,b) char big_##a[b < 0x4000 && b-a <= 3 ? -1 : 1];
-- 
cgit v1.2.3-55-g6feb


From 965b795b87c59ed45cc7f16a62301dbae65b1627 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 30 Nov 2020 13:03:03 +0100
Subject: decrease paddign: gcc-9.3.1 slaps 32-byte alignment on arrays
 willy-nilly

   text	   data	    bss	    dec	    hex	filename
1021988	    559	   5052	1027599	  fae0f	busybox_old
1021236	    559	   5052	1026847	  fab1f	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 archival/dpkg.c                               |  2 +-
 archival/libarchive/bz/blocksort.c            |  2 +-
 archival/libarchive/data_extract_to_command.c |  2 +-
 coreutils/od_bloaty.c                         |  4 ++--
 coreutils/split.c                             |  2 +-
 coreutils/stat.c                              |  2 +-
 coreutils/stty.c                              |  4 ++--
 coreutils/test.c                              |  2 +-
 e2fsprogs/e2fs_lib.c                          |  2 +-
 editors/awk.c                                 |  2 +-
 findutils/find.c                              |  2 +-
 include/libbb.h                               |  3 ++-
 include/platform.h                            |  2 ++
 libbb/capability.c                            |  2 +-
 libbb/duration.c                              |  2 +-
 libbb/hash_md5_sha.c                          | 22 +++++++++++-----------
 libbb/mode_string.c                           |  2 +-
 libbb/pw_encrypt_des.c                        | 15 +++++++--------
 libbb/speed_table.c                           |  2 +-
 libbb/xatonum.c                               |  6 +++---
 miscutils/crond.c                             |  2 +-
 miscutils/dc.c                                |  2 +-
 miscutils/hdparm.c                            |  2 +-
 miscutils/i2c_tools.c                         | 15 +++++----------
 miscutils/mt.c                                |  2 +-
 miscutils/setserial.c                         |  3 +--
 miscutils/ubi_tools.c                         |  2 +-
 miscutils/watchdog.c                          |  2 +-
 modutils/modinfo.c                            |  2 +-
 networking/ifplugd.c                          |  2 +-
 networking/interface.c                        |  2 +-
 networking/ip.c                               |  2 +-
 networking/libiproute/rt_names.c              |  2 +-
 networking/route.c                            |  6 +++---
 networking/tls.c                              |  2 +-
 networking/udhcp/dhcpd.c                      |  2 +-
 procps/nmeter.c                               |  2 +-
 procps/ps.c                                   |  2 +-
 runit/svlogd.c                                |  2 +-
 shell/ash.c                                   |  6 +++---
 shell/hush.c                                  | 12 ++++++------
 shell/shell_common.c                          |  2 +-
 util-linux/acpid.c                            |  4 ++--
 util-linux/fbset.c                            |  2 +-
 util-linux/fdisk.c                            |  2 +-
 util-linux/fdisk_osf.c                        |  4 ++--
 util-linux/fdisk_sgi.c                        |  2 +-
 util-linux/fdisk_sun.c                        |  4 ++--
 util-linux/mkfs_ext2.c                        |  2 +-
 util-linux/mount.c                            |  2 +-
 util-linux/volume_id/volume_id.c              |  8 ++++----
 51 files changed, 92 insertions(+), 96 deletions(-)

(limited to 'libbb')

diff --git a/archival/dpkg.c b/archival/dpkg.c
index 68a40bf6e..bf070a001 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -1304,7 +1304,7 @@ postrm abort-install <old_version>
 postrm abort-upgrade <old_version>
 postrm disappear <overwriter> <version>
 */
-static const char *const all_control_files[] = {
+static const char *const all_control_files[] ALIGN_PTR = {
 	"preinst", "postinst", "prerm", "postrm",
 	"list", "md5sums", "shlibs", "conffiles",
 	"config", "templates"
diff --git a/archival/libarchive/bz/blocksort.c b/archival/libarchive/bz/blocksort.c
index 92d6d8251..062fd0f54 100644
--- a/archival/libarchive/bz/blocksort.c
+++ b/archival/libarchive/bz/blocksort.c
@@ -459,7 +459,7 @@ int mainGtU(EState* state,
  * usually small, typically <= 20.
  */
 static
-const uint32_t incs[14] = {
+const uint32_t incs[14] ALIGN4 = {
 	1, 4, 13, 40, 121, 364, 1093, 3280,
 	9841, 29524, 88573, 265720,
 	797161, 2391484
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index 0fcabb4a9..f8b2ff8d2 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -20,7 +20,7 @@ enum {
 	TAR_MAX,
 };
 
-static const char *const tar_var[] = {
+static const char *const tar_var[] ALIGN_PTR = {
 	// "FILETYPE",
 	"MODE",
 	"FILENAME",
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index e9c071f3a..d5bd7bfe8 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -627,7 +627,7 @@ decode_one_format(const char *s_orig, const char *s, struct tspec *tspec)
 				bytes_to_unsigned_dec_digits,
 				bytes_to_hex_digits,
 			};
-			static const char doux_fmtstring[][sizeof(" %%0%u%s")] = {
+			static const char doux_fmtstring[][sizeof(" %%0%u%s")] ALIGN1 = {
 				" %%%u%s",
 				" %%0%u%s",
 				" %%%u%s",
@@ -1148,7 +1148,7 @@ dump_strings(off_t address, off_t end_offset)
 static int
 parse_old_offset(const char *s, off_t *offset)
 {
-	static const struct suffix_mult Bb[] = {
+	static const struct suffix_mult Bb[] ALIGN_SUFFIX = {
 		{ "B", 1024 },
 		{ "b", 512 },
 		{ "", 0 }
diff --git a/coreutils/split.c b/coreutils/split.c
index ecbc9d2d8..3fcfd95f2 100644
--- a/coreutils/split.c
+++ b/coreutils/split.c
@@ -44,7 +44,7 @@
 #include "common_bufsiz.h"
 
 #if ENABLE_FEATURE_SPLIT_FANCY
-static const struct suffix_mult split_suffixes[] = {
+static const struct suffix_mult split_suffixes[] ALIGN_SUFFIX = {
 	{ "b", 512 },
 	{ "k", 1024 },
 	{ "m", 1024*1024 },
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 8a23d687b..ee5e03edd 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -208,7 +208,7 @@ FS_TYPE(0x62656572, "sysfs")
 static const char *human_fstype(uint32_t f_type)
 {
 # define FS_TYPE(type, name) type,
-	static const uint32_t fstype[] = {
+	static const uint32_t fstype[] ALIGN4 = {
 		FS_TYPE_LIST
 	};
 # undef FS_TYPE
diff --git a/coreutils/stty.c b/coreutils/stty.c
index 40e812799..19253964c 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -487,7 +487,7 @@ static const char mode_name[] ALIGN1 =
 #undef MI_ENTRY
 #define MI_ENTRY(N,T,F,B,M) { T, F, M, B },
 
-static const struct mode_info mode_info[] = {
+static const struct mode_info mode_info[] ALIGN4 = {
 	/* This should be verbatim cut-n-paste copy of the above MI_ENTRYs */
 	MI_ENTRY("evenp",    combination, REV        | OMIT, 0,          0 )
 	MI_ENTRY("parity",   combination, REV        | OMIT, 0,          0 )
@@ -905,7 +905,7 @@ static void display_window_size(int fancy)
 	}
 }
 
-static const struct suffix_mult stty_suffixes[] = {
+static const struct suffix_mult stty_suffixes[] ALIGN_SUFFIX = {
 	{ "b",  512 },
 	{ "k", 1024 },
 	{ "B", 1024 },
diff --git a/coreutils/test.c b/coreutils/test.c
index ac7b546a3..7c6574334 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -306,7 +306,7 @@ struct operator_t {
 	unsigned char op_num, op_type;
 };
 
-static const struct operator_t ops_table[] = {
+static const struct operator_t ops_table[] ALIGN2 = {
 	{ /* "-r" */ FILRD   , UNOP   },
 	{ /* "-w" */ FILWR   , UNOP   },
 	{ /* "-x" */ FILEX   , UNOP   },
diff --git a/e2fsprogs/e2fs_lib.c b/e2fsprogs/e2fs_lib.c
index 6ce655be3..8bd4da622 100644
--- a/e2fsprogs/e2fs_lib.c
+++ b/e2fsprogs/e2fs_lib.c
@@ -127,7 +127,7 @@ int fgetsetflags(const char *name, unsigned long *get_flags, unsigned long set_f
 
 
 /* Print file attributes on an ext2 file system */
-const uint32_t e2attr_flags_value[] = {
+const uint32_t e2attr_flags_value[] ALIGN4 = {
 #ifdef ENABLE_COMPRESSION
 	EXT2_COMPRBLK_FL,
 	EXT2_DIRTY_FL,
diff --git a/editors/awk.c b/editors/awk.c
index 59dae4770..d56d6330d 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -405,7 +405,7 @@ static const char tokenlist[] ALIGN1 =
 
 #define OC_B  OC_BUILTIN
 
-static const uint32_t tokeninfo[] = {
+static const uint32_t tokeninfo[] ALIGN4 = {
 	0,
 	0,
 	OC_REGEXP,
diff --git a/findutils/find.c b/findutils/find.c
index e2947afb4..a8c3fa346 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -1441,7 +1441,7 @@ static action*** parse_params(char **argv)
 #else
 #define XATOU_SFX xatoul_sfx
 #endif
-			static const struct suffix_mult find_suffixes[] = {
+			static const struct suffix_mult find_suffixes[] ALIGN_SUFFIX = {
 				{ "c", 1 },
 				{ "w", 2 },
 				{ "", 512 },
diff --git a/include/libbb.h b/include/libbb.h
index 18dc9f935..9872dc1fb 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1026,8 +1026,9 @@ void generate_uuid(uint8_t *buf) FAST_FUNC;
 /* Last element is marked by mult == 0 */
 struct suffix_mult {
 	char suffix[4];
-	unsigned mult;
+	uint32_t mult;
 };
+#define ALIGN_SUFFIX ALIGN4
 extern const struct suffix_mult bkm_suffixes[];
 #define km_suffixes (bkm_suffixes + 1)
 extern const struct suffix_mult cwbkMG_suffixes[];
diff --git a/include/platform.h b/include/platform.h
index 43bb391bd..085387fd8 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -342,6 +342,8 @@ typedef unsigned smalluint;
 # define ALIGN2
 # define ALIGN4
 #endif
+#define ALIGN8     __attribute__((aligned(8)))
+#define ALIGN_PTR  __attribute__((aligned(sizeof(void*))))
 
 /*
  * For 0.9.29 and svn, __ARCH_USE_MMU__ indicates no-mmu reliably.
diff --git a/libbb/capability.c b/libbb/capability.c
index 23afd8eb9..e3c252a5a 100644
--- a/libbb/capability.c
+++ b/libbb/capability.c
@@ -17,7 +17,7 @@ extern int capget(cap_user_header_t header, const cap_user_data_t data);
 // This way, libcap needs not be installed in build environment.
 #include "libbb.h"
 
-static const char *const capabilities[] = {
+static const char *const capabilities[] ALIGN_PTR = {
 	"chown",
 	"dac_override",
 	"dac_read_search",
diff --git a/libbb/duration.c b/libbb/duration.c
index 22b209f4d..086da15fb 100644
--- a/libbb/duration.c
+++ b/libbb/duration.c
@@ -21,7 +21,7 @@
 
 #include "libbb.h"
 
-static const struct suffix_mult duration_suffixes[] = {
+static const struct suffix_mult duration_suffixes[] ALIGN_SUFFIX = {
 	{ "s", 1 },
 	{ "m", 60 },
 	{ "h", 60*60 },
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index d8f210173..e0db8ce67 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -111,7 +111,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
 	   They are defined in RFC 1321 as
 	   T[i] = (int)(2^32 * fabs(sin(i))), i=1..64
 	 */
-	static const uint32_t C_array[] = {
+	static const uint32_t C_array[] ALIGN4 = {
 		/* round 1 */
 		0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
 		0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
@@ -492,7 +492,7 @@ unsigned FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
 
 static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
 {
-	static const uint32_t rconsts[] = {
+	static const uint32_t rconsts[] ALIGN4 = {
 		0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
 	};
 	int i, j;
@@ -567,7 +567,7 @@ typedef uint64_t sha_K_int;
 typedef uint32_t sha_K_int;
 # define K(v) (uint32_t)(v >> 32)
 #endif
-static const sha_K_int sha_K[] = {
+static const sha_K_int sha_K[] ALIGN8 = {
 	K(0x428a2f98d728ae22ULL), K(0x7137449123ef65cdULL),
 	K(0xb5c0fbcfec4d3b2fULL), K(0xe9b5dba58189dbbcULL),
 	K(0x3956c25bf348b538ULL), K(0x59f111f1b605d019ULL),
@@ -760,7 +760,7 @@ void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
 	ctx->process_block = sha1_process_block64;
 }
 
-static const uint32_t init256[] = {
+static const uint32_t init256[] ALIGN4 = {
 	0,
 	0,
 	0x6a09e667,
@@ -773,7 +773,7 @@ static const uint32_t init256[] = {
 	0x5be0cd19,
 };
 #if NEED_SHA512
-static const uint32_t init512_lo[] = {
+static const uint32_t init512_lo[] ALIGN4 = {
 	0,
 	0,
 	0xf3bcc908,
@@ -1009,7 +1009,7 @@ static void sha3_process_block72(uint64_t *state)
 
 #if OPTIMIZE_SHA3_FOR_32
 	/*
-	static const uint32_t IOTA_CONST_0[NROUNDS] = {
+	static const uint32_t IOTA_CONST_0[NROUNDS] ALIGN4 = {
 		0x00000001UL,
 		0x00000000UL,
 		0x00000000UL,
@@ -1038,7 +1038,7 @@ static void sha3_process_block72(uint64_t *state)
 	** bits are in lsb: 0101 0000 1111 0100 1111 0001
 	*/
 	uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1);
-	static const uint32_t IOTA_CONST_1[NROUNDS] = {
+	static const uint32_t IOTA_CONST_1[NROUNDS] ALIGN4 = {
 		0x00000000UL,
 		0x00000089UL,
 		0x8000008bUL,
@@ -1174,7 +1174,7 @@ static void sha3_process_block72(uint64_t *state)
 	combine_halves(state);
 #else
 	/* Native 64-bit algorithm */
-	static const uint16_t IOTA_CONST[NROUNDS] = {
+	static const uint16_t IOTA_CONST[NROUNDS] ALIGN2 = {
 		/* Elements should be 64-bit, but top half is always zero
 		 * or 0x80000000. We encode 63rd bits in a separate word below.
 		 * Same is true for 31th bits, which lets us use 16-bit table
@@ -1210,15 +1210,15 @@ static void sha3_process_block72(uint64_t *state)
 	/* bit for CONST[0] is in msb: 0001 0110 0011 1000 0001 1011 */
 	const uint32_t IOTA_CONST_bit31 = (uint32_t)(0x16381b00);
 
-	static const uint8_t ROT_CONST[24] = {
+	static const uint8_t ROT_CONST[24] ALIGN1 = {
 		1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
 		27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
 	};
-	static const uint8_t PI_LANE[24] = {
+	static const uint8_t PI_LANE[24] ALIGN1 = {
 		10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
 		15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
 	};
-	/*static const uint8_t MOD5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/
+	/*static const uint8_t MOD5[10] ALIGN1 = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/
 
 	unsigned x;
 	unsigned round;
diff --git a/libbb/mode_string.c b/libbb/mode_string.c
index 5ffd5683e..9a286f3ff 100644
--- a/libbb/mode_string.c
+++ b/libbb/mode_string.c
@@ -27,7 +27,7 @@
 #define mode_t unsigned short
 #endif
 
-static const mode_t mode_flags[] = {
+static const mode_t mode_flags[] ALIGN4 = {
 	S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID,
 	S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID,
 	S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX
diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c
index 19a9ab15b..c6fc328d8 100644
--- a/libbb/pw_encrypt_des.c
+++ b/libbb/pw_encrypt_des.c
@@ -65,25 +65,25 @@
 
 
 /* A pile of data */
-static const uint8_t IP[64] = {
+static const uint8_t IP[64] ALIGN1 = {
 	58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,
 	62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,
 	57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,
 	61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7
 };
 
-static const uint8_t key_perm[56] = {
+static const uint8_t key_perm[56] ALIGN1 = {
 	57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
 	10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
 	63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
 	14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
 };
 
-static const uint8_t key_shifts[16] = {
+static const uint8_t key_shifts[16] ALIGN1 = {
 	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
 };
 
-static const uint8_t comp_perm[48] = {
+static const uint8_t comp_perm[48] ALIGN1 = {
 	14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
 	23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
 	41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
@@ -181,13 +181,12 @@ static const uint8_t u_sbox[8][32] = {
 };
 #endif
 
-static const uint8_t pbox[32] = {
+static const uint8_t pbox[32] ALIGN1 = {
 	16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
 	 2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
 };
 
-static const uint32_t bits32[32] =
-{
+static const uint32_t bits32[32] ALIGN4 = {
 	0x80000000, 0x40000000, 0x20000000, 0x10000000,
 	0x08000000, 0x04000000, 0x02000000, 0x01000000,
 	0x00800000, 0x00400000, 0x00200000, 0x00100000,
@@ -198,7 +197,7 @@ static const uint32_t bits32[32] =
 	0x00000008, 0x00000004, 0x00000002, 0x00000001
 };
 
-static const uint8_t bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+static const uint8_t bits8[8] ALIGN1 = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
 
 
 static int
diff --git a/libbb/speed_table.c b/libbb/speed_table.c
index 967cf8de8..cf7101e64 100644
--- a/libbb/speed_table.c
+++ b/libbb/speed_table.c
@@ -28,7 +28,7 @@ struct speed_map {
 };
 
 /* On Linux, Bxx constants are 0..15 (up to B38400) and 0x1001..0x100f */
-static const struct speed_map speeds[] = {
+static const struct speed_map speeds[] ALIGN4 = {
 	{B0, 0},
 	{B50, 50},
 	{B75, 75},
diff --git a/libbb/xatonum.c b/libbb/xatonum.c
index 7639a62aa..36b06c849 100644
--- a/libbb/xatonum.c
+++ b/libbb/xatonum.c
@@ -68,14 +68,14 @@ uint16_t FAST_FUNC xatou16(const char *numstr)
 	return xatou_range(numstr, 0, 0xffff);
 }
 
-const struct suffix_mult bkm_suffixes[] = {
+const struct suffix_mult bkm_suffixes[] ALIGN_SUFFIX = {
 	{ "b", 512 },
 	{ "k", 1024 },
 	{ "m", 1024*1024 },
 	{ "", 0 }
 };
 
-const struct suffix_mult cwbkMG_suffixes[] = {
+const struct suffix_mult cwbkMG_suffixes[] ALIGN_SUFFIX = {
 	{ "c", 1 },
 	{ "w", 2 },
 	{ "b", 512 },
@@ -96,7 +96,7 @@ const struct suffix_mult cwbkMG_suffixes[] = {
 	{ "", 0 }
 };
 
-const struct suffix_mult kmg_i_suffixes[] = {
+const struct suffix_mult kmg_i_suffixes[] ALIGN_SUFFIX = {
 	{ "KiB", 1024 },
 	{ "kiB", 1024 },
 	{ "K", 1024 },
diff --git a/miscutils/crond.c b/miscutils/crond.c
index 2e8ca8b68..fb3adc180 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -492,7 +492,7 @@ static void load_crontab(const char *fileName)
 					const char *name;
 					const char tokens[8];
 				} SpecialEntry;
-				static const SpecialEntry SpecAry[] = {
+				static const SpecialEntry SpecAry[] ALIGN8 = {
 					/*              hour  day   month weekday */
 					{ "yearly",     "0\0" "1\0" "1\0" "*" },
 					{ "annually",   "0\0" "1\0" "1\0" "*" },
diff --git a/miscutils/dc.c b/miscutils/dc.c
index ef93c20ba..51376dd75 100644
--- a/miscutils/dc.c
+++ b/miscutils/dc.c
@@ -195,7 +195,7 @@ struct op {
 	void (*function) (void);
 };
 
-static const struct op operators[] = {
+static const struct op operators[] ALIGN_PTR = {
 #if ENABLE_FEATURE_DC_LIBM
 	{"^",   power},
 //	{"exp", power},
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index 431a0ad96..01b4e8e2e 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -1366,7 +1366,7 @@ static NOINLINE void dump_identity(const struct hd_driveid *id)
 	}
 	if (id->capability & 1) {
 		if (id->dma_1word | id->dma_mword) {
-			static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
+			static const int dma_wmode_masks[] ALIGN4 = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
 			printf("\n DMA modes:  ");
 			print_flags_separated(dma_wmode_masks,
 				"*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0",
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index cc8b99a92..09364e396 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -1053,18 +1053,13 @@ struct adap_desc {
 };
 
 static const struct adap_desc adap_descs[] = {
-	{ .funcs	= "dummy",
-	  .algo		= "Dummy bus", },
-	{ .funcs	= "isa",
-	  .algo		= "ISA bus", },
-	{ .funcs	= "i2c",
-	  .algo		= "I2C adapter", },
-	{ .funcs	= "smbus",
-	  .algo		= "SMBus adapter", },
+	{ .funcs = "dummy", .algo = "Dummy bus", },
+	{ .funcs = "isa",   .algo = "ISA bus", },
+	{ .funcs = "i2c",   .algo = "I2C adapter", },
+	{ .funcs = "smbus", .algo = "SMBus adapter", },
 };
 
-struct i2c_func
-{
+struct i2c_func {
 	long value;
 	const char* name;
 };
diff --git a/miscutils/mt.c b/miscutils/mt.c
index 9f1aecfca..dbb8c13ad 100644
--- a/miscutils/mt.c
+++ b/miscutils/mt.c
@@ -30,7 +30,7 @@
 #include <sys/mtio.h>
 
 /* missing: eod/seod, stoptions, stwrthreshold, densities */
-static const short opcode_value[] = {
+static const short opcode_value[] ALIGN2 = {
 	MTBSF,
 	MTBSFM,
 	MTBSR,
diff --git a/miscutils/setserial.c b/miscutils/setserial.c
index 1e75bf433..2006861e2 100644
--- a/miscutils/setserial.c
+++ b/miscutils/setserial.c
@@ -381,8 +381,7 @@ static bool cmd_needs_arg(int cmd)
 # error "Unexpected flags size"
 #endif
 
-static const uint16_t setbits[CMD_FLAG_LAST + 1] =
-{
+static const uint16_t setbits[CMD_FLAG_LAST + 1] ALIGN2 = {
 	0,
 	ASYNC_SPD_HI,
 	ASYNC_SPD_VHI,
diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c
index 94a637eee..69ead7a13 100644
--- a/miscutils/ubi_tools.c
+++ b/miscutils/ubi_tools.c
@@ -97,7 +97,7 @@ static unsigned get_num_from_file(const char *path, unsigned max)
 int ubi_tools_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int ubi_tools_main(int argc UNUSED_PARAM, char **argv)
 {
-	static const struct suffix_mult size_suffixes[] = {
+	static const struct suffix_mult size_suffixes[] ALIGN_SUFFIX = {
 		{ "KiB", 1024 },
 		{ "MiB", 1024*1024 },
 		{ "GiB", 1024*1024*1024 },
diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c
index 971b777a3..0ed10bcf1 100644
--- a/miscutils/watchdog.c
+++ b/miscutils/watchdog.c
@@ -88,7 +88,7 @@ int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int watchdog_main(int argc UNUSED_PARAM, char **argv)
 {
 	static const int enable = WDIOS_ENABLECARD;
-	static const struct suffix_mult suffixes[] = {
+	static const struct suffix_mult suffixes[] ALIGN_SUFFIX = {
 		{ "ms", 1 },
 		{ "", 1000 },
 		{ "", 0 }
diff --git a/modutils/modinfo.c b/modutils/modinfo.c
index c5cdc7980..d15772f0d 100644
--- a/modutils/modinfo.c
+++ b/modutils/modinfo.c
@@ -20,7 +20,7 @@
 #include "libbb.h"
 #include "modutils.h"
 
-static const char *const shortcuts[] = {
+static const char *const shortcuts[] ALIGN_PTR = {
 	"filename",	// -n
 	"author",	// -a
 	"description",	// -d
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 60916eae6..18dcaff96 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -304,7 +304,7 @@ static const char api_modes[] ALIGN1 = "empwia";
 static const struct {
 	const char *name;
 	smallint (*func)(void);
-} method_table[] = {
+} method_table[] ALIGN_PTR = {
 	{ "SIOCETHTOOL"       , &detect_link_ethtool },
 	{ "SIOCGMIIPHY"       , &detect_link_mii     },
 	{ "SIOCDEVPRIVATE"    , &detect_link_priv    },
diff --git a/networking/interface.c b/networking/interface.c
index e5e55d8d4..ea6a2c8a8 100644
--- a/networking/interface.c
+++ b/networking/interface.c
@@ -746,7 +746,7 @@ static const struct hwtype *const hwtypes[] = {
 };
 
 #ifdef IFF_PORTSEL
-static const char *const if_port_text[] = {
+static const char *const if_port_text[] ALIGN_PTR = {
 	/* Keep in step with <linux/netdevice.h> */
 	"unknown",
 	"10base2",
diff --git a/networking/ip.c b/networking/ip.c
index 33bea5f49..85b1ba080 100644
--- a/networking/ip.c
+++ b/networking/ip.c
@@ -400,7 +400,7 @@ int ip_main(int argc UNUSED_PARAM, char **argv)
 		IF_FEATURE_IP_RULE("rule\0")
 		IF_FEATURE_IP_NEIGH("neigh\0")
 		;
-	static const ip_func_ptr_t ip_func_ptrs[] = {
+	static const ip_func_ptr_t ip_func_ptrs[] ALIGN_PTR = {
 		ip_print_help,
 		IF_FEATURE_IP_ADDRESS(do_ipaddr,)
 		IF_FEATURE_IP_ROUTE(do_iproute,)
diff --git a/networking/libiproute/rt_names.c b/networking/libiproute/rt_names.c
index 51f2e9bdb..3c2fad912 100644
--- a/networking/libiproute/rt_names.c
+++ b/networking/libiproute/rt_names.c
@@ -77,7 +77,7 @@ static rtnl_tab_t *rtnl_rtprot_tab;
 
 static void rtnl_rtprot_initialize(void)
 {
-	static const char *const init_tab[] = {
+	static const char *const init_tab[] ALIGN_PTR = {
 		"none",
 		"redirect",
 		"kernel",
diff --git a/networking/route.c b/networking/route.c
index 4d9aad6cc..4901109f1 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -460,9 +460,9 @@ static NOINLINE void INET6_setroute(int action, char **args)
 #endif
 
 static const
-IF_NOT_FEATURE_IPV6(uint16_t)
-IF_FEATURE_IPV6(unsigned)
-flagvals[] = { /* Must agree with flagchars[]. */
+IF_NOT_FEATURE_IPV6(uint16_t flagvals[] ALIGN2 = )
+IF_FEATURE_IPV6(uint32_t flagvals[] ALIGN4 = )
+{ /* Must agree with flagchars[]. */
 	RTF_UP,
 	RTF_GATEWAY,
 	RTF_HOST,
diff --git a/networking/tls.c b/networking/tls.c
index 341225207..e34acd69f 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -1953,7 +1953,7 @@ static void send_client_key_exchange(tls_state_t *tls)
 		premaster_size = sizeof(rsa_premaster);
 	} else {
 		/* ECDHE */
-		static const uint8_t basepoint9[CURVE25519_KEYSIZE] = {9};
+		static const uint8_t basepoint9[CURVE25519_KEYSIZE] ALIGN1 = {9};
 		uint8_t privkey[CURVE25519_KEYSIZE]; //[32]
 
 		if (!(tls->flags & GOT_EC_KEY))
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index acfdaa8c3..de16cf955 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -398,7 +398,7 @@ struct config_keyword {
 
 #define OFS(field) offsetof(struct server_data_t, field)
 
-static const struct config_keyword keywords[] = {
+static const struct config_keyword keywords[] ALIGN_PTR = {
 	/* keyword        handler           variable address    default */
 	{"start"        , udhcp_str2nip   , OFS(start_ip     ), "192.168.0.20"},
 	{"end"          , udhcp_str2nip   , OFS(end_ip       ), "192.168.0.254"},
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 856ce0202..07b7abe2f 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -838,7 +838,7 @@ static void FAST_FUNC collect_info(s_stat *s)
 typedef s_stat* init_func(const char *param);
 
 static const char options[] ALIGN1 = "ncmsfixptTbr";
-static init_func *const init_functions[] = {
+static init_func *const init_functions[] ALIGN_PTR = {
 	init_if,
 	init_cpu,
 	init_mem,
diff --git a/procps/ps.c b/procps/ps.c
index 48f96209f..711b180a0 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -375,7 +375,7 @@ static void func_pcpu(char *buf, int size, const procps_status_t *ps)
 }
 */
 
-static const ps_out_t out_spec[] = {
+static const ps_out_t out_spec[] ALIGN_PTR = {
 /* Mandated by http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html: */
 	{ 8                  , "user"  ,"USER"   ,func_user  ,PSSCAN_UIDGID  },
 	{ 8                  , "group" ,"GROUP"  ,func_group ,PSSCAN_UIDGID  },
diff --git a/runit/svlogd.c b/runit/svlogd.c
index a250058a1..040e71104 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -775,7 +775,7 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn)
 				ld->nmin = xatoi_positive(&s[1]);
 				break;
 			case 't': {
-				static const struct suffix_mult mh_suffixes[] = {
+				static const struct suffix_mult mh_suffixes[] ALIGN_SUFFIX = {
 					{ "m", 60 },
 					{ "h", 60*60 },
 					/*{ "d", 24*60*60 },*/
diff --git a/shell/ash.c b/shell/ash.c
index 8c9a590d1..40695dee0 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -2091,7 +2091,7 @@ static const struct {
 	int flags;
 	const char *var_text;
 	void (*var_func)(const char *) FAST_FUNC;
-} varinit_data[] = {
+} varinit_data[] ALIGN_PTR = {
 	/*
 	 * Note: VEXPORT would not work correctly here for NOFORK applets:
 	 * some environment strings may be constant.
@@ -4811,7 +4811,7 @@ static char *cmdnextc;
 static void
 cmdputs(const char *s)
 {
-	static const char vstype[VSTYPE + 1][3] = {
+	static const char vstype[VSTYPE + 1][3] ALIGN1 = {
 		"", "}", "-", "+", "?", "=",
 		"%", "%%", "#", "##"
 		IF_BASH_SUBSTR(, ":")
@@ -8510,7 +8510,7 @@ enum {
 	, /* thus far 29 bits used */
 };
 
-static const char *const tokname_array[] = {
+static const char *const tokname_array[] ALIGN_PTR = {
 	"end of file",
 	"newline",
 	"redirection",
diff --git a/shell/hush.c b/shell/hush.c
index f1a7e07ee..b6d9d7abb 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -596,10 +596,10 @@ typedef struct in_str {
 /* The descrip member of this structure is only used to make
  * debugging output pretty */
 static const struct {
-	int mode;
+	int32_t mode;
 	signed char default_fd;
 	char descrip[3];
-} redir_table[] = {
+} redir_table[] ALIGN4 = {
 	{ O_RDONLY,                  0, "<"  },
 	{ O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
 	{ O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
@@ -1143,7 +1143,7 @@ struct built_in_command {
 #endif
 };
 
-static const struct built_in_command bltins1[] = {
+static const struct built_in_command bltins1[] ALIGN_PTR = {
 	BLTIN("."        , builtin_source  , "Run commands in file"),
 	BLTIN(":"        , builtin_true    , NULL),
 #if ENABLE_HUSH_JOB
@@ -1228,7 +1228,7 @@ static const struct built_in_command bltins1[] = {
 /* These builtins won't be used if we are on NOMMU and need to re-exec
  * (it's cheaper to run an external program in this case):
  */
-static const struct built_in_command bltins2[] = {
+static const struct built_in_command bltins2[] ALIGN_PTR = {
 #if ENABLE_HUSH_TEST
 	BLTIN("["        , builtin_test    , NULL),
 #endif
@@ -3895,7 +3895,7 @@ struct reserved_combo {
 	char literal[6];
 	unsigned char res;
 	unsigned char assignment_flag;
-	int flag;
+	uint32_t flag;
 };
 enum {
 	FLAG_END   = (1 << RES_NONE ),
@@ -3928,7 +3928,7 @@ static const struct reserved_combo* match_reserved_word(o_string *word)
 	 * to turn the compound list into a command.
 	 * FLAG_START means the word must start a new compound list.
 	 */
-	static const struct reserved_combo reserved_list[] = {
+	static const struct reserved_combo reserved_list[] ALIGN4 = {
 # if ENABLE_HUSH_IF
 		{ "!",     RES_NONE,  NOT_ASSIGNMENT  , 0 },
 		{ "if",    RES_IF,    MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
diff --git a/shell/shell_common.c b/shell/shell_common.c
index 42c4c9c97..dcbe0d109 100644
--- a/shell/shell_common.c
+++ b/shell/shell_common.c
@@ -324,7 +324,7 @@ struct limits {
 	uint8_t factor_shift;   /* shift by to get rlim_{cur,max} values */
 };
 
-static const struct limits limits_tbl[] = {
+static const struct limits limits_tbl[] ALIGN2 = {
 	{ RLIMIT_CORE,		9,	}, // -c
 	{ RLIMIT_DATA,		10,	}, // -d
 	{ RLIMIT_NICE,		0,	}, // -e
diff --git a/util-linux/acpid.c b/util-linux/acpid.c
index d473e24fc..00613f8e3 100644
--- a/util-linux/acpid.c
+++ b/util-linux/acpid.c
@@ -99,7 +99,7 @@ struct acpi_event {
 	const char *desc;
 };
 
-static const struct acpi_event f_evt_tab[] = {
+static const struct acpi_event f_evt_tab[] ALIGN_PTR = {
 	{ "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRF 00000080" },
 	{ "EV_KEY", 0x01, "KEY_POWER", 116, 1, "button/power PWRB 00000080" },
 	{ "EV_SW", 0x05, "SW_LID", 0x00, 1, "button/lid LID0 00000080" },
@@ -110,7 +110,7 @@ struct acpi_action {
 	const char *action;
 };
 
-static const struct acpi_action f_act_tab[] = {
+static const struct acpi_action f_act_tab[] ALIGN_PTR = {
 	{ "PWRF", "PWRF/00000080" },
 	{ "LID0", "LID/00000080" },
 };
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
index 0b9a9a6bc..cc5413b40 100644
--- a/util-linux/fbset.c
+++ b/util-linux/fbset.c
@@ -193,7 +193,7 @@ static const struct cmdoptions_t {
 	const char name[9];
 	const unsigned char param_count;
 	const unsigned char code;
-} g_cmdoptions[] = {
+} g_cmdoptions[] ALIGN1 = {
 	/*"12345678" + NUL */
 //TODO: convert to index_in_strings()
 	{ "fb"      , 1, CMD_FB       },
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index 0df3ebf7d..6454baab8 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -303,7 +303,7 @@ static sector_t get_nr_sects(const struct partition *p);
 
 /* DOS partition types */
 
-static const char *const i386_sys_types[] = {
+static const char *const i386_sys_types[] ALIGN_PTR = {
 	"\x00" "Empty",
 	"\x01" "FAT12",
 	"\x04" "FAT16 <32M",
diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c
index 92180b2bc..765740ff1 100644
--- a/util-linux/fdisk_osf.c
+++ b/util-linux/fdisk_osf.c
@@ -144,7 +144,7 @@ struct xbsd_disklabel {
 #define BSD_DSTYPE_DOSPART(s)   ((s) & 3)       /* dos partition number */
 #define BSD_DSTYPE_GEOMETRY     0x10            /* drive params in label */
 
-static const char *const xbsd_dktypenames[] = {
+static const char *const xbsd_dktypenames[] ALIGN_PTR = {
 	"unknown",
 	"SMD",
 	"MSCP",
@@ -190,7 +190,7 @@ static const char *const xbsd_dktypenames[] = {
 #define BSD_FS_MSDOS    8               /* MS-DOS file system */
 #endif
 
-static const char *const xbsd_fstypes[] = {
+static const char *const xbsd_fstypes[] ALIGN_PTR = {
 	"\x00" "unused",            /* BSD_FS_UNUSED  */
 	"\x01" "swap",              /* BSD_FS_SWAP    */
 	"\x02" "Version 6",         /* BSD_FS_V6      */
diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c
index c90c801e2..acb438ac0 100644
--- a/util-linux/fdisk_sgi.c
+++ b/util-linux/fdisk_sgi.c
@@ -174,7 +174,7 @@ isinfreelist(unsigned int b)
  * end of free blocks section
  */
 
-static const char *const sgi_sys_types[] = {
+static const char *const sgi_sys_types[] ALIGN_PTR = {
 /* SGI_VOLHDR   */	"\x00" "SGI volhdr"  ,
 /* 0x01         */	"\x01" "SGI trkrepl" ,
 /* 0x02         */	"\x02" "SGI secrepl" ,
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c
index 29d7c283a..427b9487b 100644
--- a/util-linux/fdisk_sun.c
+++ b/util-linux/fdisk_sun.c
@@ -61,7 +61,7 @@ guess_device_type(void)
 	}
 }
 
-static const char *const sun_sys_types[] = {
+static const char *const sun_sys_types[] ALIGN_PTR = {
 	"\x00" "Empty"       , /* 0            */
 	"\x01" "Boot"        , /* 1            */
 	"\x02" "SunOS root"  , /* 2            */
@@ -133,7 +133,7 @@ static const struct sun_predefined_drives {
 	unsigned short ntrks;
 	unsigned short nsect;
 	unsigned short rspeed;
-} sun_drives[] = {
+} sun_drives[] ALIGN_PTR = {
 	{ "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
 	{ "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
 	{ "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
diff --git a/util-linux/mkfs_ext2.c b/util-linux/mkfs_ext2.c
index 1f525d75b..fcf374b2d 100644
--- a/util-linux/mkfs_ext2.c
+++ b/util-linux/mkfs_ext2.c
@@ -131,7 +131,7 @@ static void allocate(uint8_t *bitmap, uint32_t blocksize, uint32_t start, uint32
 static uint32_t has_super(uint32_t x)
 {
 	// 0, 1 and powers of 3, 5, 7 up to 2^32 limit
-	static const uint32_t supers[] = {
+	static const uint32_t supers[] ALIGN4 = {
 		0, 1, 3, 5, 7, 9, 25, 27, 49, 81, 125, 243, 343, 625, 729,
 		2187, 2401, 3125, 6561, 15625, 16807, 19683, 59049, 78125,
 		117649, 177147, 390625, 531441, 823543, 1594323, 1953125,
diff --git a/util-linux/mount.c b/util-linux/mount.c
index fc5161d7f..aa38847ec 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -323,7 +323,7 @@ enum {
 
 // Standard mount options (from -o options or --options),
 // with corresponding flags
-static const int32_t mount_options[] = {
+static const int32_t mount_options[] ALIGN4 = {
 	// MS_FLAGS set a bit.  ~MS_FLAGS disable that bit.  0 flags are NOPs.
 
 	IF_FEATURE_MOUNT_LOOP(
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c
index 99150a5b7..8ceb61bde 100644
--- a/util-linux/volume_id/volume_id.c
+++ b/util-linux/volume_id/volume_id.c
@@ -49,7 +49,7 @@
 typedef int FAST_FUNC (*raid_probe_fptr)(struct volume_id *id, /*uint64_t off,*/ uint64_t size);
 typedef int FAST_FUNC (*probe_fptr)(struct volume_id *id /*, uint64_t off*/);
 
-static const raid_probe_fptr raid1[] = {
+static const raid_probe_fptr raid1[] ALIGN_PTR = {
 #if ENABLE_FEATURE_VOLUMEID_LINUXRAID
 	volume_id_probe_linux_raid,
 #endif
@@ -76,7 +76,7 @@ static const raid_probe_fptr raid1[] = {
 #endif
 };
 
-static const probe_fptr raid2[] = {
+static const probe_fptr raid2[] ALIGN_PTR = {
 #if ENABLE_FEATURE_VOLUMEID_LVM
 	volume_id_probe_lvm1,
 	volume_id_probe_lvm2,
@@ -90,7 +90,7 @@ static const probe_fptr raid2[] = {
 };
 
 /* signature in the first block, only small buffer needed */
-static const probe_fptr fs1[] = {
+static const probe_fptr fs1[] ALIGN_PTR = {
 #if ENABLE_FEATURE_VOLUMEID_FAT
 	volume_id_probe_vfat,
 #endif
@@ -118,7 +118,7 @@ static const probe_fptr fs1[] = {
 };
 
 /* fill buffer with maximum */
-static const probe_fptr fs2[] = {
+static const probe_fptr fs2[] ALIGN_PTR = {
 #if ENABLE_FEATURE_VOLUMEID_LINUXSWAP
 	volume_id_probe_linux_swap,
 #endif
-- 
cgit v1.2.3-55-g6feb


From 2075aa93e007863c6b680994a7a0ba420181034f Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 2 Dec 2020 21:28:47 +0100
Subject: libbb: rename run_shell() to exec_shell()

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h      |  4 ++--
 libbb/executable.c   |  9 ---------
 libbb/run_shell.c    | 13 +++++++++++--
 loginutils/login.c   |  2 +-
 loginutils/su.c      |  2 +-
 loginutils/sulogin.c |  2 +-
 6 files changed, 16 insertions(+), 16 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index 9872dc1fb..c23018f17 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1140,7 +1140,6 @@ int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC;
 #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
 #endif
 void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
-void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
 
 /* xvfork() can't be a _function_, return after vfork in child mangles stack
  * in the parent. It must be a macro. */
@@ -1607,7 +1606,8 @@ void bb_do_delay(unsigned seconds) FAST_FUNC;
 void msleep(unsigned ms) FAST_FUNC;
 void sleep1(void) FAST_FUNC;
 void change_identity(const struct passwd *pw) FAST_FUNC;
-void run_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
+void exec_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
+void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
 
 /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL.
  * Note that getpwuid result might need xstrdup'ing
diff --git a/libbb/executable.c b/libbb/executable.c
index 29d2a2c85..a033b74d9 100644
--- a/libbb/executable.c
+++ b/libbb/executable.c
@@ -91,12 +91,3 @@ void FAST_FUNC BB_EXECVP_or_die(char **argv)
 	xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
 	bb_perror_msg_and_die("can't execute '%s'", argv[0]);
 }
-
-/* Typical idiom for applets which exec *optional* PROG [ARGS] */
-void FAST_FUNC exec_prog_or_SHELL(char **argv)
-{
-	if (argv[0]) {
-		BB_EXECVP_or_die(argv);
-	}
-	run_shell(getenv("SHELL"), /*login:*/ 1, NULL);
-}
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index a0420d982..c2ff69651 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -48,10 +48,10 @@ void FAST_FUNC set_current_security_context(security_context_t sid)
 
 #endif
 
-/* Run SHELL, or DEFAULT_SHELL if SHELL is "" or NULL.
+/* Exec SHELL, or DEFAULT_SHELL if SHELL is "" or NULL.
  * If ADDITIONAL_ARGS is not NULL, pass them to the shell.
  */
-void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additional_args)
+void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additional_args)
 {
 	const char **args;
 
@@ -84,3 +84,12 @@ void FAST_FUNC run_shell(const char *shell, int loginshell, const char **additio
 	execv(shell, (char **) args);
 	bb_perror_msg_and_die("can't execute '%s'", shell);
 }
+
+/* Typical idiom for applets which exec *optional* PROG [ARGS] */
+void FAST_FUNC exec_prog_or_SHELL(char **argv)
+{
+	if (argv[0]) {
+		BB_EXECVP_or_die(argv);
+	}
+	exec_shell(getenv("SHELL"), /*login:*/ 1, NULL);
+}
diff --git a/loginutils/login.c b/loginutils/login.c
index f0bce50ce..aacd47241 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -602,7 +602,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 	signal(SIGINT, SIG_DFL);
 
 	/* Exec login shell with no additional parameters */
-	run_shell(pw->pw_shell, 1, NULL);
+	exec_shell(pw->pw_shell, 1, NULL);
 
 	/* return EXIT_FAILURE; - not reached */
 }
diff --git a/loginutils/su.c b/loginutils/su.c
index 6f91039f9..784a53552 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -204,7 +204,7 @@ int su_main(int argc UNUSED_PARAM, char **argv)
 	 */
 
 	/* Never returns */
-	run_shell(opt_shell, flags & SU_OPT_l, (const char**)argv);
+	exec_shell(opt_shell, flags & SU_OPT_l, (const char**)argv);
 
 	/* return EXIT_FAILURE; - not reached */
 }
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index 48dafd186..127aa1de9 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -89,5 +89,5 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
 		shell = pwd->pw_shell;
 
 	/* Exec login shell with no additional parameters. Never returns. */
-	run_shell(shell, 1, NULL);
+	exec_shell(shell, 1, NULL);
 }
-- 
cgit v1.2.3-55-g6feb


From 0622416fece00507cf0ac53a2aa17ca3b1e565b2 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 2 Dec 2020 21:35:32 +0100
Subject: libbb: code shrink in exec_shell()

function                                             old     new   delta
exec_shell                                           129     120      -9

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/run_shell.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

(limited to 'libbb')

diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index c2ff69651..9bec43b7c 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -59,7 +59,7 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi
 	while (args && *args)
 		args++;
 
-	args = xmalloc(sizeof(char*) * (2 + (args - additional_args)));
+	args = xzalloc(sizeof(args[0]) * (2 + (args - additional_args)));
 
 	if (!shell || !shell[0])
 		shell = DEFAULT_SHELL;
@@ -67,12 +67,11 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi
 	args[0] = bb_get_last_path_component_nostrip(shell);
 	if (loginshell)
 		args[0] = xasprintf("-%s", args[0]);
-	args[1] = NULL;
+	/*args[1] = NULL; - already is */
 	if (additional_args) {
-		int cnt = 1;
-		for (;;)
-			if ((args[cnt++] = *additional_args++) == NULL)
-				break;
+		int cnt = 0;
+		while (*additional_args)
+			args[++cnt] = *additional_args++;
 	}
 
 #if ENABLE_SELINUX
@@ -91,5 +90,8 @@ void FAST_FUNC exec_prog_or_SHELL(char **argv)
 	if (argv[0]) {
 		BB_EXECVP_or_die(argv);
 	}
+	/* Why login=1? Both users (nsenter and unshare) do indeed exec
+	 * a _login_ shell (with dash in argv[0])!
+	 */
 	exec_shell(getenv("SHELL"), /*login:*/ 1, NULL);
 }
-- 
cgit v1.2.3-55-g6feb


From f4f6e5144b9af71dc687dc14dba4a6caf8c28361 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 2 Dec 2020 21:51:08 +0100
Subject: libbb: exec_login_shell() - new function

function                                             old     new   delta
exec_login_shell                                       -      12     +12
sulogin_main                                         247     240      -7
login_main                                           960     953      -7
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/2 up/down: 12/-14)             Total: -2 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h      | 1 +
 libbb/run_shell.c    | 9 +++++++--
 loginutils/login.c   | 2 +-
 loginutils/sulogin.c | 2 +-
 4 files changed, 10 insertions(+), 4 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index c23018f17..8f1ee7eec 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1607,6 +1607,7 @@ void msleep(unsigned ms) FAST_FUNC;
 void sleep1(void) FAST_FUNC;
 void change_identity(const struct passwd *pw) FAST_FUNC;
 void exec_shell(const char *shell, int loginshell, const char **args) NORETURN FAST_FUNC;
+void exec_login_shell(const char *shell) NORETURN FAST_FUNC;
 void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
 
 /* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL.
diff --git a/libbb/run_shell.c b/libbb/run_shell.c
index 9bec43b7c..c22bba87b 100644
--- a/libbb/run_shell.c
+++ b/libbb/run_shell.c
@@ -84,14 +84,19 @@ void FAST_FUNC exec_shell(const char *shell, int loginshell, const char **additi
 	bb_perror_msg_and_die("can't execute '%s'", shell);
 }
 
+void FAST_FUNC exec_login_shell(const char *shell)
+{
+	exec_shell(shell, 1, NULL);
+}
+
 /* Typical idiom for applets which exec *optional* PROG [ARGS] */
 void FAST_FUNC exec_prog_or_SHELL(char **argv)
 {
 	if (argv[0]) {
 		BB_EXECVP_or_die(argv);
 	}
-	/* Why login=1? Both users (nsenter and unshare) do indeed exec
+	/* Both users (nsenter and unshare) do indeed exec
 	 * a _login_ shell (with dash in argv[0])!
 	 */
-	exec_shell(getenv("SHELL"), /*login:*/ 1, NULL);
+	exec_login_shell(getenv("SHELL"));
 }
diff --git a/loginutils/login.c b/loginutils/login.c
index aacd47241..de05631d2 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -602,7 +602,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 	signal(SIGINT, SIG_DFL);
 
 	/* Exec login shell with no additional parameters */
-	exec_shell(pw->pw_shell, 1, NULL);
+	exec_login_shell(pw->pw_shell);
 
 	/* return EXIT_FAILURE; - not reached */
 }
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index 127aa1de9..69d8b5ec7 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -89,5 +89,5 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
 		shell = pwd->pw_shell;
 
 	/* Exec login shell with no additional parameters. Never returns. */
-	exec_shell(shell, 1, NULL);
+	exec_login_shell(shell);
 }
-- 
cgit v1.2.3-55-g6feb


From abaee4aada7c91da6a43a83e9a73f98916a803a4 Mon Sep 17 00:00:00 2001
From: Xabier Oneca <xoneca@gmail.com>
Date: Tue, 1 Dec 2020 23:14:59 +0100
Subject: mkdtemp: proper error detection on mktemp

On error, mktemp returns an empty string, not NULL.

Signed-off-by: Xabier Oneca <xoneca@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/platform.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/libbb/platform.c b/libbb/platform.c
index 03bbb798b..d2b263a6d 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -107,7 +107,8 @@ void* FAST_FUNC memrchr(const void *s, int c, size_t n)
 /* This is now actually part of POSIX.1, but was only added in 2008 */
 char* FAST_FUNC mkdtemp(char *template)
 {
-	if (mktemp(template) == NULL || mkdir(template, 0700) != 0)
+	/* NB: on error, mktemp returns an empty string, not NULL */
+	if (mktemp(template)[0] == '\0' || mkdir(template, 0700) != 0)
 		return NULL;
 	return template;
 }
-- 
cgit v1.2.3-55-g6feb


From 030fe31760169783537162b83af89e551bf120f6 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 11 Dec 2020 16:48:47 +0100
Subject: libbb: make msleep() result in only one syscall instead of looping

function                                             old     new   delta
msleep                                                45      52      +7

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/bb_do_delay.c   | 18 ++++++++++++++++++
 libbb/platform.c      |  1 -
 networking/ifupdown.c |  6 +++---
 3 files changed, 21 insertions(+), 4 deletions(-)

(limited to 'libbb')

diff --git a/libbb/bb_do_delay.c b/libbb/bb_do_delay.c
index 3dbf032db..9a84fa24b 100644
--- a/libbb/bb_do_delay.c
+++ b/libbb/bb_do_delay.c
@@ -36,6 +36,7 @@ void FAST_FUNC sleep1(void)
 
 void FAST_FUNC msleep(unsigned ms)
 {
+#if 0
 	/* 1. usleep(n) is not guaranteed by standards to accept n >= 1000000
 	 * 2. multiplication in usleep(ms * 1000) can overflow if ms > 4294967
 	 *    (sleep of ~71.5 minutes)
@@ -46,4 +47,21 @@ void FAST_FUNC msleep(unsigned ms)
 		ms -= 500;
 	}
 	usleep(ms * 1000);
+#else
+//usleep is often implemented as a call to nanosleep.
+//Simply do the same to implement msleep.
+//it's marginally larger, but wakes your CPU less often:
+//function    old     new   delta
+//msleep       45      52      +7
+	struct timespec ts;
+	ts.tv_sec = ms / 1000;
+	ts.tv_nsec = (ms % 1000) * 1000000;
+	/*
+	 * If a signal has non-default handler, nanosleep returns early.
+	 * Our version of msleep doesn't return early
+	 * if interrupted by such signals:
+	 */
+	while (nanosleep(&ts, &ts) != 0)
+		continue;
+#endif
 }
diff --git a/libbb/platform.c b/libbb/platform.c
index d2b263a6d..329b0237e 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -27,7 +27,6 @@ int FAST_FUNC usleep(unsigned usec)
 	 * If a signal has non-default handler, nanosleep returns early.
 	 * Our version of usleep doesn't return early
 	 * if interrupted by such signals:
-	 *
 	 */
 	while (nanosleep(&ts, &ts) != 0)
 		continue;
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 60ceb5a1f..fedf05aaf 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -1357,15 +1357,15 @@ static FILE *open_new_state_file(void)
 					IFSTATE_FILE_PATH".new");
 		}
 		/* Someone else created the .new file */
-		if (cnt > 30 * 1000) {
+		if (cnt > 30) {
 			/* Waited for 30*30/2 = 450 milliseconds, still EEXIST.
 			 * Assuming a stale file, rewriting it.
 			 */
 			flags = (O_WRONLY | O_CREAT | O_TRUNC);
 			continue;
 		}
-		usleep(cnt);
-		cnt += 1000;
+		msleep(cnt);
+		cnt++;
 	}
 
 	return xfdopen_for_write(fd);
-- 
cgit v1.2.3-55-g6feb


From fd3c512f88d43e6633bd3c3110cfa0bb321adaa8 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 14 Dec 2020 18:25:28 +0100
Subject: libbb: create and use mmap() helpers

function                                             old     new   delta
mmap_anon                                              -      22     +22
mmap_read                                              -      21     +21
xmmap_anon                                             -      16     +16
rpm_gettags                                          465     447     -18
bb_full_fd_action                                    498     480     -18
uevent_main                                          337     310     -27
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 0/3 up/down: 59/-63)             Total: -4 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 archival/rpm.c        |  2 +-
 include/libbb.h       |  3 +++
 libbb/copyfd.c        |  5 +----
 libbb/xfuncs_printf.c | 21 +++++++++++++++++++++
 modutils/modutils.c   |  2 +-
 util-linux/uevent.c   |  7 +------
 6 files changed, 28 insertions(+), 12 deletions(-)

(limited to 'libbb')

diff --git a/archival/rpm.c b/archival/rpm.c
index 68afba914..a4d850b46 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -145,7 +145,7 @@ static int rpm_gettags(const char *filename)
 	/* remember size for munmap */
 	G.mapsize = storepos;
 	/* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */
-	G.map = mmap(0, storepos, PROT_READ, MAP_PRIVATE, fd, 0);
+	G.map = mmap_read(fd, storepos);
 	if (G.map == MAP_FAILED)
 		bb_perror_msg_and_die("mmap '%s'", filename);
 
diff --git a/include/libbb.h b/include/libbb.h
index 8f1ee7eec..a74b3119f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -387,6 +387,9 @@ void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) F
 char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC;
 char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC;
 void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC;
+void *mmap_read(int fd, size_t size) FAST_FUNC;
+void *mmap_anon(size_t size) FAST_FUNC;
+void *xmmap_anon(size_t size) FAST_FUNC;
 
 
 //TODO: supply a pointer to char[11] buffer (avoid statics)?
diff --git a/libbb/copyfd.c b/libbb/copyfd.c
index d41fd10f0..7f9d92ea9 100644
--- a/libbb/copyfd.c
+++ b/libbb/copyfd.c
@@ -75,10 +75,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
 				goto use_small_buf;
 			/* We want page-aligned buffer, just in case kernel is clever
 			 * and can do page-aligned io more efficiently */
-			buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024,
-					PROT_READ | PROT_WRITE,
-					MAP_PRIVATE | MAP_ANON,
-					/* ignored: */ -1, 0);
+			buffer = mmap_anon(CONFIG_FEATURE_COPYBUF_KB * 1024);
 			buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024;
 			if (buffer == MAP_FAILED) {
  use_small_buf:
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index fcc798662..db40e996b 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -111,6 +111,27 @@ void* FAST_FUNC xmemdup(const void *s, int n)
 	return memcpy(xmalloc(n), s, n);
 }
 
+void* FAST_FUNC mmap_read(int fd, size_t size)
+{
+	return mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+}
+
+void* FAST_FUNC mmap_anon(size_t size)
+{
+	return mmap(NULL, size,
+			PROT_READ | PROT_WRITE,
+			MAP_PRIVATE | MAP_ANONYMOUS,
+			/* ignored: */ -1, 0);
+}
+
+void* FAST_FUNC xmmap_anon(size_t size)
+{
+	void *p = mmap_anon(size);
+	if (p == MAP_FAILED)
+		bb_die_memory_exhausted();
+	return p;
+}
+
 // Die if we can't open a file and return a FILE* to it.
 // Notice we haven't got xfread(), This is for use with fscanf() and friends.
 FILE* FAST_FUNC xfopen(const char *path, const char *mode)
diff --git a/modutils/modutils.c b/modutils/modutils.c
index 6f7cd9721..f7ad5e805 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -169,7 +169,7 @@ void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
 	/* st.st_size is off_t, we can't just pass it to mmap */
 	if (st.st_size <= *image_size_p) {
 		size_t image_size = st.st_size;
-		image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0);
+		image = mmap_read(fd, image_size);
 		if (image == MAP_FAILED) {
 			image = NULL;
 		} else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) {
diff --git a/util-linux/uevent.c b/util-linux/uevent.c
index 045b35432..015f1ee78 100644
--- a/util-linux/uevent.c
+++ b/util-linux/uevent.c
@@ -74,12 +74,7 @@ int uevent_main(int argc UNUSED_PARAM, char **argv)
 		// for a new uevent notification to come in.
 		// We use a fresh mmap so that buffer is not allocated
 		// until kernel actually starts filling it.
-		netbuf = mmap(NULL, USER_RCVBUF,
-					PROT_READ | PROT_WRITE,
-					MAP_PRIVATE | MAP_ANON,
-					/* ignored: */ -1, 0);
-		if (netbuf == MAP_FAILED)
-			bb_simple_perror_msg_and_die("mmap");
+		netbuf = xmmap_anon(USER_RCVBUF);
 
 		// Here we block, possibly for a very long time
 		len = safe_read(fd, netbuf, USER_RCVBUF - 1);
-- 
cgit v1.2.3-55-g6feb


From c7b858ff8d2e8b2d785f74b2d319bc9c839f4faa Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 14 Dec 2020 18:49:23 +0100
Subject: libbb: add and use infrastructure for fixed page size optimization

function                                             old     new   delta
procps_scan                                         1121    1118      -3
getpagesize                                            6       -      -6
rpm_main                                            1037    1027     -10
rpm2cpio_main                                        120     110     -10
ptok                                                  38      21     -17
time_main                                           1282    1261     -21
mkswap_main                                          317     278     -39
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 0/6 up/down: 0/-106)           Total: -106 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 archival/rpm.c      | 10 ++++++----
 include/libbb.h     | 18 ++++++++++++++++++
 libbb/procps.c      |  4 ++--
 miscutils/devmem.c  |  2 +-
 miscutils/hexedit.c | 14 +++-----------
 miscutils/time.c    |  7 ++++++-
 util-linux/mkswap.c |  2 +-
 7 files changed, 37 insertions(+), 20 deletions(-)

(limited to 'libbb')

diff --git a/archival/rpm.c b/archival/rpm.c
index a4d850b46..af8db99a6 100644
--- a/archival/rpm.c
+++ b/archival/rpm.c
@@ -83,7 +83,9 @@ struct globals {
 	void *map;
 	rpm_index *mytags;
 	int tagcount;
-	unsigned mapsize, pagesize;
+	unsigned mapsize;
+	IF_VARIABLE_ARCH_PAGESIZE(unsigned pagesize;)
+#define G_pagesize cached_pagesize(G.pagesize)
 } FIX_ALIASING;
 #define G (*(struct globals*)bb_common_bufsiz1)
 #define INIT_G() do { setup_common_bufsiz(); } while (0)
@@ -141,7 +143,7 @@ static int rpm_gettags(const char *filename)
 	G.mytags = tags;
 
 	/* Map the store */
-	storepos = (storepos + G.pagesize) & -(int)G.pagesize;
+	storepos = (storepos + G_pagesize) & -(int)G_pagesize;
 	/* remember size for munmap */
 	G.mapsize = storepos;
 	/* some NOMMU systems prefer MAP_PRIVATE over MAP_SHARED */
@@ -356,7 +358,7 @@ int rpm_main(int argc, char **argv)
 	int opt, func = 0;
 
 	INIT_G();
-	G.pagesize = getpagesize();
+	INIT_PAGESIZE(G.pagesize);
 
 	while ((opt = getopt(argc, argv, "iqpldc")) != -1) {
 		switch (opt) {
@@ -523,7 +525,7 @@ int rpm2cpio_main(int argc UNUSED_PARAM, char **argv)
 	int rpm_fd;
 
 	INIT_G();
-	G.pagesize = getpagesize();
+	INIT_PAGESIZE(G.pagesize);
 
 	rpm_fd = rpm_gettags(argv[1]);
 
diff --git a/include/libbb.h b/include/libbb.h
index a74b3119f..db5bf7a51 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -391,6 +391,24 @@ void *mmap_read(int fd, size_t size) FAST_FUNC;
 void *mmap_anon(size_t size) FAST_FUNC;
 void *xmmap_anon(size_t size) FAST_FUNC;
 
+#if defined(__x86_64__) || defined(i386)
+# define BB_ARCH_FIXED_PAGESIZE 4096
+#else /* if defined(ARCH) */
+/* add you favorite arch today! */
+#endif
+
+#if defined BB_ARCH_FIXED_PAGESIZE
+# define IF_VARIABLE_ARCH_PAGESIZE(...) /*nothing*/
+# define bb_getpagesize()     BB_ARCH_FIXED_PAGESIZE
+# define INIT_PAGESIZE(var)   ((void)0)
+# define cached_pagesize(var) BB_ARCH_FIXED_PAGESIZE
+#else
+# define IF_VARIABLE_ARCH_PAGESIZE(...) __VA_ARGS__
+# define bb_getpagesize()     getpagesize()
+# define INIT_PAGESIZE(var)   ((var) = getpagesize())
+# define cached_pagesize(var) (var)
+#endif
+
 
 //TODO: supply a pointer to char[11] buffer (avoid statics)?
 extern const char *bb_mode_string(mode_t mode) FAST_FUNC;
diff --git a/libbb/procps.c b/libbb/procps.c
index 4cc3cb2a1..975e0d4dc 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -94,15 +94,15 @@ static int read_to_buf(const char *filename, void *buf)
 
 static procps_status_t* FAST_FUNC alloc_procps_scan(void)
 {
-	unsigned n = getpagesize();
 	procps_status_t* sp = xzalloc(sizeof(procps_status_t));
-	sp->dir = xopendir("/proc");
+	unsigned n = bb_getpagesize();
 	while (1) {
 		n >>= 1;
 		if (!n) break;
 		sp->shift_pages_to_bytes++;
 	}
 	sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10;
+	sp->dir = xopendir("/proc");
 	return sp;
 }
 
diff --git a/miscutils/devmem.c b/miscutils/devmem.c
index e8dce5225..f9f0276bc 100644
--- a/miscutils/devmem.c
+++ b/miscutils/devmem.c
@@ -75,7 +75,7 @@ int devmem_main(int argc UNUSED_PARAM, char **argv)
 		bb_show_usage(); /* one of bb_strtouXX failed */
 
 	fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC));
-	mapped_size = page_size = getpagesize();
+	mapped_size = page_size = bb_getpagesize();
 	offset_in_page = (unsigned)target & (page_size - 1);
 	if (offset_in_page + width > page_size) {
 		/* This access spans pages.
diff --git a/miscutils/hexedit.c b/miscutils/hexedit.c
index 898d77376..f8ff9b62b 100644
--- a/miscutils/hexedit.c
+++ b/miscutils/hexedit.c
@@ -31,7 +31,8 @@ struct globals {
 	int fd;
 	unsigned height;
 	unsigned row;
-	unsigned pagesize;
+	IF_VARIABLE_ARCH_PAGESIZE(unsigned pagesize;)
+#define G_pagesize cached_pagesize(G.pagesize)
 	uint8_t *baseaddr;
 	uint8_t *current_byte;
 	uint8_t *eof_byte;
@@ -46,15 +47,6 @@ struct globals {
 	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
 } while (0)
 
-//TODO: move to libbb
-#if defined(__x86_64__) || defined(i386)
-# define G_pagesize 4096
-# define INIT_PAGESIZE() ((void)0)
-#else
-# define G_pagesize (G.pagesize)
-# define INIT_PAGESIZE() ((void)(G.pagesize = getpagesize()))
-#endif
-
 /* hopefully there aren't arches with PAGE_SIZE > 64k */
 #define G_mapsize  (64*1024)
 
@@ -262,7 +254,7 @@ int hexedit_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int hexedit_main(int argc UNUSED_PARAM, char **argv)
 {
 	INIT_G();
-	INIT_PAGESIZE();
+	INIT_PAGESIZE(G.pagesize);
 
 	get_terminal_width_height(-1, NULL, &G.height);
 	if (1) {
diff --git a/miscutils/time.c b/miscutils/time.c
index d15d363f3..0006c59d8 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -111,6 +111,10 @@ static void printargv(char *const *argv)
    This is funky since the pagesize could be less than 1K.
    Note: Some machines express getrusage statistics in terms of K,
    others in terms of pages.  */
+#ifdef BB_ARCH_FIXED_PAGESIZE
+# define pagesize BB_ARCH_FIXED_PAGESIZE
+# define ptok(pagesize, pages) ptok(pages)
+#endif
 static unsigned long ptok(const unsigned pagesize, const unsigned long pages)
 {
 	unsigned long tmp;
@@ -124,6 +128,7 @@ static unsigned long ptok(const unsigned pagesize, const unsigned long pages)
 	tmp = pages * pagesize; /* Larger first, */
 	return tmp / 1024;      /* then smaller.  */
 }
+#undef pagesize
 
 /* summarize: Report on the system use of a command.
 
@@ -177,7 +182,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
 {
 	unsigned vv_ms;     /* Elapsed virtual (CPU) milliseconds */
 	unsigned cpu_ticks; /* Same, in "CPU ticks" */
-	unsigned pagesize = getpagesize();
+	unsigned pagesize = bb_getpagesize();
 
 	/* Impossible: we do not use WUNTRACED flag in wait()...
 	if (WIFSTOPPED(resp->waitstatus))
diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c
index 9e51a1dcc..8fe5d0293 100644
--- a/util-linux/mkswap.c
+++ b/util-linux/mkswap.c
@@ -128,7 +128,7 @@ int mkswap_main(int argc UNUSED_PARAM, char **argv)
 
 	/* Figure out how big the device is */
 	len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1);
-	pagesize = getpagesize();
+	pagesize = bb_getpagesize();
 	len -= pagesize;
 
 	/* Announce our intentions */
-- 
cgit v1.2.3-55-g6feb


From 73d93d9f83180a6149f363aaca131e281d2a52ff Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Tue, 15 Dec 2020 23:19:22 +0100
Subject: libbb: make pw_encrypt() die if supplied salt is bad (e.g. emply)

Fished from 520-loginutils-handle-crypt-failures.patch in openwrt

function                                             old     new   delta
pw_encrypt                                           913     927     +14
des_crypt                                           1327    1318      -9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 14/-9)               Total: 5 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/pw_encrypt.c     | 11 ++++++++---
 libbb/pw_encrypt_des.c | 25 +++++++++++--------------
 2 files changed, 19 insertions(+), 17 deletions(-)

(limited to 'libbb')

diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
index 47c20690f..a60c33c35 100644
--- a/libbb/pw_encrypt.c
+++ b/libbb/pw_encrypt.c
@@ -120,6 +120,7 @@ static char *my_crypt(const char *key, const char *salt)
 	if (!des_cctx)
 		des_cctx = const_des_init();
 	des_ctx = des_init(des_ctx, des_cctx);
+	/* Can return NULL if salt is bad ("" or "<one_char>") */
 	return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
 }
 
@@ -137,6 +138,8 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
 	char *encrypted;
 
 	encrypted = my_crypt(clear, salt);
+	if (!encrypted)
+		bb_simple_error_msg_and_die("bad salt");
 
 	if (cleanup)
 		my_crypt_cleanup();
@@ -148,14 +151,16 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
 
 char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
 {
-	char *s;
+	char *encrypted;
 
-	s = crypt(clear, salt);
+	encrypted = crypt(clear, salt);
 	/*
 	 * glibc used to return "" on malformed salts (for example, ""),
 	 * but since 2.17 it returns NULL.
 	 */
-	return xstrdup(s ? s : "");
+	if (!encrypted || !encrypted[0])
+		bb_simple_error_msg_and_die("bad salt");
+	return xstrdup(encrypted);
 }
 
 #endif
diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c
index c6fc328d8..dcd3521e2 100644
--- a/libbb/pw_encrypt_des.c
+++ b/libbb/pw_encrypt_des.c
@@ -713,11 +713,15 @@ to64_msb_first(char *s, unsigned v)
 static char *
 NOINLINE
 des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
-		const unsigned char *key, const unsigned char *setting)
+		const unsigned char *key, const unsigned char *salt_str)
 {
 	uint32_t salt, r0, r1, keybuf[2];
 	uint8_t *q;
 
+	/* Bad salt? Mimic crypt() API - return NULL */
+	if (!salt_str[0] || !salt_str[1])
+		return NULL;
+
 	/*
 	 * Copy the key, shifting each character up by one bit
 	 * and padding with zeros.
@@ -732,22 +736,15 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
 	des_setkey(ctx, (char *)keybuf);
 
 	/*
-	 * setting - 2 bytes of salt
+	 * salt_str - 2 bytes of salt
 	 * key - up to 8 characters
 	 */
-	salt = (ascii_to_bin(setting[1]) << 6)
-	     |  ascii_to_bin(setting[0]);
-
-	output[0] = setting[0];
-	/*
-	 * If the encrypted password that the salt was extracted from
-	 * is only 1 character long, the salt will be corrupted.  We
-	 * need to ensure that the output string doesn't have an extra
-	 * NUL in it!
-	 */
-	output[1] = setting[1] ? setting[1] : output[0];
-
+	output[0] = salt_str[0];
+	output[1] = salt_str[1];
+	salt = (ascii_to_bin(salt_str[1]) << 6)
+	     |  ascii_to_bin(salt_str[0]);
 	setup_salt(ctx, salt);
+
 	/* Do it. */
 	do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */);
 
-- 
cgit v1.2.3-55-g6feb


From 8506dd673030539b2890dd617f885ec20f1e8a7d Mon Sep 17 00:00:00 2001
From: Ron Yorston <rmy@pobox.com>
Date: Thu, 10 Dec 2020 14:44:57 +0000
Subject: lineedit: omit directories when tab-completing from PATH

Only files should be matched when using PATH for tab-completion.

function                                             old     new   delta
complete_cmd_dir_file                                883     894     +11
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 11/0)               Total: 11 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index a3b798e3f..d64d7d0c2 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -871,6 +871,9 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 			strcpy(found, name_found);
 
 			if (S_ISDIR(st.st_mode)) {
+				/* skip directories if searching PATH */
+				if (type == FIND_EXE_ONLY && !dirbuf)
+					goto cont;
 				/* name is a directory, add slash */
 				found[len] = '/';
 				found[len + 1] = '\0';
-- 
cgit v1.2.3-55-g6feb


From 8baa643a3445882ec9c39dfcabb7374081c13aee Mon Sep 17 00:00:00 2001
From: Ron Yorston <rmy@pobox.com>
Date: Fri, 11 Dec 2020 12:34:21 +0000
Subject: lineedit: match local directories when searching PATH

When tab-completing a command we search PATH if the partial text
doesn't include a slash.  Also match subdirectories of the current
directory, in case the user intends to run a binary from one of
them.

function                                             old     new   delta
complete_cmd_dir_file                                894     917     +23
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 23/0)               Total: 23 bytes

Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index d64d7d0c2..5eb701f00 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -753,7 +753,7 @@ static int path_parse(char ***p)
 		return 1;
 
 	tmp = (char*)pth;
-	npth = 1; /* path component count */
+	npth = 2; /* path component count */
 	while (1) {
 		tmp = strchr(tmp, ':');
 		if (!tmp)
@@ -776,6 +776,8 @@ static int path_parse(char ***p)
 			break; /* :<empty> */
 		res[npth++] = tmp;
 	}
+	/* special case: match subdirectories of the current directory */
+	res[npth++] = NULL;
 	return npth;
 }
 
@@ -843,6 +845,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 		struct stat st;
 		char *found;
 
+		if (paths[i] == NULL) {
+			type = FIND_DIR_ONLY;
+			paths[i] = (char *)".";
+		}
+
 		dir = opendir(paths[i]);
 		if (!dir)
 			continue; /* don't print an error */
-- 
cgit v1.2.3-55-g6feb


From eaced1ec85315b9e11226f9a4ab935066e6946a0 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 16 Dec 2020 10:01:21 +0100
Subject: lineedit: remove ->path_lookup if ash is not configured

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h  | 16 +++++++++++-----
 libbb/lineedit.c |  2 ++
 2 files changed, 13 insertions(+), 5 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index 202e3f39c..6b7141456 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1863,14 +1863,20 @@ typedef const char *get_exe_name_t(int i) FAST_FUNC;
 typedef struct line_input_t {
 	int flags;
 	int timeout;
+# if ENABLE_FEATURE_TAB_COMPLETION
+#  if ENABLE_SHELL_ASH
 	const char *path_lookup;
-# if ENABLE_FEATURE_TAB_COMPLETION \
-&& (ENABLE_ASH  || ENABLE_SH_IS_ASH  || ENABLE_BASH_IS_ASH \
-||  ENABLE_HUSH || ENABLE_SH_IS_HUSH || ENABLE_BASH_IS_HUSH \
-)
+#   define EDITING_HAS_path_lookup 1
+#  else
+#   define EDITING_HAS_path_lookup 0
+#  endif
+#  if ENABLE_SHELL_ASH || ENABLE_SHELL_HUSH
 	/* function to fetch additional application-specific names to match */
 	get_exe_name_t *get_exe_name;
-#  define EDITING_HAS_get_exe_name 1
+#   define EDITING_HAS_get_exe_name 1
+#  else
+#   define EDITING_HAS_get_exe_name 0
+#  endif
 # endif
 # if MAX_HISTORY
 	int cnt_history;
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 5eb701f00..1a3f29656 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -743,9 +743,11 @@ static int path_parse(char ***p)
 	char *tmp;
 	char **res;
 
+#if EDITING_HAS_path_lookup
 	if (state->flags & WITH_PATH_LOOKUP)
 		pth = state->path_lookup;
 	else
+#endif
 		pth = getenv("PATH");
 
 	/* PATH="" or PATH=":"? */
-- 
cgit v1.2.3-55-g6feb


From 1d180cd7493f0a88fa39229cddcb30a0e44ade4c Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 16 Dec 2020 10:59:20 +0100
Subject: lineedit: use strncmp instead of is_prefixed_with (we know the
 length)

Also: add comments, rename some variables

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 47 +++++++++++++++++++++++++----------------------
 1 file changed, 25 insertions(+), 22 deletions(-)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 1a3f29656..0c48e8179 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -736,9 +736,9 @@ enum {
 	FIND_FILE_ONLY = 2,
 };
 
-static int path_parse(char ***p)
+static unsigned path_parse(char ***p)
 {
-	int npth;
+	unsigned npth;
 	const char *pth;
 	char *tmp;
 	char **res;
@@ -755,7 +755,7 @@ static int path_parse(char ***p)
 		return 1;
 
 	tmp = (char*)pth;
-	npth = 2; /* path component count */
+	npth = 1; /* path component count */
 	while (1) {
 		tmp = strchr(tmp, ':');
 		if (!tmp)
@@ -766,7 +766,7 @@ static int path_parse(char ***p)
 		npth++;
 	}
 
-	*p = res = xmalloc(npth * sizeof(res[0]));
+	*p = res = xzalloc((npth + 1) * sizeof(res[0]));
 	res[0] = tmp = xstrdup(pth);
 	npth = 1;
 	while (1) {
@@ -778,8 +778,8 @@ static int path_parse(char ***p)
 			break; /* :<empty> */
 		res[npth++] = tmp;
 	}
-	/* special case: match subdirectories of the current directory */
-	res[npth++] = NULL;
+	/* special case: "match subdirectories of the current directory" */
+	/*res[npth++] = NULL; - filled by xzalloc() */
 	return npth;
 }
 
@@ -790,38 +790,38 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 {
 	char *path1[1];
 	char **paths = path1;
-	int npaths;
-	int i;
-	unsigned pf_len;
-	const char *pfind;
+	unsigned npaths;
+	unsigned i;
+	unsigned baselen;
+	const char *basecmd;
 	char *dirbuf = NULL;
 
 	npaths = 1;
 	path1[0] = (char*)".";
 
-	pfind = strrchr(command, '/');
-	if (!pfind) {
+	basecmd = strrchr(command, '/');
+	if (!basecmd) {
 		if (type == FIND_EXE_ONLY)
 			npaths = path_parse(&paths);
-		pfind = command;
+		basecmd = command;
 	} else {
 		/* point to 'l' in "..../last_component" */
-		pfind++;
+		basecmd++;
 		/* dirbuf = ".../.../.../" */
-		dirbuf = xstrndup(command, pfind - command);
+		dirbuf = xstrndup(command, basecmd - command);
 # if ENABLE_FEATURE_USERNAME_COMPLETION
 		if (dirbuf[0] == '~')   /* ~/... or ~user/... */
 			dirbuf = username_path_completion(dirbuf);
 # endif
 		path1[0] = dirbuf;
 	}
-	pf_len = strlen(pfind);
+	baselen = strlen(basecmd);
 
 	if (type == FIND_EXE_ONLY && !dirbuf) {
 # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1
 		const char *p = applet_names;
 		while (*p) {
-			if (strncmp(pfind, p, pf_len) == 0)
+			if (strncmp(basecmd, p, baselen) == 0)
 				add_match(xstrdup(p));
 			while (*p++ != '\0')
 				continue;
@@ -834,7 +834,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 				const char *b = state->get_exe_name(i++);
 				if (!b)
 					break;
-				if (strncmp(pfind, b, pf_len) == 0)
+				if (strncmp(basecmd, b, baselen) == 0)
 					add_match(xstrdup(b));
 			}
 		}
@@ -847,7 +847,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 		struct stat st;
 		char *found;
 
-		if (paths[i] == NULL) {
+		if (paths[i] == NULL) { /* path_parse()'s last component? */
+			/* in PATH completion, current dir's subdir names
+			 * can be completions (but only subdirs, not files).
+			 */
 			type = FIND_DIR_ONLY;
 			paths[i] = (char *)".";
 		}
@@ -861,10 +864,10 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 			const char *name_found = next->d_name;
 
 			/* .../<tab>: bash 3.2.0 shows dotfiles, but not . and .. */
-			if (!pfind[0] && DOT_OR_DOTDOT(name_found))
+			if (!basecmd[0] && DOT_OR_DOTDOT(name_found))
 				continue;
 			/* match? */
-			if (!is_prefixed_with(name_found, pfind))
+			if (strncmp(basecmd, name_found, baselen) != 0)
 				continue; /* no */
 
 			found = concat_path_file(paths[i], name_found);
@@ -906,7 +909,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
 	}
 	free(dirbuf);
 
-	return pf_len;
+	return baselen;
 }
 
 /* build_match_prefix:
-- 
cgit v1.2.3-55-g6feb


From a97a795dcb41943943b8ecfe039e23673365af55 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 16 Dec 2020 11:14:08 +0100
Subject: lineedit: disable completion and fancy prompts if no shells are
 selected

function                                             old     new   delta
get_previous_history                                  51      56      +5
get_next_history                                      47      52      +5
null_str                                               1       -      -1
beep                                                  10       -     -10
bb_msg_unknown                                        10       -     -10
bb_internal_setpwent                                  24       -     -24
remove_chunk                                          30       -     -30
goto_new_line                                         33       -     -33
bb_internal_endpwent                                  36       -     -36
deinit_S                                              51       -     -51
free_tab_completion_data                              54       -     -54
read_line_input                                     3171    3114     -57
rewind                                                68       -     -68
add_match                                             70       -     -70
complete_username                                     77       -     -77
quote_special_chars                                   78       -     -78
build_match_prefix                                   557       -    -557
complete_cmd_dir_file                                697       -    -697
parse_and_put_prompt                                 823      53    -770
input_tab                                            926       -    -926
------------------------------------------------------------------------------
(add/remove: 0/17 grow/shrink: 2/2 up/down: 10/-3549)       Total: -3539 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 0c48e8179..c3b5738e2 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -57,12 +57,23 @@
 #if ENABLE_FEATURE_EDITING
 
 
+#if !ENABLE_SHELL_ASH && !ENABLE_SHELL_HUSH
+/* so far only shells use these features */
+# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
+# undef ENABLE_FEATURE_TAB_COMPLETION
+# undef ENABLE_FEATURE_USERNAME_COMPLETION
+# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
+# define ENABLE_FEATURE_TAB_COMPLETION       0
+# define ENABLE_FEATURE_USERNAME_COMPLETION  0
+#endif
+
+
 #define ENABLE_USERNAME_OR_HOMEDIR \
 	(ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT)
-#define IF_USERNAME_OR_HOMEDIR(...)
 #if ENABLE_USERNAME_OR_HOMEDIR
-# undef IF_USERNAME_OR_HOMEDIR
 # define IF_USERNAME_OR_HOMEDIR(...) __VA_ARGS__
+#else
+# define IF_USERNAME_OR_HOMEDIR(...) /*nothing*/
 #endif
 
 
@@ -743,11 +754,11 @@ static unsigned path_parse(char ***p)
 	char *tmp;
 	char **res;
 
-#if EDITING_HAS_path_lookup
+# if EDITING_HAS_path_lookup
 	if (state->flags & WITH_PATH_LOOKUP)
 		pth = state->path_lookup;
 	else
-#endif
+# endif
 		pth = getenv("PATH");
 
 	/* PATH="" or PATH=":"? */
@@ -1885,9 +1896,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 {
 	int prmt_size = 0;
 	char *prmt_mem_ptr = xzalloc(1);
-# if ENABLE_USERNAME_OR_HOMEDIR
 	char *cwd_buf = NULL;
-# endif
 	char flg_not_length = '[';
 	char cbuf[2];
 
@@ -1954,11 +1963,9 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 				c = *prmt_ptr++;
 
 				switch (c) {
-# if ENABLE_USERNAME_OR_HOMEDIR
 				case 'u':
 					pbuf = user_buf ? user_buf : (char*)"";
 					break;
-# endif
 				case 'H':
 				case 'h':
 					pbuf = free_me = safe_gethostname();
@@ -1976,7 +1983,6 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 					strftime_HHMMSS(timebuf, sizeof(timebuf), NULL)[-3] = '\0';
 					pbuf = timebuf;
 					break;
-# if ENABLE_USERNAME_OR_HOMEDIR
 				case 'w': /* current dir */
 				case 'W': /* basename of cur dir */
 					if (!cwd_buf) {
@@ -2003,7 +2009,6 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 					if (cp)
 						pbuf = (char*)cp + 1;
 					break;
-# endif
 // bb_process_escape_sequence does this now:
 //				case 'e': case 'E':     /* \e \E = \033 */
 //					c = '\033';
@@ -2064,10 +2069,8 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 		free(free_me);
 	} /* while */
 
-# if ENABLE_USERNAME_OR_HOMEDIR
 	if (cwd_buf != (char *)bb_msg_unknown)
 		free(cwd_buf);
-# endif
 	/* see comment (above this function) about multiline prompt redrawing */
 	cmdedit_prompt = prompt_last_line = prmt_mem_ptr;
 	prmt_ptr = strrchr(cmdedit_prompt, '\n');
@@ -2075,7 +2078,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
 		prompt_last_line = prmt_ptr + 1;
 	put_prompt();
 }
-#endif
+#endif /* FEATURE_EDITING_FANCY_PROMPT */
 
 #if ENABLE_FEATURE_EDITING_WINCH
 static void cmdedit_setwidth(void)
-- 
cgit v1.2.3-55-g6feb


From eb0c2e218ca1b0d733157bc2a11f8621d4ed2409 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 16 Dec 2020 21:36:36 +0100
Subject: libbb: introduce and use xsettimeofday()

function                                             old     new   delta
xsettimeofday                                          -      25     +25
rdate_main                                           274     260     -14
step_time                                            348     331     -17
set_kernel_timezone_and_clock                        119     102     -17
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/3 up/down: 25/-48)            Total: -23 bytes
   text	   data	    bss	    dec	    hex	filename
1020753	    559	   5052	1026364	  fa93c	busybox_old
1020708	    559	   5052	1026319	  fa90f	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h       |  2 ++
 libbb/xfuncs.c        | 12 ------------
 libbb/xfuncs_printf.c | 18 ++++++++++++++++++
 networking/ntpd.c     |  3 +--
 util-linux/hwclock.c  |  6 ++----
 util-linux/rdate.c    |  7 +++----
 6 files changed, 26 insertions(+), 22 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index 6b7141456..1c3d905b6 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -657,6 +657,8 @@ void parse_datestr(const char *date_str, struct tm *ptm) FAST_FUNC;
 time_t validate_tm_time(const char *date_str, struct tm *ptm) FAST_FUNC;
 char *strftime_HHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC;
 char *strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC;
+void xsettimeofday(const struct timeval *tv) FAST_FUNC;
+
 
 int xsocket(int domain, int type, int protocol) FAST_FUNC;
 void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) FAST_FUNC;
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index ee2dbdef1..d93d8aaf5 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -417,15 +417,3 @@ int FAST_FUNC wait4pid(pid_t pid)
 		return WTERMSIG(status) + 0x180;
 	return 0;
 }
-
-// Useful when we do know that pid is valid, and we just want to wait
-// for it to exit. Not existing pid is fatal. waitpid() status is not returned.
-int FAST_FUNC wait_for_exitstatus(pid_t pid)
-{
-	int exit_status, n;
-
-	n = safe_waitpid(pid, &exit_status, 0);
-	if (n < 0)
-		bb_simple_perror_msg_and_die("waitpid");
-	return exit_status;
-}
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index db40e996b..6c220434d 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -702,3 +702,21 @@ void FAST_FUNC xvfork_parent_waits_and_exits(void)
 	}
 	/* Child continues */
 }
+
+// Useful when we do know that pid is valid, and we just want to wait
+// for it to exit. Not existing pid is fatal. waitpid() status is not returned.
+int FAST_FUNC wait_for_exitstatus(pid_t pid)
+{
+	int exit_status, n;
+
+	n = safe_waitpid(pid, &exit_status, 0);
+	if (n < 0)
+		bb_simple_perror_msg_and_die("waitpid");
+	return exit_status;
+}
+
+void FAST_FUNC xsettimeofday(const struct timeval *tv)
+{
+	if (settimeofday(tv, NULL))
+		bb_simple_perror_msg_and_die("settimeofday");
+}
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 032dc51ac..06f6017d0 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -1147,8 +1147,7 @@ step_time(double offset)
 	gettimeofday(&tvc, NULL); /* never fails */
 	dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset;
 	d_to_tv(dtime, &tvn);
-	if (settimeofday(&tvn, NULL) == -1)
-		bb_simple_perror_msg_and_die("settimeofday");
+	xsettimeofday(&tvn);
 
 	VERB2 {
 		tval = tvc.tv_sec;
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index 77aa2d7c3..dd66ec199 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -184,10 +184,8 @@ static void set_kernel_timezone_and_clock(int utc, const struct timeval *hctosys
 	/*tz.tz_dsttime = 0; already is */
 	set_kernel_tz(&tz); /* MIGHT warp_clock() if 1st call since boot */
 
-	if (hctosys) { /* it's --hctosys: set time too */
-		if (settimeofday(hctosys, NULL))
-			bb_simple_perror_msg_and_die("settimeofday");
-	}
+	if (hctosys) /* it's --hctosys: set time too */
+		xsettimeofday(hctosys);
 }
 
 static void to_sys_clock(const char **pp_rtcname, int utc)
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index bb1dc519a..9b80141c9 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -96,11 +96,10 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
 		if (time(NULL) == remote_time)
 			bb_simple_error_msg("current time matches remote time");
 		else {
-			struct timespec ts;
+			struct timeval ts;
 			ts.tv_sec = remote_time;
-			ts.tv_nsec = 0;
-			if (clock_settime(CLOCK_REALTIME, &ts) < 0)
-				bb_simple_perror_msg_and_die("can't set time of day");
+			ts.tv_usec = 0;
+			xsettimeofday(&ts);
 		}
 	}
 
-- 
cgit v1.2.3-55-g6feb


From bb15969333d0476256c92edc068894a50d9159d4 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 16 Dec 2020 23:00:51 +0100
Subject: libbb: do not compile selinux_or_die() if !SELINUX

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/xfuncs_printf.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'libbb')

diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 6c220434d..aea995a5c 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -523,20 +523,20 @@ void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg)
 		bb_simple_perror_msg_and_die(errmsg);
 }
 
+#if ENABLE_SELINUX
 // selinux_or_die() - die if SELinux is disabled.
 void FAST_FUNC selinux_or_die(void)
 {
-#if ENABLE_SELINUX
 	int rc = is_selinux_enabled();
 	if (rc == 0) {
 		bb_simple_error_msg_and_die("SELinux is disabled");
 	} else if (rc < 0) {
 		bb_simple_error_msg_and_die("is_selinux_enabled() failed");
 	}
+}
 #else
-	bb_simple_error_msg_and_die("SELinux support is disabled");
+/* not defined, other code must have no calls to it */
 #endif
-}
 
 int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...)
 {
-- 
cgit v1.2.3-55-g6feb


From 072313162870e9675c3e6f346a804a324a907f93 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 17 Dec 2020 11:22:44 +0100
Subject: Fixes for Hurd build

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 applets/applet_tables.c     | 4 ++++
 libbb/die_if_bad_username.c | 4 ++++
 2 files changed, 8 insertions(+)

(limited to 'libbb')

diff --git a/applets/applet_tables.c b/applets/applet_tables.c
index ce2037440..7ba929b12 100644
--- a/applets/applet_tables.c
+++ b/applets/applet_tables.c
@@ -20,6 +20,10 @@
 #undef ARRAY_SIZE
 #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
 
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
 #include "../include/autoconf.h"
 #include "../include/applet_metadata.h"
 
diff --git a/libbb/die_if_bad_username.c b/libbb/die_if_bad_username.c
index e5e1160c4..d05dc74c5 100644
--- a/libbb/die_if_bad_username.c
+++ b/libbb/die_if_bad_username.c
@@ -8,6 +8,10 @@
  */
 #include "libbb.h"
 
+#ifndef LOGIN_NAME_MAX
+#define LOGIN_NAME_MAX 256
+#endif
+
 /* To avoid problems, the username should consist only of
  * letters, digits, underscores, periods, at signs and dashes,
  * and not start with a dash (as defined by IEEE Std 1003.1-2001).
-- 
cgit v1.2.3-55-g6feb


From 4bc59a4cf73f1dd9326d150bf6654b643e740fe2 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 17 Dec 2020 15:05:14 +0100
Subject: mount: fix a race when a free loop device is snatched under us by
 another mount.

function                                             old     new   delta
set_loop                                             850     809     -41

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/loop.c | 138 +++++++++++++++++++++++++++++++----------------------------
 1 file changed, 73 insertions(+), 65 deletions(-)

(limited to 'libbb')

diff --git a/libbb/loop.c b/libbb/loop.c
index 85b2724e5..153990998 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -98,9 +98,7 @@ int FAST_FUNC get_free_loop(void)
 
 /* Returns opened fd to the loop device, <0 on error.
  * *device is loop device to use, or if *device==NULL finds a loop device to
- * mount it on and sets *device to a strdup of that loop device name.  This
- * search will re-use an existing loop device already bound to that
- * file/offset if it finds one.
+ * mount it on and sets *device to a strdup of that loop device name.
  */
 int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offset,
 		unsigned long long sizelimit, unsigned flags)
@@ -109,9 +107,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
 	char *try;
 	bb_loop_info loopinfo;
 	struct stat statbuf;
-	int i, dfd, ffd, mode, rc;
-
-	rc = dfd = -1;
+	int i, lfd, ffd, mode, rc;
 
 	/* Open the file.  Barf if this doesn't work.  */
 	mode = (flags & BB_LO_FLAGS_READ_ONLY) ? O_RDONLY : O_RDWR;
@@ -127,24 +123,23 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
 
 	try = *device;
 	if (!try) {
+ get_free_loopN:
 		i = get_free_loop();
-		if (i == -2) { /* no /dev/loop-control */
-			i = 0;
-			try = dev;
-			goto old_style;
-		}
 		if (i == -1) {
 			close(ffd);
 			return -1; /* no free loop devices */
 		}
-		try = *device = xasprintf(LOOP_FORMAT, i);
-		goto try_to_open;
+		if (i >= 0) {
+			try = xasprintf(LOOP_FORMAT, i);
+			goto open_lfd;
+		}
+		/* i == -2: no /dev/loop-control. Do an old-style search for a free device */
+		try = dev;
 	}
 
- old_style:
-	/* Find a loop device.  */
-	/* 1048575 (0xfffff) is a max possible minor number in Linux circa 2010 */
-	for (i = 0; rc && i < 1048576; i++) {
+	/* Find a loop device */
+	/* 0xfffff is a max possible minor number in Linux circa 2010 */
+	for (i = 0; i <= 0xfffff; i++) {
 		sprintf(dev, LOOP_FORMAT, i);
 
 		IF_FEATURE_MOUNT_LOOP_CREATE(errno = 0;)
@@ -153,72 +148,85 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
 			 && errno == ENOENT
 			 && try == dev
 			) {
-				/* Node doesn't exist, try to create it.  */
+				/* Node doesn't exist, try to create it */
 				if (mknod(dev, S_IFBLK|0644, makedev(7, i)) == 0)
-					goto try_to_open;
+					goto open_lfd;
 			}
-			/* Ran out of block devices, return failure.  */
+			/* Ran out of block devices, return failure */
 			rc = -1;
 			break;
 		}
- try_to_open:
-		/* Open the sucker and check its loopiness.  */
-		dfd = open(try, mode);
-		if (dfd < 0 && errno == EROFS) {
+ open_lfd:
+		/* Open the sucker and check its loopiness */
+		lfd = rc = open(try, mode);
+		if (lfd < 0 && errno == EROFS) {
 			mode = O_RDONLY;
-			dfd = open(try, mode);
+			lfd = rc = open(try, mode);
 		}
-		if (dfd < 0) {
+		if (lfd < 0) {
 			if (errno == ENXIO) {
 				/* Happens if loop module is not loaded */
-				rc = -1;
+				/* rc is -1; */
 				break;
 			}
-			goto try_again;
+			goto try_next_loopN;
 		}
 
-		rc = ioctl(dfd, BB_LOOP_GET_STATUS, &loopinfo);
+		rc = ioctl(lfd, BB_LOOP_GET_STATUS, &loopinfo);
 
-		/* If device is free, claim it.  */
+		/* If device is free, try to claim it */
 		if (rc && errno == ENXIO) {
-			/* Associate free loop device with file.  */
-			if (ioctl(dfd, LOOP_SET_FD, ffd) == 0) {
-				memset(&loopinfo, 0, sizeof(loopinfo));
-				safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
-				loopinfo.lo_offset = offset;
-				loopinfo.lo_sizelimit = sizelimit;
-				/*
-				 * Used by mount to set LO_FLAGS_AUTOCLEAR.
-				 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
-				 * Note that closing LO_FLAGS_AUTOCLEARed dfd before mount
-				 * is wrong (would free the loop device!)
-				 */
-				loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY);
-				rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
-				if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) {
-					/* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */
-					/* (this code path is not tested) */
-					loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR;
-					rc = ioctl(dfd, BB_LOOP_SET_STATUS, &loopinfo);
-				}
-				if (rc != 0) {
-					ioctl(dfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
+			/* Associate free loop device with file */
+			if (ioctl(lfd, LOOP_SET_FD, ffd)) {
+				/* Ouch. Are we racing with other mount? */
+				if (!*device   /* yes */
+				 && try != dev /* tried a _kernel-offered_ loopN? */
+				) {
+					free(try);
+					close(lfd);
+//TODO: add "if (--failcount != 0) ..."?
+					goto get_free_loopN;
 				}
+				goto try_next_loopN;
 			}
-		} else {
-			rc = -1;
-		}
-		if (rc != 0) {
-			close(dfd);
+			memset(&loopinfo, 0, sizeof(loopinfo));
+			safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
+			loopinfo.lo_offset = offset;
+			loopinfo.lo_sizelimit = sizelimit;
+			/*
+			 * Used by mount to set LO_FLAGS_AUTOCLEAR.
+			 * LO_FLAGS_READ_ONLY is not set because RO is controlled by open type of the file.
+			 * Note that closing LO_FLAGS_AUTOCLEARed lfd before mount
+			 * is wrong (would free the loop device!)
+			 */
+			loopinfo.lo_flags = (flags & ~BB_LO_FLAGS_READ_ONLY);
+			rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo);
+			if (rc != 0 && (loopinfo.lo_flags & BB_LO_FLAGS_AUTOCLEAR)) {
+				/* Old kernel, does not support LO_FLAGS_AUTOCLEAR? */
+				/* (this code path is not tested) */
+				loopinfo.lo_flags -= BB_LO_FLAGS_AUTOCLEAR;
+				rc = ioctl(lfd, BB_LOOP_SET_STATUS, &loopinfo);
+			}
+			if (rc == 0) {
+				/* SUCCESS! */
+				if (try != dev) /* tried a kernel-offered free loopN? */
+					*device = try; /* malloced */
+				if (!*device)   /* was looping in search of free "/dev/loopN"? */
+					*device = xstrdup(dev);
+				rc = lfd; /* return this */
+				break;
+			}
+			/* failure, undo LOOP_SET_FD */
+			ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
 		}
- try_again:
-		if (*device) break;
-	}
+		/* else: device is not free (rc == 0) or error other than ENXIO */
+		close(lfd);
+ try_next_loopN:
+		rc = -1;
+		if (*device) /* was looking for a particular "/dev/loopN"? */
+			break; /* yes, do not try other names */
+	} /* for() */
+
 	close(ffd);
-	if (rc == 0) {
-		if (!*device)
-			*device = xstrdup(dev);
-		return dfd;
-	}
 	return rc;
 }
-- 
cgit v1.2.3-55-g6feb


From 251e08ffa626d4b7c7e5f626aee7067b86b2ceba Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 17 Dec 2020 20:53:43 +0100
Subject: move ADJTIME_PATH define to header files

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/rtc_.h       | 6 ++++++
 include/usage.src.h  | 6 ++++++
 libbb/rtc.c          | 6 ------
 util-linux/hwclock.c | 5 -----
 util-linux/rtcwake.c | 5 -----
 5 files changed, 12 insertions(+), 16 deletions(-)

(limited to 'libbb')

diff --git a/include/rtc_.h b/include/rtc_.h
index 750fc20ec..24ff5363f 100644
--- a/include/rtc_.h
+++ b/include/rtc_.h
@@ -11,6 +11,12 @@
 
 PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
 
+#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
+# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
+#else
+# define ADJTIME_PATH "/etc/adjtime"
+#endif
+
 int rtc_adjtime_is_utc(void) FAST_FUNC;
 int rtc_xopen(const char **default_rtc, int flags) FAST_FUNC;
 void rtc_read_tm(struct tm *ptm, int fd) FAST_FUNC;
diff --git a/include/usage.src.h b/include/usage.src.h
index d22efd3ba..1ac252d1b 100644
--- a/include/usage.src.h
+++ b/include/usage.src.h
@@ -25,6 +25,12 @@
 	" (default "CONFIG_FEATURE_DEFAULT_PASSWD_ALGO")"
 #endif
 
+#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
+# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
+#else
+# define ADJTIME_PATH "/etc/adjtime"
+#endif
+
 INSERT
 
 #define busybox_notes_usage \
diff --git a/libbb/rtc.c b/libbb/rtc.c
index c4117ba34..54b52f23a 100644
--- a/libbb/rtc.c
+++ b/libbb/rtc.c
@@ -7,12 +7,6 @@
 #include "libbb.h"
 #include "rtc_.h"
 
-#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
-# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
-#else
-# define ADJTIME_PATH "/etc/adjtime"
-#endif
-
 int FAST_FUNC rtc_adjtime_is_utc(void)
 {
 	int utc = 0;
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index dd66ec199..25db7cdad 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -344,11 +344,6 @@ static void from_sys_clock(const char **pp_rtcname, int utc)
 //     --test           dry run; implies --verbose
 // -v, --verbose        display more details
 
-//usage:#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
-//usage:# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
-//usage:#else
-//usage:# define ADJTIME_PATH "/etc/adjtime"
-//usage:#endif
 //usage:#define hwclock_trivial_usage
 //usage:	IF_LONG_OPTS(
 //usage:       "[-swul] [--systz] [-f DEV]"
diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c
index be7e95099..eac16077d 100644
--- a/util-linux/rtcwake.c
+++ b/util-linux/rtcwake.c
@@ -32,11 +32,6 @@
 
 //kbuild:lib-$(CONFIG_RTCWAKE) += rtcwake.o
 
-//usage:#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
-//usage:# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
-//usage:#else
-//usage:# define ADJTIME_PATH "/etc/adjtime"
-//usage:#endif
 //usage:#define rtcwake_trivial_usage
 //usage:       "[-a | -l | -u] [-d DEV] [-m MODE] [-s SEC | -t TIME]"
 //usage:#define rtcwake_full_usage "\n\n"
-- 
cgit v1.2.3-55-g6feb


From 15733cb48e570716cad6ece2d752507ecd767131 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 17 Dec 2020 23:38:06 +0100
Subject: mount: if we race with other loop mount, we forget to close loop dev

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/loop.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/libbb/loop.c b/libbb/loop.c
index 153990998..cb8fa2442 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -187,7 +187,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
 //TODO: add "if (--failcount != 0) ..."?
 					goto get_free_loopN;
 				}
-				goto try_next_loopN;
+				goto close_and_try_next_loopN;
 			}
 			memset(&loopinfo, 0, sizeof(loopinfo));
 			safe_strncpy((char *)loopinfo.lo_file_name, file, LO_NAME_SIZE);
@@ -220,6 +220,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse
 			ioctl(lfd, LOOP_CLR_FD, 0); // actually, 0 param is unnecessary
 		}
 		/* else: device is not free (rc == 0) or error other than ENXIO */
+ close_and_try_next_loopN:
 		close(lfd);
  try_next_loopN:
 		rc = -1;
-- 
cgit v1.2.3-55-g6feb


From 00eb23b47aa79461b913b320eba3c95b90e6eec4 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 21 Dec 2020 21:36:58 +0100
Subject: bc: do not allocate line editing state until needed

function                                             old     new   delta
xc_read_line                                         324     353     +29
free_line_input_t                                     34      39      +5
xc_vm_init                                           656     640     -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 34/-16)             Total: 18 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h  |  4 ++++
 libbb/lineedit.c | 18 +++++++++++-------
 miscutils/bc.c   | 37 ++++++++++++++++++-------------------
 shell/ash.c      |  3 +--
 shell/hush.c     |  3 +--
 5 files changed, 35 insertions(+), 30 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index 1c3d905b6..cae54658b 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1906,7 +1906,11 @@ enum {
 	FOR_SHELL        = DO_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
 };
 line_input_t *new_line_input_t(int flags) FAST_FUNC;
+#if ENABLE_FEATURE_EDITING_SAVEHISTORY
 void free_line_input_t(line_input_t *n) FAST_FUNC;
+#else
+# define free_line_input_t(n) free(n)
+#endif
 /*
  * maxsize must be >= 2.
  * Returns:
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index c3b5738e2..b3e7abac5 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -1417,15 +1417,19 @@ void FAST_FUNC show_history(const line_input_t *st)
 		printf("%4d %s\n", i, st->history[i]);
 }
 
+# if ENABLE_FEATURE_EDITING_SAVEHISTORY
 void FAST_FUNC free_line_input_t(line_input_t *n)
 {
-# if ENABLE_FEATURE_EDITING_SAVEHISTORY
-	int i = n->cnt_history;
-	while (i > 0)
-		free(n->history[--i]);
-#endif
-	free(n);
+	if (n) {
+		int i = n->cnt_history;
+		while (i > 0)
+			free(n->history[--i]);
+		free(n);
+	}
 }
+# else
+/* #defined to free() in libbb.h */
+# endif
 
 # if ENABLE_FEATURE_EDITING_SAVEHISTORY
 /* We try to ensure that concurrent additions to the history
@@ -1506,7 +1510,7 @@ void save_history(line_input_t *st)
 {
 	FILE *fp;
 
-	if (!st->hist_file)
+	if (!st || !st->hist_file)
 		return;
 	if (st->cnt_history <= st->cnt_history_in_file)
 		return;
diff --git a/miscutils/bc.c b/miscutils/bc.c
index f339b895c..1227e2d13 100644
--- a/miscutils/bc.c
+++ b/miscutils/bc.c
@@ -2545,6 +2545,8 @@ static void xc_read_line(BcVec *vec, FILE *fp)
 # if ENABLE_FEATURE_EDITING
 	if (G_ttyin && fp == stdin) {
 		int n, i;
+		if (!G.line_input_state)
+			G.line_input_state = new_line_input_t(DO_HISTORY);
 #  define line_buf bb_common_bufsiz1
 		n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE);
 		if (n <= 0) { // read errors or EOF, or ^D, or ^C
@@ -6872,22 +6874,6 @@ static BC_STATUS zxc_program_exec(void)
 }
 #define zxc_program_exec(...) (zxc_program_exec(__VA_ARGS__) COMMA_SUCCESS)
 
-static unsigned xc_vm_envLen(const char *var)
-{
-	char *lenv;
-	unsigned len;
-
-	lenv = getenv(var);
-	len = BC_NUM_PRINT_WIDTH;
-	if (!lenv) return len;
-
-	len = bb_strtou(lenv, NULL, 10) - 1;
-	if (errno || len < 2 || len >= INT_MAX)
-		len = BC_NUM_PRINT_WIDTH;
-
-	return len;
-}
-
 static BC_STATUS zxc_vm_process(const char *text)
 {
 	BcStatus s;
@@ -7377,12 +7363,25 @@ static void xc_program_init(void)
 	bc_char_vec_init(&G.input_buffer);
 }
 
+static unsigned xc_vm_envLen(const char *var)
+{
+	char *lenv;
+	unsigned len;
+
+	lenv = getenv(var);
+	len = BC_NUM_PRINT_WIDTH;
+	if (!lenv) return len;
+
+	len = bb_strtou(lenv, NULL, 10) - 1;
+	if (errno || len < 2 || len >= INT_MAX)
+		len = BC_NUM_PRINT_WIDTH;
+
+	return len;
+}
+
 static int xc_vm_init(const char *env_len)
 {
 	G.prog.len = xc_vm_envLen(env_len);
-#if ENABLE_FEATURE_EDITING
-	G.line_input_state = new_line_input_t(DO_HISTORY);
-#endif
 	bc_vec_init(&G.files, sizeof(char *), NULL);
 
 	xc_program_init();
diff --git a/shell/ash.c b/shell/ash.c
index 87d329f87..f4d296289 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -14177,8 +14177,7 @@ exitshell(void)
 	char *p;
 
 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
-	if (line_input_state)
-		save_history(line_input_state);
+	save_history(line_input_state); /* may be NULL */
 #endif
 	savestatus = exitstatus;
 	TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
diff --git a/shell/hush.c b/shell/hush.c
index a8f7237d5..f0f0da746 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2056,8 +2056,7 @@ static sighandler_t pick_sighandler(unsigned sig)
 static void hush_exit(int exitcode)
 {
 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
-	if (G.line_input_state)
-		save_history(G.line_input_state);
+	save_history(G.line_input_state); /* may be NULL */
 #endif
 
 	fflush_all();
-- 
cgit v1.2.3-55-g6feb


From fae7332ebf0f059039a8ede16a57da9646051159 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 21 Dec 2020 21:55:03 +0100
Subject: lineedit: add a comment about possible use of tcflush()

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 1 +
 1 file changed, 1 insertion(+)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index b3e7abac5..499be4972 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -2911,6 +2911,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 		 * before it comes in. UGLY!
 		 */
 		usleep(20*1000);
+// MAYBE? tcflush(STDIN_FILENO, TCIFLUSH); /* flushes data received but not read */
 	}
 #endif
 
-- 
cgit v1.2.3-55-g6feb


From 96717d9fb4560ad98a737108f83c7b247ef04674 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 21 Dec 2020 22:50:23 +0100
Subject: lineedit: code shrink

function                                             old     new   delta
read_line_input                                     3171    3157     -14

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/lineedit.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'libbb')

diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 499be4972..75de88e77 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -216,9 +216,6 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics;
 #define INIT_S() do { \
 	(*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \
 	barrier(); \
-	cmdedit_termw = 80; \
-	IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) \
-	IF_FEATURE_EDITING_VI(delptr = delbuf;) \
 } while (0)
 
 static void deinit_S(void)
@@ -2393,6 +2390,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 	char read_key_buffer[KEYCODE_BUFFER_SIZE];
 
 	INIT_S();
+	//command_len = 0; - done by INIT_S()
+	//cmdedit_y = 0;  /* quasireal y, not true if line > xt*yt */
+	cmdedit_termw = 80;
+	IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;)
+	IF_FEATURE_EDITING_VI(delptr = delbuf;)
 
 	n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0
 		| TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */
@@ -2441,8 +2443,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 #endif
 
 	/* prepare before init handlers */
-	cmdedit_y = 0;  /* quasireal y, not true if line > xt*yt */
-	command_len = 0;
 #if ENABLE_UNICODE_SUPPORT
 	command_ps = xzalloc(maxsize * sizeof(command_ps[0]));
 #else
-- 
cgit v1.2.3-55-g6feb


From 77a51a2709de1b646ab493f0bf771d896de6efc2 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Tue, 29 Dec 2020 16:53:11 +0100
Subject: randomconfig fixes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/procps.c                    |  2 +-
 loginutils/login.c                |  4 ++--
 miscutils/dc.c                    |  2 +-
 miscutils/devfsd.c                |  4 ++--
 miscutils/i2c_tools.c             |  6 ++++--
 networking/libiproute/ipaddress.c |  6 ++++++
 networking/telnet.c               |  4 ++++
 networking/traceroute.c           |  2 +-
 runit/runsv.c                     | 18 +++++++++++++-----
 shell/hush.c                      |  4 +++-
 testsuite/mount.tests             |  2 ++
 testsuite/xargs.tests             |  2 +-
 util-linux/fdisk.c                |  7 +++++--
 13 files changed, 45 insertions(+), 18 deletions(-)

(limited to 'libbb')

diff --git a/libbb/procps.c b/libbb/procps.c
index 975e0d4dc..75969947b 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -177,6 +177,7 @@ static char *skip_fields(char *str, int count)
 }
 #endif
 
+#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
 static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix)
 {
 	char *tp = is_prefixed_with(buf, prefix);
@@ -186,7 +187,6 @@ static char* skip_whitespace_if_prefixed_with(char *buf, const char *prefix)
 	return tp;
 }
 
-#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
 int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
 		void (*cb)(struct smaprec *, void *), void *data)
 {
diff --git a/loginutils/login.c b/loginutils/login.c
index de05631d2..21c32fc25 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -341,7 +341,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 #if ENABLE_LOGIN_SESSION_AS_CHILD
 	pid_t child_pid;
 #endif
-	pid_t my_pid;
+	IF_FEATURE_UTMP(pid_t my_pid;)
 
 	INIT_G();
 
@@ -524,7 +524,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
 	if (pw->pw_uid != 0)
 		die_if_nologin();
 
-	my_pid = getpid();
+	IF_FEATURE_UTMP(my_pid = getpid();)
 	update_utmp(my_pid, USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL);
 
 #if ENABLE_LOGIN_SESSION_AS_CHILD
diff --git a/miscutils/dc.c b/miscutils/dc.c
index 51376dd75..e94dc39e0 100644
--- a/miscutils/dc.c
+++ b/miscutils/dc.c
@@ -100,7 +100,7 @@ static void mod(void)
 	 * 0
 	 */
 	if (d == 0) {
-		bb_error_msg("remainder by zero");
+		bb_simple_error_msg("remainder by zero");
 		pop();
 		push(0);
 		return;
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c
index 17d8fb6b9..e5bb8a2d8 100644
--- a/miscutils/devfsd.c
+++ b/miscutils/devfsd.c
@@ -362,7 +362,7 @@ static const char bb_msg_variable_not_found[] ALIGN1 = "variable: %s not found";
 
 static void safe_memcpy(char *dest, const char *src, int len)
 {
-	memcpy(dest , src, len);
+	memcpy(dest, src, len);
 	dest[len] = '\0';
 }
 
@@ -1106,7 +1106,7 @@ static int copy_inode(const char *destpath, const struct stat *dest_stat,
 do_chown:
 			if (chown(destpath, source_stat->st_uid, source_stat->st_gid) == 0)
 				return TRUE;
-		/*break;*/
+			/*break;*/
 	}
 	return FALSE;
 }   /*  End Function copy_inode  */
diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c
index 57cac5d47..cda17ee00 100644
--- a/miscutils/i2c_tools.c
+++ b/miscutils/i2c_tools.c
@@ -273,7 +273,7 @@ static int i2c_bus_lookup(const char *bus_str)
 	return xstrtou_range(bus_str, 10, 0, 0xfffff);
 }
 
-#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CTRANSFER
+#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP
 static int i2c_parse_bus_addr(const char *addr_str)
 {
 	/* Slave address must be in range 0x03 - 0x77. */
@@ -286,14 +286,16 @@ static void i2c_set_pec(int fd, int pec)
 				itoptr(pec ? 1 : 0),
 				"can't set PEC");
 }
+#endif
 
+#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP || ENABLE_I2CTRANSFER
 static void i2c_set_slave_addr(int fd, int addr, int force)
 {
 	ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE,
 				itoptr(addr),
 				"can't set address to 0x%02x", addr);
 }
-#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */
+#endif
 
 #if ENABLE_I2CGET || ENABLE_I2CSET
 static int i2c_parse_data_addr(const char *data_addr)
diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c
index 71e8fb6a7..91fabb1fd 100644
--- a/networking/libiproute/ipaddress.c
+++ b/networking/libiproute/ipaddress.c
@@ -21,6 +21,12 @@
 #define IFF_LOWER_UP  0x10000  /* driver signals L1 up */
 #endif
 
+#ifndef IFA_F_NOPREFIXROUTE
+# define IFA_FLAGS           8
+/* ifa_flags */
+# define IFA_F_NOPREFIXROUTE 0x200
+#endif
+
 struct filter_t {
 	char *label;
 	/* Flush cmd buf. If !NULL, print_addrinfo() constructs flush commands in it */
diff --git a/networking/telnet.c b/networking/telnet.c
index 19a414b30..7a0253525 100644
--- a/networking/telnet.c
+++ b/networking/telnet.c
@@ -368,12 +368,16 @@ static void put_iac2_msb_lsb(unsigned x_y)
 }
 #define put_iac2_x_y(x,y) put_iac2_msb_lsb(((x)<<8) + (y))
 
+#if ENABLE_FEATURE_TELNET_WIDTH \
+ || ENABLE_FEATURE_TELNET_TTYPE \
+ || ENABLE_FEATURE_TELNET_AUTOLOGIN
 static void put_iac4_msb_lsb(unsigned x_y_z_t)
 {
 	put_iac2_msb_lsb(x_y_z_t >> 16);
 	put_iac2_msb_lsb(x_y_z_t);  /* "... & 0xffff" is implicit */
 }
 #define put_iac4_x_y_z_t(x,y,z,t) put_iac4_msb_lsb(((x)<<24) + ((y)<<16) + ((z)<<8) + (t))
+#endif
 
 static void put_iac3_IAC_x_y_merged(unsigned wwdd_and_c)
 {
diff --git a/networking/traceroute.c b/networking/traceroute.c
index ec3ac8b6f..3f1a9ab46 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -483,7 +483,7 @@ wait_for_reply(unsigned *timestamp_us, int *left_ms)
 				&G.from_lsa->u.sa, &G.from_lsa->len);
 #endif
 		if (read_len < 0)
-			bb_perror_msg_and_die("recv");
+			bb_simple_perror_msg_and_die("recv");
 		t = monotonic_us();
 		*left_ms -= (t - *timestamp_us) / 1000;
 		*timestamp_us = t;
diff --git a/runit/runsv.c b/runit/runsv.c
index 7e22862cd..d395d4528 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -58,11 +58,19 @@ static void gettimeofday_ns(struct timespec *ts)
 #else
 static void gettimeofday_ns(struct timespec *ts)
 {
-	BUILD_BUG_ON(sizeof(struct timeval) != sizeof(struct timespec));
-	BUILD_BUG_ON(sizeof(((struct timeval*)ts)->tv_usec) != sizeof(ts->tv_nsec));
-	/* Cheat */
-	gettimeofday((void*)ts, NULL);
-	ts->tv_nsec *= 1000;
+	if (sizeof(struct timeval) == sizeof(struct timespec)
+	 && sizeof(((struct timeval*)ts)->tv_usec) == sizeof(ts->tv_nsec)
+	) {
+		/* Cheat */
+		gettimeofday((void*)ts, NULL);
+		ts->tv_nsec *= 1000;
+	} else {
+		/* For example, musl has "incompatible" layouts */
+		struct timeval tv;
+	        gettimeofday(&tv, NULL);
+		ts->tv_sec = tv.tv_sec;
+		ts->tv_nsec = tv.tv_usec * 1000;
+	}
 }
 #endif
 
diff --git a/shell/hush.c b/shell/hush.c
index f5cbbc39f..9fead37da 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -653,7 +653,7 @@ struct command {
 /* used for "[[ EXPR ]]" */
 # define CMD_TEST2_SINGLEWORD_NOGLOB 2
 #endif
-#if ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
+#if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
 /* used to prevent word splitting and globbing in "export v=t*" */
 # define CMD_SINGLEWORD_NOGLOB 3
 #endif
@@ -8762,6 +8762,7 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
 				 */
 				if (WIFSIGNALED(status)) {
 					int sig = WTERMSIG(status);
+#if ENABLE_HUSH_JOB
 					if (G.run_list_level == 1
 					/* ^^^^^ Do not print in nested contexts, example:
 					 * echo `sleep 1; sh -c 'kill -9 $$'` - prints "137", NOT "Killed 137"
@@ -8771,6 +8772,7 @@ static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
 						/* strsignal() is for bash compat. ~600 bloat versus bbox's get_signame() */
 						puts(sig == SIGINT || sig == SIGPIPE ? "" : strsignal(sig));
 					}
+#endif
 					/* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
 					/* MIPS has 128 sigs (1..128), if sig==128,
 					 * 128 + sig would result in exitcode 256 -> 0!
diff --git a/testsuite/mount.tests b/testsuite/mount.tests
index 91c2e8b42..b6d5ebe08 100755
--- a/testsuite/mount.tests
+++ b/testsuite/mount.tests
@@ -34,6 +34,8 @@ umount -d "$testdir" 2>/dev/null
 #   file input will be file called "input"
 #   test can create a file "actual" instead of writing to stdout
 
+# This will always fail on !CONFIG_MANDATORY_FILE_LOCKING kernels
+test "$SKIP_MOUNT_MAND_TESTS" = "1" || \
 testing "mount -o remount,mand" \
 "mount -o loop mount.image1m $testdir "\
 "&& grep -Fc $testdir </proc/mounts "\
diff --git a/testsuite/xargs.tests b/testsuite/xargs.tests
index e7c7c4b3d..c5e7b99e9 100755
--- a/testsuite/xargs.tests
+++ b/testsuite/xargs.tests
@@ -61,7 +61,7 @@ testing "xargs -n2" \
 
 SKIP=
 
-optional FEATURE_XARGS_SUPPORT_QUOTES
+optional FEATURE_XARGS_SUPPORT_QUOTES FEATURE_XARGS_SUPPORT_REPL_STR
 testing "xargs -I skips empty lines and leading whitespace" \
 	"xargs -I% echo '[%]'" \
 	"[2]\n[4]\n[6 6 ]\n[7]\n" \
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index 6454baab8..c50ceead1 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -185,8 +185,11 @@ struct hd_geometry {
 
 #define HDIO_GETGEO     0x0301  /* get device geometry */
 
-/* TODO: #if ENABLE_FEATURE_FDISK_WRITABLE */
+/* TODO: just #if ENABLE_FEATURE_FDISK_WRITABLE */
 /* (currently fdisk_sun/sgi.c do not have proper WRITABLE #ifs) */
+#if ENABLE_FEATURE_FDISK_WRITABLE \
+ || ENABLE_FEATURE_SGI_LABEL \
+ || ENABLE_FEATURE_SUN_LABEL
 static const char msg_building_new_label[] ALIGN1 =
 "Building a new %s. Changes will remain in memory only,\n"
 "until you decide to write them. After that the previous content\n"
@@ -194,7 +197,7 @@ static const char msg_building_new_label[] ALIGN1 =
 
 static const char msg_part_already_defined[] ALIGN1 =
 "Partition %u is already defined, delete it before re-adding\n";
-/* #endif */
+#endif
 
 
 struct partition {
-- 
cgit v1.2.3-55-g6feb


From 89a55972fd5d7f0ab815c2a62be69a8f34718353 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 30 Dec 2020 01:04:56 +0100
Subject: libbb/procps: smaller global data for username/groupname cache

function                                             old     new   delta
get_cached                                           101     133     +32
cache_user_group                                       -       4      +4
get_cached_username                                   17      14      -3
username                                               8       -      -8
groupname                                              8       -      -8
clear_username_cache                                  65      47     -18
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 1/2 up/down: 36/-37)             Total: -1 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/procps.c | 45 +++++++++++++++++----------------------------
 1 file changed, 17 insertions(+), 28 deletions(-)

(limited to 'libbb')

diff --git a/libbb/procps.c b/libbb/procps.c
index 75969947b..f56b71b21 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -21,40 +21,29 @@ typedef struct cache_t {
 	int size;
 } cache_t;
 
-static cache_t username, groupname;
+static cache_t *cache_user_group;
 
-static void clear_cache(cache_t *cp)
-{
-	free(cp->cache);
-	cp->cache = NULL;
-	cp->size = 0;
-}
 void FAST_FUNC clear_username_cache(void)
 {
-	clear_cache(&username);
-	clear_cache(&groupname);
-}
-
-#if 0 /* more generic, but we don't need that yet */
-/* Returns -N-1 if not found. */
-/* cp->cache[N] is allocated and must be filled in this case */
-static int get_cached(cache_t *cp, uid_t id)
-{
-	int i;
-	for (i = 0; i < cp->size; i++)
-		if (cp->cache[i].id == id)
-			return i;
-	i = cp->size++;
-	cp->cache = xrealloc_vector(cp->cache, 2, i);
-	cp->cache[i++].id = id;
-	return -i;
+	if (cache_user_group) {
+		free(cache_user_group[0].cache);
+		free(cache_user_group[1].cache);
+		free(cache_user_group);
+		cache_user_group = NULL;
+	}
 }
-#endif
 
-static char* get_cached(cache_t *cp, uid_t id,
+static char* get_cached(int user_group, uid_t id,
 			char* FAST_FUNC x2x_utoa(uid_t id))
 {
+	cache_t *cp;
 	int i;
+
+	if (!cache_user_group)
+		cache_user_group = xzalloc(sizeof(cache_user_group[0]) * 2);
+
+	cp = &cache_user_group[user_group];
+
 	for (i = 0; i < cp->size; i++)
 		if (cp->cache[i].id == id)
 			return cp->cache[i].name;
@@ -67,11 +56,11 @@ static char* get_cached(cache_t *cp, uid_t id,
 }
 const char* FAST_FUNC get_cached_username(uid_t uid)
 {
-	return get_cached(&username, uid, uid2uname_utoa);
+	return get_cached(0, uid, uid2uname_utoa);
 }
 const char* FAST_FUNC get_cached_groupname(gid_t gid)
 {
-	return get_cached(&groupname, gid, gid2group_utoa);
+	return get_cached(1, gid, gid2group_utoa);
 }
 
 
-- 
cgit v1.2.3-55-g6feb


From 3c13da3dab539eac948de48640d8862857d0c8d0 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Wed, 30 Dec 2020 23:48:01 +0100
Subject: libbb: introduce and use xgettimeofday(), do not truncate 64-bit
 time_t in shells

function                                             old     new   delta
xgettimeofday                                          -      11     +11
get_local_var_value                                  280     281      +1
svlogd_main                                         1323    1322      -1
change_epoch                                          67      66      -1
timestamp_and_log                                    461     458      -3
hwclock_main                                         301     298      -3
fmt_time_bernstein_25                                135     132      -3
step_time                                            331     326      -5
script_main                                         1207    1202      -5
machtime                                              34      28      -6
curtime                                               61      54      -7
ts_main                                              423     415      -8
nmeter_main                                          761     751     -10
gettime1900d                                          67      46     -21
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/12 up/down: 12/-73)           Total: -61 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 include/libbb.h         |  1 +
 libbb/time.c            |  6 +++---
 libbb/xfuncs_printf.c   | 11 +++++++++++
 miscutils/ts.c          |  4 ++--
 networking/inetd.c      |  2 +-
 networking/ntpd.c       |  4 ++--
 networking/traceroute.c |  2 +-
 procps/nmeter.c         |  8 ++++----
 runit/runsv.c           |  4 ++--
 runit/svlogd.c          |  4 ++--
 shell/ash.c             | 10 +++++-----
 shell/hush.c            | 10 +++++-----
 sysklogd/syslogd.c      |  2 +-
 util-linux/hwclock.c    |  8 ++++----
 util-linux/mdev.c       |  2 +-
 util-linux/script.c     |  2 +-
 16 files changed, 46 insertions(+), 34 deletions(-)

(limited to 'libbb')

diff --git a/include/libbb.h b/include/libbb.h
index cae54658b..dad6fc687 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -657,6 +657,7 @@ void parse_datestr(const char *date_str, struct tm *ptm) FAST_FUNC;
 time_t validate_tm_time(const char *date_str, struct tm *ptm) FAST_FUNC;
 char *strftime_HHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC;
 char *strftime_YYYYMMDDHHMMSS(char *buf, unsigned len, time_t *tp) FAST_FUNC;
+void xgettimeofday(struct timeval *tv) FAST_FUNC;
 void xsettimeofday(const struct timeval *tv) FAST_FUNC;
 
 
diff --git a/libbb/time.c b/libbb/time.c
index 74a69eefb..cf5f2e5c8 100644
--- a/libbb/time.c
+++ b/libbb/time.c
@@ -291,19 +291,19 @@ unsigned FAST_FUNC monotonic_sec(void)
 unsigned long long FAST_FUNC monotonic_ns(void)
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
 }
 unsigned long long FAST_FUNC monotonic_us(void)
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	return tv.tv_sec * 1000000ULL + tv.tv_usec;
 }
 unsigned long long FAST_FUNC monotonic_ms(void)
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	return tv.tv_sec * 1000ULL + tv.tv_usec / 1000;
 }
 unsigned FAST_FUNC monotonic_sec(void)
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index aea995a5c..99596b9d0 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -720,3 +720,14 @@ void FAST_FUNC xsettimeofday(const struct timeval *tv)
 	if (settimeofday(tv, NULL))
 		bb_simple_perror_msg_and_die("settimeofday");
 }
+
+void FAST_FUNC xgettimeofday(struct timeval *tv)
+{
+#if 0
+	if (gettimeofday(tv, NULL))
+		bb_simple_perror_msg_and_die("gettimeofday");
+#else
+	/* Never fails on Linux */
+	gettimeofday(tv, NULL);
+#endif
+}
diff --git a/miscutils/ts.c b/miscutils/ts.c
index f2d367654..6e5d77bda 100644
--- a/miscutils/ts.c
+++ b/miscutils/ts.c
@@ -47,13 +47,13 @@ int ts_main(int argc UNUSED_PARAM, char **argv)
 
 #define date_buf bb_common_bufsiz1
 	setup_common_bufsiz();
-	gettimeofday(&base, NULL);
+	xgettimeofday(&base);
 
 	while ((line = xmalloc_fgets(stdin)) != NULL) {
 		struct timeval ts;
 		struct tm tm_time;
 
-		gettimeofday(&ts, NULL);
+		xgettimeofday(&ts);
 		if (opt) {
 			/* -i and/or -s */
 			struct timeval ts1 = ts1;
diff --git a/networking/inetd.c b/networking/inetd.c
index 9f5a436d6..febfb7b73 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1701,7 +1701,7 @@ static uint32_t machtime(void)
 {
 	struct timeval tv;
 
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	return htonl((uint32_t)(tv.tv_sec + 2208988800U));
 }
 /* ARGSUSED */
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 5a540a391..46d8f3495 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -560,7 +560,7 @@ static double
 gettime1900d(void)
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL); /* never fails */
+	xgettimeofday(&tv);
 	G.cur_time = tv.tv_sec + (1.0e-6 * tv.tv_usec) + OFFSET_1900_1970;
 	return G.cur_time;
 }
@@ -1144,7 +1144,7 @@ step_time(double offset)
 	char buf[sizeof("yyyy-mm-dd hh:mm:ss") + /*paranoia:*/ 4];
 	time_t tval;
 
-	gettimeofday(&tvc, NULL); /* never fails */
+	xgettimeofday(&tvc);
 	dtime = tvc.tv_sec + (1.0e-6 * tvc.tv_usec) + offset;
 	d_to_tv(dtime, &tvn);
 	xsettimeofday(&tvn);
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 3f1a9ab46..bd63e4449 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -505,7 +505,7 @@ send_probe(int seq, int ttl)
 		struct outdata6_t *pkt = (void *) outdata;
 		pkt->ident6 = ident;
 		pkt->seq6   = htonl(seq);
-		/*gettimeofday(&pkt->tv, &tz);*/
+		/*xgettimeofday(&pkt->tv);*/
 		icp = outicmp6;
 	} else
 #endif
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 07b7abe2f..f08938654 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -952,11 +952,11 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
 	reset_outbuf();
 
 	if (G.delta >= 0) {
-		gettimeofday(&G.tv, NULL);
+		xgettimeofday(&G.tv);
 		usleep(G.delta > 1000000 ? 1000000 : G.delta - G.tv.tv_usec % G.deltanz);
 	}
 
-	gettimeofday(&G.start, NULL);
+	xgettimeofday(&G.start);
 	G.tv = G.start;
 	while (1) {
 		collect_info(first);
@@ -971,7 +971,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
 		if (G.delta >= 0) {
 			int rem;
 			// can be commented out, will sacrifice sleep time precision a bit
-			gettimeofday(&G.tv, NULL);
+			xgettimeofday(&G.tv);
 			if (need_seconds)
 				rem = G.delta - ((ullong)G.tv.tv_sec*1000000 + G.tv.tv_usec) % G.deltanz;
 			else
@@ -983,7 +983,7 @@ int nmeter_main(int argc UNUSED_PARAM, char **argv)
 			}
 			usleep(rem);
 		}
-		gettimeofday(&G.tv, NULL);
+		xgettimeofday(&G.tv);
 	}
 
 	/*return 0;*/
diff --git a/runit/runsv.c b/runit/runsv.c
index d395d4528..ecab8cdf5 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -62,12 +62,12 @@ static void gettimeofday_ns(struct timespec *ts)
 	 && sizeof(((struct timeval*)ts)->tv_usec) == sizeof(ts->tv_nsec)
 	) {
 		/* Cheat */
-		gettimeofday((void*)ts, NULL);
+		xgettimeofday((void*)ts);
 		ts->tv_nsec *= 1000;
 	} else {
 		/* For example, musl has "incompatible" layouts */
 		struct timeval tv;
-	        gettimeofday(&tv, NULL);
+		xgettimeofday(&tv);
 		ts->tv_sec = tv.tv_sec;
 		ts->tv_nsec = tv.tv_usec * 1000;
 	}
diff --git a/runit/svlogd.c b/runit/svlogd.c
index 040e71104..294e31aca 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -351,7 +351,7 @@ static void fmt_time_human_30nul(char *s, char dt_delim)
 	struct tm *ptm;
 	struct timeval tv;
 
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	ptm = gmtime_r(&tv.tv_sec, &tm);
 	/* ^^^ using gmtime_r() instead of gmtime() to not use static data */
 	sprintf(s, "%04u-%02u-%02u%c%02u:%02u:%02u.%06u000",
@@ -376,7 +376,7 @@ static void fmt_time_bernstein_25(char *s)
 	struct timeval tv;
 	unsigned sec_hi;
 
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	sec_hi = (0x400000000000000aULL + tv.tv_sec) >> 32;
 	tv.tv_sec = (time_t)(0x400000000000000aULL) + tv.tv_sec;
 	tv.tv_usec *= 1000;
diff --git a/shell/ash.c b/shell/ash.c
index f16d7fb6a..54f004375 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -11371,10 +11371,10 @@ static void FAST_FUNC
 change_epoch(struct var *vepoch, const char *fmt)
 {
 	struct timeval tv;
-	char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3];
+	char buffer[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
 
-	gettimeofday(&tv, NULL);
-	sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec);
+	xgettimeofday(&tv);
+	sprintf(buffer, fmt, (unsigned long long)tv.tv_sec, (unsigned)tv.tv_usec);
 	setvar(vepoch->var_text, buffer, VNOFUNC);
 	vepoch->flags &= ~VNOFUNC;
 }
@@ -11382,13 +11382,13 @@ change_epoch(struct var *vepoch, const char *fmt)
 static void FAST_FUNC
 change_seconds(const char *value UNUSED_PARAM)
 {
-	change_epoch(&vepochs, "%lu");
+	change_epoch(&vepochs, "%llu");
 }
 
 static void FAST_FUNC
 change_realtime(const char *value UNUSED_PARAM)
 {
-	change_epoch(&vepochr, "%lu.%06u");
+	change_epoch(&vepochr, "%llu.%06u");
 }
 #endif
 
diff --git a/shell/hush.c b/shell/hush.c
index 9fead37da..65f08659f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1027,7 +1027,7 @@ struct globals {
 	struct sigaction sa;
 	char optstring_buf[sizeof("eixcs")];
 #if BASH_EPOCH_VARS
-	char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3];
+	char epoch_buf[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
 #endif
 #if ENABLE_FEATURE_EDITING
 	char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN];
@@ -2277,13 +2277,13 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
 	{
 		const char *fmt = NULL;
 		if (strcmp(name, "EPOCHSECONDS") == 0)
-			fmt = "%lu";
+			fmt = "%llu";
 		else if (strcmp(name, "EPOCHREALTIME") == 0)
-			fmt = "%lu.%06u";
+			fmt = "%llu.%06u";
 		if (fmt) {
 			struct timeval tv;
-			gettimeofday(&tv, NULL);
-			sprintf(G.epoch_buf, fmt, (unsigned long)tv.tv_sec,
+			xgettimeofday(&tv);
+			sprintf(G.epoch_buf, fmt, (unsigned long long)tv.tv_sec,
 					(unsigned)tv.tv_usec);
 			return G.epoch_buf;
 		}
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 598f28d0c..6ddfd771a 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -842,7 +842,7 @@ static void timestamp_and_log(int pri, char *msg, int len)
 #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
 	if (!timestamp) {
 		struct timeval tv;
-		gettimeofday(&tv, NULL);
+		xgettimeofday(&tv);
 		now = tv.tv_sec;
 		timestamp = ctime(&now) + 4; /* skip day of week */
 		/* overwrite year by milliseconds, zero terminate */
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
index 25db7cdad..723b09589 100644
--- a/util-linux/hwclock.c
+++ b/util-linux/hwclock.c
@@ -79,7 +79,7 @@ static time_t read_rtc(const char **pp_rtcname, struct timeval *sys_tv, int utc)
 		int before = tm_time.tm_sec;
 		while (1) {
 			rtc_read_tm(&tm_time, fd);
-			gettimeofday(sys_tv, NULL);
+			xgettimeofday(sys_tv);
 			if (before != (int)tm_time.tm_sec)
 				break;
 		}
@@ -205,7 +205,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc)
 	int rtc;
 
 	rtc = rtc_xopen(pp_rtcname, O_WRONLY);
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	/* Prepare tm_time */
 	if (sizeof(time_t) == sizeof(tv.tv_sec)) {
 		if (utc)
@@ -253,7 +253,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc)
 		unsigned rem_usec;
 		time_t t;
 
-		gettimeofday(&tv, NULL);
+		xgettimeofday(&tv);
 
 		t = tv.tv_sec;
 		rem_usec = 1000000 - tv.tv_usec;
@@ -274,7 +274,7 @@ static void from_sys_clock(const char **pp_rtcname, int utc)
 		}
 
 		/* gmtime/localtime took some time, re-get cur time */
-		gettimeofday(&tv, NULL);
+		xgettimeofday(&tv);
 
 		if (tv.tv_sec < t /* we are still in old second */
 		 || (tv.tv_sec == t && tv.tv_usec < adj) /* not too far into next second */
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index ebf83d1a3..dbbcbc655 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -963,7 +963,7 @@ static void load_firmware(const char *firmware, const char *sysfs_path)
 static char *curtime(void)
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL);
+	xgettimeofday(&tv);
 	sprintf(
 		strftime_HHMMSS(G.timestr, sizeof(G.timestr), &tv.tv_sec),
 		".%06u",
diff --git a/util-linux/script.c b/util-linux/script.c
index 4eac5e94f..963435335 100644
--- a/util-linux/script.c
+++ b/util-linux/script.c
@@ -172,7 +172,7 @@ int script_main(int argc UNUSED_PARAM, char **argv)
 						struct timeval tv;
 						double newtime;
 
-						gettimeofday(&tv, NULL);
+						xgettimeofday(&tv);
 						newtime = tv.tv_sec + (double) tv.tv_usec / 1000000;
 						fprintf(timing_fp, "%f %u\n", newtime - oldtime, count);
 						oldtime = newtime;
-- 
cgit v1.2.3-55-g6feb


From 09aba8bac466ce8fb94a6b5ee587d81415ff4c44 Mon Sep 17 00:00:00 2001
From: Alex Samorukov <samm@os2.kiev.ua>
Date: Mon, 4 Jan 2021 01:36:05 +0100
Subject: Fix missing "crypt.h" compilation error on the FreeBSD

FreeBSD does not use crypt.h, but unistd.h which is already included

Signed-off-by: Alex Samorukov <samm@os2.kiev.ua>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 libbb/pw_encrypt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'libbb')

diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
index a60c33c35..3463fd95b 100644
--- a/libbb/pw_encrypt.c
+++ b/libbb/pw_encrypt.c
@@ -7,7 +7,9 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 #if !ENABLE_USE_BB_CRYPT
-#include <crypt.h>
+# if !defined(__FreeBSD__)
+#  include <crypt.h>
+# endif
 #endif
 #include "libbb.h"
 
-- 
cgit v1.2.3-55-g6feb