#!/usr/athena/bin/perl
#
# update.pl -- upgrade a Redhat-Athena system from RPMS in some directory.
#   It will only upgrade packages which are already installed.
#   It also takes into account Athena-isms for things like login, sendmail.cf,
#   etc.
#

$rpmdir = "/afs/sipb.mit.edu/project/linux/redhat/current/i386/updates";
$athrpmdir = "/afs/sipb.mit.edu/project/linux/packages/RedHat/RPMS/i386";

$update_script = "/afs/sipb.mit.edu/project/linux/redhat/redhat-4.0.0/i386/updates/update.pl";

$test_mode=0;
if ($#argv >= 0) {
    foreach $argument(@ARGV) {
	$test_mode=1 if ($argument eq "--test");
    }
}

sub ListDir {
    local (@allfiles);

    opendir (THISDIR, $_[0]);
    @allfiles = grep (!/^\./, readdir (THISDIR));
    closedir (THISDIR);
    return map { "$_[0]/$_" } @allfiles;
}

sub FindRPMS {
    local (@rpmlist);
    local ($rpm, $name, $inst);

    @rpmlist = ();

    foreach $rpm (@_) {
	next if ($rpm =~ /\/kernel-/);
        next unless ($rpm =~ /([^\/]*)-[0-9].*-.*\..*\.rpm/);
	$name = $1;

	$inst = `rpm -q $name 2>/dev/null`;
	chop $inst;
	push (@rpmlist, $rpm) if ($inst);
    }

    return @rpmlist;
}

# This currently deals with /bin/login and /etc/sendmail.cf.  It doesn't
# deal with /etc/inetd.conf or /etc/services.  Oops.

sub RemoveHacks {
    if ( -f "/bin/login.redhat" ) {
	unlink ("/bin/login");
	rename ("/bin/login.redhat", "/bin/login");
    }
    if ( -f "/etc/sendmail.cf.redhat" ) {
	unlink ("/etc/sendmail.cf");
	rename ("/etc/sendmail.cf.redhat", "/etc/sendmail.cf");
    }
}

sub InstallHacks {
    if ( -f "/bin/athena/login" && ! -f "/bin/login.redhat" ) {
	rename ("/bin/login", "/bin/login.redhat");
	system ("cd /bin; ln -s athena/login");
    }
    if ( -f "/etc/athena/sendmail.cf" && ! -f "/etc/sendmail.cf.redhat" ) {
	rename ("/etc/sendmail.cf", "/etc/sendmail.cf.redhat");
	system ("cp -p /etc/athena/sendmail.cf /etc");
    }
    if ( `grep -c zephyr /etc/services` == 0 ) {
	rename ("/etc/services", "/etc/services.redhat");
	system ("sed -f /etc/athena/services.sed /etc/services.redhat > /etc/services");
    }

    if ( `grep -c rkinit /etc/inetd.conf` == 0 ) {
	rename ("/etc/inetd.conf", "/etc/inetd.conf.redhat");
	system ("sed -f /etc/athena/inetd.conf.sed /etc/inetd.conf.redhat > /etc/inetd.conf");
    }

    if ( `grep -c " login authorization" /etc/pam.conf` != 0 ) {
	print STDERR "Fixing /etc/pam.conf.\n";
	rename ("/etc/pam.conf", "/etc/pam.conf.broken");
	system ("gawk -f /afs/sipb.mit.edu/project/linux/redhat/current/i386/updates/pam.conf.awk /etc/pam.conf.broken > /etc/pam.conf");
    }

    if ( -u "/usr/X11R6/bin/SuperProbe" ) {
	print STDERR "Fixing permissions of /usr/X11R6/bin/SuperProbe.\n";
	chmod 0755, "/usr/X11R6/bin/SuperProbe";
    }
}

# chdir $rpmdir || die "Cannot cd to $rpmdir";
die "Must be run as root" if ($< && $>);

# print STDERR &FindRPMS(&ListDir($rpmdir)), "\n";

&RemoveHacks;
# Sigh.  --nodeps shouldn't be necessary, but some packages have broken
# dependency info.

@pkgs = &FindRPMS(&ListDir($rpmdir), &ListDir($athrpmdir));

if ($test_mode==0) {
    system ("rpm", "-Uvh", "--replacefiles", "--nodeps", @pkgs);
    &InstallHacks;
}

else {
    # test mode.. only examine what packages are new; do not update!

    $rpm_command="rpm -Uvh --replacefiles --test @pkgs";

    @new_pkgs=();
    $tempfile="/tmp/update_pl.$$";

    `$rpm_command >& $tempfile`;
    open(RPM_OUT,"$tempfile");
    while(<RPM_OUT>) {
	chop;
	@rpm_out=split(/\s\s+/,$_);
	$t1=shift(@rpm_out);
	foreach $t2(@rpm_out) {
	    if ($t2=~/is already installed/) {
		print "$t1 is already installed\n";
	    }
	    else {
		print "$t1 is new\n";
		push(@new_pkgs,$t1);
		break;
	    }
	    $t1=$t2;
	}
    }
    close(RPM_OUT);
    unlink("$tempfile");
    if ($#new_pkgs>=0) {
	print "The following packages are out of date: @new_stuff\n";
	print "Run $update_script to make the updrade, or use rpm (man rpm)\n";
	print "to update the individual packages by hand.\n";
    }
    else {
	print "No new RedHat packages.\n";
    }
    exit(($#new_pkgs>=0));
}
