#!/usr/bin/perl -l

=head1 NAME

curiouscat - grep the output of a command, only printing stdout/stderr if match

=head1 SYNOPSIS

cgrep [-v] [-f PATTERNFILE | PATTERN ] COMMAND...

=head1 DESCRIPTION

curiouscat runs a command, buffering the output from both standard out
and standard error, looking for a matching pattern.  If a matching
pattern is found, stdout and stderr are printed and curiouscat exits
with the exit code of COMMAND.

If the -v switch is passed, curiouscat switches into reverse mode
where it will print if there are any lines not matching PATTERN.

=head1 AUTHOR

Copyright 2010, 2013 by Collabora Limited, written by Tollef Fog Heen
<tollef.fog.heen@collabora.co.uk>

Licensed under the GNU GPL.

=cut

use warnings;
use strict;
use IPC::Run qw( start pump finish timeout );

$|=1;

my $reverse = 0;
my @patterns = ();
my $patternfile;
use Getopt::Long;
GetOptions("v" => \$reverse,
	"f=s" => \$patternfile) || die "usage: curiouscat [-v] [-f PATTERNFILE | PATTERN ]  COMMAND...\n";

if (defined $patternfile) {
	my $p;
	open $p, "<", $patternfile or die "Can't open $patternfile: $!";
	chomp(@patterns = <$p>);
} else {
	@patterns = (shift @ARGV);
}
my @command = @ARGV;

my ($in, $out, $err);
my $h = IPC::Run::start \@command, \*STDIN, \$out, \$err;

$h->finish;

if ($reverse) {
	for my $line (split(/$\//, $out), split(/$\//, $err)) {
		my $nomatch = 1;
		for my $p (@patterns) {
			if ($line =~ /$p/m ) {
				$nomatch = 0;
				last;
			}
		}
		if ($nomatch) {
			print STDOUT $out;
			print STDERR $err;
			last;
		}
	}
} else {
	for my $p (@patterns) {
		if ($out =~ /$p/m or $err =~ /$p/m) {
			print STDOUT $out;
			print STDERR $err;
		}
	}
}
exit $h->result or 0;
