#!/usr/bin/perl # # $Id: simphosts,v 2.0 90/09/11 11:07:41 hakanson Rel $ # # Simplify hosts(5) format file. # Marion Hakanson (hakanson@cse.ogi.edu) # Oregon Graduate Institute of Science and Technology # # Copyright (c) 1990, Marion Hakanson. # # You may distribute under the terms of the GNU General Public License # as specified in the README file that comes with the dnsparse kit. # # The input file is read, and the mappings are stored up in the order # encountered (earlier ones will override any later ones which may # overlap or otherwise be redundant), in the same manner as that used # by the bsd host-table-based resolution code. When the entire file # has been processed, each address is printed (in the order that they # were encountered) as follows: # addr first-canon-for-addr # # Next, the remaining (not yet printed) names are sorted, and each # one is printed, one-per-line, as follows: # first-addr-for-name first-canon-for-name name # (if the two names are identical, only one is printed). # # Thus, if we've done the job right, the resulting table (also in legal # hosts(5) format) should be functionally equivalent to the original, # yet in a canonical form which can be compared textually without # having semantically meaningless differences cloud the issue. # # Note that if one runs the result through this script another time, # one should end up with the same result yet again. if ( $#ARGV >= $[ ) { open(HOSTS, $ARGV[$[]) || die "Cannot open $ARGV[$[]: $!, aborted"; } else { open(HOSTS, "<&STDIN") || die 'Cannot dup STDIN, aborted'; } # Print header comments as encountered while ( <HOSTS> ) { last unless ( /^\s*#/ ); print; } exit if ( eof(HOSTS) ); # Note that $_ was set from above do { # All other comments are removed unless ( /^\s*#/ ) { chop; s/#.*//; ($addr, @names) = split; $canon = $names[$[]; unless ( defined($addr_to_name{$addr}) ) { $addr_to_name{$addr} = $canon; push(@addrlist, $addr); } foreach $name ( @names ) { unless ( defined($name_to_addr{$name}) ) { $name_to_addr{$name} = $addr; push(@namelist, $name); } unless ( defined($name_to_canon{$name}) ) { $name_to_canon{$name} = $canon; } } } } while (<HOSTS>); # First print the addr-to-name mappings foreach $addr (@addrlist) { $realcanon = $addr_to_name{$addr}; print "$addr\t$realcanon\n"; $printed{$realcanon} = 1; } # A nice separator print "#\n"; # Now sort the names and print out their data @namelist = sort(@namelist); foreach $name (@namelist) { # Skip those we printed above next if ( $printed{$name} ); $addr = $name_to_addr{$name}; $canon = $name_to_canon{$name}; $realcanon = $addr_to_name{$addr}; print "$addr\t$canon"; print " $name" if ( $name ne $canon ); # Flag an anomaly (but preserve it) if ( $realcanon ne $canon ) { print "\t# HEY! $realcanon should be canonical here"; } print "\n"; }