#!/usr/bin/perl -w

# a thanks to ganesh@cse.iitb.ernet.in for beta testing :-)

unless ($> == 0){
    print STDERR "$0: must be run as root!!\n";
    exit 1;
}

if(!defined($DEBUG)){
    $DEBUG = 0;
}

if($#ARGV >= 0){
    print STDERR "requiring $ARGV[0]\n" if $DEBUG;
    require $ARGV[0];
}else{
    print STDERR "requiring default /etc/rpm-updates.conf\n" if $DEBUG;
    require "/etc/rpm-updates.conf";
}

if(defined($have_ftp)){
    *get_config = \&net_get_config;
    *do_ugpkg = \&net_do_ugpkg;
}else{
    *get_config = \&cmd_get_config;
    *do_ugpkg = \&cmd_do_ugpkg;
}

$update_url = 'ftp://' . $update_index_host  . $update_index_path;

print STDERR "chdir()'ing to /var/tmp\n" if $DEBUG;
unless(chdir("/var/tmp")){
    print STDERR "chdir error: $!\n";
    exit 1;
}
&get_config;

sub net_get_config{
    my($ftp_cfg);
    print STDERR "connecting to $update_index_host\n" if $DEBUG;
    unless(defined($ftp_cfg = Net::FTP->new($update_index_host))){
	print STDERR "Net::FTP->net error: $@\n";
	exit 1;
    }
    print STDERR "loging in with $login, $password\n" if $DEBUG;
    unless($ftp_cfg->login($login, $password)){
	print STDERR "login error: $!\n";
	exit 1;
    }
    $ftp_cfg->type('I');
    print STDERR "chdir()'ing on ftp server to $update_index_path\n"
	if $DEBUG;
    unless($ftp_cfg->cwd($update_index_path)){
	print STDERR "error chdir()'ing on remote server while ",
	"trying to get index file: $!\n";
	exit 1;
    }
    unless(defined(@filelist = $ftp_cfg->ls)){
	print STDERR "error getting listing of index files: $!\n";
	exit 1;
    }

    # sort through filelist for our custom file
    foreach $i ( @filelist ){
	if ( $i eq $prefered_file ){
	    print STDERR "using preffered file $i\n"
		if $DEBUG;
	    unless($ftp_cfg->get($i)){
		print STDERR "error getting $i: $!\n";
		exit 1;
	    }
	    $ftp_cfg->quit;
	    &do_updates($i);
	    exit(0);
	}
    }
    # couldn't find our specific file, use defaults
    print STDERR "couldn't find preffered file, using default\n" 
	if $DEBUG;
    unless($ftp_cfg->get($default_file)){
	print STDERR "error getting default config file: $!\n";
	exit 1;
    }
    $ftp_cfg->quit;
    $password = (split('@', $password))[0];
    &do_updates($default_file);
    exit(0);
}

sub cmd_get_config{
    my($retval);
    if($DEBUG){
	print STDERR "running ", $ftp_cmd, " ", $update_url, 
	$prefered_file, "\n" ;
    }
    if(($retval=system ($ftp_cmd . " " . $update_url . $prefered_file)) == 0) {
	print STDERR "running do_updates on $prefered_file\n" if $DEBUG;
	&do_updates ($prefered_file) ;
    }
    unless($retval){
	if ($DEBUG){
	    print STDERR "running ", $ftp_cmd, " ", $update_url, 
	    $prefered_file, "\n" ;
	}
	if(system ($ftp_cmd . " " . $update_url . $default_file) == 0){
	    print STDERR "running do_updates on $prefered_file\n" if $DEBUG;
	    &do_updates ($default_file) ;
	}else{
	    print STDERR "couldn't get any config files! $!\n";
	    exit(1);
	}
    }
}


sub net_do_ugpkg{
    my($pkg, $pkg_local, $rpm_uvh, $ugcmd);
    $rpm_uvh = "rpm -Uvh ";
    $pkg = shift;
    $pkg_local = $pkg . '.' . $$;
    $ugcmd = $rpm_uvh . $pkg_local;

    print STDERR "retrieving $pkg as $pkg_local\n" if $DEBUG;
    if(defined($ftp_upg->get($pkg, $pkg_local))){
	print STDERR "running $ugcmd\n" if $DEBUG;
	unless(system($ugcmd) == 0){
	    print STDERR "$ugcmd failed: $!\n";
	}
	print STDERR "unlinking $pkg_local\n" if $DEBUG;
	unless(unlink($pkg_local) == 1){
	    print STDERR "unlink failed: $!\n";
	}
    }else{
	print STDERR "Could not open $pkg - skipping\n";
    }
}

sub cmd_do_ugpkg{
    my ($rpm_uvh, $rpmfile, $ugcmd);
    $rpm_uvh = "rpm -Uvh ftp://" . $update_rpms_host . 
	$update_rpms_dir . '/';
    $rpmfile = shift;
    $ugcmd = $rpm_uvh . $rpmfile;
    print STDERR "running $ugcmd\n" if $DEBUG;
    unless(system($ugcmd) == 0){
	print STDERR "$ugcmd failed: $!\n";
    }
}

sub do_updates{
    # file format:
    # package_name package_file_name
    my($rpm_check, $rest, $update_file);
    $rpm_check = "/bin/rpm -q ";
    $rest = "2>&1";
    $update_file = shift(@_);
    
    print STDERR "parsing /var/tmp/$update_file config file\n"
	if $DEBUG;
    unless(open(FLIST, "</var/tmp/$update_file")) {
	print STDERR "error opening /var/tmp/$update_file: $!\n";
	exit(1);
    }
    while(<FLIST>){
	next if /^#/;
	next if /^\n$/;
	print "$update_file: ", $_ if $DEBUG;
	($name, $file) = split;
	$updlist{$name} = $file;
    }
    print STDERR "done\n" if $DEBUG;
    close(FLIST);
    print STDERR "unlinking /var/tmp/$update_file\n" if $DEBUG;
    unless(unlink($update_file) == 1){
	print STDERR "error unlinking /var/tmp/$update_file: $!\n";
    }
    foreach $i ( keys %updlist ){
	chop($output = qx { $rpm_check $i $rest});
	($updatepkg) = ($updlist{$i} =~ /(.*)\..*\.rpm/);
	if ($output =~ m/is not installed$/ || $updatepkg eq $output) {
	    print "removing ", $updlist{$i}, " from list\n"
		if $DEBUG;
	    delete $updlist{$i};
	}else{
	    print "adding ", $updlist{$i}, " to list\n";
	}
    }

    if($have_ftp){
	print STDERR "creating Net::FTP to $update_rpms_host\n"
	    if $DEBUG;
	unless($ftp_upg = Net::FTP->new($update_rpms_host)){
	    print STDERR "error in Net::FTP to $update_rpms_host: $@\n";
	    exit(1);
	}
	print STDERR "logging in with $login, $password\n" if $DEBUG;
	unless($ftp_upg->login($login, $password)){
	    print STDERR "error loging in to $update_rpms_host: $!\n";
	    exit(1);
	}
	$ftp_upg->type('I');
	print STDERR "chdiring to $update_rpms_dir\n" if $DEBUG;
	unless($ftp_upg->cwd($update_rpms_dir)){
	    print STDERR "error chdiring to $update_rpms_dir\n";
	    exit(1);
	}
    }
    
    foreach $i ( keys %updlist){
	&do_ugpkg($updlist{$i});
    }
    
    if(defined($have_ftp)){
	$ftp_upg->quit;
    }
    exit(0);
}
