Apply post-1.19.0 patches, bump version to 1.19.1

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/Makefile b/Makefile
index 7a1abda..138d1d4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 19
-SUBLEVEL = 0
+SUBLEVEL = 1
 EXTRAVERSION =
 NAME = Unnamed
 
diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c
index 44d8942..d1061a2 100644
--- a/archival/libarchive/decompress_uncompress.c
+++ b/archival/libarchive/decompress_uncompress.c
@@ -163,7 +163,8 @@
 
 		if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
 			rsize = safe_read(fd_in, inbuf + insize, IBUFSIZ);
-//error check??
+			if (rsize < 0)
+				bb_error_msg_and_die(bb_msg_read_error);
 			insize += rsize;
 		}
 
@@ -195,6 +196,8 @@
 
 
 			if (oldcode == -1) {
+				if (code >= 256)
+					bb_error_msg_and_die("corrupted data"); /* %ld", code); */
 				oldcode = code;
 				finchar = (int) oldcode;
 				outbuf[outpos++] = (unsigned char) finchar;
@@ -239,6 +242,8 @@
 
 			/* Generate output characters in reverse order */
 			while ((long) code >= (long) 256) {
+				if (stackp <= &htabof(0))
+					bb_error_msg_and_die("corrupted data");
 				*--stackp = tab_suffixof(code);
 				code = tab_prefixof(code);
 			}
@@ -263,8 +268,7 @@
 						}
 
 						if (outpos >= OBUFSIZ) {
-							full_write(fd_out, outbuf, outpos);
-//error check??
+							xwrite(fd_out, outbuf, outpos);
 							IF_DESKTOP(total_written += outpos;)
 							outpos = 0;
 						}
@@ -292,8 +296,7 @@
 	} while (rsize > 0);
 
 	if (outpos > 0) {
-		full_write(fd_out, outbuf, outpos);
-//error check??
+		xwrite(fd_out, outbuf, outpos);
 		IF_DESKTOP(total_written += outpos;)
 	}
 
diff --git a/editors/sed.c b/editors/sed.c
index 5c4e9cc..1552cf3 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -75,6 +75,13 @@
 #include "libbb.h"
 #include "xregex.h"
 
+#if 0
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg(...) ((void)0)
+#endif
+
+
 enum {
 	OPT_in_place = 1 << 0,
 };
@@ -89,6 +96,7 @@
 	regex_t *end_match;     /* sed -e '/match/,/end_match/cmd' */
 	regex_t *sub_match;     /* For 's/sub_match/string/' */
 	int beg_line;           /* 'sed 1p'   0 == apply commands to all lines */
+	int beg_line_orig;      /* copy of the above, needed for -i */
 	int end_line;           /* 'sed 1,3p' 0 == one line only. -1 = last line ($) */
 
 	FILE *sw_file;          /* File (sw) command writes to, -1 for none. */
@@ -123,7 +131,7 @@
 	regex_t *previous_regex_ptr;
 
 	/* linked list of sed commands */
-	sed_cmd_t sed_cmd_head, *sed_cmd_tail;
+	sed_cmd_t *sed_cmd_head, **sed_cmd_tail;
 
 	/* Linked list of append lines */
 	llist_t *append_head;
