aboutsummaryrefslogtreecommitdiff
path: root/findutils
diff options
context:
space:
mode:
Diffstat (limited to 'findutils')
-rw-r--r--findutils/grep.c355
-rw-r--r--findutils/xargs.c25
2 files changed, 186 insertions, 194 deletions
diff --git a/findutils/grep.c b/findutils/grep.c
index e26a8d5ad..241099c79 100644
--- a/findutils/grep.c
+++ b/findutils/grep.c
@@ -19,42 +19,71 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * 20 *
21 */ 21 */
22/*
23 * Jun 2003 by Vladimir Oleynik <dzo@simtreas.ru> -
24 * correction "-e pattern1 -e -e pattern2" logic and more optimizations.
25*/
22 26
23#include <stdio.h> 27#include <stdio.h>
24#include <stdlib.h> 28#include <stdlib.h>
25#include <getopt.h> 29#include <getopt.h>
26#include <regex.h> 30#include <regex.h>
27#include <string.h> /* for strerror() */ 31#include <string.h>
28#include <errno.h> 32#include <errno.h>
29#include "busybox.h" 33#include "busybox.h"
30 34
31 35
32extern int optind; /* in unistd.h */
33extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */
34
35/* options */ 36/* options */
36static int reflags = REG_NOSUB; 37#define GREP_OPTS "lnqvscFiHhe:f:"
37static int print_filename = 0; 38#define GREP_OPT_l 1
38static int print_line_num = 0; 39static char print_files_with_matches;
39static int print_match_counts = 0; 40#define GREP_OPT_n 2
40static int be_quiet = 0; 41static char print_line_num;
41static int invert_search = 0; 42#define GREP_OPT_q 4
42static int suppress_err_msgs = 0; 43static char be_quiet;
43static int print_files_with_matches = 0; 44#define GREP_OPT_v 8
44static int fgrep_flag = 0; 45typedef char invert_search_t;
46static invert_search_t invert_search;
47#define GREP_OPT_s 16
48static char suppress_err_msgs;
49#define GREP_OPT_c 32
50static char print_match_counts;
51#define GREP_OPT_F 64
52static char fgrep_flag;
53#define GREP_OPT_i 128
54#define GREP_OPT_H 256
55#define GREP_OPT_h 512
56#define GREP_OPT_e 1024
57#define GREP_OPT_f 2048
58#ifdef CONFIG_FEATURE_GREP_CONTEXT
59#define GREP_OPT_CONTEXT "A:B:C"
60#define GREP_OPT_A 4096
61#define GREP_OPT_B 8192
62#define GREP_OPT_C 16384
63#define GREP_OPT_E 32768U
64#else
65#define GREP_OPT_CONTEXT ""
66#define GREP_OPT_E 4096
67#endif
68#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS
69# define OPT_EGREP "E"
70#else
71# define OPT_EGREP ""
72#endif
73
74static int reflags;
75static int print_filename;
45 76
46#ifdef CONFIG_FEATURE_GREP_CONTEXT 77#ifdef CONFIG_FEATURE_GREP_CONTEXT
47extern char *optarg; /* in getopt.h */ 78static int lines_before;
48static int lines_before = 0; 79static int lines_after;
49static int lines_after = 0; 80static char **before_buf;
50static char **before_buf = NULL; 81static int last_line_printed;
51static int last_line_printed = 0;
52#endif /* CONFIG_FEATURE_GREP_CONTEXT */ 82#endif /* CONFIG_FEATURE_GREP_CONTEXT */
53 83
54/* globals used internally */ 84/* globals used internally */
55static llist_t *pattern_head = NULL; /* growable list of patterns to match */ 85static llist_t *pattern_head; /* growable list of patterns to match */
56static int matched; /* keeps track of whether we ever matched */ 86static char *cur_file; /* the current file we are reading */
57static char *cur_file = NULL; /* the current file we are reading */
58 87
59 88
60static void print_line(const char *line, int linenum, char decoration) 89static void print_line(const char *line, int linenum, char decoration)
@@ -74,11 +103,13 @@ static void print_line(const char *line, int linenum, char decoration)
74 puts(line); 103 puts(line);
75} 104}
76 105
106extern void xregcomp(regex_t *preg, const char *regex, int cflags);
107
77 108
78static void grep_file(FILE *file) 109static int grep_file(FILE *file)
79{ 110{
80 char *line = NULL; 111 char *line;
81 int ret; 112 invert_search_t ret;
82 int linenum = 0; 113 int linenum = 0;
83 int nmatches = 0; 114 int nmatches = 0;
84#ifdef CONFIG_FEATURE_GREP_CONTEXT 115#ifdef CONFIG_FEATURE_GREP_CONTEXT
@@ -91,15 +122,10 @@ static void grep_file(FILE *file)
91 llist_t *pattern_ptr = pattern_head; 122 llist_t *pattern_ptr = pattern_head;
92 123
93 linenum++; 124 linenum++;
94 125 ret = 0;
95 while (pattern_ptr) { 126 while (pattern_ptr) {
96 if (fgrep_flag) { 127 if (fgrep_flag) {
97 if (strstr(line, pattern_ptr->data)) { 128 ret = strstr(line, pattern_ptr->data) != NULL;
98 /* Match found */
99 ret = 0;
100 } else {
101 ret = 1;
102 }
103 } else { 129 } else {
104 /* 130 /*
105 * test for a postitive-assertion match (regexec returns success (0) 131 * test for a postitive-assertion match (regexec returns success (0)
@@ -109,15 +135,22 @@ static void grep_file(FILE *file)
109 */ 135 */
110 regex_t regex; 136 regex_t regex;
111 xregcomp(&regex, pattern_ptr->data, reflags); 137 xregcomp(&regex, pattern_ptr->data, reflags);
112 ret = regexec(&regex, line, 0, NULL, 0); 138 ret = regexec(&regex, line, 0, NULL, 0) == 0;
113 regfree(&regex); 139 regfree(&regex);
114 } 140 }
115 if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) { 141 if (!ret)
142 break;
143 pattern_ptr = pattern_ptr->link;
144 } /* while (pattern_ptr) */
145
146 if ((ret ^ invert_search)) {
147
148 if (print_files_with_matches || be_quiet)
149 free(line);
116 150
117 /* if we found a match but were told to be quiet, stop here and 151 /* if we found a match but were told to be quiet, stop here */
118 * return success */
119 if (be_quiet) 152 if (be_quiet)
120 exit(0); 153 return -1;
121 154
122 /* keep track of matches */ 155 /* keep track of matches */
123 nmatches++; 156 nmatches++;
@@ -177,8 +210,6 @@ static void grep_file(FILE *file)
177 print_n_lines_after--; 210 print_n_lines_after--;
178 } 211 }
179#endif /* CONFIG_FEATURE_GREP_CONTEXT */ 212#endif /* CONFIG_FEATURE_GREP_CONTEXT */
180 pattern_ptr = pattern_ptr->link;
181 } /* for */
182 free(line); 213 free(line);
183 } 214 }
184 215
@@ -190,9 +221,6 @@ static void grep_file(FILE *file)
190 if (print_match_counts) { 221 if (print_match_counts) {
191 if (print_filename) 222 if (print_filename)
192 printf("%s:", cur_file); 223 printf("%s:", cur_file);
193 if (print_files_with_matches && nmatches > 0)
194 printf("1\n");
195 else
196 printf("%d\n", nmatches); 224 printf("%d\n", nmatches);
197 } 225 }
198 226
@@ -201,188 +229,163 @@ static void grep_file(FILE *file)
201 puts(cur_file); 229 puts(cur_file);
202 } 230 }
203 231
204 232 return nmatches;
205 /* remember if we matched */
206 if (nmatches != 0)
207 matched = 1;
208}
209
210#if 0
211static void add_pattern(char *restr)
212{
213// regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes));
214// xregcomp(&regexes[nregexes-1], restr, reflags);
215 pattern_head = llist_add_to(pattern_head, restr);
216} 233}
217#endif
218 234
219static void load_regexes_from_file(const char *filename) 235static void load_regexes_from_file(llist_t *fopt)
220{ 236{
221 char *line; 237 char *line;
222 FILE *f = bb_xfopen(filename, "r"); 238 FILE *f;
239
240 while(fopt) {
241 llist_t *cur = fopt;
242 char *ffile = cur->data;
243
244 fopt = cur->link;
245 free(cur);
246 f = bb_xfopen(ffile, "r");
223 while ((line = bb_get_chomped_line_from_file(f)) != NULL) { 247 while ((line = bb_get_chomped_line_from_file(f)) != NULL) {
224 pattern_head = llist_add_to(pattern_head, line); 248 pattern_head = llist_add_to(pattern_head, line);
225 } 249 }
226}
227
228
229#ifdef CONFIG_FEATURE_CLEAN_UP
230static void destroy_regexes(void)
231{
232 llist_t *pattern_head_ptr;
233
234 if (pattern_head == NULL)
235 return;
236
237 /* destroy all the elments in the pattern list */
238 while (pattern_head) {
239 pattern_head_ptr = pattern_head;
240 pattern_head = pattern_head->link;
241 free(pattern_head_ptr->data);
242 free(pattern_head_ptr);
243 } 250 }
244} 251}
245#endif
246 252
247 253
248extern int grep_main(int argc, char **argv) 254extern int grep_main(int argc, char **argv)
249{ 255{
250 int opt; 256 FILE *file;
251#if defined (CONFIG_FEATURE_GREP_CONTEXT) 257 int matched;
252 char *junk; 258 unsigned long opt;
253#endif 259 llist_t *fopt;
254
255#ifdef CONFIG_FEATURE_CLEAN_UP
256 /* destroy command strings on exit */
257 atexit(destroy_regexes);
258#endif
259
260#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS
261 if (strcmp(bb_get_last_path_component(argv[0]), "egrep") == 0)
262 reflags |= REG_EXTENDED;
263#endif
264 260
265 /* do normal option parsing */ 261 /* do normal option parsing */
266 while ((opt = getopt(argc, argv, "iHhlnqvsce:f:F"
267#ifdef CONFIG_FEATURE_GREP_CONTEXT 262#ifdef CONFIG_FEATURE_GREP_CONTEXT
268"A:B:C:" 263 {
269#endif 264 char *junk;
270#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS 265 char *slines_after;
271"E" 266 char *slines_before;
272#endif 267 char *Copt;
273)) > 0) { 268
274 switch (opt) { 269 bb_opt_complementaly = "H-h:e*:f*:C-AB";
275 case 'i': 270 opt = bb_getopt_ulflags(argc, argv,
276 reflags |= REG_ICASE; 271 GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP,
277 break; 272 &pattern_head, &fopt,
278 case 'l': 273 &slines_after, &slines_before, &Copt);
279 print_files_with_matches++; 274
280 break; 275 if(opt & GREP_OPT_C) {
281 case 'H': 276 /* C option unseted A and B options, but next -A or -B
282 print_filename++; 277 may be ovewrite own option */
283 break; 278 if(!(opt & GREP_OPT_A)) /* not overwtited */
284 case 'h': 279 slines_after = Copt;
285 print_filename--; 280 if(!(opt & GREP_OPT_B)) /* not overwtited */
286 break; 281 slines_before = Copt;
287 case 'n': 282 opt |= GREP_OPT_A|GREP_OPT_B; /* set for parse now */
288 print_line_num++; 283 }
289 break; 284 if(opt & GREP_OPT_A) {
290 case 'q': 285 lines_after = strtoul(slines_after, &junk, 10);
291 be_quiet++;
292 break;
293 case 'v':
294 invert_search++;
295 break;
296 case 's':
297 suppress_err_msgs++;
298 break;
299 case 'c':
300 print_match_counts++;
301 break;
302 case 'e':
303 pattern_head = llist_add_to(pattern_head, strdup(optarg));
304 break;
305#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS
306 case 'E':
307 reflags |= REG_EXTENDED;
308 break;
309#endif
310 case 'F':
311 fgrep_flag = 1;
312 break;
313 case 'f':
314 load_regexes_from_file(optarg);
315 break;
316#ifdef CONFIG_FEATURE_GREP_CONTEXT
317 case 'A':
318 lines_after = strtoul(optarg, &junk, 10);
319 if(*junk != '\0')
320 bb_error_msg_and_die("invalid context length argument");
321 break;
322 case 'B':
323 lines_before = strtoul(optarg, &junk, 10);
324 if(*junk != '\0') 286 if(*junk != '\0')
325 bb_error_msg_and_die("invalid context length argument"); 287 bb_error_msg_and_die("invalid context length argument");
326 before_buf = (char **)xcalloc(lines_before, sizeof(char *)); 288 }
327 break; 289 if(opt & GREP_OPT_B) {
328 case 'C': 290 lines_before = strtoul(slines_before, &junk, 10);
329 lines_after = lines_before = strtoul(optarg, &junk, 10);
330 if(*junk != '\0') 291 if(*junk != '\0')
331 bb_error_msg_and_die("invalid context length argument"); 292 bb_error_msg_and_die("invalid context length argument");
332 before_buf = (char **)xcalloc(lines_before, sizeof(char *));
333 break;
334#endif /* CONFIG_FEATURE_GREP_CONTEXT */
335 default:
336 bb_show_usage();
337 } 293 }
294 /* sanity checks after parse may be invalid numbers ;-) */
295 if ((opt & (GREP_OPT_c|GREP_OPT_q|GREP_OPT_l))) {
296 opt &= ~GREP_OPT_n;
297 lines_before = 0;
298 lines_after = 0;
299 } else if(lines_before > 0)
300 before_buf = (char **)xcalloc(lines_before, sizeof(char *));
338 } 301 }
302#else
303 /* with auto sanity checks */
304 bb_opt_complementaly = "H-h:e*:f*:c-n:q-n:l-n";
305 opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP,
306 &pattern_head, &fopt);
307
308#endif
309 print_files_with_matches = opt & GREP_OPT_l;
310 print_line_num = opt & GREP_OPT_n;
311 be_quiet = opt & GREP_OPT_q;
312 invert_search = (opt & GREP_OPT_v) != 0; /* 0 | 1 */
313 suppress_err_msgs = opt & GREP_OPT_s;
314 print_match_counts = opt & GREP_OPT_c;
315 fgrep_flag = opt & GREP_OPT_F;
316 if(opt & GREP_OPT_H)
317 print_filename++;
318 if(opt & GREP_OPT_h)
319 print_filename--;
320 if(opt & GREP_OPT_f)
321 load_regexes_from_file(fopt);
322
323#ifdef CONFIG_FEATURE_GREP_EGREP_ALIAS
324 if(bb_applet_name[0] == 'e' || (opt & GREP_OPT_E))
325 reflags = REG_EXTENDED | REG_NOSUB;
326 else
327#endif
328 reflags = REG_NOSUB;
329
330 if(opt & GREP_OPT_i)
331 reflags |= REG_ICASE;
332
333 argv += optind;
334 argc -= optind;
339 335
340 /* if we didn't get a pattern from a -e and no command file was specified, 336 /* if we didn't get a pattern from a -e and no command file was specified,
341 * argv[optind] should be the pattern. no pattern, no worky */ 337 * argv[optind] should be the pattern. no pattern, no worky */
342 if (pattern_head == NULL) { 338 if (pattern_head == NULL) {
343 if (argv[optind] == NULL) 339 if (*argv == NULL)
344 bb_show_usage(); 340 bb_show_usage();
345 else { 341 else {
346 pattern_head = llist_add_to(pattern_head, strdup(argv[optind])); 342 pattern_head = llist_add_to(pattern_head, *argv++);
347 optind++; 343 argc--;
348 } 344 }
349 } 345 }
350 346
351 /* sanity checks */
352 if (print_match_counts || be_quiet || print_files_with_matches) {
353 print_line_num = 0;
354#ifdef CONFIG_FEATURE_GREP_CONTEXT
355 lines_before = 0;
356 lines_after = 0;
357#endif
358 }
359
360 /* argv[(optind)..(argc-1)] should be names of file to grep through. If 347 /* argv[(optind)..(argc-1)] should be names of file to grep through. If
361 * there is more than one file to grep, we will print the filenames */ 348 * there is more than one file to grep, we will print the filenames */
362 if ((argc-1) - (optind) > 0) 349 if (argc > 1) {
363 print_filename++; 350 print_filename++;
364 351
365 /* If no files were specified, or '-' was specified, take input from 352 /* If no files were specified, or '-' was specified, take input from
366 * stdin. Otherwise, we grep through all the files specified. */ 353 * stdin. Otherwise, we grep through all the files specified. */
367 if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { 354 } else if (argc == 0) {
368 grep_file(stdin); 355 argc++;
369 } 356 }
370 else { 357 matched = 0;
371 int i; 358 while (argc--) {
372 FILE *file; 359 cur_file = *argv++;
373 for (i = optind; i < argc; i++) { 360 if(!cur_file || (*cur_file == '-' && !cur_file[1])) {
374 cur_file = argv[i]; 361 cur_file = "-";
362 file = stdin;
363 } else {
375 file = fopen(cur_file, "r"); 364 file = fopen(cur_file, "r");
365 }
376 if (file == NULL) { 366 if (file == NULL) {
377 if (!suppress_err_msgs) 367 if (!suppress_err_msgs)
378 bb_perror_msg("%s", cur_file); 368 bb_perror_msg("%s", cur_file);
369 } else {
370 matched += grep_file(file);
371 if(matched < 0) {
372 /* we found a match but were told to be quiet, stop here and
373 * return success */
374 break;
379 } 375 }
380 else {
381 grep_file(file);
382 fclose(file); 376 fclose(file);
383 } 377 }
384 } 378 }
379
380#ifdef CONFIG_FEATURE_CLEAN_UP
381 /* destroy all the elments in the pattern list */
382 while (pattern_head) {
383 llist_t *pattern_head_ptr = pattern_head;
384
385 pattern_head = pattern_head->link;
386 free(pattern_head_ptr);
385 } 387 }
388#endif
386 389
387 return !matched; /* invert return value 0 = success, 1 = failed */ 390 return !matched; /* invert return value 0 = success, 1 = failed */
388} 391}
diff --git a/findutils/xargs.c b/findutils/xargs.c
index d4bed57f0..2b18f8f28 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -66,24 +66,13 @@ int xargs_main(int argc, char **argv)
66 char *file_to_act_on; 66 char *file_to_act_on;
67 char **args; 67 char **args;
68 int i, a; 68 int i, a;
69 char flg_vi = 0; /* verbose |& interactive */ 69 char flg_vi; /* verbose |& interactive */
70 char flg_no_empty = 0; 70 char flg_no_empty;
71 71
72 while ((a = getopt(argc, argv, "prt")) > 0) { 72 bb_opt_complementaly = "pt";
73 switch(a) { 73 a = bb_getopt_ulflags(argc, argv, "tpr");
74 case 'p': 74 flg_vi = a & 3;
75 flg_vi |= 3; 75 flg_no_empty = a & 4;
76 break;
77 case 't':
78 flg_vi |= 1;
79 break;
80 case 'r':
81 flg_no_empty = 1;
82 break;
83 default:
84 bb_show_usage();
85 }
86 }
87 76
88 a = argc - optind; 77 a = argc - optind;
89 argv += optind; 78 argv += optind;
@@ -110,7 +99,7 @@ int xargs_main(int argc, char **argv)
110 fputc(' ', stderr); 99 fputc(' ', stderr);
111 fputs(args[i], stderr); 100 fputs(args[i], stderr);
112 } 101 }
113 fprintf(stderr, "%s", ((flg_vi & 2) ? " ?..." : "\n")); 102 fputs(((flg_vi & 2) ? " ?..." : "\n"), stderr);
114 } 103 }
115 if((flg_vi & 2) == 0 || bb_ask_confirmation() != 0 ) { 104 if((flg_vi & 2) == 0 || bb_ask_confirmation() != 0 ) {
116 xargs_exec(args); 105 xargs_exec(args);