grep.c revision b97d8211fa5c382f32e9a9f606a8566bd2ec09fb
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 673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley * 773e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley * TODO: -ABC 8e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 9b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob LandleyUSE_GREP(NEWTOY(grep, "A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN)) 10c49b9a97559d2009e9076e063b2e9acbc13fb9efRob LandleyUSE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN)) 11c49b9a97559d2009e9076e063b2e9acbc13fb9efRob LandleyUSE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN)) 12e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 13e999ca008416e3d41c1079bcb4d151b43c95dc3aStrakeconfig GREP 14e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake bool "grep" 15205b496e42ceb72bf0755fec4f4675a467c401e1Rob Landley default y 16e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake help 17b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley usage: grep [-EFivwcloqsHbhn] [-A NUM] [-m MAX] [-e REGEX]... [-f REGFILE] [FILE]... 18f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 19f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley Show lines matching regular expressions. If no -e, first argument is 20f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley regular expression to match. With no files (or "-" filename) read stdin. 21f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley Returns 0 if matched, 1 if no match found. 22f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 23f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -e Regex to match. (May be repeated.) 24f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -f File containing regular expressions to match. 25f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 26f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley match type: 27b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley -A NUM lines after match 28f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -E extended regex syntax -F fixed (match literal string) 29fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley -i case insensitive -m stop after this many lines matched 30fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley -r recursive (on dir) -v invert match 31fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley -w whole word (implies -E) -x whole line 32d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley -z input NUL terminated 33f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 34f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley display modes: (default: matched line) 35f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -c count of matching lines -l show matching filenames 36f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -o only matching part -q quiet (errors only) 37d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley -s silent (no error msg) -Z output NUL terminated 38f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 39d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley output prefix (default: filename if checking more than 1 file) 40f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -H force filename -b byte offset of match 41f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley -h hide filename -n line number of match 42c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley 43c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landleyconfig EGREP 44c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley bool 45c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley default y 46c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley depends on GREP 47c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley 48c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landleyconfig FGREP 49c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley bool 50c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley default y 51c49b9a97559d2009e9076e063b2e9acbc13fb9efRob Landley depends on GREP 52e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake*/ 53e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 54e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#define FOR_grep 55e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#include "toys.h" 56e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake#include <regex.h> 57e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 58e999ca008416e3d41c1079bcb4d151b43c95dc3aStrakeGLOBALS( 59dad378bb17f1910014383bf196e87028e98d81d6Rob Landley long m; 60dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley struct arg_list *f; 61dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley struct arg_list *e; 62b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley long a; 63e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake) 64e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 6573e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley// Show matches in one file 66f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landleystatic void do_grep(int fd, char *name) 67f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{ 68dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley FILE *file = fdopen(fd, "r"); 69b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley long offset = 0, after = 0; 7073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley int lcount = 0, mcount = 0; 71b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley char *bars = 0, indelim = '\n' * !(toys.optflags&FLAG_z), 72d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley outdelim = '\n' * !(toys.optflags&FLAG_Z); 73e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 7431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (!fd) name = "(standard input)"; 7531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley 76dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!file) { 77d3a435e53c94ec25b4ae5fa2614f49ef8884e08aRob Landley perror_msg_raw(name); 78dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley return; 79dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 80dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 8173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley // Loop through lines of input 82e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake for (;;) { 836c64f5f186d26d4c95d408979d33831935e026f1Rob Landley char *line = 0, *start; 8473e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley regmatch_t matches; 85dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley size_t unused; 86dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley long len; 87030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley int mmatch = 0; 88e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 89dad378bb17f1910014383bf196e87028e98d81d6Rob Landley lcount++; 90d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley if (0 > (len = getdelim(&line, &unused, indelim, file))) break; 91d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley if (line[len-1] == indelim) line[len-1] = 0; 92dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 93dad378bb17f1910014383bf196e87028e98d81d6Rob Landley start = line; 94e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 9573e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley // Loop through matches in this line 9673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley do { 97dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley int rc = 0, skip = 0; 98dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 9973e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley // Handle non-regex matches 100dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (toys.optflags & FLAG_F) { 101fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley struct arg_list *seek, fseek; 102dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley char *s = 0; 103dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 104dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley for (seek = TT.e; seek; seek = seek->next) { 105e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley if (toys.optflags & FLAG_x) { 106e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley int i = (toys.optflags & FLAG_i); 107e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley 108e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley if ((i ? strcasecmp : strcmp)(seek->arg, line)) s = line; 109e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley } else if (!*seek->arg) { 110fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley seek = &fseek; 111fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley fseek.arg = s = line; 112fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley break; 113fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } 114dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (toys.optflags & FLAG_i) { 115dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley long ll = strlen(seek->arg);; 116dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 117dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley // Alas, posix hasn't got strcasestr() 118dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley for (s = line; *s; s++) if (!strncasecmp(s, seek->arg, ll)) break; 119dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!*s) s = 0; 120dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else s = strstr(line, seek->arg); 121dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (s) break; 122dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 123dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 124dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (s) { 12573e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley matches.rm_so = (s-line); 12673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley skip = matches.rm_eo = (s-line)+strlen(seek->arg); 127dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else rc = 1; 128dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else { 12973e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley rc = regexec((regex_t *)toybuf, start, 1, &matches, 130dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley start==line ? 0 : REG_NOTBOL); 13173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley skip = matches.rm_eo; 132dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 133dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 134dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (toys.optflags & FLAG_x) 13573e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (matches.rm_so || line[matches.rm_eo]) rc = 1; 13673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley 13773e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (!rc && (toys.optflags & FLAG_w)) { 13873e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley char c = 0; 13973e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley 14073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if ((start+matches.rm_so)!=line) { 14173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley c = start[matches.rm_so-1]; 14273e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (!isalnum(c) && c != '_') c = 0; 14373e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley } 14473e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (!c) { 14573e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley c = start[matches.rm_eo]; 14673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (!isalnum(c) && c != '_') c = 0; 14773e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley } 14873e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (c) { 14973e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley start += matches.rm_so+1; 15073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley 15173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley continue; 15273e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley } 15373e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley } 154dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 155dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_v) { 156dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_o) { 15773e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (rc) skip = matches.rm_eo = strlen(start); 15873e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley else if (!matches.rm_so) { 159dad378bb17f1910014383bf196e87028e98d81d6Rob Landley start += skip; 160dad378bb17f1910014383bf196e87028e98d81d6Rob Landley continue; 16173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley } else matches.rm_eo = matches.rm_so; 162dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } else { 163dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (!rc) break; 16473e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley matches.rm_eo = strlen(start); 165dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 16673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley matches.rm_so = 0; 167dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } else if (rc) break; 1686c64f5f186d26d4c95d408979d33831935e026f1Rob Landley 169b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley if (bars) { 170b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley xputs(bars); 171b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley bars = 0; 172b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley } 173030970bd70e14849b0f2598bfa0982402fc7e2e7Rob Landley mmatch++; 174e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley toys.exitval = 0; 175e6e685cdb8f6e30607c25dcac5f8dc93d4230c20Rob Landley if (toys.optflags & FLAG_q) xexit(); 176dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_l) { 177d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley printf("%s%c", name, outdelim); 1786c64f5f186d26d4c95d408979d33831935e026f1Rob Landley free(line); 1796c64f5f186d26d4c95d408979d33831935e026f1Rob Landley fclose(file); 1806c64f5f186d26d4c95d408979d33831935e026f1Rob Landley return; 181dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 182fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (toys.optflags & FLAG_o) 18373e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (matches.rm_eo == matches.rm_so) 184fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley break; 185fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 1866c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (!(toys.optflags & FLAG_c)) { 1876c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_H) printf("%s:", name); 1886c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_n) printf("%d:", lcount); 1896c64f5f186d26d4c95d408979d33831935e026f1Rob Landley if (toys.optflags & FLAG_b) 1906c64f5f186d26d4c95d408979d33831935e026f1Rob Landley printf("%ld:", offset + (start-line) + 19173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley ((toys.optflags & FLAG_o) ? matches.rm_so : 0)); 192b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley if (!(toys.optflags & FLAG_o)) { 193b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley xprintf("%s%c", line, outdelim); 194b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley if (TT.a) after = TT.a; 195b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley } else { 196b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley xprintf("%.*s%c", (int)(matches.rm_eo-matches.rm_so), 197b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley start+matches.rm_so, outdelim); 198e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 199e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 200dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 201dad378bb17f1910014383bf196e87028e98d81d6Rob Landley start += skip; 20273e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (!(toys.optflags & FLAG_o)) break; 20373e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley } while (*start); 204dad378bb17f1910014383bf196e87028e98d81d6Rob Landley offset += len; 2056c64f5f186d26d4c95d408979d33831935e026f1Rob Landley 206b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley if (mmatch) mcount++; 207b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley else if (after) { 208b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley if (after>0) { 209b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley xprintf("%s%c", line, outdelim); 210b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley if (!--after) after = -1; 211b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley } else bars = "--"; 212b97d8211fa5c382f32e9a9f606a8566bd2ec09fbRob Landley } 213dad378bb17f1910014383bf196e87028e98d81d6Rob Landley free(line); 214dad378bb17f1910014383bf196e87028e98d81d6Rob Landley 215dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if ((toys.optflags & FLAG_m) && mcount >= TT.m) break; 216dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 217e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 218dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_c) { 219fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (toys.optflags & FLAG_H) printf("%s:", name); 220d3657e9e8846e11f376fcb6fae60b15dae853479Rob Landley xprintf("%d%c", mcount, outdelim); 221e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 222e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 223dad378bb17f1910014383bf196e87028e98d81d6Rob Landley // loopfiles will also close the fd, but this frees an (opaque) struct. 224dad378bb17f1910014383bf196e87028e98d81d6Rob Landley fclose(file); 225e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake} 226e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 227dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landleystatic void parse_regex(void) 228f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{ 22931f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley struct arg_list *al, *new, *list = NULL; 230dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley long len = 0; 231dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley char *s, *ss; 232dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 233dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley // Add all -f lines to -e list. (Yes, this is leaking allocation context for 234dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley // exit to free. Not supporting nofork for this command any time soon.) 23531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley al = TT.f ? TT.f : TT.e; 23631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley while (al) { 237dc3731783ead154d5a0d8d318566468474b43013Rob Landley if (TT.f) s = ss = xreadfile(al->arg, 0, 0); 23831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley else s = ss = al->arg; 239dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 24073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley // Split lines at \n, add individual lines to new list. 241fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley do { 242dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley ss = strchr(s, '\n'); 24331f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (ss) *(ss++) = 0; 24431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley new = xmalloc(sizeof(struct arg_list)); 24531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley new->next = list; 24631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley new->arg = s; 24731f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley list = new; 248dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley s = ss; 249fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } while (ss && *s); 25073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley 25173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley // Advance, when we run out of -f switch to -e. 25231f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley al = al->next; 25331f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (!al && TT.f) { 25431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley TT.f = 0; 25531f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley al = TT.e; 25631f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley } 257e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 25831f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley TT.e = list; 259f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley 260dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!(toys.optflags & FLAG_F)) { 261fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley char *regstr; 26273e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley int i; 263e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 26431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley // Convert strings to one big regex 2653ad73e1344afa7812671d08456591b8cde952775William Haddon for (al = TT.e; al; al = al->next) 2663ad73e1344afa7812671d08456591b8cde952775William Haddon len += strlen(al->arg)+1+!(toys.optflags & FLAG_E); 267e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 268fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley regstr = s = xmalloc(len); 269dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley for (al = TT.e; al; al = al->next) { 270dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley s = stpcpy(s, al->arg); 27131f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley if (!(toys.optflags & FLAG_E)) *(s++) = '\\'; 272dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley *(s++) = '|'; 273e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 27431f07104445bc0c0cbc942d86ee9d31d08c344d8Rob Landley *(s-=(1+!(toys.optflags & FLAG_E))) = 0; 275e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 27673e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley i = regcomp((regex_t *)toybuf, regstr, 277dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley ((toys.optflags & FLAG_E) ? REG_EXTENDED : 0) | 278dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley ((toys.optflags & FLAG_i) ? REG_ICASE : 0)); 2797b7b284ce4c1bd53d442927d9a570fcf84e0187cStrake 28073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (i) { 28173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley regerror(i, (regex_t *)toybuf, toybuf+sizeof(regex_t), 282dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley sizeof(toybuf)-sizeof(regex_t)); 283dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley error_exit("bad REGEX: %s", toybuf); 284dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 285e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake } 286e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake} 287e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 288fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landleystatic int do_grep_r(struct dirtree *new) 289fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley{ 290fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley char *name; 291fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 292fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (new->parent && !dirtree_notdotdot(new)) return 0; 293fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (S_ISDIR(new->st.st_mode)) return DIRTREE_RECURSE; 294fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 295fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley // "grep -r onefile" doesn't show filenames, but "grep -r onedir" should. 296fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (new->parent && !(toys.optflags & FLAG_h)) toys.optflags |= FLAG_H; 297fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 298fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley name = dirtree_path(new, 0); 299fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley do_grep(openat(dirtree_parentfd(new), new->name, 0), name); 300fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley free(name); 301fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 302fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley return 0; 303fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley} 304fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 305f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landleyvoid grep_main(void) 306f97eaf158aa0baf868f0b19d192f7d302c1484e9Rob Landley{ 307adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley char **ss = toys.optargs; 308fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 309dad378bb17f1910014383bf196e87028e98d81d6Rob Landley // Handle egrep and fgrep 31073e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley if (*toys.which->name == 'e') toys.optflags |= FLAG_E; 311dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (*toys.which->name == 'f') toys.optflags |= FLAG_F; 3121fa68247345fa6e2cefe4fb4d88ef75f614b18c4M. Farkas-Dyck 313dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley if (!TT.e && !TT.f) { 314adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley if (!*ss) error_exit("no REGEX"); 315dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley TT.e = xzalloc(sizeof(struct arg_list)); 316adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley TT.e->arg = *(ss++); 317dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley toys.optc--; 318dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley } 319dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley 320dd2d23930241a30a8eb4f0fc9d70bc86c4a6cb6eRob Landley parse_regex(); 321e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 322fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (!(toys.optflags & FLAG_h) && toys.optc>1) toys.optflags |= FLAG_H; 323e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake 324174ba2bed2f33fe90926b08a3e9ec4e3ce7febabStrake toys.exitval = 1; 325dad378bb17f1910014383bf196e87028e98d81d6Rob Landley if (toys.optflags & FLAG_s) { 326dad378bb17f1910014383bf196e87028e98d81d6Rob Landley close(2); 327dad378bb17f1910014383bf196e87028e98d81d6Rob Landley xopen("/dev/null", O_RDWR); 328dad378bb17f1910014383bf196e87028e98d81d6Rob Landley } 329fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley 330fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (toys.optflags & FLAG_r) { 33173e3a644c1af8e28ca45c3b5169dee8acc06b179Rob Landley // Iterate through -r arguments. Use "." as default if none provided. 332adcbaf530f3ec351ec2932ebe9b77140f79eda4aRob Landley for (ss = *ss ? ss : (char *[]){".", 0}; *ss; ss++) { 333fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley if (!strcmp(*ss, "-")) do_grep(0, *ss); 334fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley else dirtree_read(*ss, do_grep_r); 335fce85e9d287cef03777d3c2d97b2a0b43242ee21Rob Landley } 33694983f2dddde86e8f121abe97a28aa1f6c87a3dbRob Landley } else loopfiles_rw(ss, O_RDONLY, 0, 1, do_grep); 337e999ca008416e3d41c1079bcb4d151b43c95dc3aStrake} 338