1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#!/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;
}
|