#!/afs/athena/contrib/perl/perl

#
# $Id: pgputil.pl,v 1.7 1993/01/23 07:29:27 marc Exp $
#

## pgputil.pl. Copyright 1993, Marc Horowitz <marc@mit.edu>
## 
## This program may be freely redistributed and used as long as the RCS
## Id, copyright, and this message are left intact.  It may also be used
## as the basis for other programs, as long as this program is
## acknowledged in the code and documentation, and it is made clear that
## the new program is a derivative work, and not the original.  Although
## not required, it would be nice if any modifications were sent back to
## me.

$save = "";

sub next {
    local($ret);

    return() if !defined($save);

    while(1) {
	$_ = $save || <>;
	$save = "";
	if (! $_) {
	    undef $save;
	    return($ret);
	} elsif (/^\s/) {
	    $ret .= $_;
	} elsif ($ret) {
	    $save = $_;
	    return($ret);
	} else {
	    $ret = $_;
	}
    }
}

sub parsekvv {
    local($keyid,$ring,$lastpub);

    while($_ = &next()) {
	if (/^Key ring:\s+'(.*)'$/) {
	    $ring = $1;
	} elsif (m!^pub\s+\d+/([0-9A-F]+)\s+\d+/\d+/\d+\s+!) {
	    $lastpub = $1;
	    $publine{$lastpub} = $_;
	    ($pubindent{$lastpub} = $_) =~ s!\d{4}/\d\d/\d\d!$&  !;
	} elsif (/^sig\s+([0-9A-F]+)/) {
	    $keyid = $1;
	    $sigindent{$keyid} = $_;
	    ($sigline{$keyid} = $_) =~ s/^(sig\s+[0-9A-F]{6})\s\s/$1/;
	    $siglist{$keyid} .= $lastpub." " if $siglist{$keyid} !~ /$lastpub/;
	}
    }
}

sub findsigned {
    local($level,@from) = @_;
    local($tmp,@next);

    foreach $hash (@from) {
	next if (defined $depth{$hash});

	$depth{$hash} = $level;
	for $nexth (split(' ',$siglist{$hash})) {
	    push(@next,$nexth);
	    $signedby{$nexth} = $hash if !defined $signedby{$nexth};
	}
    }

    if (@next) {
	&findsigned($level+1,@next);
    }
}

($zero = $0) =~ s!^.*/([^/]+)$!$1!;

sub usage {
    die  "usage: $zero signators [ file ... ]\n"
	,"       $zero recurse [ -v ] <keyid> [ file ... ]\n";
}

sub signators {
    &parsekvv();

    print "Type bits/keyID   Date       User ID\n";

    foreach $hash (keys %siglist) {
	next if ($sigline{$hash} =~ /Unknown signator/);

	print $sigline{$hash};
	foreach $pubhash (split(' ',$siglist{$hash})) {
	    print $pubindent{$pubhash};
	}
    }
}

sub recurse {
    for (@ARGV) {
	if (/^-v/) {
	    $verbose++;
	} else {
	    push(@newargv, $_);
	}
    }
    @ARGV = @newargv;
    $keyid = shift(@ARGV);

    if ($keyid !~ /^[0-9A-F]{6}$/) { &usage; }

    &parsekvv();
    $signedby{$keyid} = "";
    &findsigned(0, $keyid);

    foreach $pubhash (keys %depth) {
	$out{sprintf("%02d%s",$depth{$pubhash},$pubhash)} = 
	    sprintf("%2d %s",$depth{$pubhash},$publine{$pubhash});
    }

    foreach $k (sort keys %out) {
	print $out{$k};

	if ($verbose) {
	    $sig = $signedby{substr($k,2,6)};

	    while($sig) {
		($x = $pubindent{$sig}) =~ 
		print "   ",$x;
		$sig = $signedby{$sig};
	    }
	}
    }
}


## dispatch

$cmd = shift(@ARGV) || &usage();

if ($cmd =~ /^s/) {
    &signators();
} elsif ($cmd =~ /^r/) {
    &recurse();
} else {
    &usage();
}
