summaryrefslogtreecommitdiffstats
path: root/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'main.cc')
-rw-r--r--main.cc467
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;
- }