#!PERLPROG
#
#	program:	hosts
#	purpose:	Generate a listing of hosts within a domain.
#			The default just lists all domain record names, one per line.
#			The "-a" option restricts the output to only "A" resource-
#			records, and makes the first output field be the IP address,
#			with the second field being the domain name.
#			The "-r" option does a recursive domain traversal.
#	input:		Domain name on command line.
#	output:		List of hosts within the domain,
#			or the word "ERROR" (distinguishable from a real
#			record because it has no period on the end).
#	exit value:	0 if succeeds, 1 if fails (and "ERROR" output).
#	author:		Paul Balyoz
#

#
# Temporary storage for a zone dump
#
@a = split(/\//,$0);
$TMP="/tmp/$a[$#a].$$";

#
# Usage and Mydie functions
#
sub usage {
        print STDERR "usage: $0 [-r] dom.ain.\n";
	print "ERROR\n";
	unlink $TMP;
        exit 1;
}

sub mydie {
	local($str) = @_;

        print STDERR "$str\n";
	print "ERROR\n";
	unlink $TMP;
        exit 1;
}

#
# Parse command-line arguments
#

require 'getopts.pl';
&Getopts('ra') || &usage(1);

# Set flags
$recursive = $addronly = 0;
$opt_r && $recursive++;
$opt_a && $addronly++;

# Domain name is only thing left
$#ARGV != 0 && &usage;
$dom = $ARGV[0];
$dom eq "" && &usage;

#
# Determine what zone the given domain lives in.
#

$zone=`DOMBIN/zone $dom`;
$? != 0 && &mydie ("hosts: could not tell what zone $dom is in.");
chop ($zone);

#
# Get a dump of that zone
#

system "DOMBIN/axfr $zone > $TMP";
$? != 0 && &mydie ("hosts: could not transfer zone $dom");

#
# Send a recursive, selected group of domains thru uniq and domsort.
# Even though "uniq" seems redundant considering the "-u" option to domsort,
# it serves a purpose: to remove many redundant entries before sorting,
# to speed things up.
#

open (DOMSORT, "| uniq | DOMBIN/domsort -u") || &mydie ("could not launch domsort with a pipe");

#
# If recursion is specified, handle things one way.
#

if ($recursive) {
	open (ZONEDATA, $TMP) || &mydie ("hosts: could not open temp file $TMP");
	while (<ZONEDATA>) {
		chop;
#print "input=<$_>\n";
		@fields = split;
		if ($fields[0] =~ /\.$dom$/i || $fields[0] =~ /^$dom$/i) {
			if ($fields[1] ne "NS" && $fields[1] ne "SOA") {
				if (! $addronly || $fields[1] eq "A") {
					print DOMSORT $fields[0]."\n";
#print "\tanswer=<$fields[0]>\n";
				}
			} else {	# NS or SOA record:
				if ($fields[0] =~ /\.$dom$/i) {
					($index = $fields[0]) =~ tr/A-Z/a-z/;
					$subzones{$index} = $fields[0];
#print "\tstash recursive <$fields[0]>\n";
				}
			}
		}
	}
	if (%subzones) {
		 foreach $i (sort keys(%subzones)) {
			system "PERLPROG $0 -r $subzones{$i}";
		}
	}
	close (ZONEDATA);

#
# Not recursive, so handle things a different way.
#

} else {
	open (ZONEDATA, $TMP) || &mydie ("hosts: could not open temp file $TMP");
	while (<ZONEDATA>) {
		chop;
#print "input=<$_>\n";
		@fields = split;
		if ($fields[0] =~ /^[^\.]+\.$dom$/i || $fields[0] =~ /^$dom$/i) {
			if ($fields[1] ne "NS" && $fields[1] ne "SOA") {
				if (! $addronly || $fields[1] eq "A") {
					print DOMSORT $fields[0]."\n";
				}
			}
		}
	}
	close (ZONEDATA);
}

#
# Clean up and exit.
#
close (DOMSORT);

unlink($TMP);
exit 0;
