diff options
Diffstat (limited to 'main.cc')
-rw-r--r-- | main.cc | 467 |
1 files changed, 0 insertions, 467 deletions
diff --git a/main.cc b/main.cc deleted file mode 100644 index 04956b6..0000000 --- a/main.cc +++ /dev/null @@ -1,467 +0,0 @@ -/* Zutils - Utilities dealing with compressed files - Copyright (C) 2009, 2010, 2011, 2012, 2013 Antonio Diaz Diaz. - - 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 - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define _FILE_OFFSET_BITS 64 - -#include <cerrno> -#include <climits> -#include <csignal> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <list> -#include <string> -#include <vector> -#include <dirent.h> -#include <fcntl.h> -#include <stdint.h> -#include <unistd.h> -#include <sys/stat.h> -#if defined(__MSVCRT__) || defined(__OS2__) -#include <io.h> -#endif - -#include "arg_parser.h" -#include "zutils.h" -#include "rc.h" - -#if CHAR_BIT != 8 -#error "Environments where CHAR_BIT != 8 are not supported." -#endif - - -namespace { - -#ifdef O_BINARY -const int o_binary = O_BINARY; -#else -const int o_binary = 0; -#endif - -enum Mode { m_none, m_zcat, m_zgrep, m_ztest }; - - -void show_help() - { - std::printf( "Zutils is a collection of utilities able to deal with any combination of\n" - "compressed and uncompressed files transparently. If any given file,\n" - "including standard input, is compressed, its decompressed content is used.\n" - "\nThe supported formats are bzip2, gzip, lzip and xz.\n" - "\nUsage: %s <operation> [options] [files]\n", invocation_name ); - std::printf( "\nTry '%s <operation> --help' for more specific help.\n", invocation_name ); - std::printf( "\nOperations:\n" - " -h, --help display this help and exit\n" - " -V, --version output version information and exit\n" - " --zcat zcat operation\n" - " --zgrep zgrep operation\n" - " --ztest ztest operation\n" ); - show_help_addr(); - } - - -int simple_extension_index( const std::string & name ) - { - for( int i = 0; i < num_formats; ++i ) - { - const std::string ext( simple_extensions[i] ); - if( name.size() > ext.size() && - name.compare( name.size() - ext.size(), ext.size(), ext ) == 0 ) - return i; - } - return -1; - } - - -int open_instream( std::string & input_filename, const Mode program_mode, - const bool search ) - { - int infd = open( input_filename.c_str(), O_RDONLY | o_binary ); - if( infd < 0 ) - { - if( search && ( program_mode == m_zcat || program_mode == m_zgrep ) && - simple_extension_index( input_filename ) < 0 ) - { - for( int i = 0; i < num_formats; ++i ) - { - const std::string name( input_filename + - simple_extensions[format_order[i]] ); - infd = open( name.c_str(), O_RDONLY | o_binary ); - if( infd >= 0 ) { input_filename = name; break; } - } - } - if( infd < 0 ) - show_error2( "Can't open input file", input_filename.c_str() ); - } - return infd; - } - -#include "zcat.cc" -#include "zgrep.cc" -#include "ztest.cc" - -} // end namespace - - -int main( const int argc, const char * const argv[] ) - { - enum { format_opt = 256, help_opt, verbose_opt, - bz2_opt, gz_opt, lz_opt, xz_opt, - zcat_opt, zgrep_opt, ztest_opt }; - const Arg_parser::Option * options = 0; - int infd = -1; - int format_index = -1; - Mode program_mode = m_none; - bool recursive = false; - std::string input_filename; - std::list< std::string > filenames; - Cat_options cat_options; - std::vector< const char * > grep_args; // args to grep, maybe empty - std::vector< const char * > ztest_args; // args to ztest, maybe empty - invocation_name = argv[0]; - - const Arg_parser::Option m_zcat_options[] = - { - { 'A', "show-all", Arg_parser::no }, // cat - { 'b', "number-nonblank", Arg_parser::no }, // cat - { 'c', "stdout", Arg_parser::no }, // gzip - { 'd', "decompress", Arg_parser::no }, // gzip - { 'e', 0, Arg_parser::no }, // cat - { 'E', "show-ends", Arg_parser::no }, // cat - { 'f', "force", Arg_parser::no }, // gzip - { 'h', "help", Arg_parser::no }, - { 'l', "list", Arg_parser::no }, // gzip - { 'L', "license", Arg_parser::no }, // gzip - { 'n', "number", Arg_parser::no }, // cat - { 'N', "no-rcfile", Arg_parser::no }, - { 'q', "quiet", Arg_parser::no }, - { 'r', "recursive", Arg_parser::no }, - { 's', "squeeze-blank", Arg_parser::no }, // cat - { 't', 0, Arg_parser::no }, // cat - { 'T', "show-tabs", Arg_parser::no }, // cat - { 'v', "show-nonprinting", Arg_parser::no }, // cat - { 'V', "version", Arg_parser::no }, - { format_opt, "format", Arg_parser::yes }, - { verbose_opt, "verbose", Arg_parser::no }, - { bz2_opt, "bz2", Arg_parser::yes }, - { gz_opt, "gz", Arg_parser::yes }, - { lz_opt, "lz", Arg_parser::yes }, - { xz_opt, "xz", Arg_parser::yes }, - { zcat_opt, "zcat", Arg_parser::no }, - { 0 , 0, Arg_parser::no } }; - - const Arg_parser::Option m_zgrep_options[] = - { - { 'a', "text", Arg_parser::no }, // grep GNU - { 'A', "after-context", Arg_parser::yes }, // grep GNU - { 'b', "byte-offset", Arg_parser::no }, // grep GNU - { 'B', "before-context", Arg_parser::yes }, // grep GNU - { 'c', "count", Arg_parser::no }, // grep - { 'C', "context", Arg_parser::yes }, // grep GNU - { 'e', "regexp", Arg_parser::yes }, // grep - { 'E', "extended-regexp", Arg_parser::no }, // grep - { 'f', "file ", Arg_parser::yes }, // grep - { 'F', "fixed-strings", Arg_parser::no }, // grep - { 'h', "no-filename", Arg_parser::no }, // grep GNU - { 'H', "with-filename", Arg_parser::no }, // grep GNU - { 'i', "ignore-case", Arg_parser::no }, // grep - { 'I', 0, Arg_parser::no }, // grep GNU - { 'l', "files-with-matches", Arg_parser::no }, // grep - { 'L', "files-without-match", Arg_parser::no }, // grep GNU - { 'm', "max-count", Arg_parser::yes }, // grep GNU - { 'n', "line-number", Arg_parser::no }, // grep - { 'N', "no-rcfile", Arg_parser::no }, - { 'o', "only-matching", Arg_parser::no }, // grep - { 'q', "quiet", Arg_parser::no }, - { 'r', "recursive", Arg_parser::no }, - { 's', "no-messages", Arg_parser::no }, // grep - { 'v', "invert-match", Arg_parser::no }, // grep - { 'V', "version", Arg_parser::no }, - { 'w', "word-regexp", Arg_parser::no }, // grep GNU - { 'x', "line-regexp", Arg_parser::no }, // grep - { format_opt, "format", Arg_parser::yes }, - { help_opt, "help", Arg_parser::no }, - { verbose_opt, "verbose", Arg_parser::no }, - { bz2_opt, "bz2", Arg_parser::yes }, - { gz_opt, "gz", Arg_parser::yes }, - { lz_opt, "lz", Arg_parser::yes }, - { xz_opt, "xz", Arg_parser::yes }, - { zgrep_opt, "zgrep", Arg_parser::no }, - { 0 , 0, Arg_parser::no } }; - - const Arg_parser::Option m_ztest_options[] = - { - { 'h', "help", Arg_parser::no }, - { 'N', "no-rcfile", Arg_parser::no }, - { 'q', "quiet", Arg_parser::no }, - { 'r', "recursive", Arg_parser::no }, - { 'v', "verbose", Arg_parser::no }, - { 'V', "version", Arg_parser::no }, - { format_opt, "format", Arg_parser::yes }, - { bz2_opt, "bz2", Arg_parser::yes }, - { gz_opt, "gz", Arg_parser::yes }, - { lz_opt, "lz", Arg_parser::yes }, - { xz_opt, "xz", Arg_parser::yes }, - { ztest_opt, "ztest", Arg_parser::no }, - { 0 , 0, Arg_parser::no } }; - - { // parse operation - const Arg_parser::Option operations[] = - { - { 'h', "help", Arg_parser::no }, - { 'V', "version", Arg_parser::no }, - { zcat_opt, "zcat", Arg_parser::no }, - { zgrep_opt, "zgrep", Arg_parser::no }, - { ztest_opt, "ztest", Arg_parser::no }, - { 0 , 0, Arg_parser::no } }; - - const Arg_parser parser( argv[1], ( argc > 2 ) ? argv[2] : 0, operations ); - if( parser.error().size() ) // bad operation - { show_error( parser.error().c_str(), 0, true ); return 1; } - - if( parser.arguments() > 0 ) - { - switch( parser.code( 0 ) ) - { - case 0 : break; - case 'h': show_help(); return 0; - case 'V': show_version(); return 0; - case zcat_opt : program_mode = m_zcat; options = m_zcat_options; - util_name = "zcat"; break; - case zgrep_opt : program_mode = m_zgrep; options = m_zgrep_options; - util_name = "zgrep"; break; - case ztest_opt : program_mode = m_ztest; options = m_ztest_options; - util_name = "ztest"; break; - default : internal_error( "uncaught option" ); - } - } - -#if defined(__MSVCRT__) || defined(__OS2__) - setmode( STDIN_FILENO, O_BINARY ); - setmode( STDOUT_FILENO, O_BINARY ); -#endif - - if( program_mode == m_none ) - { - show_error( "You must specify the operation to be performed.", 0, true ); - return 1; - } - } // end parse operation - - const int eretval = ( program_mode == m_zgrep ) ? 2 : 1; - const Arg_parser parser( argc, argv, options ); - if( parser.error().size() ) // bad option - { show_error( parser.error().c_str(), 0, true ); return eretval; } - - maybe_process_config_file( parser ); - - int argind = 0; - int grep_show_name = -1; - int grep_list_mode = 0; // 1 = list matches, -1 = list non matches - bool grep_pattern_found = false; - for( ; argind < parser.arguments(); ++argind ) - { - const int code = parser.code( argind ); - const char * const arg = parser.argument( argind ).c_str(); - if( !code ) - { - if( program_mode == m_zgrep && !grep_pattern_found ) - { grep_args.push_back( arg ); grep_pattern_found = true; continue; } - else break; // no more options - } - switch( code ) // common options - { - case 'N': continue; - case format_opt: format_index = parse_format_type( arg ); continue; - case bz2_opt: parse_compressor( arg, fmt_bz2, eretval ); continue; - case gz_opt: parse_compressor( arg, fmt_gz, eretval ); continue; - case lz_opt: parse_compressor( arg, fmt_lz, eretval ); continue; - case xz_opt: parse_compressor( arg, fmt_xz, eretval ); continue; - } - switch( program_mode ) - { - case m_none: internal_error( "invalid operation" ); break; - case m_zcat: - switch( code ) - { - case 'A': cat_options.show_ends = true; - cat_options.show_nonprinting = true; - cat_options.show_tabs = true; break; - case 'b': cat_options.number_lines = 1; break; - case 'c': break; - case 'd': break; - case 'e': cat_options.show_nonprinting = true; // fall through - case 'E': cat_options.show_ends = true; break; - case 'f': break; - case 'h': show_zcat_help(); return 0; - case 'l': break; - case 'L': break; - case 'n': if( cat_options.number_lines == 0 ) - { cat_options.number_lines = 2; } break; - case 'q': verbosity = -1; break; - case 'r': recursive = true; break; - case 's': cat_options.squeeze_blank = true; break; - case 't': cat_options.show_nonprinting = true; // fall through - case 'T': cat_options.show_tabs = true; break; - case 'v': cat_options.show_nonprinting = true; break; - case 'V': show_version( "Zcat" ); return 0; - case verbose_opt : if( verbosity < 4 ) ++verbosity; break; - case zcat_opt : break; - default : internal_error( "uncaught option" ); - } break; - case m_zgrep: - switch( code ) - { - case 'a': grep_args.push_back( "-a" ); break; - case 'A': grep_args.push_back( "-A" ); grep_args.push_back( arg ); break; - case 'b': grep_args.push_back( "-b" ); break; - case 'B': grep_args.push_back( "-B" ); grep_args.push_back( arg ); break; - case 'c': grep_args.push_back( "-c" ); break; - case 'C': grep_args.push_back( "-C" ); grep_args.push_back( arg ); break; - case 'e': grep_args.push_back( "-e" ); grep_args.push_back( arg ); - grep_pattern_found = true; break; - case 'E': grep_args.push_back( "-E" ); break; - case 'f': grep_args.push_back( "-f" ); grep_args.push_back( arg ); - grep_pattern_found = true; break; - case 'F': grep_args.push_back( "-F" ); break; - case 'h': grep_show_name = false; break; - case 'H': grep_show_name = true; break; - case 'i': grep_args.push_back( "-i" ); break; - case 'I': grep_args.push_back( "-I" ); break; - case 'l': grep_args.push_back( "-l" ); grep_list_mode = 1; break; - case 'L': grep_args.push_back( "-L" ); grep_list_mode = -1; break; - case 'm': grep_args.push_back( "-m" ); grep_args.push_back( arg ); break; - case 'n': grep_args.push_back( "-n" ); break; - case 'o': grep_args.push_back( "-o" ); break; - case 'q': grep_args.push_back( "-q" ); verbosity = -1; break; - case 'r': recursive = true; break; - case 's': grep_args.push_back( "-s" ); verbosity = -1; break; - case 'v': grep_args.push_back( "-v" ); break; - case 'V': show_version( "Zgrep" ); return 0; - case 'w': grep_args.push_back( "-w" ); break; - case 'x': grep_args.push_back( "-x" ); break; - case help_opt : show_zgrep_help(); return 0; - case verbose_opt : if( verbosity < 4 ) ++verbosity; break; - case zgrep_opt : break; - default : internal_error( "uncaught option" ); - } break; - case m_ztest: - switch( code ) - { - case 'h': show_ztest_help(); return 0; - case 'q': verbosity = -1; ztest_args.push_back( "-q" ); break; - case 'r': recursive = true; break; - case 'v': if( verbosity < 4 ) ++verbosity; - ztest_args.push_back( "-v" ); break; - case 'V': show_version( "Ztest" ); return 0; - case ztest_opt : break; - default : internal_error( "uncaught option" ); - } break; - } - } // end process options - - if( program_mode == m_zgrep && !grep_pattern_found ) - { show_error( "Pattern not found." ); return 2; } - - for( ; argind < parser.arguments(); ++argind ) - filenames.push_back( parser.argument( argind ) ); - - if( filenames.empty() ) filenames.push_back("-"); - - if( grep_show_name < 0 ) - grep_show_name = ( filenames.size() != 1 || recursive ); - - int retval = ( program_mode == m_zgrep ) ? 1 : 0; - while( !filenames.empty() ) - { - input_filename = filenames.front(); - filenames.pop_front(); - if( !input_filename.size() || input_filename == "-" ) - { - input_filename.clear(); - infd = STDIN_FILENO; - } - else - { - if( recursive ) - { - struct stat st; - if( stat( input_filename.c_str(), &st ) == 0 && S_ISDIR( st.st_mode ) ) - { - DIR * const dirp = opendir( input_filename.c_str() ); - if( !dirp ) - { - show_error2( "Can't open directory", input_filename.c_str() ); - if( retval < 1 ) retval = 1; continue; - } - std::list< std::string > tmp_list; - while( true ) - { - const struct dirent * const entryp = readdir( dirp ); - if( !entryp ) { closedir( dirp ); break; } - std::string tmp_name( entryp->d_name ); - if( tmp_name != "." && tmp_name != ".." ) - tmp_list.push_back( input_filename + "/" + tmp_name ); - } - filenames.splice( filenames.begin(), tmp_list ); - continue; - } - } - infd = open_instream( input_filename, program_mode, format_index < 0 ); - if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } - } - - int tmp = 0; - switch( program_mode ) - { - case m_none: - break; - case m_zcat: - tmp = cat( infd, format_index, input_filename, cat_options ); - break; - case m_zgrep: - if( infd == STDIN_FILENO ) - tmp = zgrep_stdin( infd, format_index, grep_args ); - else tmp = zgrep_file( infd, format_index, input_filename, grep_args, - grep_list_mode, grep_show_name ); - break; - case m_ztest: - if( infd == STDIN_FILENO ) - tmp = ztest_stdin( infd, format_index, ztest_args ); - else tmp = ztest_file( infd, format_index, input_filename, ztest_args ); - break; - } - if( program_mode == m_zgrep ) - { if( tmp == 0 || ( tmp == 2 && retval == 1 ) ) retval = tmp; } - else if( tmp > retval ) retval = tmp; - - if( input_filename.size() ) - { close( infd ); infd = -1; } - } - - if( std::fclose( stdout ) != 0 ) - { - show_error( "Can't close stdout", errno ); - switch( program_mode ) - { - case m_none: break; - case m_zcat: retval = 1; break; - case m_zgrep: if( retval != 0 || verbosity >= 0 ) retval = 2; break; - case m_ztest: if( retval == 0 ) retval = 1; break; - } - } - return retval; - } |