grep.c revision 205b496e42ceb72bf0755fec4f4675a467c401e1
1e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake/* grep.c - print lines what match given regular expression
2e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake *
3e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake * Copyright 2013 CE Strake <strake888 at gmail.com>
4e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake *
5dad378bb17f1910014383bf196e87028e98d81d6Rob Landley * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
6e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
7fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob LandleyUSE_GREP(NEWTOY(grep, "EFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN))
8dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob LandleyUSE_GREP(OLDTOY(egrep, grep, OPTSTR_grep, TOYFLAG_BIN))
9dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob LandleyUSE_GREP(OLDTOY(fgrep, grep, OPTSTR_grep, TOYFLAG_BIN))
10e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
11e999ca008416e3d41c1079bcb4d151b43c95dc3aStrakeconfig GREP
12e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake  bool "grep"
13205b496e42ceb72bf0755fec4f4675a467c401e1Rob Landley  default y
14e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake  help
15dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    usage: grep [-EFivwcloqsHbhn] [-m MAX] [-e REGEX]... [-f REGFILE] [FILE]...
16f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley
17f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    Show lines matching regular expressions. If no -e, first argument is
18f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    regular expression to match. With no files (or "-" filename) read stdin.
19f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    Returns 0 if matched, 1 if no match found.
20f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley
21f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -e  Regex to match. (May be repeated.)
22f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -f  File containing regular expressions to match.
23f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley
24f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    match type:
25f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -E  extended regex syntax    -F  fixed (match literal string)
26fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    -i  case insensitive         -m  stop after this many lines matched
27fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    -r  recursive (on dir)       -v  invert match
28fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    -w  whole word (implies -E)  -x  whole line
29f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley
30f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    display modes: (default: matched line)
31f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -c  count of matching lines  -l  show matching filenames
32f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -o  only matching part       -q  quiet (errors only)
33f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -s  silent (no error msg)
34f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley
35f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    prefix modes (default: filename if checking more than 1 file)
36f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -H  force filename           -b  byte offset of match
37f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    -h  hide filename            -n  line number of match
38e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake*/
39e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
40e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#define FOR_grep
41e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#include "toys.h"
42e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#include <regex.h>
43e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
44e999ca008416e3d41c1079bcb4d151b43c95dc3aStrakeGLOBALS(
45dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  long m;
46dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  struct arg_list *f;
47dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  struct arg_list *e;
48dad378bb17f1910014383bf196e87028e98d81d6Rob Landley
49fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  struct arg_list *regex;
50e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake)
51e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
52f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landleystatic void do_grep(int fd, char *name)
53f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{
54dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  FILE *file = fdopen(fd, "r");
55dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  long offset = 0;
56dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  int lcount = 0, mcount = 0, which = toys.optflags & FLAG_w ? 2 : 0;
57e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
5831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley  if (!fd) name = "(standard input)";
5931f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley
60dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  if (!file) {
61dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    perror_msg("%s", name);
62dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    return;
63dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  }
64dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
65e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake  for (;;) {
66dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    char *line = 0, *start;
677b7b284ce4c1bd53d442927d9a570fcf84e0187cStrake    regmatch_t matches[3];
68dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    size_t unused;
69dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    long len;
70030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley    int mmatch = 0;
71e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
72dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    lcount++;
73dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (0 > (len = getline(&line, &unused, file))) break;
74dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (line[len-1] == '\n') line[len-1] = 0;
75dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
76dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    start = line;
77e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
78dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    for (;;)
79f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley    {
80dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      int rc = 0, skip = 0;
81dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
82dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      if (toys.optflags & FLAG_F) {
83fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley        struct arg_list *seek, fseek;
84dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        char *s = 0;
85dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
86dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        for (seek = TT.e; seek; seek = seek->next) {
87fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley          if (!*seek->arg) {
88fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley            seek = &fseek;
89fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley            fseek.arg = s = line;
90fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley            break;
91fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley          }
92dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley          if (toys.optflags & FLAG_i) {
93dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley            long ll = strlen(seek->arg);;
94dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
95dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley            // Alas, posix hasn't got strcasestr()
96dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley            for (s = line; *s; s++) if (!strncasecmp(s, seek->arg, ll)) break;
97dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley            if (!*s) s = 0;
98dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley          } else s = strstr(line, seek->arg);
99dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley          if (s) break;
100dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        }
101dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
102dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        if (s) {
103dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley          matches[which].rm_so = (s-line);
104dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley          skip = matches[which].rm_eo = (s-line)+strlen(seek->arg);
105dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        } else rc = 1;
106dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      } else {
107dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        rc = regexec((regex_t *)toybuf, start, 3, matches,
108dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley                     start==line ? 0 : REG_NOTBOL);
109dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        skip = matches[which].rm_eo;
110dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      }
111dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
112dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      if (toys.optflags & FLAG_x)
113dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley        if (matches[which].rm_so || line[matches[which].rm_eo]) rc = 1;
114dad378bb17f1910014383bf196e87028e98d81d6Rob Landley
115dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      if (toys.optflags & FLAG_v) {
116dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        if (toys.optflags & FLAG_o) {
117dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          if (rc) skip = matches[which].rm_eo = strlen(start);
118dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          else if (!matches[which].rm_so) {
119dad378bb17f1910014383bf196e87028e98d81d6Rob Landley            start += skip;
120dad378bb17f1910014383bf196e87028e98d81d6Rob Landley            continue;
121dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          } else matches[which].rm_eo = matches[which].rm_so;
122dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        } else {
123dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          if (!rc) break;
124dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          matches[which].rm_eo = strlen(start);
125dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        }
126dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        matches[which].rm_so = 0;
127dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      } else if (rc) break;
128dad378bb17f1910014383bf196e87028e98d81d6Rob Landley
129030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley      mmatch++;
130dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      if (toys.optflags & FLAG_q) {
131dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        toys.exitval = 0;
132f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley        xexit();
133dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      }
134dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      if (toys.optflags & FLAG_l) {
135dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        printf("%s\n", name);
136dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        free(line);
137dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        fclose(file);
138e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake        return;
139dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      }
140fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley      if (toys.optflags & FLAG_o)
141fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley        if (matches[which].rm_eo == matches[which].rm_so)
142fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley          break;
143fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
144dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      if (!(toys.optflags & FLAG_c)) {
145fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley        if (toys.optflags & FLAG_H) printf("%s:", name);
146dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        if (toys.optflags & FLAG_n) printf("%d:", lcount);
147dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        if (toys.optflags & FLAG_b)
148dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          printf("%ld:", offset + (start-line) +
149dad378bb17f1910014383bf196e87028e98d81d6Rob Landley              ((toys.optflags & FLAG_o) ? matches[which].rm_so : 0));
150dad378bb17f1910014383bf196e87028e98d81d6Rob Landley        if (!(toys.optflags & FLAG_o)) xputs(line);
151e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake        else {
152dad378bb17f1910014383bf196e87028e98d81d6Rob Landley          xprintf("%.*s\n", matches[which].rm_eo - matches[which].rm_so,
153dad378bb17f1910014383bf196e87028e98d81d6Rob Landley                  start + matches[which].rm_so);
154e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake        }
155e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake      }
156dad378bb17f1910014383bf196e87028e98d81d6Rob Landley
157dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      start += skip;
158dad378bb17f1910014383bf196e87028e98d81d6Rob Landley      if (!(toys.optflags & FLAG_o) || !*start) break;
159e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake    }
160dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    offset += len;
161e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
162dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    free(line);
163dad378bb17f1910014383bf196e87028e98d81d6Rob Landley
164030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley    if (mmatch) mcount++;
165dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    if ((toys.optflags & FLAG_m) && mcount >= TT.m) break;
166dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  }
167e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
168dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  if (toys.optflags & FLAG_c) {
169fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    if (toys.optflags & FLAG_H) printf("%s:", name);
170dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    xprintf("%d\n", mcount);
171e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake  }
172e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
173dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  // loopfiles will also close the fd, but this frees an (opaque) struct.
174dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  fclose(file);
175e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake}
176e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
177dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landleystatic void parse_regex(void)
178f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{
17931f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley  struct arg_list *al, *new, *list = NULL;
180dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  long len = 0;
181dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  char *s, *ss;
182dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
183dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  // Add all -f lines to -e list. (Yes, this is leaking allocation context for
184dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  // exit to free. Not supporting nofork for this command any time soon.)
18531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley  al = TT.f ? TT.f : TT.e;
18631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley  while (al) {
18731f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    if (TT.f) s = ss = xreadfile(al->arg);
18831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    else s = ss = al->arg;
189dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
190fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    do {
191dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      ss = strchr(s, '\n');
19231f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      if (ss) *(ss++) = 0;
19331f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      new = xmalloc(sizeof(struct arg_list));
19431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      new->next = list;
19531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      new->arg = s;
19631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      list = new;
197dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      s = ss;
198fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    } while (ss && *s);
19931f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    al = al->next;
20031f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    if (!al && TT.f) {
20131f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      TT.f = 0;
20231f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      al = TT.e;
20331f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    }
204e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake  }
20531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley  TT.e = list;
206f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley
207dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  if (!(toys.optflags & FLAG_F)) {
208dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    int w = toys.optflags & FLAG_w;
209fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    char *regstr;
210e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
21131f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    // Convert strings to one big regex
212dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (w) len = 36;
21331f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    for (al = TT.e; al; al = al->next) len += strlen(al->arg)+1;
214e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
215fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    regstr = s = xmalloc(len);
216dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (w) s = stpcpy(s, "(^|[^_[:alnum:]])(");
217dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    for (al = TT.e; al; al = al->next) {
218dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      s = stpcpy(s, al->arg);
21931f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley      if (!(toys.optflags & FLAG_E)) *(s++) = '\\';
220dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      *(s++) = '|';
221e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake    }
22231f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley    *(s-=(1+!(toys.optflags & FLAG_E))) = 0;
223dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (w) strcpy(s, ")($|[^_[:alnum:]])");
224e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
225fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    w = regcomp((regex_t *)toybuf, regstr,
226dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley                ((toys.optflags & FLAG_E) ? REG_EXTENDED : 0) |
227dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley                ((toys.optflags & FLAG_i) ? REG_ICASE    : 0));
2287b7b284ce4c1bd53d442927d9a570fcf84e0187cStrake
229dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (w) {
230dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      regerror(w, (regex_t *)toybuf, toybuf+sizeof(regex_t),
231dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley               sizeof(toybuf)-sizeof(regex_t));
232dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley      error_exit("bad REGEX: %s", toybuf);
233dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    }
234e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake  }
235e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake}
236e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
237fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landleystatic int do_grep_r(struct dirtree *new)
238fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley{
239fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  char *name;
240fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
241fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  if (new->parent && !dirtree_notdotdot(new)) return 0;
242fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  if (S_ISDIR(new->st.st_mode)) return DIRTREE_RECURSE;
243fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
244fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  // "grep -r onefile" doesn't show filenames, but "grep -r onedir" should.
245fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  if (new->parent && !(toys.optflags & FLAG_h)) toys.optflags |= FLAG_H;
246fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
247fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  name = dirtree_path(new, 0);
248fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  do_grep(openat(dirtree_parentfd(new), new->name, 0), name);
249fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  free(name);
250fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
251fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  return 0;
252fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley}
253fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
254f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landleyvoid grep_main(void)
255f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{
256fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  char **ss;
257fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
258dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  // Handle egrep and fgrep
259dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  if (*toys.which->name == 'e' || (toys.optflags & FLAG_w))
260dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    toys.optflags |= FLAG_E;
261dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  if (*toys.which->name == 'f') toys.optflags |= FLAG_F;
2621fa68247345fa6e2cefe4fb4d88ef75f614b18c4M. Farkas-Dyck
263dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  if (!TT.e && !TT.f) {
264dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    if (!*toys.optargs) error_exit("no REGEX");
265dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    TT.e = xzalloc(sizeof(struct arg_list));
266dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    TT.e->arg = *(toys.optargs++);
267dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley    toys.optc--;
268dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  }
269dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley
270dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley  parse_regex();
271e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
272fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  if (!(toys.optflags & FLAG_h) && toys.optc>1) toys.optflags |= FLAG_H;
273e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake
274174ba2bed2f33fe90926b08a3e9ec4e3ce7febabStrake  toys.exitval = 1;
275dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  if (toys.optflags & FLAG_s) {
276dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    close(2);
277dad378bb17f1910014383bf196e87028e98d81d6Rob Landley    xopen("/dev/null", O_RDWR);
278dad378bb17f1910014383bf196e87028e98d81d6Rob Landley  }
279fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley
280fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  if (toys.optflags & FLAG_r) {
281fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    for (ss=toys.optargs; *ss; ss++) {
282fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley      if (!strcmp(*ss, "-")) do_grep(0, *ss);
283fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley      else dirtree_read(*ss, do_grep_r);
284fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley    }
285fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley  } else loopfiles_rw(toys.optargs, O_RDONLY, 0, 1, do_grep);
286e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake}
287