#!/usr/bin/perl

use strict 'vars';
use File::Find;
use File::Spec;
use Getopt::Long;
use English;
my $version = '$Id: findexec,v 1.3 2009/03/31 03:45:05 nebu Exp $';
my $self = rel2abs($0);
my $long_verbose = 0;
my $long_dir = undef;
my $long_help = undef;
my ($dir, $derror);
$SIG{'INT'} = \&catch_sigint; # catch SIGINT (CTRL-C) signals
GetOptions
(
    'help!'    => \$long_help,
    'verbose!' => \$long_verbose,
    'dir=s'    => \$long_dir
) || usage();

if (defined($long_dir) && !defined($long_help))
{
    $dir = $long_dir;
    if(-d $dir and -r $dir)
    {
        $dir = rel2abs($dir);
        find(\&found, $dir);
    }
    else
    {
        $derror = "Unknown Error";
        $derror = "Directory \"$dir\" is not readable" if (-d and !-r $dir);
        $derror = "Directory \"$dir\" does not exist" if (!-d $dir);
        print "$self: Error: $derror\n" and exit;
    }
}
elsif ($long_help)
{
    usage(undef);
}
else
{
    usage("Missing Operand!");
}

sub usage
{
    my $msg = shift;
    print "Error: $msg\n" if defined($msg);
    print "findexec - Find executables\n";
    print "Usage: $self [-v|--verbose] -d|--dir [DIR]\n\n";
    print "  -d|--dir       Define the Directory (required!)\n";
    print "  -v|--verbose   Enable verbose messages.\n";
    print "  -h|--help      Print this Help and exit.\n\n";
    print "$version\n";
    exit;
}

sub found
{
    my $findfile = $File::Find::name;
    my $finddir = $File::Find::dir;
    #my $findfile = rel2abs($File::Find::name);
    if(-f $findfile and -r $findfile)
    {
        if(-x $findfile)
        {
            print "$findfile\n";
        }
        else
        {
            verbose("not executable: $findfile");
        }
    }
    else
    {
        verbose("is a directory: $findfile") if(-d $findfile and -r $findfile);
        verbose("is a directory, but nor readable: $findfile") if(-d $findfile and !-r $findfile);
        verbose("not a file: $findfile") if (!-f $findfile and -r $findfile);
        verbose("not readable: $findfile") if(-f $findfile and !-r $findfile);
    }
}

sub verbose
{
    my $msg = shift;
    if($long_verbose)
    {
        print "verbose: $msg\n";
    }
}

# FIXME: use a perl-internal solution instead of readlink
sub rel2abs
{
    my $file = shift;
    #return File::Spec->rel2abs($file);
    my $p = qx[readlink -e $file];
    $p =~ s/(\n|\r)//i;
    return $p;
}

sub catch_sigint
{
    print "\nCaught CTRL-C (SIGINT), Aborting.\n";
    # don't judge me, it works just fine
    qx[kill -9 $PID] and exit;
}
