#!/usr/local/bin/perl -w

# $Id$
# $Source$

use strict;
use Getopt::Std;
use RPM::Perlonly;
use Data::Dumper;

my @RPMPATHS=(
	"/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/7.3/en/os/i386/RedHat/RPMS",
	"/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/updates/7.3/en/os/i386",
	"/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/updates/7.3/en/os/i686",
	"/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/updates/7.3/en/os/noarch",
	"/home/ward/REDHAT73/homemade",
);

my %instrpms = ();
my %refrpms = ();
my %option = ();

&cmdline;

# Met pathread en RPM-Perlonly-1.0.1 moet het mogelijk zijn te bepalen
# welke RPM de nieuwste is. Hierna is het (denk ik) relatief eenvoudig
# te bepalen op welke systemen er dus packages geupdate moeten worden...

sub pathread {
	my %entry = ();
	my ( $line, $prefix );
	foreach $prefix ( @RPMPATHS ) {
		opendir DH, $prefix;
		while ($line = readdir DH) {
			if ($line =~ /\.rpm$/ ) {
#				&splitname($line);
				tie my %rpm, "RPM::Perlonly", "$prefix/$line" or die "Problem, could not open $line: $!";
				#foreach ( sort keys %rpm ) {
				#	print "$_	-> $rpm{$_}\n";
				#}
				#print "Fullname $line\n";
				#print "	NAME:		$rpm{'NAME'}\n";
				#print "	VERSION:	$rpm{'VERSION'}\n";
				#print "	RELEASE:	$rpm{'RELEASE'}\n";
				if ( ! exists( $rpm{'EPOCH'} ) ) {
					$rpm{'EPOCH'} = 0;
				}
				#print "	ARCH:		$rpm{'ARCH'}\n";
				push @{$refrpms{$rpm{'NAME'}}}, ( {
					'NAME', $rpm{'NAME'},
					'BUILDTIME', $rpm{'BUILDTIME'},
					'VERSION', $rpm{'VERSION'},
					'RELEASE', $rpm{'RELEASE'},
					'EPOCH', $rpm{'EPOCH'},
					'ARCH', $rpm{'ARCH'},
					'FILENAME', $line
				} );
				untie(%rpm);
			}
			#print "$line\n";
		}
		closedir DH;
	}
	&outputnewest(%refrpms);
}

sub fileread($) {
	my $file = shift;
	my $VAR1;
	open FH, "<$file" or die "Couldn't open $file: $!";
	my $data = do { local $/; <FH>; };
	close FH;
	eval $data;
	%refrpms = %{$VAR1};
	&outputnewest(%refrpms);
}

sub serverread($) {
	my $server = shift;
	my $name;
	if ( $option{l} ) {
		open CH, "rpm -qa|" or die "Can't fork: $!";
	} else {
		open CH, "ssh -x $server rpm -qa|" or die "Can't fork: $!";
	}
	while ( <CH> ) {
		chomp;
		$name = $_;
		$name =~ s/(.*?)-([^-]*)-([^-]*)$/$1/;
		unless ( $option{q} ) {
			print "$_\n";
			print "$name\n";
		}
		push @{$instrpms{$name}}, $_;
	}
	close CH;
}

sub comparerpms() {
	my ( $correct, $installed );
	foreach ( sort keys %instrpms ) {
		if ( exists $refrpms{$_} ) {
			$correct = @{$refrpms{$_}}[0]->{'FILENAME'};
			$correct =~ s/\.(i[36]86|athlon|noarch)(\.rpm)?$//;
			foreach $installed ( @{$instrpms{$_}} ) {
				unless ( $correct eq $installed ) {
					print "\ncorrect:	$correct\n";
					print "installed:	$installed\n";
				}
			}
		} else {
			print "\n$_ doesn't exist in reference tree\n";
			foreach my $rpm ( @{ $instrpms{$_} } ) {
				print "		$rpm\n";
			}
		}
	}
}

sub outputnewest(@) {
	my %allrpms = @_;
	if ( $option{q} ) { return; }
	foreach ( sort keys %allrpms) {
#		print scalar( @{$allrpms{$_}} ) . " $_\n";
		if ( scalar( @{$allrpms{$_}} ) > 1 ) {
			@{$allrpms{$_}} = sort buildtimesort @{$allrpms{$_}};
#			foreach my $rpm ( sort buildtimesort @{$allrpms{$_}} ) {
#				print "	" . %{$rpm}->{'BUILDTIME'} . " " . %{$rpm}->{'FILENAME'} . "\n";
#			}
		}
		print @{$allrpms{$_}}[0]->{'FILENAME'}."\n";
	}
}

sub buildtimesort {
	my $a = %{$a}->{'BUILDTIME'};
	my $b = %{$b}->{'BUILDTIME'};
	if ( $a > $b ) {
		return -1;
	} else {
		return 1;
	}
}

sub splitname($$) {
	my $fullname = shift;
	my $packagename;
	my $version;
	my $build;
	my $arch;

	if ( $fullname =~ /(.*?)-([^-]*)-([^-]*)\.(i[36]86|athlon|noarch)(\.rpm)?$/ ) {
		$packagename = $1;
		$version = $2;
		$build =$3;
		$arch = $4;
		print "Fullname $fullname\n";
		print "	PACKAGE:	$packagename\n";
		print "	VERSION:	$version\n";
		print "	BUILD:		$build\n";
		print "	ARCH:		$arch\n";
		return ( $packagename, $version, $build, $arch );
	} else {
		print "The magic don't work for $fullname\n";
	}
}

sub cmdline {
	getopts("f:hlo:pqs:", \%option);
	
	if ( $option{h} ) { &help; }
	unless ( $option{f} || $option{l} || $option{p} || $option{s} ) { &help; }

	if (
		( $option{f} && ( $option{p} || $option{o} ) ) ||
		( $option{l} && $option{s} )
	) {
		&help;
	}

	if ( $option{f} ) {
		&fileread($option{f});
	} elsif ( $option{p}  ) {
		&pathread;
		if ( $option{o} ) {
			open(FH, ">$option{o}") or die "Couldn't open $option{o}: $!";
			print FH Dumper(\%refrpms);
			close(FH);
		}
	}
	if ( $option{l} ) {
		&serverread("localhost");
	} elsif ( $option{s} ) {
		&serverread($option{s});
	}
	if ( ( $option{f} || $option{p} ) && ( $option{l} || $option{s} ) ) {
		&comparerpms;
	}
}

sub help() {
	print << "EOT";

	Usage: $0 [option]

	-f <file>	Read reference rpms from file
	-h		Display this help
	-l		Read installed rpms from localhost, overrides -s
	-o <file>	Write reference rpms to file, only useful in combination with -p
	-p		Read rpms from build in mirror paths
	-q		Quiet down a bit
	-s <server>	Read rpms from server

	Usually you'll want to run this program like
		$0 -p -o <file>
	to build an index to compare you're systems to and then proceed
	with something like
		$0 -f <file> -s <server>
	for each server which you want to check the status of.

EOT
	exit;
}

# sorteer routine die "menselijk" sorteerd; bijv.:
# boneym100 elvis1 elvis2 elvis10
#sub wardsort {
#	my @a = split(/([0-9]+)/,$a);
#	my @b = split(/([0-9]+)/,$b);
#
#	foreach my $x (@a)
#	{
#		my $y = shift @b;
#		my $r = ($x =~ /^[0-9]+$/ && $y =~ /^[0-9]+$/) ?
#					($x <=> $y) :  ($x cmp $y);
#		$r && return $r;
#	}
#	return -1 if (@b);
#	0;
#}
