#! @PERL_PATH@

# ip2hostname - a filter to turn IP addresses into host names wherever possible.

# $Id: ip2hostname,v 1.8 2001/02/13 04:42:20 plonka Exp $
# Dave Plonka <plonka@doit.wisc.edu>

use FindBin;
use Socket;
use Getopt::Std;

sub usage {
   my $status = shift;
   print STDERR <<_EOF_
usage: $FindBin::Script [-h] [ -p printf_format ] [ [-i extension] file [...] ]
       -h - help (shows this usage information)
	    (mnemonic: 'h'elp)
       -p printf_format - use this printf format for IP address and hostname,
			  respectively.
			  The default format is '%.0s%s', which supresses
			  the printing of the IP address (i.e. "%.0s" specifies
			  printing a string with a maximum width of zero).
			  To maintain column widths (since both the IP address
			  and hostname vary in lenght), a format like this may
			  be useful:
			  '%-16.16s %-20s'
	    (mnemonic: 'p'rintf format)
       -i extension - edit the files in place (rather than sending to
		      standard output) This option requires file name(s)
		      argument(s).
		      The extension is added to the name of the old file
		      to make a backup copy.
		      If you don't wish to make a backup, use "-I".
	    (mnemonic: edit 'i'n place)
       -I - like "-i" but no backup is made.
	    (mnemonic: edit 'I'n place, trusting this script 'I'mplicitly. ;^)
_EOF_
   ;
   exit $status
}

getopts('hp:Ii:') || usage(2);
usage(0) if ($opt_h);

$| = 1;

my $oldargv;
my %cache;

while (<>) {
   # { this is straight from the "perlrun" man page:
   if ('-' ne $ARGV && ($opt_I || $opt_i) && $ARGV ne $oldargv) {
      if ('' eq $opt_i) {
	 unlink($ARGV) or die "unlink \"$ARGV\": $!\n"
      } else {
         rename($ARGV, $ARGV . $opt_i) or die "rename \"$ARGV\": $!\n"
      }
      open(ARGVOUT, ">$ARGV");
      select(ARGVOUT);
      $oldargv = $ARGV;
   }
   # }

   my $s = $_;
   my $prev = '';
   my($name, $val);
   while ($s =~ m/(\d+\.)\d+\.\d+\.\d+/) {
      my $ip = $&;
      $s =~ s/$1//;
      next if ($ip eq $prev);
      if (defined($cache{$ip})) {
         $name = $cache{$ip}
      } else {
         $name = gethostbyaddr(inet_aton($ip), AF_INET);
         $cache{$ip} = $name
      }
      if ('' eq $name) {
         $name = $ip
      }
      if ($opt_p) {
         $val = sprintf($opt_p, $ip, $name)
      } else {
         $val = $name
      }
      s/$ip/$val/g;
      $prev = $ip
   }
   print
}
