zgrep.cc (zutils-1.8.tar.lz) | : | zgrep.cc (zutils-1.9.tar.lz) | ||
---|---|---|---|---|
/* Zgrep - search compressed files for a regular expression | /* Zgrep - search compressed files for a regular expression | |||
Copyright (C) 2010-2019 Antonio Diaz Diaz. | Copyright (C) 2010-2020 Antonio Diaz Diaz. | |||
This program is free software: you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 2 of the License, or | the Free Software Foundation, either version 2 of the License, or | |||
(at your option) any later version. | (at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#define _FILE_OFFSET_BITS 64 | #define _FILE_OFFSET_BITS 64 | |||
#include <cerrno> | #include <cerrno> | |||
#include <climits> | #include <climits> | |||
#include <csignal> | #include <csignal> | |||
#include <cstdio> | #include <cstdio> | |||
#include <cstdlib> | #include <cstdlib> | |||
#include <cstring> | #include <cstring> | |||
skipping to change at line 49 | skipping to change at line 49 | |||
#include "rc.h" | #include "rc.h" | |||
#include "zutils.h" | #include "zutils.h" | |||
namespace { | namespace { | |||
#include "recursive.cc" | #include "recursive.cc" | |||
#include "zcatgrep.cc" | #include "zcatgrep.cc" | |||
void show_help() | void show_help() | |||
{ | { | |||
std::printf( "Zgrep is a front end to the grep program that allows transparent | std::printf( "zgrep is a front end to the program grep that allows transparent | |||
search\n" | search\n" | |||
"on any combination of compressed and uncompressed files. If any | "on any combination of compressed and uncompressed files. If any | |||
given\n" | file\n" | |||
"file is compressed, its decompressed content is used. If a given | "given is compressed, its decompressed content is used. If a file | |||
file\n" | given\n" | |||
"does not exist, and its name does not end with one of the known\ n" | "does not exist, and its name does not end with one of the known\ n" | |||
"extensions, zgrep tries the compressed file names corresponding to the\n" | "extensions, zgrep tries the compressed file names corresponding to the\n" | |||
"formats supported.\n" | "formats supported. If a file fails to decompress, zgrep continue | |||
s\n" | ||||
"searching the rest of the files.\n" | ||||
"\nIf a file is specified as '-', data are read from standard inp ut,\n" | "\nIf a file is specified as '-', data are read from standard inp ut,\n" | |||
"decompressed if needed, and fed to grep. Data read from standard input\n" | "decompressed if needed, and fed to grep. Data read from standard input\n" | |||
"must be of the same type; all uncompressed or all in the same\n" | "must be of the same type; all uncompressed or all in the same\n" | |||
"compression format.\n" | "compressed format.\n" | |||
"\nIf no files are specified, recursive searches examine the curr ent\n" | "\nIf no files are specified, recursive searches examine the curr ent\n" | |||
"working directory, and nonrecursive searches read standard input .\n" | "working directory, and nonrecursive searches read standard input .\n" | |||
"\nThe formats supported are bzip2, gzip, lzip and xz.\n" | "\nThe formats supported are bzip2, gzip, lzip, and xz.\n" | |||
"\nUsage: zgrep [options] <pattern> [files]\n" | "\nUsage: zgrep [options] <pattern> [files]\n" | |||
"\nExit status is 0 if match, 1 if no match, 2 if trouble.\n" | "\nExit status is 0 if match, 1 if no match, 2 if trouble.\n" | |||
"Some options only work if the grep program used supports them.\n " | ||||
"\nOptions:\n" | "\nOptions:\n" | |||
" --help display this help and exit\n" | " --help display this help and exit\n" | |||
" -V, --version output version information and ex it\n" | " -V, --version output version information and ex it\n" | |||
" -a, --text treat all files as text\n" | " -a, --text treat all files as text\n" | |||
" -A, --after-context=<n> print <n> lines of trailing conte xt\n" | " -A, --after-context=<n> print <n> lines of trailing conte xt\n" | |||
" -b, --byte-offset print the byte offset of each lin e\n" | " -b, --byte-offset print the byte offset of each lin e\n" | |||
" -B, --before-context=<n> print <n> lines of leading contex t\n" | " -B, --before-context=<n> print <n> lines of leading contex t\n" | |||
" -c, --count only print a count of matching li nes per file\n" | " -c, --count only print a count of matching li nes per file\n" | |||
" -C, --context=<n> print <n> lines of output context \n" | " -C, --context=<n> print <n> lines of output context \n" | |||
" --color[=<when>] show matched strings in color\n" | " --color[=<when>] show matched strings in color\n" | |||
skipping to change at line 89 | skipping to change at line 91 | |||
" -H, --with-filename print the filename for each match \n" | " -H, --with-filename print the filename for each match \n" | |||
" -i, --ignore-case ignore case distinctions\n" | " -i, --ignore-case ignore case distinctions\n" | |||
" -I ignore binary files\n" | " -I ignore binary files\n" | |||
" -l, --files-with-matches only print names of files contain ing matches\n" | " -l, --files-with-matches only print names of files contain ing matches\n" | |||
" -L, --files-without-match only print names of files contain ing no matches\n" | " -L, --files-without-match only print names of files contain ing no matches\n" | |||
" -m, --max-count=<n> stop after <n> matches\n" | " -m, --max-count=<n> stop after <n> matches\n" | |||
" -M, --format=<list> process only the formats in <list >\n" | " -M, --format=<list> process only the formats in <list >\n" | |||
" -n, --line-number print the line number of each lin e\n" | " -n, --line-number print the line number of each lin e\n" | |||
" -N, --no-rcfile don't read runtime configuration file\n" | " -N, --no-rcfile don't read runtime configuration file\n" | |||
" -o, --only-matching show only the part of a line matc hing <pattern>\n" | " -o, --only-matching show only the part of a line matc hing <pattern>\n" | |||
" -O, --force-format=<fmt> force given format (bz2, gz, lz, xz)\n" | " -O, --force-format=<fmt> force the format given (bz2, gz, lz, xz)\n" | |||
" -q, --quiet suppress all messages\n" | " -q, --quiet suppress all messages\n" | |||
" -r, --recursive operate recursively on directorie s\n" | " -r, --recursive operate recursively on directorie s\n" | |||
" -R, --dereference-recursive recursively follow symbolic links \n" | " -R, --dereference-recursive recursively follow symbolic links \n" | |||
" -s, --no-messages suppress error messages\n" | " -s, --no-messages suppress error messages\n" | |||
" -v, --invert-match select non-matching lines\n" | " -v, --invert-match select non-matching lines\n" | |||
" --verbose verbose mode (show error messages )\n" | " --verbose verbose mode (show error messages )\n" | |||
" -w, --word-regexp match only whole words\n" | " -w, --word-regexp match only whole words\n" | |||
" -x, --line-regexp match only whole lines\n" | " -x, --line-regexp match only whole lines\n" | |||
" --bz2=<command> set compressor and options for bz ip2 format\n" | " --bz2=<command> set compressor and options for bz ip2 format\n" | |||
" --gz=<command> set compressor and options for gz ip format\n" | " --gz=<command> set compressor and options for gz ip format\n" | |||
" --lz=<command> set compressor and options for lz ip format\n" | " --lz=<command> set compressor and options for lz ip format\n" | |||
" --xz=<command> set compressor and options for xz format\n" | " --xz=<command> set compressor and options for xz format\n" | |||
"Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n " | "\nNumbers may be followed by a multiplier: k = kB = 10^3 = 1000, \n" | |||
"Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30 , etc...\n" ); | "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30 , etc...\n" ); | |||
show_help_addr(); | show_help_addr(); | |||
} | } | |||
int zgrep_stdin( int infd, const int format_index, | int zgrep_stdin( int infd, const int format_index, | |||
const std::vector< const char * > & grep_args ) | const std::vector< const char * > & grep_args ) | |||
{ | { | |||
Children children; | Children children; | |||
if( !set_data_feeder( "", &infd, children, format_index ) ) return 2; | if( !set_data_feeder( "", &infd, children, format_index ) ) return 2; | |||
const pid_t grep_pid = fork(); | const pid_t grep_pid = fork(); | |||
skipping to change at line 216 | skipping to change at line 218 | |||
return retval; | return retval; | |||
} | } | |||
} // end namespace | } // end namespace | |||
int main( const int argc, const char * const argv[] ) | int main( const int argc, const char * const argv[] ) | |||
{ | { | |||
enum { help_opt = 256, verbose_opt, color_opt, | enum { help_opt = 256, verbose_opt, color_opt, | |||
bz2_opt, gz_opt, lz_opt, xz_opt }; | bz2_opt, gz_opt, lz_opt, xz_opt }; | |||
int format_index = -1; | int format_index = -1; | |||
int list_mode = 0; // 1 = list matches, -1 = list non matches | int list_mode = 0; // 1 = list matches, -1 = list non-matches | |||
int recursive = 0; // 1 = '-r', 2 = '-R' | int recursive = 0; // 1 = '-r', 2 = '-R' | |||
int show_name = -1; // tri-state bool | int show_name = -1; // tri-state bool | |||
bool no_messages = false; | bool no_messages = false; | |||
std::list< std::string > filenames; | std::list< std::string > filenames; | |||
std::vector< const char * > grep_args; // args to grep, maybe empty | std::vector< const char * > grep_args; // args to grep, maybe empty | |||
std::string color_option; // needed because of optional arg | std::string color_option; // needed because of optional arg | |||
invocation_name = argv[0]; | ||||
program_name = "zgrep"; | program_name = "zgrep"; | |||
invocation_name = ( argc > 0 ) ? argv[0] : program_name; | ||||
const Arg_parser::Option options[] = | const Arg_parser::Option options[] = | |||
{ | { | |||
{ 'a', "text", Arg_parser::no }, // grep GNU | { 'a', "text", Arg_parser::no }, // grep GNU | |||
{ 'A', "after-context", Arg_parser::yes }, // grep GNU | { 'A', "after-context", Arg_parser::yes }, // grep GNU | |||
{ 'b', "byte-offset", Arg_parser::no }, // grep GNU | { 'b', "byte-offset", Arg_parser::no }, // grep GNU | |||
{ 'B', "before-context", Arg_parser::yes }, // grep GNU | { 'B', "before-context", Arg_parser::yes }, // grep GNU | |||
{ 'c', "count", Arg_parser::no }, // grep | { 'c', "count", Arg_parser::no }, // grep | |||
{ 'C', "context", Arg_parser::yes }, // grep GNU | { 'C', "context", Arg_parser::yes }, // grep GNU | |||
{ 'e', "regexp", Arg_parser::yes }, // grep | { 'e', "regexp", Arg_parser::yes }, // grep | |||
skipping to change at line 364 | skipping to change at line 366 | |||
if( show_name < 0 ) show_name = ( filenames.size() != 1 || recursive ); | if( show_name < 0 ) show_name = ( filenames.size() != 1 || recursive ); | |||
std::string input_filename; | std::string input_filename; | |||
int retval = 1; | int retval = 1; | |||
bool error = false; | bool error = false; | |||
bool stdin_used = false; | bool stdin_used = false; | |||
while( next_filename( filenames, input_filename, error, recursive, | while( next_filename( filenames, input_filename, error, recursive, | |||
false, no_messages ) ) | false, no_messages ) ) | |||
{ | { | |||
int infd; | int infd; | |||
if( input_filename.empty() ) | if( input_filename == "." ) | |||
{ | { | |||
if( stdin_used ) continue; else stdin_used = true; | if( stdin_used ) continue; else stdin_used = true; | |||
infd = STDIN_FILENO; | infd = STDIN_FILENO; input_filename = "-"; | |||
} | } | |||
else | else | |||
{ | { | |||
infd = open_instream( input_filename, format_index < 0, no_messages ); | infd = open_instream( input_filename, format_index < 0, no_messages ); | |||
if( infd < 0 ) { error = true; continue; } | if( infd < 0 ) { error = true; continue; } | |||
} | } | |||
int tmp; | int tmp; | |||
if( infd == STDIN_FILENO ) | if( infd == STDIN_FILENO ) | |||
tmp = zgrep_stdin( infd, format_index, grep_args ); | tmp = zgrep_stdin( infd, format_index, grep_args ); | |||
else tmp = zgrep_file( infd, format_index, input_filename, grep_args, | else tmp = zgrep_file( infd, format_index, input_filename, grep_args, | |||
list_mode, show_name ); | list_mode, show_name ); | |||
if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp; | if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp; | |||
if( input_filename.size() ) close( infd ); | if( close( infd ) != 0 ) | |||
{ show_file_error( input_filename.c_str(), "Error closing input file", | ||||
errno ); error = true; } | ||||
if( retval == 0 && verbosity < 0 ) break; | if( retval == 0 && verbosity < 0 ) break; | |||
} | } | |||
if( std::fclose( stdout ) != 0 ) | if( std::fclose( stdout ) != 0 ) | |||
{ | { | |||
show_error( "Error closing stdout", errno ); | show_error( "Error closing stdout", errno ); | |||
error = true; | error = true; | |||
} | } | |||
if( error && ( retval != 0 || verbosity >= 0 ) ) retval = 2; | if( error && ( retval != 0 || verbosity >= 0 ) ) retval = 2; | |||
return retval; | return retval; | |||
End of changes. 16 change blocks. | ||||
29 lines changed or deleted | 34 lines changed or added |