--- old/usr/src/cmd/grep/grep.c	Mon Sep 17 14:32:32 2012
+++ new/usr/src/cmd/grep/grep.c	Mon Sep 17 14:32:32 2012
@@ -52,6 +52,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <ftw.h>
+#include <limits.h>
+#include <sys/param.h>
 
 static const char *errstr[] = {
 	"Range endpoint too large.",
@@ -73,6 +76,7 @@
 #define	errmsg(msg, arg)	(void) fprintf(stderr, gettext(msg), arg)
 #define	BLKSIZE	512
 #define	GBUFSIZ	8192
+#define	MAX_DEPTH	1000
 
 static int	temp;
 static long long	lnum;
@@ -83,6 +87,8 @@
 static int	bflag;
 static int	lflag;
 static int	cflag;
+static int	rflag;
+static int	Rflag;
 static int	vflag;
 static int	sflag;
 static int	iflag;
@@ -93,13 +99,16 @@
 static int	nfile;
 static long long	tln;
 static int	nsucc;
+static int	outfn = 0;
 static int	nlflag;
 static char	*ptr, *ptrend;
 static char	*expbuf;
 
-static void	execute(char *);
+static void	execute(const char *, int);
 static void	regerr(int);
-static int	succeed(char *);
+static void	prepare(const char *);
+static int	recursive(const char *, const struct stat *, int, struct FTW *);
+static int	succeed(const char *);
 
 int
 main(int argc, char **argv)
@@ -114,7 +123,7 @@
 #endif
 	(void) textdomain(TEXT_DOMAIN);
 
-	while ((c = getopt(argc, argv, "hqblcnsviyw")) != -1)
+	while ((c = getopt(argc, argv, "hqblcnRrsviyw")) != -1)
 		switch (c) {
 		case 'h':
 			hflag++;
@@ -131,6 +140,12 @@
 		case 'n':
 			nflag++;
 			break;
+		case 'R':
+			Rflag++;
+			/* FALLTHROUGH */
+		case 'r':
+			rflag++;
+			break;
 		case 'b':
 			bflag++;
 			break;
@@ -152,7 +167,8 @@
 		}
 
 	if (errflg || (optind >= argc)) {
-		errmsg("Usage: grep [-c|-l|-q] -hbnsviw pattern file . . .\n",
+		errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hbnsviw "
+		    "pattern file . . .\n",
 		    (char *)NULL);
 		exit(2);
 	}
@@ -190,17 +206,81 @@
 		regerr(regerrno);
 
 	if (--argc == 0)
-		execute(NULL);
+		execute(NULL, 0);
 	else
 		while (argc-- > 0)
-			execute(*++argv);
+			prepare(*++argv);
 
 	return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
 }
 
 static void
-execute(char *file)
+prepare(const char *path)
 {
+	struct	stat st;
+	int	walkflags = FTW_CHDIR;
+	char	*buf = NULL;
+
+	if (rflag) {
+		if (stat(path, &st) != -1 &&
+		    (st.st_mode & S_IFMT) == S_IFDIR) {
+			outfn = 1;
+
+			/*
+			 * Add trailing slash if arg
+			 * is directory, to resolve symlinks.
+			 */
+			if (path[strlen(path) - 1] != '/') {
+				(void) asprintf(&buf, "%s/", path);
+				if (buf != NULL)
+					path = buf;
+			}
+
+			/*
+			 * Search through subdirs if path is directory.
+			 * Don't follow symlinks if Rflag is not set.
+			 */
+			if (!Rflag)
+				walkflags |= FTW_PHYS;
+
+			if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) {
+				if (!sflag)
+					errmsg("grep: can't open %s\n", path);
+				nsucc = 2;
+			}
+			return;
+		}
+	}
+	execute(path, 0);
+}
+
+static int
+recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw)
+{
+	/*
+	 * process files and follow symlinks if Rflag set.
+	 */
+	if (info != FTW_F) {
+		if (!sflag &&
+		    (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) {
+			/* report broken symlinks and unreadable files */
+			errmsg("grep: can't open %s\n", name);
+		}
+		return (0);
+	}
+
+	/* skip devices and pipes if Rflag is not set */
+	if (!Rflag && !S_ISREG(statp->st_mode))
+		return (0);
+
+	/* pass offset to relative name from FTW_CHDIR */
+	execute(name, ftw->base);
+	return (0);
+}
+
+static void
+execute(const char *file, int base)
+{
 	char	*lbuf, *p;
 	long	count;
 	long	offset = 0;
@@ -221,7 +301,7 @@
 
 	if (file == NULL)
 		temp = 0;
-	else if ((temp = open(file, O_RDONLY)) == -1) {
+	else if ((temp = open(file + base, O_RDONLY)) == -1) {
 		if (!sflag)
 			errmsg("grep: can't open %s\n", file);
 		nsucc = 2;
@@ -235,6 +315,7 @@
 		if (cflag && !qflag) {
 			if (nfile > 1 && !hflag && file)
 				(void) fprintf(stdout, "%s:", file);
+			if (!rflag)
 			(void) fprintf(stdout, "%lld\n", tln);
 		}
 		return;
@@ -329,7 +410,8 @@
 	(void) close(temp);
 
 	if (cflag && !qflag) {
-		if (nfile > 1 && !hflag && file)
+		if (!hflag && file && (nfile > 1 ||
+		    (rflag && outfn)))
 			(void) fprintf(stdout, "%s:", file);
 		(void) fprintf(stdout, "%lld\n", tln);
 	}
@@ -336,7 +418,7 @@
 }
 
 static int
-succeed(char *f)
+succeed(const char *f)
 {
 	int nchars;
 	nsucc = (nsucc == 2) ? 2 : 1;
@@ -359,9 +441,10 @@
 		return (1);
 	}
 
-	if (nfile > 1 && !hflag)
+	if (!hflag && (nfile > 1 || (rflag && outfn))) {
 		/* print filename */
 		(void) fprintf(stdout, "%s:", f);
+	}
 
 	if (bflag)
 		/* print block number */
