+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+sub vernum($) {
+ if ($_[0] =~ m!^((?:\d+\.)+\d+)$!) {
+ my ($maj, $min) = split /\./, $1;
+ return int($maj) * 256 + int($min);
+ }
+
+ return 0;
+}
+
+sub vercmp($$$) {
+ my ($op, $v1, $v2) = @_;
+
+ if ($op eq 'lt') { return $v1 < $v2 }
+ elsif ($op eq 'le') { return $v1 <= $v2 }
+ elsif ($op eq 'gt') { return $v1 > $v2 }
+ elsif ($op eq 'ge') { return $v1 >= $v2 }
+ elsif ($op eq 'eq') { return $v1 == $v2 }
+
+ return 0;
+}
+
+sub findbin($$$) {
+ my ($basename, $compare, $maxvstr) = @_;
+
+ my $lastversion = 0;
+ my $cmpversion = vernum($maxvstr);
+ my $prog = undef;
+
+ foreach my $dir (split /:/, $ENV{'PATH'}) {
+ foreach my $bin (glob("$dir/$basename?*"), "$dir/$basename") {
+ if (-x $bin && open BIN, '-|', $bin, '--version') {
+ my $vers = 0;
+ my $line = readline(BIN) || '';
+
+ foreach my $token (split /\s+/, $line) {
+ $vers = vernum($token);
+ last if $vers > 0;
+ }
+
+ if ($vers > 0 && (!$cmpversion || vercmp($compare, $vers, $cmpversion))) {
+ if ($vers > $lastversion) {
+ $lastversion = $vers;
+ $prog = $bin;
+ }
+ }
+
+ close BIN;
+ }
+ }
+ }
+
+ return $prog;
+}
+
+my $bin = findbin($ARGV[0], $ARGV[1], $ARGV[2]);
+
+if (defined $bin) {
+ printf "%s\n", $bin;
+ exit 0;
+}
+else {
+ warn "Cannot find a $ARGV[0] command with version $ARGV[1] $ARGV[2]\n";
+ exit 1;
+}