#!/usr/local/bin/perl -w
# patchinfo - get info about a Sun patch (or many) from its file
#
# by Rob Funk <funk+@osu.edu>, 21 Feb 2000
#
#    By default, prints most applicable combination of
#    Solaris Release, Unbundled Product, and Unbundled Release.
# Options:
#   -s    Show Synopsis instead of default
#   -v    Show all key/value pairs
#   -c    Send entire README file to standard output
#   -w    Write README to file, filename in form 109999-01.README

my $tar="/usr/local/bin/tar";# must be GNU tar, since we use O switch
my $gzip="/usr/local/bin/gzip";
my $compress="/usr/local/bin/gzip";# can be compress or gzip
my $unzip="/usr/local/bin/unzip";# /usr/bin/unzip on Solaris 7 and up
my $awk="/usr/bin/nawk";# shouldn't be needed since we're in Perl

sub get_type {
    my $type;
    my ($f)=@_;

    # find out type of file
#    $type=`/bin/file $f`; # slow but accurate
#    if ($type =~ /gzip/) {
#	$type="gzip";
#    } elsif ($type =~ /zip/) {
#	$type="zip";
#    } elsif ($type =~ /compress/) {
#	$type="compress";
#    } else {
	# get it from filename (fast)
	if ($f =~ /\.zip$/i) {
	    $type="zip";
	} elsif ($f =~ /\.Z$/) {
	    $type="compress";
	} elsif ($f =~ /\.g?z$/) {
	    $type="gzip";
	} else {
	    print STDERR "Unknown file type for $f\n";
	    $type="";
	}
#    }

    return $type;
}

sub get_readme {
    my ($f,$type)=@_;
    my ($rlist,$readme);
    my ($min,$n);
    $min=99999;

    if ($type eq "compress") {
	$rlist="$compress -dc $f | $tar tf -";
    } elsif ($type eq "gzip") {
	$rlist="$gzip -dc $f | $tar tf -";
    } elsif ($type eq "zip") {
	$rlist="$unzip -l $f"; # | $awk '{print $4}'
    }

    if (! open(RLIST,"$rlist |")) {
	print(STDERR "Cannot list patch contents\n");
	$readme="";
	return $readme;
    }
    while (<RLIST>) {
	next unless (/(^|\/)README/);
	chomp;
	if ($type eq "zip") {
	    $_=(split(/\s+/,$_))[4];
	}
	$n=s,/,/,g; # count slashes
	# take the README that's shallowest in the tree (fewest slashes)
	if ($n < $min) {
	    $min=$n;
	    $readme=$_;
	}
    }
    close(RLIST);
    return $readme;
}

sub get_subject {
    my($f,$r,$type)=@_;
    my ($rcat,$outfile);
    my ($k,$v,@v);
    my (%h);

    if ($type eq "compress") {
	$rcat="$compress -dc $f | $tar xOf - $r";
    } elsif ($type eq "gzip") {
	$rcat="$gzip -dc $f | $tar xOf - $r";
    } elsif ($type eq "zip") {
	$rcat="$unzip -p $f $r";
    }

    if (! open(RCAT,"$rcat |")) {
	print(STDERR "Cannot open readme file\n");
	$out="";
	return $out;
    }
    if ($write) {
	$outfile=$f;
	$outfile =~ s,^.*/,,; # strip off initial path
	$outfile =~ s,\..*$,,;# strip off trailing extensions
	#$outfile =~ s,(\d{6})-\d{2},$1,; # strip off version
	$outfile = "$outfile.README";
	if (! open(F,">$outfile")) {
	    print STDERR "Cannot open $outfile for write\n";
	    $out="";
	    return $out;
	}
	print STDERR "Writing to $outfile\n";
	select F;
    }
    while (<RCAT>) {
	print if ($cat or $write);
	chomp;
	s/^Patch-ID#/Patch-ID:/;
	if (/: / and /^[A-Z]/) {
	    ($k,@v) = split(/: /,$_);
	    $v=join(": ",@v);
	    next if ($k =~ /^ /);
	    next if ($v =~ /^ /);
	    $k =~ s/ +/ /g; $k =~ s/^ | $//g;
	    $v =~ s/ +/ /g; $v =~ s/^ | $//g;
	    if ($k and $v) {
		$v =~ s/Enterptise/Enterprise/g; # common(?) misspelling
		$k=lc($k);
		print "{$k} $v\n" if ($verbose);
		$h{$k} = $v;
	    }
	}
    }
    close(RCAT);
    if ($write) {
	select STDOUT;
	close F;
    }

    if ($h{"unbundled product"}) {
	if ($h{"unbundled release"}) {
	    $out=sprintf("%s %s",$h{"unbundled product"},$h{"unbundled release"});
	} else {
	    $out=$h{"unbundled product"};
	}
	if ($h{"solaris release"} and $h{"solaris release"} !~ /[, ]/) {
	    $out=sprintf("Solaris %s ; $out",$h{"solaris release"});
	}
    } elsif ($h{"solaris release"}) {
	$out=sprintf("Solaris %s",$h{"solaris release"});
    } elsif ($h{"sunos release"}) {
	if ($h{"sunos release"} =~ /^SunOS/) {
	    $out=$h{"sunos release"};
	} else {
	    $out=sprintf("SunOS %s",$h{"sunos release"});
	}
    } else { $out="" }

    if ($synopsis) {
	$out=$h{"synopsis"};
    }

    return $out;
}

#########
my ($type,$readme,$subject);
my (@flags,@args);
local ($verbose,$cat,$synopsis); # globals for flags

@flags=grep(/^-/,@ARGV);
@args=grep(!/^-/,@ARGV);
foreach $flag (@flags) {
    if ($flag eq "-h") {
	print <<EOH;
patchinfo - get info about a Sun patch (or many) from its file.
    by Rob Funk <funk+\@osu.edu>

Usage:  patchinfo [options] file ...
    By default, prints most applicable combination of
    Solaris Release, Unbundled Product, and Unbundled Release.
Options:
  -s    Show Synopsis instead of default
  -v    Show all key/value pairs
  -c    Send entire README file to standard output
  -w    Write README to file, filename in form 109999-01.README
  -h    This help listing
EOH
	exit 0;
    }

    if ($flag eq "-v") { $verbose=1; }
    if ($flag eq "-c") { $cat=1; }
    if ($flag eq "-s") { $synopsis=1; }
    if ($flag eq "-w") { $write=1; }
}

foreach $file (@args) {
    $type=get_type($file);
    next unless ($type);
    $readme=get_readme($file,$type);
    next unless ($readme);
    $subject=get_subject($file,$readme,$type);
    next unless ($subject);
    next if ($cat or $verbose or $write);
    if ($#args > 0) {
	print "$file: $subject\n";
    } else {
	print "$subject\n";
    }
}

exit 0;
