Apply post-1.18.2 fixes, bump version to 1.18.3

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/Makefile b/Makefile
index e8bead0..656ee2c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 18
-SUBLEVEL = 2
+SUBLEVEL = 3
 EXTRAVERSION =
 NAME = Unnamed
 
diff --git a/archival/tar.c b/archival/tar.c
index 82caec7..c0b9261 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -1037,8 +1037,10 @@
 			tar_handle->src_fd = tar_fd;
 			tar_handle->seek = seek_by_read;
 		} else {
-			if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) {
-				get_header_ptr = get_header_tar;
+			if (ENABLE_FEATURE_TAR_AUTODETECT
+			 && flags == O_RDONLY
+			 && get_header_ptr == get_header_tar
+			) {
 				tar_handle->src_fd = open_zipped(tar_filename);
 				if (tar_handle->src_fd < 0)
 					bb_perror_msg_and_die("can't open '%s'", tar_filename);
diff --git a/coreutils/wc.c b/coreutils/wc.c
index fe3f274..6e22c66 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -81,11 +81,11 @@
  * column order in "wc -cmlwL" output:
  */
 enum {
-	WC_LINES    = 0,
-	WC_WORDS    = 1,
-	WC_UNICHARS = 2,
-	WC_CHARS    = 3,
-	WC_LENGTH   = 4,
+	WC_LINES    = 0, /* -l */
+	WC_WORDS    = 1, /* -w */
+	WC_UNICHARS = 2, /* -m */
+	WC_BYTES    = 3, /* -c */
+	WC_LENGTH   = 4, /* -L */
 	NUM_WCS     = 5,
 };
 
@@ -104,10 +104,10 @@
 
 	init_unicode();
 
-	print_type = getopt32(argv, "lwcmL");
+	print_type = getopt32(argv, "lwmcL");
 
 	if (print_type == 0) {
-		print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_CHARS);
+		print_type = (1 << WC_LINES) | (1 << WC_WORDS) | (1 << WC_BYTES);
 	}
 
 	argv += optind;
@@ -157,7 +157,7 @@
 			}
 
 			/* Cater for -c and -m */
