grep.c revision adcbaf530f3ec351ec2932ebe9b77140f79eda4a
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 76c64f5f186d26d4c95d408979d33831935e026f1Rob LandleyUSE_GREP(NEWTOY(grep, "ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN)) 8c49b9a97559d2009e9076e063b2e9acbc13fb9efRob LandleyUSE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN)) 9c49b9a97559d2009e9076e063b2e9acbc13fb9efRob LandleyUSE_FGREP(OLDTOY(fgrep, 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 29d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley -z input NUL terminated 30f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 31f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley display modes: (default: matched line) 32f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -c count of matching lines -l show matching filenames 33f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -o only matching part -q quiet (errors only) 34d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley -s silent (no error msg) -Z output NUL terminated 35f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 36d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley output prefix (default: filename if checking more than 1 file) 37f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -H force filename -b byte offset of match 38f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -h hide filename -n line number of match 39c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley 40c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landleyconfig EGREP 41c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley bool 42c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley default y 43c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley depends on GREP 44c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley 45c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landleyconfig FGREP 46c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley bool 47c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley default y 48c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley depends on GREP 49e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake*/ 50e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 51e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#define FOR_grep 52e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#include "toys.h" 53e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#include <regex.h> 54e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 55e999ca008416e3d41c1079bcb4d151b43c95dc3aStrakeGLOBALS( 56dad378bb17f1910014383bf196e87028e98d81d6Rob Landley long m; 57dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley struct arg_list *f; 58dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley struct arg_list *e; 59dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 60fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley struct arg_list *regex; 61e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake) 62e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 63f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landleystatic void do_grep(int fd, char *name) 64f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{ 65dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley FILE *file = fdopen(fd, "r"); 66dad378bb17f1910014383bf196e87028e98d81d6Rob Landley long offset = 0; 676c64f5f186d26d4c95d408979d33831935e026f1Rob Landley int lcount = 0, mcount = 0, which = toys.optflags & FLAG_w ? 2 : 0; 68d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley char indelim = '\n' * !(toys.optflags&FLAG_z), 69d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley outdelim = '\n' * !(toys.optflags&FLAG_Z); 70e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 7131f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (!fd) name = "(standard input)"; 7231f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley 73dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!file) { 74dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley perror_msg("%s", name); 75dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley return; 76dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 77dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 78e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake for (;;) { 796c64f5f186d26d4c95d408979d33831935e026f1Rob Landley char *line = 0, *start; 807b7b284ce4c1bd53d442927d9a570fcf84e0187cStrake regmatch_t matches[3]; 81dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley size_t unused; 82dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley long len; 83030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley int mmatch = 0; 84e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 85dad378bb17f1910014383bf196e87028e98d81d6Rob Landley lcount++; 86d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley if (0 > (len = getdelim(&line, &unused, indelim, file))) break; 87d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley if (line[len-1] == indelim) line[len-1] = 0; 88dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 89dad378bb17f1910014383bf196e87028e98d81d6Rob Landley start = line; 90e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 916c64f5f186d26d4c95d408979d33831935e026f1Rob Landley for (;;) 926c64f5f186d26d4c95d408979d33831935e026f1Rob Landley { 93dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley int rc = 0, skip = 0; 94dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 95dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (toys.optflags & FLAG_F) { 96fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley struct arg_list *seek, fseek; 97dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley char *s = 0; 98dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 99dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley for (seek = TT.e; seek; seek = seek->next) { 100e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley if (toys.optflags & FLAG_x) { 101e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley int i = (toys.optflags & FLAG_i); 102e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley 103e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley if ((i ? strcasecmp : strcmp)(seek->arg, line)) s = line; 104e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley } else if (!*seek->arg) { 105fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley seek = &fseek; 106fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley fseek.arg = s = line; 107fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley break; 108fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } 109dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (toys.optflags & FLAG_i) { 110dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley long ll = strlen(seek->arg);; 111dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 112dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley // Alas, posix hasn't got strcasestr() 113dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley for (s = line; *s; s++) if (!strncasecmp(s, seek->arg, ll)) break; 114dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!*s) s = 0; 115dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else s = strstr(line, seek->arg); 116dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (s) break; 117dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 118dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 119dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (s) { 120dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley matches[which].rm_so = (s-line); 121dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley skip = matches[which].rm_eo = (s-line)+strlen(seek->arg); 122dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else rc = 1; 123dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else { 124dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley rc = regexec((regex_t *)toybuf, start, 3, matches, 125dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley start==line ? 0 : REG_NOTBOL); 126dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley skip = matches[which].rm_eo; 127dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 128dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 129dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (toys.optflags & FLAG_x) 130dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (matches[which].rm_so || line[matches[which].rm_eo]) rc = 1; 131dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 132dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_v) { 133dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_o) { 134dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (rc) skip = matches[which].rm_eo = strlen(start); 135dad378bb17f1910014383bf196e87028e98d81d6Rob Landley else if (!matches[which].rm_so) { 136dad378bb17f1910014383bf196e87028e98d81d6Rob Landley start += skip; 137dad378bb17f1910014383bf196e87028e98d81d6Rob Landley continue; 138dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } else matches[which].rm_eo = matches[which].rm_so; 139dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } else { 140dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (!rc) break; 141dad378bb17f1910014383bf196e87028e98d81d6Rob Landley matches[which].rm_eo = strlen(start); 142dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 143dad378bb17f1910014383bf196e87028e98d81d6Rob Landley matches[which].rm_so = 0; 144dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else if (rc) break; 1456c64f5f186d26d4c95d408979d33831935e026f1Rob Landley 146030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley mmatch++; 147e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley toys.exitval = 0; 148e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley if (toys.optflags & FLAG_q) xexit(); 149dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_l) { 150d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley printf("%s%c", name, outdelim); 1516c64f5f186d26d4c95d408979d33831935e026f1Rob Landley free(line); 1526c64f5f186d26d4c95d408979d33831935e026f1Rob Landley fclose(file); 1536c64f5f186d26d4c95d408979d33831935e026f1Rob Landley return; 154dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 155fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (toys.optflags & FLAG_o) 156fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (matches[which].rm_eo == matches[which].rm_so) 157fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley break; 158fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 1596c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (!(toys.optflags & FLAG_c)) { 1606c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_H) printf("%s:", name); 1616c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_n) printf("%d:", lcount); 1626c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_b) 1636c64f5f186d26d4c95d408979d33831935e026f1Rob Landley printf("%ld:", offset + (start-line) + 1646c64f5f186d26d4c95d408979d33831935e026f1Rob Landley ((toys.optflags & FLAG_o) ? matches[which].rm_so : 0)); 1656c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (!(toys.optflags & FLAG_o)) xprintf("%s%c", line, outdelim); 166e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake else { 1676c64f5f186d26d4c95d408979d33831935e026f1Rob Landley xprintf("%.*s%c", matches[which].rm_eo - matches[which].rm_so, 1686c64f5f186d26d4c95d408979d33831935e026f1Rob Landley start + matches[which].rm_so, outdelim); 169e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 170e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 171dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 172dad378bb17f1910014383bf196e87028e98d81d6Rob Landley start += skip; 173dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (!(toys.optflags & FLAG_o) || !*start) break; 174e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 175dad378bb17f1910014383bf196e87028e98d81d6Rob Landley offset += len; 1766c64f5f186d26d4c95d408979d33831935e026f1Rob Landley 177dad378bb17f1910014383bf196e87028e98d81d6Rob Landley free(line); 178dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 179030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley if (mmatch) mcount++; 180dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if ((toys.optflags & FLAG_m) && mcount >= TT.m) break; 181dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 182e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 183dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_c) { 184fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (toys.optflags & FLAG_H) printf("%s:", name); 185d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley xprintf("%d%c", mcount, outdelim); 186e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 187e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 188dad378bb17f1910014383bf196e87028e98d81d6Rob Landley // loopfiles will also close the fd, but this frees an (opaque) struct. 189dad378bb17f1910014383bf196e87028e98d81d6Rob Landley fclose(file); 190e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake} 191e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 192dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landleystatic void parse_regex(void) 193f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{ 19431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley struct arg_list *al, *new, *list = NULL; 195dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley long len = 0; 196dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley char *s, *ss; 197dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 198dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley // Add all -f lines to -e list. (Yes, this is leaking allocation context for 199dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley // exit to free. Not supporting nofork for this command any time soon.) 20031f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley al = TT.f ? TT.f : TT.e; 20131f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley while (al) { 202dc3731783ead154d5a0d8d318566468474b43013Rob Landley if (TT.f) s = ss = xreadfile(al->arg, 0, 0); 20331f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley else s = ss = al->arg; 204dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 205fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley do { 206dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley ss = strchr(s, '\n'); 20731f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (ss) *(ss++) = 0; 20831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley new = xmalloc(sizeof(struct arg_list)); 20931f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley new->next = list; 21031f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley new->arg = s; 21131f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley list = new; 212dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley s = ss; 213fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } while (ss && *s); 21431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley al = al->next; 21531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (!al && TT.f) { 21631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley TT.f = 0; 21731f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley al = TT.e; 21831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley } 219e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 22031f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley TT.e = list; 221f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 222dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!(toys.optflags & FLAG_F)) { 223dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley int w = toys.optflags & FLAG_w; 224fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley char *regstr; 225e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 22631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley // Convert strings to one big regex 227dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (w) len = 36; 2283ad73e1344afa7812671d08456591b8cde952775William Haddon for (al = TT.e; al; al = al->next) 2293ad73e1344afa7812671d08456591b8cde952775William Haddon len += strlen(al->arg)+1+!(toys.optflags & FLAG_E); 230e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 231fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley regstr = s = xmalloc(len); 232dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (w) s = stpcpy(s, "(^|[^_[:alnum:]])("); 233dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley for (al = TT.e; al; al = al->next) { 234dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley s = stpcpy(s, al->arg); 23531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (!(toys.optflags & FLAG_E)) *(s++) = '\\'; 236dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley *(s++) = '|'; 237e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 23831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley *(s-=(1+!(toys.optflags & FLAG_E))) = 0; 239dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (w) strcpy(s, ")($|[^_[:alnum:]])"); 240e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 241fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley w = regcomp((regex_t *)toybuf, regstr, 242dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley ((toys.optflags & FLAG_E) ? REG_EXTENDED : 0) | 243dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley ((toys.optflags & FLAG_i) ? REG_ICASE : 0)); 2447b7b284ce4c1bd53d442927d9a570fcf84e0187cStrake 245dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (w) { 246dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley regerror(w, (regex_t *)toybuf, toybuf+sizeof(regex_t), 247dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley sizeof(toybuf)-sizeof(regex_t)); 248dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley error_exit("bad REGEX: %s", toybuf); 249dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 250e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 251e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake} 252e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 253fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landleystatic int do_grep_r(struct dirtree *new) 254fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley{ 255fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley char *name; 256fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 257fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (new->parent && !dirtree_notdotdot(new)) return 0; 258fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (S_ISDIR(new->st.st_mode)) return DIRTREE_RECURSE; 259fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 260fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley // "grep -r onefile" doesn't show filenames, but "grep -r onedir" should. 261fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (new->parent && !(toys.optflags & FLAG_h)) toys.optflags |= FLAG_H; 262fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 263fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley name = dirtree_path(new, 0); 264fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley do_grep(openat(dirtree_parentfd(new), new->name, 0), name); 265fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley free(name); 266fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 267fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley return 0; 268fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley} 269fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 270f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landleyvoid grep_main(void) 271f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{ 272adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley char **ss = toys.optargs; 273fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 274dad378bb17f1910014383bf196e87028e98d81d6Rob Landley // Handle egrep and fgrep 275dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (*toys.which->name == 'e' || (toys.optflags & FLAG_w)) 276dad378bb17f1910014383bf196e87028e98d81d6Rob Landley toys.optflags |= FLAG_E; 277dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (*toys.which->name == 'f') toys.optflags |= FLAG_F; 2781fa68247345fa6e2cefe4fb4d88ef75f614b18c4M. Farkas-Dyck 279dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!TT.e && !TT.f) { 280adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley if (!*ss) error_exit("no REGEX"); 281dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley TT.e = xzalloc(sizeof(struct arg_list)); 282adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley TT.e->arg = *(ss++); 283dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley toys.optc--; 284dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 285dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 286dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley parse_regex(); 287e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 288fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (!(toys.optflags & FLAG_h) && toys.optc>1) toys.optflags |= FLAG_H; 289e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 290174ba2bed2f33fe90926b08a3e9ec4e3ce7febabStrake toys.exitval = 1; 291dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_s) { 292dad378bb17f1910014383bf196e87028e98d81d6Rob Landley close(2); 293dad378bb17f1910014383bf196e87028e98d81d6Rob Landley xopen("/dev/null", O_RDWR); 294dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 295fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 296fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (toys.optflags & FLAG_r) { 297adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley for (ss = *ss ? ss : (char *[]){".", 0}; *ss; ss++) { 298fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (!strcmp(*ss, "-")) do_grep(0, *ss); 299fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley else dirtree_read(*ss, do_grep_r); 300fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } 301fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } else loopfiles_rw(toys.optargs, O_RDONLY, 0, 1, do_grep); 302e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake} 303