@@ -148,7 +156,7 @@
 #if ENABLE_FEATURE_CLEAN_UP
 static void sed_free_and_close_stuff(void)
 {
-	sed_cmd_t *sed_cmd = G.sed_cmd_head.next;
+	sed_cmd_t *sed_cmd = G.sed_cmd_head;
 
 	llist_free(G.append_head, free);
 
@@ -599,6 +607,7 @@
 
 		/* first part (if present) is an address: either a '$', a number or a /regex/ */
 		cmdstr += get_address(cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match);
+		sed_cmd->beg_line_orig = sed_cmd->beg_line;
 
 		/* second part (if present) will begin with a comma */
 		if (*cmdstr == ',') {
@@ -630,8 +639,8 @@
 		cmdstr = parse_cmd_args(sed_cmd, cmdstr);
 
 		/* Add the command to the command array */
-		G.sed_cmd_tail->next = sed_cmd;
-		G.sed_cmd_tail = G.sed_cmd_tail->next;
+		*G.sed_cmd_tail = sed_cmd;
+		G.sed_cmd_tail = &sed_cmd->next;
 	}
 
 	/* If we glued multiple lines together, free the memory. */
@@ -777,7 +786,7 @@
 {
 	sed_cmd_t *sed_cmd;
 
-	for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
+	for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
 		if (sed_cmd->cmd == ':' && sed_cmd->string && !strcmp(sed_cmd->string, label)) {
 			return sed_cmd;
 		}
@@ -953,24 +962,24 @@
 
 	/* For every line, go through all the commands */
  restart:
-	for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
+	for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
 		int old_matched, matched;
 
 		old_matched = sed_cmd->in_match;
 
 		/* Determine if this command matches this line: */
 
-		//bb_error_msg("match1:%d", sed_cmd->in_match);
-		//bb_error_msg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line
-		//		&& !sed_cmd->beg_match && !sed_cmd->end_match));
-		//bb_error_msg("match3:%d", (sed_cmd->beg_line > 0
-		//	&& (sed_cmd->end_line || sed_cmd->end_match
-		//	    ? (sed_cmd->beg_line <= linenum)
-		//	    : (sed_cmd->beg_line == linenum)
-		//	    )
-		//	)
-		//bb_error_msg("match4:%d", (beg_match(sed_cmd, pattern_space)));
-		//bb_error_msg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL));
+		dbg("match1:%d", sed_cmd->in_match);
+		dbg("match2:%d", (!sed_cmd->beg_line && !sed_cmd->end_line
+				&& !sed_cmd->beg_match && !sed_cmd->end_match));
+		dbg("match3:%d", (sed_cmd->beg_line > 0
+			&& (sed_cmd->end_line || sed_cmd->end_match
+			    ? (sed_cmd->beg_line <= linenum)
+			    : (sed_cmd->beg_line == linenum)
+			    )
+			));
+		dbg("match4:%d", (beg_match(sed_cmd, pattern_space)));
+		dbg("match5:%d", (sed_cmd->beg_line == -1 && next_line == NULL));
 
 		/* Are we continuing a previous multi-line match? */
 		sed_cmd->in_match = sed_cmd->in_match
@@ -981,7 +990,14 @@
 			|| (sed_cmd->beg_line > 0
 			    && (sed_cmd->end_line || sed_cmd->end_match
 				  /* note: even if end is numeric and is < linenum too,
-				   * GNU sed matches! We match too */
+				   * GNU sed matches! We match too, therefore we don't
+				   * check here that linenum <= end.
+				   * Example:
+				   * printf '1\n2\n3\n4\n' | sed -n '1{N;N;d};1p;2,3p;3p;4p'
+				   * first three input lines are deleted;
+				   * 4th line is matched and printed
+				   * by "2,3" (!) and by "4" ranges
+				   */
 				? (sed_cmd->beg_line <= linenum)    /* N,end */
 				: (sed_cmd->beg_line == linenum)    /* N */
 				)
@@ -994,16 +1010,14 @@
 		/* Snapshot the value */
 		matched = sed_cmd->in_match;
 
-		//bb_error_msg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d",
-		//sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum);
+		dbg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d",
+			sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum);
 
 		/* Is this line the end of the current match? */
 
 		if (matched) {
 			/* once matched, "n,xxx" range is dead, disabling it */
-			if (sed_cmd->beg_line > 0
-			 && !(option_mask32 & OPT_in_place) /* but not for -i */
-			) {
+			if (sed_cmd->beg_line > 0) {
 				sed_cmd->beg_line = -2;
 			}
 			sed_cmd->in_match = !(
@@ -1017,7 +1031,8 @@
 				/* or does this line matches our last address regex */
 				|| (sed_cmd->end_match && old_matched
 				     && (regexec(sed_cmd->end_match,
-				                 pattern_space, 0, NULL, 0) == 0))
+				                 pattern_space, 0, NULL, 0) == 0)
+				)
 			);
 		}
 