-			++counts[WC_CHARS];
+			++counts[WC_BYTES];
 			if (unicode_status != UNICODE_ON /* every byte is a new char */
 			 || (c & 0xc0) != 0x80 /* it isn't a 2nd+ byte of a Unicode char */
 			) {
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 5e0fb0d..0c879f6 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -52,6 +52,7 @@
 	 * Interested party can wait on pid and learn exit code.
 	 * If 111 - then it (most probably) failed to exec */
 	if (failed) {
+		safe_waitpid(pid, NULL, 0); /* prevent zombie */
 		errno = failed;
 		return -1;
 	}
diff --git a/loginutils/Config.src b/loginutils/Config.src
index 8158bce..4c771bb 100644
--- a/loginutils/Config.src
+++ b/loginutils/Config.src
@@ -186,7 +186,6 @@
 config LOGIN
 	bool "login"
 	default y
-	select FEATURE_SUID
 	select FEATURE_SYSLOG
 	help
 	  login is used when signing onto a system.
@@ -229,7 +228,6 @@
 config PASSWD
 	bool "passwd"
 	default y
-	select FEATURE_SUID
 	select FEATURE_SYSLOG
 	help
 	  passwd changes passwords for user and group accounts. A normal user
@@ -265,7 +263,6 @@
 config SU
 	bool "su"
 	default y
-	select FEATURE_SUID
 	select FEATURE_SYSLOG
 	help
 	  su is used to become another user during a login session.
@@ -295,7 +292,6 @@
 config VLOCK
 	bool "vlock"
 	default y
-	select FEATURE_SUID
 	help
 	  Build the "vlock" applet which allows you to lock (virtual) terminals.
 
diff --git a/miscutils/Config.src b/miscutils/Config.src
index 4912daf..da52e14 100644
--- a/miscutils/Config.src
+++ b/miscutils/Config.src
@@ -170,7 +170,6 @@
 config CRONTAB
 	bool "crontab"
 	default y
-	select FEATURE_SUID
 	help
 	  Crontab manipulates the crontab for a particular user. Only
 	  the superuser may specify a different user and/or crontab directory.
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c
index f4f17e7..188a7f2 100644
--- a/modutils/modprobe-small.c
+++ b/modutils/modprobe-small.c
@@ -205,6 +205,7 @@
 	/* Read (possibly compressed) module */
 	len = 64 * 1024 * 1024; /* 64 Mb at most */
 	module_image = xmalloc_open_zipped_read_close(pathname, &len);
+	/* module_image == NULL is ok here, find_keyword handles it */
 //TODO: optimize redundant module body reads
 
 	/* "alias1 symbol:sym1 alias2 symbol:sym2" */
@@ -845,6 +846,8 @@
 
 		len = MAXINT(ssize_t);
 		map = xmalloc_open_zipped_read_close(*argv, &len);
+		if (!map)
+			bb_perror_msg_and_die("can't read '%s'", *argv);
 		if (init_module(map, len,
 			IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : "")
 			IF_NOT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE("")
diff --git a/modutils/modutils.c b/modutils/modutils.c
index 565d0d2..415dbbe 100644
--- a/modutils/modutils.c
+++ b/modutils/modutils.c
@@ -71,12 +71,11 @@
 	optlen = 0;
 	while (*++argv) {
 		options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
-		/* Older versions were enclosing space-containing *argv in "",
-		 * but both modprobe and insmod from module-init-tools 3.11.1
-		 * don't do this anymore. (As to extra trailing space,
-		 * insmod adds it but modprobe does not. We do in both cases)
-		 */
-		optlen += sprintf(options + optlen, "%s ", *argv);
+		/* Spaces handled by "" pairs, but no way of escaping quotes */
+//TODO: module-init-tools version 3.11.1 quotes only value:
+//it generates var="val with spaces", not "var=val with spaces"
+//(and it won't quote var *name* even if it has spaces)
+		optlen += sprintf(options + optlen, (strchr(*argv, ' ') ? "\"%s\" " : "%s "), *argv);
 	}
 	return options;
 }
diff --git a/networking/ping.c b/networking/ping.c
index 3aba490..5fc80fe 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -394,7 +394,7 @@
 #if ENABLE_PING6
 static void sendping6(int junk UNUSED_PARAM)
 {
-	struct icmp6_hdr *pkt = alloca(datalen + sizeof(struct icmp6_hdr) + 4);
+	struct icmp6_hdr *pkt = G.snd_packet;
 
 	//memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4);
 	pkt->icmp6_type = ICMP6_ECHO_REQUEST;
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index 311f79e..0a60261 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -375,7 +375,7 @@
 		new->data = xmalloc(length + OPT_DATA);
 		new->data[OPT_CODE] = optflag->code;
 		new->data[OPT_LEN] = length;
-		memcpy(new->data + OPT_DATA, buffer, length);
+		memcpy(new->data + OPT_DATA, (allocated ? allocated : buffer), length);
 
 		curr = opt_list;
 		while (*curr && (*curr)->data[OPT_CODE] < optflag->code)
diff --git a/shell/hush.c b/shell/hush.c
index f9f8152..58d2c11 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -4123,15 +4123,26 @@
 				 && dest.length == 0 && !dest.has_quoted_part
 				) {
 					/* This newline can be ignored. But...
-					 * without the below check, interactive shell
-					 * will ignore even lines with bare <newline>,
-					 * and show the continuation prompt:
+					 * Without check #1, interactive shell
+					 * ignores even bare <newline>,
+					 * and shows the continuation prompt:
 					 * ps1_prompt$ <enter>
-					 * ps2> _   <=== wrong prompt, should be ps1
+					 * ps2> _   <=== wrong, should be ps1
+					 * Without check #2, "cmd & <newline>"
+					 * is similarly mistreated.
+					 * (BTW, this makes "cmd & cmd"
+					 * and "cmd && cmd" non-orthogonal.
+					 * Really, ask yourself, why
+					 * "cmd && <newline>" doesn't start
+					 * cmd but waits for more input?
+					 * No reason...)
 					 */
 					struct pipe *pi = ctx.list_head;
-					if (pi->num_cmds != 0)
+					if (pi->num_cmds != 0       /* check #1 */
+					 && pi->followup != PIPE_BG /* check #2 */
+					) {
 						continue;
+					}
 				}
 				/* Treat newline as a command separator. */
 				done_pipe(&ctx, PIPE_SEQ);
diff --git a/util-linux/Config.src b/util-linux/Config.src
index c71b4de..0f865ac 100644
--- a/util-linux/Config.src
+++ b/util-linux/Config.src
@@ -354,7 +354,6 @@
 config IPCRM
 	bool "ipcrm"
 	default y
-	select FEATURE_SUID
 	help
 	  The ipcrm utility allows the removal of System V interprocess
 	  communication (IPC) objects and the associated data structures
@@ -364,7 +363,6 @@
 	bool "ipcs"
 	default y
 	depends on PLATFORM_LINUX
-	select FEATURE_SUID
 	help
 	  The ipcs utility is used to provide information on the currently
 	  allocated System V interprocess (IPC) objects in the system.