#!/usr/local/bin/perl # # $Id$ # # $debug = 1; sub usage { die "usage: $0 before after changes\n";} sub unique { local(@list) = @_; local(%ary); print "unique? ",join(" ",@list),"\n" if $debug; foreach (@list) { return(0) if $ary{$_}++; } 1; } $before = shift(@ARGV) || &usage; $debug++ if $before =~ /^-d/; $before = shift(@ARGV) || &usage if $debug; $after = shift(@ARGV) || &usage; $changes = shift(@ARGV) || &usage; @ARGV && &usage; %policy = ( "FIRST",2, "pw_min_life",2, "pw_max_life",3, "pw_min_length",4, "pw_min_classes",5, "pw_history_num",6, "policy_refcnt",7, "LAST",7, ); %princ = ( "FIRST",2, "kvno",2, "mod_name",3, "max_life",4, "princ_expire_time",5, "expiration",5, "pw_expiration",6, "attributes",7, "policy",8, "aux_attributes",9, "LAST",9, ); %keytab = ( "LAST",-1, ); sub re { # @_ = ($cnt, $line) local($cnt, $line) = @_; local(@fields) = split(' ',$line); @list = ('\S+') x $cnt; for $f (@fields[3..$#fields]) { ($f =~ /=/) || die "Bad field: $f in $_"; if (!defined($this{$`})) { die "Bad parameter $` in $_"; } if (($list[$this{$`}] = $') eq '\S+') { $list[$this{$`}] = '[^\s]+'; } } join('\s+',@list)."\$"; } open(CHANGES, $changes) || die "Couldn't open $changes: $!\n"; while() { next if s/^\s*\#\#\!\s*\#//; next if !s/^\s*\#\#\!\s*//; split; if ($_[1] =~ /princ/) { %this = %princ; $this = "princ"; } elsif ($_[1] =~ /policy/) { %this = %policy; $this = "policy"; } elsif ($_[1] =~ /keytab/) { %this = %keytab; $this = $_[1]; } else { die "Bad line: $_"; } $cnt = $this{"LAST"}+1; if ($_[0] =~ /add/) { $diff{"+$this\t$_[2]"} = &re($cnt,$_); } elsif ($_[0] =~ /delete/) { $diff{"-$this\t$_[2]"} = &re($cnt,$_); } elsif ($_[0] =~ /changefrom/) { $diff{"-$this\t$_[2]"} = &re($cnt,$_); } elsif ($_[0] =~ /changeto/) { $ndiff{"-$this\t$_[2]"} = &re($cnt,$_); } else { die "Bad line: $_"; } } close(CHANGES); if ($debug) { for (keys %diff) { print " %diff: \"$_\" /$diff{$_}/\n"; } for (keys %ndiff) { print "%ndiff: \"$_\" /$ndiff{$_}/\n"; } print "\n"; } open(DIFF,"gdiff -u0 $before $after|") || die "Couldn't diff: $!\n"; $warnings = 0; while() { next if /^\+{3}/; next if /^\-{3}/; next if /^@@/; print "LINE: $_" if $debug; split; $key = "$_[0]\t$_[1]"; $re = $diff{$key}; delete $diff{$key}; print "%diff: \"$key\" /$re/\n" if $debug; if (!$re) { warn "Unexpected: \"$key\"\n"; $warnings++; next; } if (!/$re/) { warn "Failed: $key\n"; $warnings++; next; } if ($new = $ndiff{$key}) { delete $ndiff{$key}; @new = split(/\\s\+/, $new); for ($i=1;$i<@new;$i++) { print "NEW: $new[$i]\n" if $debug; if ($new[$i] ne '\S+') { $_[$i] = $new[$i]; } } $_[0] =~ s/^\-//; $key =~ s/^\-/\+/; $diff{$key} = join("\t",@_); } } close(DIFF); open(BEFORE, $before) || die "Couldn't open $before: $!\n"; while() { next if !/^keytab/; split; if (!$seen{$key = $_[0]." ".$_[1]}++) { $key =~ s/-\d+$//; $ktkeys{$key} .= " ".$_[2]; $kttimes{$key} .= " ".$_[3]; } } close(BEFORE); open(AFTER, $after) || die "Couldn't open $after: $!\n"; while() { next if !/^keytab/; split; if (!$seen{$key = $_[0]." ".$_[1]}++) { $key =~ s/-\d+$//; $ktkeys{$key} .= " ".$_[2]; $kttimes{$key} .= " ".$_[3]; } } close(AFTER); for (keys %diff) { warn "Unseen: \"$_\" /$diff{$_}/\n"; $warnings++; } for (keys %ndiff) { warn "Unseen changes: \"$_\" /$ndiff{$_}/\n"; $warnings++; } for (keys %ktkeys) { if (!&unique(split(' ',$ktkeys{$_}))) { warn "Some keys not unique for $_\n"; $warnings++; } } for (keys %kttimes) { if (!&unique(split(' ',$kttimes{$_}))) { warn "Some timestamps not unique for $_\n"; $warnings++; } } if ($warnings) { warn "$warnings warnings.\n"; } exit($warnings);