@@ -1407,11 +1422,12 @@
 		add_input_file(stdin);
 	} else {
 		int i;
-		FILE *file;
 
 		for (i = 0; argv[i]; i++) {
 			struct stat statbuf;
 			int nonstdoutfd;
+			FILE *file;
+			sed_cmd_t *sed_cmd;
 
 			if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) {
 				add_input_file(stdin);
@@ -1423,11 +1439,13 @@
 				status = EXIT_FAILURE;
 				continue;
 			}
+			add_input_file(file);
 			if (!(opt & OPT_in_place)) {
-				add_input_file(file);
 				continue;
 			}
 
+			/* -i: process each FILE separately: */
+
 			G.outname = xasprintf("%sXXXXXX", argv[i]);
 			nonstdoutfd = xmkstemp(G.outname);
 			G.nonstdout = xfdopen_for_write(nonstdoutfd);
@@ -1438,15 +1456,20 @@
 			 * but GNU sed 4.2.1 does not preserve them either */
 			fchmod(nonstdoutfd, statbuf.st_mode);
 			fchown(nonstdoutfd, statbuf.st_uid, statbuf.st_gid);
-			add_input_file(file);
+
 			process_files();
 			fclose(G.nonstdout);
-
 			G.nonstdout = stdout;
+
 			/* unlink(argv[i]); */
 			xrename(G.outname, argv[i]);
 			free(G.outname);
 			G.outname = NULL;
+
+			/* Re-enable disabled range matches */
+			for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) {
+				sed_cmd->beg_line = sed_cmd->beg_line_orig;
+			}
 		}
 		/* Here, to handle "sed 'cmds' nonexistent_file" case we did:
 		 * if (G.current_input_file >= G.input_file_count)
diff --git a/findutils/find.c b/findutils/find.c
index 05f88d2..fc0fc5c 100644
--- a/findutils/find.c
+++ b/findutils/find.c
@@ -932,7 +932,10 @@
  * expression is reached.
  */
 		/* Options */
