grep: add proper support for pattern_list
From POSIX.1-2008:
The pattern_list's value shall consist of one or more patterns
separated by <newline> characters;
As such, given patterns need to be split at newline characters. Without
doing so, busybox grep will interpret the newline as part of the pattern
which is not in accordance with POSIX.
See also: https://bugs.busybox.net/show_bug.cgi?id=12721
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/findutils/grep.c b/findutils/grep.c
index 84a6f7b..55e9c0a 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -650,6 +650,13 @@
}
}
+static void load_pattern_list(llist_t **lst, char *pattern)
+{
+ char *p;
+ while ((p = strsep(&pattern, "\n")) != NULL)
+ llist_add_to(lst, new_grep_list_data(p, 0));
+}
+
static int FAST_FUNC file_action_grep(const char *filename,
struct stat *statbuf,
void* matched,
@@ -754,10 +761,12 @@
#endif
invert_search = ((option_mask32 & OPT_v) != 0); /* 0 | 1 */
- { /* convert char **argv to grep_list_data_t */
- llist_t *cur;
+ { /* convert char **argv to pattern_list */
+ llist_t *cur, *new = NULL;
for (cur = pattern_head; cur; cur = cur->link)
- cur->data = new_grep_list_data(cur->data, 0);
+ load_pattern_list(&new, cur->data);
+ llist_free(pattern_head, NULL);
+ pattern_head = new;
}
if (option_mask32 & OPT_f) {
load_regexes_from_file(fopt);
@@ -806,11 +815,9 @@
/* if we didn't get a pattern from -e and no command file was specified,
* first parameter should be the pattern. no pattern, no worky */
if (pattern_head == NULL) {
- char *pattern;
if (*argv == NULL)
bb_show_usage();
- pattern = new_grep_list_data(*argv++, 0);
- llist_add_to(&pattern_head, pattern);
+ load_pattern_list(&pattern_head, *argv++);
}
/* argv[0..(argc-1)] should be names of file to grep through. If
diff --git a/testsuite/grep.tests b/testsuite/grep.tests
index 9c1f354..e382788 100755
--- a/testsuite/grep.tests
+++ b/testsuite/grep.tests
@@ -190,6 +190,18 @@
"" \
" aa bb cc\n"
+testing "grep PATTERN can be a newline-delimited list" \
+ 'grep -Fv "$(printf "foo\nbar\n")"' \
+ "baz\n" \
+ "" \
+ "foo\nbar\nbaz\n"
+
+testing "grep -e PATTERN can be a newline-delimited list" \
+ 'grep -Fv -e "$(printf "foo\nbar\n")"' \
+ "baz\n" \
+ "" \
+ "foo\nbar\nbaz\n"
+
# -r on symlink to dir should recurse into dir
mkdir -p grep.testdir/foo
echo bar > grep.testdir/foo/file