X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=grep.c;h=fec8d0913c7dafc4e2b6248a6ac567557b475ad5;hb=05e782ddd3dc58245c889529bb8aeeaddf24bf71;hp=abdd4423602ea0cb0e3717c761bc728348f37614;hpb=61677feff7f549a48267c2c0c50a7420de6e2599;p=oweals%2Fbusybox.git diff --git a/grep.c b/grep.c index abdd44236..fec8d0913 100644 --- a/grep.c +++ b/grep.c @@ -1,10 +1,8 @@ -/* vi: set sw=4 ts=4: */ /* - * Mini grep implementation for busybox + * Mini grep implementation for busybox using libc regex. * - * - * Copyright (C) 1999,2000 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000,2001 by Lineo, inc. + * Written by Mark Whitley , * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,144 +20,174 @@ * */ -/* - 18-Dec-1999 Konstantin Boldyshev - - + -q option (be quiet) - + exit code depending on grep result (TRUE or FALSE) - (useful for scripts) -*/ - -#include "internal.h" -#include "regexp.h" #include -#include +#include +#include +#include +#include /* for strerror() */ #include -#include -#include -#include -#include - -static const char grep_usage[] = - "grep [OPTIONS]... PATTERN [FILE]...\n\n" - "Search for PATTERN in each FILE or standard input.\n\n" - "OPTIONS:\n" - "\t-h\tsuppress the prefixing filename on output\n" - "\t-i\tignore case distinctions\n" - "\t-n\tprint line number with output lines\n" - "\t-q\tbe quiet. Returns 0 if result was found, 1 otherwise\n\n" -#if defined BB_REGEXP - "This version of grep matches full regular expresions.\n"; -#else - "This version of grep matches strings (not regular expresions).\n"; -#endif - -static int match = FALSE, beQuiet = FALSE; - -static void do_grep(FILE * fp, char *needle, char *fileName, int tellName, - int ignoreCase, int tellLine) -{ - char *cp; - long line = 0; - char haystack[BUF_SIZE]; +#include "busybox.h" - while (fgets(haystack, sizeof(haystack), fp)) { - line++; - cp = &haystack[strlen(haystack) - 1]; +extern void xregcomp(regex_t *preg, const char *regex, int cflags); - if (*cp != '\n') - fprintf(stderr, "%s: Line too long\n", fileName); +extern int optind; /* in unistd.h */ +extern int errno; /* for use with strerror() */ - if (find_match(haystack, needle, ignoreCase) == TRUE) { - if (tellName == TRUE) - printf("%s:", fileName); +/* options */ +static int ignore_case = 0; +static int print_filename = 0; +static int print_line_num = 0; +static int print_count_only = 0; +static int be_quiet = 0; +static int invert_search = 0; +static int suppress_err_msgs = 0; - if (tellLine == TRUE) - printf("%ld:", line); +/* globals */ +static regex_t regex; /* storage space for compiled regular expression */ +static int matched; /* keeps track of whether we ever matched */ +static char *cur_file = NULL; /* the current file we are reading */ - if (beQuiet == FALSE) - fputs(haystack, stdout); - match = TRUE; - } - } -} +static void print_matched_line(char *line, int linenum) +{ + if (print_count_only) + return; + if (print_filename) + printf("%s:", cur_file); + if (print_line_num) + printf("%i:", linenum); -extern int grep_main(int argc, char **argv) + puts(line); +} + +static void grep_file(FILE *file) { - FILE *fp; - char *cp; - char *needle; - char *fileName; - int tellName = TRUE; - int ignoreCase = TRUE; - int tellLine = FALSE; + char *line = NULL; + int ret; + int linenum = 0; + int nmatches = 0; + + while ((line = get_line_from_file(file)) != NULL) { + chomp(line); + linenum++; + ret = regexec(®ex, line, 0, NULL, 0); + if (ret == 0 && !invert_search) { /* match */ + + /* if we found a match but were told to be quiet, stop here and + * return success */ + if (be_quiet) { + regfree(®ex); + exit(0); + } + nmatches++; + print_matched_line(line, linenum); - ignoreCase = FALSE; - tellLine = FALSE; + } + else if (ret == REG_NOMATCH && invert_search) { + if (be_quiet) { + regfree(®ex); + exit(0); + } - argc--; - argv++; - if (argc < 1) { - usage(grep_usage); + nmatches++; + print_matched_line(line, linenum); + } + + free(line); } - if (**argv == '-') { - argc--; - cp = *argv++; + /* special-case post processing */ + if (print_count_only) { + if (print_filename) + printf("%s:", cur_file); + printf("%i\n", nmatches); + } - while (*++cp) - switch (*cp) { + /* record if we matched */ + if (nmatches != 0) + matched = 1; +} + +extern int grep_main(int argc, char **argv) +{ + int opt; + int reflags; + + /* do normal option parsing */ + while ((opt = getopt(argc, argv, "iHhnqvsc")) > 0) { + switch (opt) { case 'i': - ignoreCase = TRUE; + ignore_case++; + break; + case 'H': + print_filename++; break; - case 'h': - tellName = FALSE; + print_filename--; break; - case 'n': - tellLine = TRUE; + print_line_num++; break; - case 'q': - beQuiet = TRUE; + be_quiet++; break; - - default: - usage(grep_usage); - } + case 'v': + invert_search++; + break; + case 's': + suppress_err_msgs++; + break; + case 'c': + print_count_only++; + break; + } } - needle = *argv++; - argc--; - - if (argc == 0) { - do_grep(stdin, needle, "stdin", FALSE, ignoreCase, tellLine); - } else { - /* Never print the filename for just one file */ - if (argc == 1) - tellName = FALSE; - while (argc-- > 0) { - fileName = *argv++; - - fp = fopen(fileName, "r"); - if (fp == NULL) { - perror(fileName); - continue; - } - - do_grep(fp, needle, fileName, tellName, ignoreCase, tellLine); + /* argv[optind] should be the regex pattern; no pattern, no worky */ + if (argv[optind] == NULL) + usage(grep_usage); - if (ferror(fp)) - perror(fileName); - fclose(fp); + /* compile the regular expression + * we're not going to mess with sub-expressions, and we need to + * treat newlines right. */ + reflags = REG_NOSUB; + if (ignore_case) + reflags |= REG_ICASE; + xregcomp(®ex, argv[optind], reflags); + + /* argv[(optind+1)..(argc-1)] should be names of file to grep through. If + * there is more than one file to grep, we will print the filenames */ + if ((argc-1) - (optind+1) > 0) + print_filename++; + + /* If no files were specified, or '-' was specified, take input from + * stdin. Otherwise, we grep through all the files specified. */ + if (argv[optind+1] == NULL || (strcmp(argv[optind+1], "-") == 0)) { + grep_file(stdin); + } + else { + int i; + FILE *file; + for (i = optind + 1; i < argc; i++) { + cur_file = argv[i]; + file = fopen(cur_file, "r"); + if (file == NULL) { + if (!suppress_err_msgs) + perror_msg("%s", cur_file); + } + else { + grep_file(file); + fclose(file); + } } } - exit(match); -} + regfree(®ex); -/* END CODE */ + if (!matched) + return 1; + + return 0; +}