-		if (0) { }
+		if (parm == OPT_FOLLOW) {
+                        dbg("follow enabled: %d", __LINE__);
+                        G.recurse_flags |= ACTION_FOLLOWLINKS | ACTION_DANGLING_OK;
+		}
 #if ENABLE_FEATURE_FIND_XDEV
 		else if (parm == OPT_XDEV) {
 			dbg("%d", __LINE__);
diff --git a/findutils/grep.c b/findutils/grep.c
index 3acfa91..5f42242 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -562,20 +562,20 @@
 
 static void load_regexes_from_file(llist_t *fopt)
 {
-	char *line;
-	FILE *f;
-
 	while (fopt) {
+		char *line;
+		FILE *fp;
 		llist_t *cur = fopt;
 		char *ffile = cur->data;
 
 		fopt = cur->link;
 		free(cur);
-		f = xfopen_stdin(ffile);
-		while ((line = xmalloc_fgetline(f)) != NULL) {
+		fp = xfopen_stdin(ffile);
+		while ((line = xmalloc_fgetline(fp)) != NULL) {
 			llist_add_to(&pattern_head,
 				new_grep_list_data(line, ALLOCATED));
 		}
+		fclose_if_not_stdin(fp);
 	}
 }
 
@@ -659,15 +659,19 @@
 #endif
 	invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */
 
-	if (pattern_head != NULL) {
-		/* convert char **argv to grep_list_data_t */
+	{	/* convert char **argv to grep_list_data_t */
 		llist_t *cur;
-
 		for (cur = pattern_head; cur; cur = cur->link)
 			cur->data = new_grep_list_data(cur->data, 0);
 	}
-	if (option_mask32 & OPT_f)
+	if (option_mask32 & OPT_f) {
 		load_regexes_from_file(fopt);
+		if (!pattern_head) { /* -f EMPTY_FILE? */
+			/* GNU grep treats it as "nothing matches" */
+			llist_add_to(&pattern_head, new_grep_list_data((char*) "", 0));
+			invert_search ^= 1;
+		}
+	}
 
 	if (ENABLE_FEATURE_GREP_FGREP_ALIAS && applet_name[0] == 'f')
 		option_mask32 |= OPT_F;
diff --git a/include/platform.h b/include/platform.h
index e22dbdb..826a4c4 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -417,6 +417,8 @@
 # undef HAVE_STRVERSCMP
 # undef HAVE_XTABS
 # undef HAVE_DPRINTF
+# undef HAVE_UNLOCKED_STDIO
+# undef HAVE_UNLOCKED_LINE_OPS
 #endif
 
 #if defined(__FreeBSD__)
diff --git a/libbb/getpty.c b/libbb/getpty.c
index 6a15cff..435e4d0 100644
--- a/libbb/getpty.c
+++ b/libbb/getpty.c
@@ -19,20 +19,22 @@
 	if (p > 0) {
 		grantpt(p); /* chmod+chown corresponding slave pty */
 		unlockpt(p); /* (what does this do?) */
-#ifndef HAVE_PTSNAME_R
-		const char *name;
-		name = ptsname(p); /* find out the name of slave pty */
-		if (!name) {
-			bb_perror_msg_and_die("ptsname error (is /dev/pts mounted?)");
+# ifndef HAVE_PTSNAME_R
+		{
+			const char *name;
+			name = ptsname(p); /* find out the name of slave pty */
+			if (!name) {
+				bb_perror_msg_and_die("ptsname error (is /dev/pts mounted?)");
+			}
+			safe_strncpy(line, name, GETPTY_BUFSIZE);
 		}
-		safe_strncpy(line, name, GETPTY_BUFSIZE);
-#else
+# else
 		/* find out the name of slave pty */
 		if (ptsname_r(p, line, GETPTY_BUFSIZE-1) != 0) {
 			bb_perror_msg_and_die("ptsname error (is /dev/pts mounted?)");
 		}
 		line[GETPTY_BUFSIZE-1] = '\0';
-#endif
+# endif
 		return p;
 	}
 #else
diff --git a/libbb/match_fstype.c b/libbb/match_fstype.c
index 83d6e67..c792d13 100644
--- a/libbb/match_fstype.c
+++ b/libbb/match_fstype.c
@@ -10,6 +10,8 @@
  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
 
+#ifdef HAVE_MNTENT_H
+
 #include "libbb.h"
 
 int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype)
@@ -40,3 +42,5 @@
 
 	return !match;
 }
+
+#endif /* HAVE_MNTENT_H */
diff --git a/libbb/procps.c b/libbb/procps.c
index 1dea615..e15ddd1 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -284,27 +284,25 @@
 void BUG_comm_size(void);
 procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
 {
-	struct dirent *entry;
-	char buf[PROCPS_BUFSIZE];
-	char filename[sizeof("/proc//cmdline") + sizeof(int)*3];
-	char *filename_tail;
-	long tasknice;
-	unsigned pid;
-	int n;
-	struct stat sb;
-
 	if (!sp)
 		sp = alloc_procps_scan();
 
 	for (;;) {
+		struct dirent *entry;
+		char buf[PROCPS_BUFSIZE];
+		long tasknice;
+		unsigned pid;
+		int n;
+		char filename[sizeof("/proc/%u/task/%u/cmdline") + sizeof(int)*3 * 2];
+		char *filename_tail;
+
 #if ENABLE_FEATURE_SHOW_THREADS
-		if ((flags & PSSCAN_TASKS) && sp->task_dir) {
+		if (sp->task_dir) {
 			entry = readdir(sp->task_dir);
 			if (entry)
 				goto got_entry;
 			closedir(sp->task_dir);
 			sp->task_dir = NULL;
-			sp->main_thread_pid = 0;
 		}
 #endif
 		entry = readdir(sp->dir);
@@ -321,9 +319,9 @@
 			/* We found another /proc/PID. Do not use it,
 			 * there will be /proc/PID/task/PID (same PID!),
 			 * so just go ahead and dive into /proc/PID/task. */
-			char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3];
-			sprintf(task_dir, "/proc/%u/task", pid);
-			sp->task_dir = xopendir(task_dir);
+			sprintf(filename, "/proc/%u/task", pid);
+			/* Note: if opendir fails, we just go to next /proc/XXX */
+			sp->task_dir = opendir(filename);
 			sp->main_thread_pid = pid;
 			continue;
 		}
@@ -347,9 +345,15 @@
 		}
 #endif
 
-		filename_tail = filename + sprintf(filename, "/proc/%u/", pid);
+#if ENABLE_FEATURE_SHOW_THREADS
+		if (sp->task_dir)
+			filename_tail = filename + sprintf(filename, "/proc/%u/task/%u/", sp->main_thread_pid, pid);
+		else
+#endif
+			filename_tail = filename + sprintf(filename, "/proc/%u/", pid);
 
 		if (flags & PSSCAN_UIDGID) {
+			struct stat sb;
 			if (stat(filename, &sb))
 				continue; /* process probably exited */
 			/* Effective UID/GID, not real */
diff --git a/libbb/udp_io.c b/libbb/udp_io.c
index b8fb675..7985a97 100644
--- a/libbb/udp_io.c
+++ b/libbb/udp_io.c
@@ -13,7 +13,7 @@
  * We don't check for errors here. Not supported == won't be used
  */
 void FAST_FUNC
-socket_want_pktinfo(int fd)
+socket_want_pktinfo(int fd UNUSED_PARAM)
 {
 #ifdef IP_PKTINFO
 	setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int));
diff --git a/miscutils/less.c b/miscutils/less.c
index 9543fb9..045fd2d 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -721,8 +721,8 @@
 	while (match_status == 0) {
 		char *new = xasprintf("%s%.*s"HIGHLIGHT"%.*s"NORMAL,
 				growline ? growline : "",
-				match_structs.rm_so, str,
-				match_structs.rm_eo - match_structs.rm_so,
+				(int)match_structs.rm_so, str,
+				(int)(match_structs.rm_eo - match_structs.rm_so),
 						str + match_structs.rm_so);
 		free(growline);
 		growline = new;
@@ -990,7 +990,8 @@
 	 */
 	if (key >= 0 && key < ' ' && key != 0x0d && key != 8)
 		goto again;
-	return key;
+
+	return key64;
 }
 
 static char* less_gets(int sz)
diff --git a/shell/cttyhack.c b/shell/cttyhack.c
index 4261289..37ea137 100644
--- a/shell/cttyhack.c
+++ b/shell/cttyhack.c
@@ -122,10 +122,12 @@
 		do {
 #ifdef __linux__
 			int s = open_read_close("/sys/class/tty/console/active",
-				console + 5, sizeof(console) - 5 - 1);
+				console + 5, sizeof(console) - 5);
 			if (s > 0) {
-				/* found active console via sysfs (Linux 2.6.38+) */
-				console[5 + s] = '\0';
+				/* found active console via sysfs (Linux 2.6.38+)
+				 * sysfs string looks like "ttyS0\n" so zap the newline:
+				 */
+				console[4 + s] = '\0';
 				break;
 			}
 
diff --git a/testsuite/sed.tests b/testsuite/sed.tests
index e9d0ed6..ba163e9 100755
--- a/testsuite/sed.tests
+++ b/testsuite/sed.tests
@@ -6,7 +6,7 @@
 
 . ./testing.sh
 
-# testing "description" "arguments" "result" "infile" "stdin"
+# testing "description" "commands" "result" "infile" "stdin"
 
 # Corner cases
 testing "sed no files (stdin)" 'sed ""' "hello\n" "" "hello\n"
@@ -225,7 +225,7 @@
 #testing "sed -g (exhaustive)" "sed -e 's/[[:space:]]*/,/g'" ",1,2,3,4,5," \
 #	"" "12345"
 
-# testing "description" "arguments" "result" "infile" "stdin"
+# testing "description" "commands" "result" "infile" "stdin"
 
 testing "sed n command must reset 'substituted' bit" \
 	"sed 's/1/x/;T;n;: next;s/3/y/;t quit;n;b next;: quit;q'" \
@@ -291,6 +291,10 @@
 	"sed 's/r/\r/'" \
 	"\rrr\n" "" "rrr\n"
 
-# testing "description" "arguments" "result" "infile" "stdin"
+testing "sed -i finishes ranges correctly" \
+	"sed '1,2d' -i input; echo \$?; cat input" \
+	"0\n3\n4\n" "1\n2\n3\n4\n" ""
+
+# testing "description" "commands" "result" "infile" "stdin"
 
 exit $FAILCOUNT
diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c
index 43ddb40..e53e24c 100644
--- a/util-linux/swaponoff.c
+++ b/util-linux/swaponoff.c
@@ -114,7 +114,8 @@
 #if !ENABLE_FEATURE_SWAPON_PRI
 	ret = getopt32(argv, "a");
 #else
-	opt_complementary = "p+";
+	if (applet_name[5] == 'n')
+		opt_complementary = "p+";
 	ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags);
 
 	if (ret & 2) { // -p