Print this page
3047 grep support for -r would be useful


  35 /*
  36  * grep -- print lines matching (or not matching) a pattern
  37  *
  38  *      status returns:
  39  *              0 - ok, and some matches
  40  *              1 - ok, but no matches
  41  *              2 - some error
  42  */
  43 
  44 #include <sys/types.h>
  45 
  46 #include <ctype.h>
  47 #include <fcntl.h>
  48 #include <locale.h>
  49 #include <memory.h>
  50 #include <regexpr.h>
  51 #include <stdio.h>
  52 #include <stdlib.h>
  53 #include <string.h>
  54 #include <unistd.h>



  55 
  56 static const char *errstr[] = {
  57         "Range endpoint too large.",
  58         "Bad number.",
  59         "``\\digit'' out of range.",
  60         "No remembered search string.",
  61         "\\( \\) imbalance.",
  62         "Too many \\(.",
  63         "More than 2 numbers given in \\{ \\}.",
  64         "} expected after \\.",
  65         "First number exceeds second in \\{ \\}.",
  66         "[ ] imbalance.",
  67         "Regular expression overflow.",
  68         "Illegal byte sequence.",
  69         "Unknown regexp error code!!",
  70         NULL
  71 };
  72 
  73 #define errmsg(msg, arg)        (void) fprintf(stderr, gettext(msg), arg)
  74 #define BLKSIZE 512
  75 #define GBUFSIZ 8192

  76 
  77 static int      temp;
  78 static long long        lnum;
  79 static char     *linebuf;
  80 static char     *prntbuf = NULL;
  81 static long     fw_lPrntBufLen = 0;
  82 static int      nflag;
  83 static int      bflag;
  84 static int      lflag;
  85 static int      cflag;


  86 static int      vflag;
  87 static int      sflag;
  88 static int      iflag;
  89 static int      wflag;
  90 static int      hflag;
  91 static int      qflag;
  92 static int      errflg;
  93 static int      nfile;
  94 static long long        tln;
  95 static int      nsucc;

  96 static int      nlflag;
  97 static char     *ptr, *ptrend;
  98 static char     *expbuf;
  99 
 100 static void     execute(char *);
 101 static void     regerr(int);
 102 static int      succeed(char *);


 103 
 104 int
 105 main(int argc, char **argv)
 106 {
 107         int     c;
 108         char    *arg;
 109         extern int      optind;
 110 
 111         (void) setlocale(LC_ALL, "");
 112 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 113 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 114 #endif
 115         (void) textdomain(TEXT_DOMAIN);
 116 
 117         while ((c = getopt(argc, argv, "hqblcnsviyw")) != -1)
 118                 switch (c) {
 119                 case 'h':
 120                         hflag++;
 121                         break;
 122                 case 'q':       /* POSIX: quiet: status only */
 123                         qflag++;
 124                         break;
 125                 case 'v':
 126                         vflag++;
 127                         break;
 128                 case 'c':
 129                         cflag++;
 130                         break;
 131                 case 'n':
 132                         nflag++;
 133                         break;






 134                 case 'b':
 135                         bflag++;
 136                         break;
 137                 case 's':
 138                         sflag++;
 139                         break;
 140                 case 'l':
 141                         lflag++;
 142                         break;
 143                 case 'y':
 144                 case 'i':
 145                         iflag++;
 146                         break;
 147                 case 'w':
 148                         wflag++;
 149                         break;
 150                 case '?':
 151                         errflg++;
 152                 }
 153 
 154         if (errflg || (optind >= argc)) {
 155                 errmsg("Usage: grep [-c|-l|-q] -hbnsviw pattern file . . .\n",

 156                     (char *)NULL);
 157                 exit(2);
 158         }
 159 
 160         argv = &argv[optind];
 161         argc -= optind;
 162         nfile = argc - 1;
 163 
 164         if (strrchr(*argv, '\n') != NULL)
 165                 regerr(41);
 166 
 167         if (iflag) {
 168                 for (arg = *argv; *arg != NULL; ++arg)
 169                         *arg = (char)tolower((int)((unsigned char)*arg));
 170         }
 171 
 172         if (wflag) {
 173                 unsigned int    wordlen;
 174                 char            *wordbuf;
 175 
 176                 wordlen = strlen(*argv) + 5; /* '\\' '<' *argv '\\' '>' '\0' */
 177                 if ((wordbuf = malloc(wordlen)) == NULL) {
 178                         errmsg("grep: Out of memory for word\n", (char *)NULL);
 179                         exit(2);
 180                 }
 181 
 182                 (void) strcpy(wordbuf, "\\<");
 183                 (void) strcat(wordbuf, *argv);
 184                 (void) strcat(wordbuf, "\\>");
 185                 *argv = wordbuf;
 186         }
 187 
 188         expbuf = compile(*argv, (char *)0, (char *)0);
 189         if (regerrno)
 190                 regerr(regerrno);
 191 
 192         if (--argc == 0)
 193                 execute(NULL);
 194         else
 195                 while (argc-- > 0)
 196                         execute(*++argv);
 197 
 198         return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
 199 }
 200 
 201 static void
 202 execute(char *file)
 203 {
































































 204         char    *lbuf, *p;
 205         long    count;
 206         long    offset = 0;
 207         char    *next_ptr = NULL;
 208         long    next_count = 0;
 209 
 210         tln = 0;
 211 
 212         if (prntbuf == NULL) {
 213                 fw_lPrntBufLen = GBUFSIZ + 1;
 214                 if ((prntbuf = malloc(fw_lPrntBufLen)) == NULL) {
 215                         exit(2); /* out of memory - BAIL */
 216                 }
 217                 if ((linebuf = malloc(fw_lPrntBufLen)) == NULL) {
 218                         exit(2); /* out of memory - BAIL */
 219                 }
 220         }
 221 
 222         if (file == NULL)
 223                 temp = 0;
 224         else if ((temp = open(file, O_RDONLY)) == -1) {
 225                 if (!sflag)
 226                         errmsg("grep: can't open %s\n", file);
 227                 nsucc = 2;
 228                 return;
 229         }
 230 
 231         /* read in first block of bytes */
 232         if ((count = read(temp, prntbuf, GBUFSIZ)) <= 0) {
 233                 (void) close(temp);
 234 
 235                 if (cflag && !qflag) {
 236                         if (nfile > 1 && !hflag && file)
 237                                 (void) fprintf(stdout, "%s:", file);

 238                         (void) fprintf(stdout, "%lld\n", tln);
 239                 }
 240                 return;
 241         }
 242 
 243         lnum = 0;
 244         ptr = prntbuf;
 245         for (;;) {
 246                 /* look for next newline */
 247                 if ((ptrend = memchr(ptr + offset, '\n', count)) == NULL) {
 248                         offset += count;
 249 
 250                         /*
 251                          * shift unused data to the beginning of the buffer
 252                          */
 253                         if (ptr > prntbuf) {
 254                                 (void) memmove(prntbuf, ptr, offset);
 255                                 ptr = prntbuf;
 256                         }
 257 


 312                 } else
 313                         /*
 314                          * Use record as is
 315                          */
 316                         lbuf = ptr;
 317 
 318                 /* lflag only once */
 319                 if ((step(lbuf, expbuf) ^ vflag) && succeed(file) == 1)
 320                         break;
 321 
 322                 if (!nlflag)
 323                         break;
 324 
 325                 ptr = next_ptr;
 326                 count = next_count;
 327                 offset = 0;
 328         }
 329         (void) close(temp);
 330 
 331         if (cflag && !qflag) {
 332                 if (nfile > 1 && !hflag && file)

 333                         (void) fprintf(stdout, "%s:", file);
 334                 (void) fprintf(stdout, "%lld\n", tln);
 335         }
 336 }
 337 
 338 static int
 339 succeed(char *f)
 340 {
 341         int nchars;
 342         nsucc = (nsucc == 2) ? 2 : 1;
 343 
 344         if (f == NULL)
 345                 f = "<stdin>";
 346 
 347         if (qflag) {
 348                 /* no need to continue */
 349                 return (1);
 350         }
 351 
 352         if (cflag) {
 353                 tln++;
 354                 return (0);
 355         }
 356 
 357         if (lflag) {
 358                 (void) fprintf(stdout, "%s\n", f);
 359                 return (1);
 360         }
 361 
 362         if (nfile > 1 && !hflag)
 363                 /* print filename */
 364                 (void) fprintf(stdout, "%s:", f);

 365 
 366         if (bflag)
 367                 /* print block number */
 368                 (void) fprintf(stdout, "%lld:", (offset_t)
 369                     ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));
 370 
 371         if (nflag)
 372                 /* print line number */
 373                 (void) fprintf(stdout, "%lld:", lnum);
 374 
 375         if (nlflag) {
 376                 /* newline at end of line */
 377                 *ptrend = '\n';
 378                 nchars = ptrend - ptr + 1;
 379         } else {
 380                 /* don't write sentinel \0 */
 381                 nchars = ptrend - ptr;
 382         }
 383 
 384         (void) fwrite(ptr, 1, nchars, stdout);




  35 /*
  36  * grep -- print lines matching (or not matching) a pattern
  37  *
  38  *      status returns:
  39  *              0 - ok, and some matches
  40  *              1 - ok, but no matches
  41  *              2 - some error
  42  */
  43 
  44 #include <sys/types.h>
  45 
  46 #include <ctype.h>
  47 #include <fcntl.h>
  48 #include <locale.h>
  49 #include <memory.h>
  50 #include <regexpr.h>
  51 #include <stdio.h>
  52 #include <stdlib.h>
  53 #include <string.h>
  54 #include <unistd.h>
  55 #include <ftw.h>
  56 #include <limits.h>
  57 #include <sys/param.h>
  58 
  59 static const char *errstr[] = {
  60         "Range endpoint too large.",
  61         "Bad number.",
  62         "``\\digit'' out of range.",
  63         "No remembered search string.",
  64         "\\( \\) imbalance.",
  65         "Too many \\(.",
  66         "More than 2 numbers given in \\{ \\}.",
  67         "} expected after \\.",
  68         "First number exceeds second in \\{ \\}.",
  69         "[ ] imbalance.",
  70         "Regular expression overflow.",
  71         "Illegal byte sequence.",
  72         "Unknown regexp error code!!",
  73         NULL
  74 };
  75 
  76 #define errmsg(msg, arg)        (void) fprintf(stderr, gettext(msg), arg)
  77 #define BLKSIZE 512
  78 #define GBUFSIZ 8192
  79 #define MAX_DEPTH       1000
  80 
  81 static int      temp;
  82 static long long        lnum;
  83 static char     *linebuf;
  84 static char     *prntbuf = NULL;
  85 static long     fw_lPrntBufLen = 0;
  86 static int      nflag;
  87 static int      bflag;
  88 static int      lflag;
  89 static int      cflag;
  90 static int      rflag;
  91 static int      Rflag;
  92 static int      vflag;
  93 static int      sflag;
  94 static int      iflag;
  95 static int      wflag;
  96 static int      hflag;
  97 static int      qflag;
  98 static int      errflg;
  99 static int      nfile;
 100 static long long        tln;
 101 static int      nsucc;
 102 static int      outfn = 0;
 103 static int      nlflag;
 104 static char     *ptr, *ptrend;
 105 static char     *expbuf;
 106 
 107 static void     execute(const char *, int);
 108 static void     regerr(int);
 109 static void     prepare(const char *);
 110 static int      recursive(const char *, const struct stat *, int, struct FTW *);
 111 static int      succeed(const char *);
 112 
 113 int
 114 main(int argc, char **argv)
 115 {
 116         int     c;
 117         char    *arg;
 118         extern int      optind;
 119 
 120         (void) setlocale(LC_ALL, "");
 121 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 122 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 123 #endif
 124         (void) textdomain(TEXT_DOMAIN);
 125 
 126         while ((c = getopt(argc, argv, "hqblcnRrsviyw")) != -1)
 127                 switch (c) {
 128                 case 'h':
 129                         hflag++;
 130                         break;
 131                 case 'q':       /* POSIX: quiet: status only */
 132                         qflag++;
 133                         break;
 134                 case 'v':
 135                         vflag++;
 136                         break;
 137                 case 'c':
 138                         cflag++;
 139                         break;
 140                 case 'n':
 141                         nflag++;
 142                         break;
 143                 case 'R':
 144                         Rflag++;
 145                         /* FALLTHROUGH */
 146                 case 'r':
 147                         rflag++;
 148                         break;
 149                 case 'b':
 150                         bflag++;
 151                         break;
 152                 case 's':
 153                         sflag++;
 154                         break;
 155                 case 'l':
 156                         lflag++;
 157                         break;
 158                 case 'y':
 159                 case 'i':
 160                         iflag++;
 161                         break;
 162                 case 'w':
 163                         wflag++;
 164                         break;
 165                 case '?':
 166                         errflg++;
 167                 }
 168 
 169         if (errflg || (optind >= argc)) {
 170                 errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hbnsviw "
 171                     "pattern file . . .\n",
 172                     (char *)NULL);
 173                 exit(2);
 174         }
 175 
 176         argv = &argv[optind];
 177         argc -= optind;
 178         nfile = argc - 1;
 179 
 180         if (strrchr(*argv, '\n') != NULL)
 181                 regerr(41);
 182 
 183         if (iflag) {
 184                 for (arg = *argv; *arg != NULL; ++arg)
 185                         *arg = (char)tolower((int)((unsigned char)*arg));
 186         }
 187 
 188         if (wflag) {
 189                 unsigned int    wordlen;
 190                 char            *wordbuf;
 191 
 192                 wordlen = strlen(*argv) + 5; /* '\\' '<' *argv '\\' '>' '\0' */
 193                 if ((wordbuf = malloc(wordlen)) == NULL) {
 194                         errmsg("grep: Out of memory for word\n", (char *)NULL);
 195                         exit(2);
 196                 }
 197 
 198                 (void) strcpy(wordbuf, "\\<");
 199                 (void) strcat(wordbuf, *argv);
 200                 (void) strcat(wordbuf, "\\>");
 201                 *argv = wordbuf;
 202         }
 203 
 204         expbuf = compile(*argv, (char *)0, (char *)0);
 205         if (regerrno)
 206                 regerr(regerrno);
 207 
 208         if (--argc == 0)
 209                 execute(NULL, 0);
 210         else
 211                 while (argc-- > 0)
 212                         prepare(*++argv);
 213 
 214         return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
 215 }
 216 
 217 static void
 218 prepare(const char *path)
 219 {
 220         struct  stat st;
 221         int     walkflags = FTW_CHDIR;
 222         char    *buf = NULL;
 223 
 224         if (rflag) {
 225                 if (stat(path, &st) != -1 &&
 226                     (st.st_mode & S_IFMT) == S_IFDIR) {
 227                         outfn = 1;
 228 
 229                         /*
 230                          * Add trailing slash if arg
 231                          * is directory, to resolve symlinks.
 232                          */
 233                         if (path[strlen(path) - 1] != '/') {
 234                                 (void) asprintf(&buf, "%s/", path);
 235                                 if (buf != NULL)
 236                                         path = buf;
 237                         }
 238 
 239                         /*
 240                          * Search through subdirs if path is directory.
 241                          * Don't follow symlinks if Rflag is not set.
 242                          */
 243                         if (!Rflag)
 244                                 walkflags |= FTW_PHYS;
 245 
 246                         if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) {
 247                                 if (!sflag)
 248                                         errmsg("grep: can't open %s\n", path);
 249                                 nsucc = 2;
 250                         }
 251                         return;
 252                 }
 253         }
 254         execute(path, 0);
 255 }
 256 
 257 static int
 258 recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw)
 259 {
 260         /*
 261          * process files and follow symlinks if Rflag set.
 262          */
 263         if (info != FTW_F) {
 264                 if (!sflag &&
 265                     (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) {
 266                         /* report broken symlinks and unreadable files */
 267                         errmsg("grep: can't open %s\n", name);
 268                 }
 269                 return (0);
 270         }
 271 
 272         /* skip devices and pipes if Rflag is not set */
 273         if (!Rflag && !S_ISREG(statp->st_mode))
 274                 return (0);
 275 
 276         /* pass offset to relative name from FTW_CHDIR */
 277         execute(name, ftw->base);
 278         return (0);
 279 }
 280 
 281 static void
 282 execute(const char *file, int base)
 283 {
 284         char    *lbuf, *p;
 285         long    count;
 286         long    offset = 0;
 287         char    *next_ptr = NULL;
 288         long    next_count = 0;
 289 
 290         tln = 0;
 291 
 292         if (prntbuf == NULL) {
 293                 fw_lPrntBufLen = GBUFSIZ + 1;
 294                 if ((prntbuf = malloc(fw_lPrntBufLen)) == NULL) {
 295                         exit(2); /* out of memory - BAIL */
 296                 }
 297                 if ((linebuf = malloc(fw_lPrntBufLen)) == NULL) {
 298                         exit(2); /* out of memory - BAIL */
 299                 }
 300         }
 301 
 302         if (file == NULL)
 303                 temp = 0;
 304         else if ((temp = open(file + base, O_RDONLY)) == -1) {
 305                 if (!sflag)
 306                         errmsg("grep: can't open %s\n", file);
 307                 nsucc = 2;
 308                 return;
 309         }
 310 
 311         /* read in first block of bytes */
 312         if ((count = read(temp, prntbuf, GBUFSIZ)) <= 0) {
 313                 (void) close(temp);
 314 
 315                 if (cflag && !qflag) {
 316                         if (nfile > 1 && !hflag && file)
 317                                 (void) fprintf(stdout, "%s:", file);
 318                         if (!rflag)
 319                         (void) fprintf(stdout, "%lld\n", tln);
 320                 }
 321                 return;
 322         }
 323 
 324         lnum = 0;
 325         ptr = prntbuf;
 326         for (;;) {
 327                 /* look for next newline */
 328                 if ((ptrend = memchr(ptr + offset, '\n', count)) == NULL) {
 329                         offset += count;
 330 
 331                         /*
 332                          * shift unused data to the beginning of the buffer
 333                          */
 334                         if (ptr > prntbuf) {
 335                                 (void) memmove(prntbuf, ptr, offset);
 336                                 ptr = prntbuf;
 337                         }
 338 


 393                 } else
 394                         /*
 395                          * Use record as is
 396                          */
 397                         lbuf = ptr;
 398 
 399                 /* lflag only once */
 400                 if ((step(lbuf, expbuf) ^ vflag) && succeed(file) == 1)
 401                         break;
 402 
 403                 if (!nlflag)
 404                         break;
 405 
 406                 ptr = next_ptr;
 407                 count = next_count;
 408                 offset = 0;
 409         }
 410         (void) close(temp);
 411 
 412         if (cflag && !qflag) {
 413                 if (!hflag && file && (nfile > 1 ||
 414                     (rflag && outfn)))
 415                         (void) fprintf(stdout, "%s:", file);
 416                 (void) fprintf(stdout, "%lld\n", tln);
 417         }
 418 }
 419 
 420 static int
 421 succeed(const char *f)
 422 {
 423         int nchars;
 424         nsucc = (nsucc == 2) ? 2 : 1;
 425 
 426         if (f == NULL)
 427                 f = "<stdin>";
 428 
 429         if (qflag) {
 430                 /* no need to continue */
 431                 return (1);
 432         }
 433 
 434         if (cflag) {
 435                 tln++;
 436                 return (0);
 437         }
 438 
 439         if (lflag) {
 440                 (void) fprintf(stdout, "%s\n", f);
 441                 return (1);
 442         }
 443 
 444         if (!hflag && (nfile > 1 || (rflag && outfn))) {
 445                 /* print filename */
 446                 (void) fprintf(stdout, "%s:", f);
 447         }
 448 
 449         if (bflag)
 450                 /* print block number */
 451                 (void) fprintf(stdout, "%lld:", (offset_t)
 452                     ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));
 453 
 454         if (nflag)
 455                 /* print line number */
 456                 (void) fprintf(stdout, "%lld:", lnum);
 457 
 458         if (nlflag) {
 459                 /* newline at end of line */
 460                 *ptrend = '\n';
 461                 nchars = ptrend - ptr + 1;
 462         } else {
 463                 /* don't write sentinel \0 */
 464                 nchars = ptrend - ptr;
 465         }
 466 
 467         (void) fwrite(ptr, 1, nchars, stdout);