#!/usr/bin/perl

use strict ;
use warnings ;
use autodie ;

use Carp ;
use File::Copy ;
use Getopt::Long::Descriptive ;
use IPC::Run qw/run/ ;

use Stanford::Orange::Util qw/run_command_improved / ;
use Stanford::Orange::LogTrend qw/ list_files_in_order / ;

my $DEBUG = 0 ;

my ($opt, $usage) = describe_options(
    'run-through-filter-syslog %o directory regex',
    ['nomail|n',  'send to stdout rather than e-mail'],
    ['verbose|v', 'print extra stuff'],
    ['help',      'print usage message and exit'],
    ['manual|m',  'print man page'],
) ;

sub get_man_page {
    my @cmd = ('perldoc', '-t', $0) ;
    my ($stdout, $stderr, $exit_value) = run_command_improved(@cmd) ;
    return $stdout ;
}

sub progress {
    my ($msg) = @_ ;

    if ($DEBUG) {
        print $msg . "\n" ;
    }
    return ;
}

sub exit_with_error {
    my ($msg) = @_ ;
    print $msg . "\n" ;
    exit 1 ;
}

sub run_through_filter_syslog {
    my ($file) = @_ ;

    # Do we need to uncompress?
    my ($compression_ext, $de_compress) ;
    if ($file =~ m{gz$}xsm) {
        $compression_ext = 'gz' ;
        $de_compress     = 'gunzip' ;
    } elsif ($file =~ m{xz$}xsm) {
        $compression_ext = 'xz' ;
        $de_compress     = 'unxz' ;
    } else {
        $compression_ext = undef ;
    }

    my $file_to_process ;
    my $fh ;

    if ($compression_ext) {
        progress("we need to decompress $file") ;
        progress("decompress program is $de_compress") ;

        $fh              = File::Temp->new() ;
        $file_to_process = $fh->filename ;

        my $file_to_process_xx = $file_to_process . q{.} . $compression_ext ;
        progress("will decompress file $file_to_process_xx") ;

        my $size = -s $file ;
        progress("undecompressed file has size $size") ;

        # Copy
        copy($file, $file_to_process_xx) ;
        progress("file copied to $file_to_process_xx") ;

        # Uncompress
        my @cmd = ($de_compress, '--force', $file_to_process_xx) ;
        progress('decompression command: ' . join(q{ }, @cmd)) ;
        progress("about to decompress $file_to_process_xx...") ;
        my ($stdout, $stderr, $rc) = run_command_improved(@cmd) ;
        if ($stderr) {
            croak "error ${de_compress}'ing file '$file_to_process_xx': $stderr" ;
        }
        progress('...de-compression finished') ;
    } else {
        $file_to_process = $file ;
    }

    # We now have an uncompressed file we can run through filter-syslog.
    my @cmd = ('filter-syslog') ;

    if ($opt->nomail()) {
        push(@cmd, '-n') ;
    }

    my ($out) ;
    progress('about to run filter-syslog command: ' . join(q{ }, @cmd)) ;

    # $ENV{'IPCRUNDEBUG'} = 'basic' ;

    open(my $INFH, '<', $file_to_process) ;

    run \@cmd, $INFH, \$out ;
    progress('finished filter-syslog command') ;

    close($INFH) ;

    if ($opt->nomail()) {
        print $out ;
    }

    return ;
}

##################################################################################

if ($opt->help) {
    print $usage->text() ;
    exit 0 ;
} elsif ($opt->manual()) {
    print get_man_page() ;
    exit 0 ;
}

if ($opt->verbose()) {
    $DEBUG = 1 ;
}
progress("\$DEBUG is $DEBUG") ;

# Get the two main arguments.
my $directory = $ARGV[0] ;
my $regex     = $ARGV[1] ;

if (!$directory || !$regex) {
    print $usage->text() ;
    exit 0 ;
}

progress("directory is '$directory'") ;
progress("regex     is '$regex'") ;

# Get the files in $directory matching $regex in order of when they were
# last modified with most recent FIRST.
my @files = list_files_in_order($directory, $regex) ;
progress('files in order: ' . join("\n", @files)) ;

# If there are no files matching, exit with an error.
if (scalar(@files) == 0) {
    exit_with_error("no files found matching regex '$regex' in $directory") ;
}

# Take the first file in the list (this is the most recent one).
my $file_newest = $files[0] ;
progress("most recent file is '$file_newest'") ;

# Run through filter-syslog
my $results = run_through_filter_syslog($file_newest) ;

exit 0 ;

__END__

=head1 NAME

run-through-filter-syslog - Process file through filter-syslog

=head1 SYNOPSIS

run-through-filter-syslog [B<-n>] [B<-v>] dir reg

=head1 DESCRIPTION

Given a directory B<dir> and a Perl-compatible regular-expression
B<regex> the B<run-through-filter-syslog> program looks for the newest
file in B<dir> whose filename matches B<regex>. It takes this file,
uncompresses it (if necessary), and then runs it through
B<filter-syslog>.

If the option B<-n> is used, then the output is not mailed to the e-mail
specified in B</etc/filter-syslog.conf> but instead directed to stdout.

=head1 OPTIONS

=over 4

=item B<-n>

The output of B<filter-syslog> is normally mailed to the e-mail
specified in B</etc/filter-syslog.conf>. If the B<-n> option is used
no e-mail is sent and instead the output is sent to stdout.

=item B<-v>

Show verbose output.

=back

=head1 EXIT STATUS

B<run-through-filter-syslog> will exit with 0 on success, and 1 if there are any problems.

=head1 EXAMPLES

Send the latest archived Apache error log through filter-syslog and send
to the e-mail specified in B</etc/filter-syslog.conf>:

    run-through-filter-syslog /var/log/apache2/OLD '^error_log'

Do the same as above but send out to stdout rather than sending to an
e-mail address:

    run-through-filter-syslog -n /var/log/apache2/OLD '^error_log'

=head1 SEE ALSO

filter-syslog(1)

=head1 AUTHOR

Adam Lewenberg <adamhl@stanford.edu>

=head1 COPYRIGHT AND LICENSE

Copyright 2016 The Board of Trustees of the Leland Stanford Junior
University.  All rights reserved.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Stanford University not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission.  Stanford University makes no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.

THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

=cut

#############################################################################
#############################################################################
