Initial revision
diff --git a/grep.c b/grep.c
new file mode 100644
index 0000000..3779e55
--- /dev/null
+++ b/grep.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999 by David I. Bell
+ * Permission is granted to use, distribute, or modify this source,
+ * provided that this copyright notice remains intact.
+ *
+ * The "grep" command, taken from sash.
+ * This provides basic file searching.
+ *
+ * Permission to distribute this code under the GPL has been granted.
+ * Modified for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com>
+ */
+
+#include "internal.h"
+#ifdef BB_GREP
+
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+#include <ctype.h>
+
+
+const char grep_usage[] =
+"Search the input file(s) for lines matching the given pattern.\n"
+"\tI search stdin if no files are given.\n"
+"\tI can't grok full regular expressions.\n"
+"usage: grep [in] PATTERN [FILES]...\n"
+"\ti=ignore case, n=list line numbers\n";
+
+
+
+static	BOOL	search
+	(const char * string, const char * word, BOOL ignoreCase);
+
+
+extern int 
+grep_main(struct FileInfo * unused, int argc, char ** argv)
+{
+	FILE *		fp;
+	const char *	word;
+	const char *	name;
+	const char *	cp;
+	BOOL		tellName;
+	BOOL		ignoreCase;
+	BOOL		tellLine;
+	long		line;
+	char		buf[BUF_SIZE];
+
+	ignoreCase = FALSE;
+	tellLine = FALSE;
+
+	argc--;
+	argv++;
+	if (argc < 1)
+	{
+		fprintf(stderr, "%s", grep_usage);
+		return 1;
+	}
+
+	if (**argv == '-')
+	{
+		argc--;
+		cp = *argv++;
+
+		while (*++cp) switch (*cp)
+		{
+			case 'i':
+				ignoreCase = TRUE;
+				break;
+
+			case 'n':
+				tellLine = TRUE;
+				break;
+
+			default:
+				fprintf(stderr, "Unknown option\n");
+				return 1;
+		}
+	}
+
+	word = *argv++;
+	argc--;
+
+	tellName = (argc > 1);
+
+	while (argc-- > 0)
+	{
+		name = *argv++;
+
+		fp = fopen(name, "r");
+
+		if (fp == NULL)
+		{
+			perror(name);
+
+			continue;
+		}
+
+		line = 0;
+
+		while (fgets(buf, sizeof(buf), fp))
+		{
+			line++;
+
+			cp = &buf[strlen(buf) - 1];
+
+			if (*cp != '\n')
+				fprintf(stderr, "%s: Line too long\n", name);
+
+			if (search(buf, word, ignoreCase))
+			{
+				if (tellName)
+					printf("%s: ", name);
+
+				if (tellLine)
+					printf("%ld: ", line);
+
+				fputs(buf, stdout);
+			}
+		}
+
+		if (ferror(fp))
+			perror(name);
+
+		fclose(fp);
+	}
+	return 0;
+}
+
+
+/*
+ * See if the specified word is found in the specified string.
+ */
+static BOOL
+search(const char * string, const char * word, BOOL ignoreCase)
+{
+	const char *	cp1;
+	const char *	cp2;
+	int		len;
+	int		lowFirst;
+	int		ch1;
+	int		ch2;
+
+	len = strlen(word);
+
+	if (!ignoreCase)
+	{
+		while (TRUE)
+		{
+			string = strchr(string, word[0]);
+
+			if (string == NULL)
+				return FALSE;
+
+			if (memcmp(string, word, len) == 0)
+				return TRUE;
+
+			string++;
+		}
+	}
+
+	/*
+	 * Here if we need to check case independence.
+	 * Do the search by lower casing both strings.
+	 */
+	lowFirst = *word;
+
+	if (isupper(lowFirst))
+		lowFirst = tolower(lowFirst);
+
+	while (TRUE)
+	{
+		while (*string && (*string != lowFirst) &&
+			(!isupper(*string) || (tolower(*string) != lowFirst)))
+		{
+			string++;
+		}
+
+		if (*string == '\0')
+			return FALSE;
+
+		cp1 = string;
+		cp2 = word;
+
+		do
+		{
+			if (*cp2 == '\0')
+				return TRUE;
+
+			ch1 = *cp1++;
+
+			if (isupper(ch1))
+				ch1 = tolower(ch1);
+
+			ch2 = *cp2++;
+
+			if (isupper(ch2))
+				ch2 = tolower(ch2);
+
+		}
+		while (ch1 == ch2);
+
+		string++;
+	}
+}
+
+#endif
+/* END CODE */