sub sub { \ my $file = shift; \ \ $file =~ m#(.+)/([^/]+)\.zone$# or die "parse error"; \ my $admin_dir = $1; \ my $domain_name = $2; \ \ my @mx; \ my $stuff = "\$INCLUDE $file\n"; \ my $origin = $domain_name; \ my $this_name; \ while ( 1 ) \ { \ last if ( $stuff =~ m/^\s+$/ ); \ \ $stuff =~ s/^\s*\n// and next; \ $stuff =~ s/^\s*;.*\n// and next; \ \ if ( $stuff =~ s/^\$ORIGIN\s+(\S+).+?$//i ) \ { \ $origin = $1; \ next; \ } \ \ if ( $stuff =~ s/^\$INCLUDE\s+(\S+).*?$//i ) \ { \ local $/; \ my $fh = new IO::File "< $1" or die "could not open $1"; \ $fh->input_record_separator(undef); \ $stuff = <$fh> . $stuff; \ close $fh; \ next; \ } \ \ $stuff =~ \ s/ \ ^ \ \s* \ (?:(\S+)\s+)? \ (?:\d+\s+)? \ (?:IN\s+)? \ (?:([a-zA-Z]+)\s+) \ ( \ (?: \ [^\(\n]+ (?: \; .* )? \ | \ \( \ (?: \ [^\)\n\;]* \ (?: \; .* )? \n \ | \ [^\)\n\;]+ \ )*? \ \) \ )+? \ ) \ \n \ //x \ or ( $stuff =~ s/^.*\n//, next ); \ my ($name, $rtype, $rinfo) = ($1, $2, $3); \ $this_name = $name if ( defined $name ); \ $this_name = $origin if ( $this_name eq "@" ); \ \ if ( lc($rtype) eq "mx" and $rinfo !~ /;\s*?/i ) \ { \ my $fh = new IO::File "< $admin_dir/info.username" \ or die "no info.username file\n"; \ my $username = <$fh>; \ chomp $username; \ undef $fh; \ push @mx, "$this_name:$username"; \ } \ } \ \ return [join("\n", @mx), [] ]; } ----- One condition for use: if you do use this code to create a zone file syntax checker, please tell me about it. ~ David Harris