You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2010/03/09 19:51:59 UTC
svn commit: r921052 - in /spamassassin/trunk: MANIFEST
lib/Mail/SpamAssassin/Conf.pm lib/Mail/SpamAssassin/Dns.pm
lib/Mail/SpamAssassin/DnsResolver.pm
lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm t/dnsbl_subtests.t
Author: mmartinec
Date: Tue Mar 9 18:51:58 2010
New Revision: 921052
URL: http://svn.apache.org/viewvc?rev=921052&view=rev
Log:
Bug 6362: Change urirhssub mask syntax:
- provided a supporting test t/dnsbl_subtests.t;
- provided config directives dns_server and clear_dns_servers,
offering means to specify a list of DNS servers with
optional port numbers, needed by dnsbl_subtests.t, which
is running its own test DNS server in a subprocess
Added:
spamassassin/trunk/t/dnsbl_subtests.t (with props)
Modified:
spamassassin/trunk/MANIFEST
spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
Modified: spamassassin/trunk/MANIFEST
URL: http://svn.apache.org/viewvc/spamassassin/trunk/MANIFEST?rev=921052&r1=921051&r2=921052&view=diff
==============================================================================
--- spamassassin/trunk/MANIFEST (original)
+++ spamassassin/trunk/MANIFEST Tue Mar 9 18:51:58 2010
@@ -537,3 +537,4 @@ t/uribl_domains_only.t
t/data/spam/dnsbl_ipsonly.eml
t/uribl_all_types.t
t/uribl_ips_only.t
+t/dnsbl_subtests.t
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm?rev=921052&r1=921051&r2=921052&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Tue Mar 9 18:51:58 2010
@@ -84,7 +84,7 @@ use re 'taint';
use Mail::SpamAssassin::Util;
use Mail::SpamAssassin::NetSet;
-use Mail::SpamAssassin::Constants qw(:sa);
+use Mail::SpamAssassin::Constants qw(:sa :ip);
use Mail::SpamAssassin::Conf::Parser;
use Mail::SpamAssassin::Logger;
use Mail::SpamAssassin::Util::TieOneStringHash;
@@ -1314,6 +1314,74 @@ Please note, the DNS test queries for NS
}
});
+=item dns_server ip-addr-port (default: first entry provided by Net::DNS)
+
+Specifies an IP address of a DNS server, and optionally its port number.
+The I<dns_server> directive may be specified multiple times, each entry
+adding to a list of available resolving name servers. The I<ip-addr-port>
+argument can either be an IPv4 or IPv6 address, optionally enclosed in
+brackets, and optionally followed by a colon and a port number. In absence
+of a port number a standard port number 53 is assumed. When an IPv6 address
+is specified along with a port number, the address B<must> be enclosed in
+brackets to avoid parsing ambiguity regarding a colon separator,
+
+Examples :
+ dns_server 127.0.0.1
+ dns_server 127.0.0.1:53
+ dns_server [127.0.0.1]:53
+ dns_server [::1]:53
+
+In absence of I<dns_server> directives, the list of name servers is provided
+by Net::DNS module, which typically obtains the list from /etc/resolv.conf,
+but this may be platform dependent. Please consult Net::DNS documentation
+for details.
+
+=cut
+
+ push (@cmds, {
+ setting => 'dns_server',
+ type => $CONF_TYPE_STRING,
+ code => sub {
+ no warnings 'uninitialized';
+ my ($self, $key, $value, $line) = @_;
+ my($address,$port); local($1,$2,$3);
+ if ($value =~ /^(?: \[ ([^\]]*) \] | ([^:]*) ) : (\d+) \z/sx) {
+ ($address, $port) = ($1.$2, $3);
+ } elsif ($value =~ /^(?: \[ ([^\]]*) \] | ([0-9a-fA-F.:]+) ) \z/sx) {
+ ($address, $port) = ($1.$2, '53');
+ } else {
+ return $INVALID_VALUE;
+ }
+ my $IP_ADDRESS = IP_ADDRESS;
+ if ($address =~ /$IP_ADDRESS/ && $port >= 1 && $port <= 65535) {
+ $self->{dns_server} = [] if !$self->{dns_server};
+ # checked, untainted, stored in a normalized form
+ push(@{$self->{dns_servers}}, untaint_var("[$address]:$port"));
+ } else {
+ return $INVALID_VALUE;
+ }
+ }
+ });
+
+=item clear_dns_servers
+
+Empty the list of explicitly configured DNS servers through a I<dns_server>
+directive, falling back to Net::DNS -supplied defaults.
+
+=cut
+
+ push (@cmds, {
+ setting => 'clear_dns_servers',
+ type => $CONF_TYPE_NOARGS,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ unless (!defined $value || $value eq '') {
+ return $INVALID_VALUE;
+ }
+ undef $self->{dns_servers};
+ }
+ });
+
=item dns_test_interval n (default: 600 seconds)
If dns_available is set to 'test' (which is the default), the dns_test_interval
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm?rev=921052&r1=921051&r2=921052&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm Tue Mar 9 18:51:58 2010
@@ -688,7 +688,7 @@ sub is_dns_available {
while( $ns = shift(@nameservers)) {
for(my $retry = 3; $retry > 0 and $#domains>-1; $retry--) {
my $domain = splice(@domains, rand(@domains), 1);
- dbg("dns: trying ($retry) $domain...");
+ dbg("dns: trying ($retry) $domain, server $ns ...");
my $result = $self->lookup_ns($domain);
if(defined $result) {
if (scalar @$result > 0) {
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm?rev=921052&r1=921051&r2=921052&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm Tue Mar 9 18:51:58 2010
@@ -158,15 +158,31 @@ sub get_resolver {
=item $res->nameservers()
-Wrapper for Net::DNS::Resolver->nameservers to get or set list of nameservers
+Get or set a list of nameservers
=cut
sub nameservers {
my $self = shift;
- my $res = $self->{res};
+
+ if (@_) {
+ $self->{available_dns_servers} = [@_];
+ dbg("dns: servers set by a caller to: %s",
+ join(', ',@{$self->{available_dns_servers}}));
+ } elsif (!$self->{available_dns_servers}) {
+ my $res = $self->{res};
+ my @ns_addr_port; # list of name servers: [addr]:port entries
+ if ($self->{conf}->{dns_servers}) { # specified in a config file
+ @ns_addr_port = @{$self->{conf}->{dns_servers}};
+ dbg("dns: servers set by config to: %s", join(', ',@ns_addr_port));
+ } elsif ($res) { # default as provided by Net::DNS, e.g. /etc/resolv.conf
+ @ns_addr_port = map { "[$_]:" . $res->{port} } @{$res->{nameservers}};
+ dbg("dns: servers obtained from Net::DNS : %s", join(', ',@ns_addr_port));
+ }
+ $self->{available_dns_servers} = \@ns_addr_port;
+ }
$self->connect_sock_if_reqd();
- return $res->nameservers(@_) if $res;
+ return @{$self->{available_dns_servers}};
}
=item $res->connect_sock()
@@ -187,24 +203,29 @@ sub connect_sock {
my $sock;
my $errno;
+ # list of name servers: [addr]:port entries
+ my @ns_addr_port = @{$self->{available_dns_servers}};
+ # use the first name server in a list
+ my($ns_addr,$ns_port); local($1,$2);
+ ($ns_addr,$ns_port) = ($1,$2) if $ns_addr_port[0] =~ /^\[(.*)\]:(\d+)\z/;
+
# IO::Socket::INET6 may choose wrong LocalAddr if family is unspecified,
# causing EINVAL failure when automatically assigned local IP address
# and remote address do not belong to the same address family:
use Mail::SpamAssassin::Constants qw(:ip);
my $ip64 = IP_ADDRESS;
my $ip4 = IPV4_ADDRESS;
- my $ns = $self->{res}->{nameservers}[0];
my $ipv6opt = !($self->{force_ipv4});
# ensure families of src and dest addresses match (bug 4412 comment 29)
my $srcaddr;
- if ($ipv6opt && $ns=~/^${ip64}$/o && $ns!~/^${ip4}$/o) {
+ if ($ipv6opt && $ns_addr =~ /^${ip64}$/o && $ns_addr !~ /^${ip4}$/o) {
$srcaddr = "::";
} else {
$srcaddr = "0.0.0.0";
}
-
- dbg("dns: name server: %s, LocalAddr: %s", $ns,$srcaddr);
+ dbg("dns: LocalAddr: %s, name server(s): %s",
+ $srcaddr, join(', ',@ns_addr_port));
# find next available unprivileged port (1024 - 65535)
# starting at a random value to spread out use of ports
@@ -213,8 +234,8 @@ sub connect_sock {
my $lport = 1024 + (($port_offset + $i) % 64511);
my %args = (
- PeerAddr => $ns,
- PeerPort => $self->{res}->{port},
+ PeerAddr => $ns_addr,
+ PeerPort => $ns_port,
Proto => 'udp',
LocalPort => $lport,
Type => SOCK_DGRAM,
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm?rev=921052&r1=921051&r2=921052&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm Tue Mar 9 18:51:58 2010
@@ -312,6 +312,7 @@ sub parsed_metadata {
my $rulecf = $scanner->{conf}->{uridnsbls}->{$rulename};
my $tflags = $scanner->{conf}->{tflags}->{$rulename};
+ $tflags = '' if !defined $tflags;
if ($rulecf->{is_rhsbl} && $tflags =~ /\b ips_only \b/x) {
$scanner->{uridnsbl_active_rules_rhsbl_ipsonly}->{$rulename} = 1;
@@ -985,6 +986,8 @@ sub complete_dnsbl_lookup {
$match = 1;
} elsif ($subtest =~ m{^ (\d+) (?: ([/-]) (\d+) )? \z}x) {
my($n1,$delim,$n2) = ($1,$2,$3);
+ # dbg("uridnsbl: %s/%s, %s, %s", $rulename, $dom, $rdatanum,
+ # !defined $n2 ? $n1 : "$n1 $delim $n2");
$match =
!defined $n2 ? $rdatanum & $n1 # mask only
: $delim eq '-' ? $rdatanum >= $n1 && $rdatanum <= $n2 # range
Added: spamassassin/trunk/t/dnsbl_subtests.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/dnsbl_subtests.t?rev=921052&view=auto
==============================================================================
--- spamassassin/trunk/t/dnsbl_subtests.t (added)
+++ spamassassin/trunk/t/dnsbl_subtests.t Tue Mar 9 18:51:58 2010
@@ -0,0 +1,269 @@
+#!/usr/bin/perl
+
+# supporting tests for: Bug 6362 - Change urirhssub mask syntax
+
+use strict;
+use warnings;
+use re 'taint';
+use lib '.'; use lib 't';
+
+use SATest; sa_t_init("dnsbl_subtests");
+use Test;
+
+use vars qw(%patterns %anti_patterns);
+use constant num_tests => 30;
+use constant DO_RUN => 1;
+
+BEGIN {
+ plan tests => (DO_RUN ? num_tests : 0);
+};
+
+exit unless DO_RUN;
+
+my $prefix = '.';
+if (-e 'test_dir') { # running from test directory, not ..
+ $prefix = '..';
+}
+
+# Bug 5761 (no 127.0.0.1 in jail, use SPAMD_LOCALHOST if specified)
+my $dns_server_localaddr = $ENV{'SPAMD_LOCALHOST'};
+$dns_server_localaddr = '127.0.0.1' if !$dns_server_localaddr;
+$dns_server_localaddr = '::1' if !$dns_server_localaddr;
+
+my $dns_server_localport = '5353'; # some port (mdns), hopefully free
+
+# test zone
+my $z = 'sa-dbl-test.spamassassin.org';
+
+my $local_conf = <<"EOD";
+ use_bayes 0
+ use_razor2 0
+ use_pyzor 0
+# use_auto_whitelist 0
+# use_dcc 0
+ score NO_RELAYS 0
+ score NO_RECEIVED 0
+ score TVD_SPACE_RATIO 0
+
+ rbl_timeout 5
+ dns_available yes
+ clear_dns_servers
+ dns_server [$dns_server_localaddr]:$dns_server_localport
+
+ urirhssub X_URIBL_Y_2A $z A 127.0.1.2
+ body X_URIBL_Y_2A eval:check_uridnsbl('X_URIBL_Y_2A')
+
+ urirhssub X_URIBL_Y_2B $z A 127.0.1.2-127.0.1.2
+ body X_URIBL_Y_2B eval:check_uridnsbl('X_URIBL_Y_2B')
+
+ urirhssub X_URIBL_Y_2C $z A 127.0.1.2/0xffffffff
+ body X_URIBL_Y_2C eval:check_uridnsbl('X_URIBL_Y_2C')
+
+ urirhssub X_URIBL_Y_2D $z A 127.0.1.2/255.255.255.255
+ body X_URIBL_Y_2D eval:check_uridnsbl('X_URIBL_Y_2D')
+
+ urirhssub X_URIBL_Y_2E $z A 127.0.1.2/127.0.1.2
+ body X_URIBL_Y_2E eval:check_uridnsbl('X_URIBL_Y_2E')
+
+ urirhssub X_URIBL_Y_2F $z A 0/128.255.254.253
+ body X_URIBL_Y_2F eval:check_uridnsbl('X_URIBL_Y_2F')
+
+ urirhssub X_URIBL_Y_2G $z A 2
+ body X_URIBL_Y_2G eval:check_uridnsbl('X_URIBL_Y_2G')
+
+ urirhssub X_URIBL_N_2G $z A 5
+ body X_URIBL_N_2G eval:check_uridnsbl('X_URIBL_N_2G')
+
+ urirhssub X_URIBL_Y_ANY $z A 127.0.1.1-127.0.1.254
+ body X_URIBL_Y_ANY eval:check_uridnsbl('X_URIBL_Y_ANY')
+
+ urirhssub X_URIBL_Y_3 $z A 127.0.1.3-127.0.1.19
+ body X_URIBL_Y_3 eval:check_uridnsbl('X_URIBL_Y_3')
+
+ urirhssub X_URIBL_N_3 $z A 127.0.1.4-127.0.1.18
+ body X_URIBL_N_3 eval:check_uridnsbl('X_URIBL_Y_3')
+
+ urirhssub X_URIBL_N_0A $z A 127.0.0.0
+ body X_URIBL_N_0A eval:check_uridnsbl('X_URIBL_N_0A')
+
+ urirhssub X_URIBL_N_0B $z A 127.0.1.0
+ body X_URIBL_N_0B eval:check_uridnsbl('X_URIBL_N_0B')
+
+ urirhssub X_URIBL_N_255A $z A 127.0.1.255
+ body X_URIBL_N_255A eval:check_uridnsbl('X_URIBL_N_255A')
+
+ urirhssub X_URIBL_N_255B $z A 0.0.0.255/0.0.0.255
+ body X_URIBL_N_255B eval:check_uridnsbl('X_URIBL_N_255B')
+EOD
+
+my(@testzone) = map { chomp; s/[ \t]+//; $_ } split(/^/, <<"EOD");
+ $z 3600 IN SOA ns.$z hostmaster.$z (1 10800 1800 2419200 3600)
+ $z 3600 IN NS ns.$z
+ $z 3600 IN MX 0 .
+ ns.$z 3600 IN A 127.0.0.1
+ ns.$z 3600 IN AAAA ::1
+ foo.$z 3600 IN A 10.1.2.3
+ foo.$z 3600 IN A 10.1.2.4
+ dbltest.com.$z 3600 IN A 127.0.1.2
+ dbltest.com.$z 3600 IN TXT "test answer on dbltest.com"
+ dbltest03.com.$z 3600 IN A 127.0.1.3
+ dbltest19.com.$z 3600 IN A 127.0.1.19
+ dbltest20.com.$z 3600 IN A 127.0.1.20
+ dbltest21.com.$z 3600 IN A 127.0.1.21
+ dbltest39.com.$z 3600 IN A 127.0.1.39
+ dbltest40.com.$z 3600 IN A 127.0.1.40
+ dbltest50.com.$z 3600 IN A 127.0.1.50
+ dbltest59.com.$z 3600 IN A 127.0.1.59
+ dbltest99.com.$z 3600 IN A 127.0.1.99
+ dbltestER.com.$z 3600 IN A 127.0.1.255
+ dbltestER.com.$z 3600 IN TXT "No IP queries allowed"
+ 10.1.2.3.$z 3600 IN A 127.0.1.255
+ 10.1.2.3.$z 3600 IN TXT "No IP queries allowed"
+EOD
+
+# ---------------------------------------------------------------------------
+
+use Net::DNS::Nameserver;
+
+sub reply_handler {
+ my($qname, $qclass, $qtype, $peerhost,$query,$conn) = @_;
+ my($rcode, @ans, @auth, @add);
+ my $qclass_uc = uc $qclass;
+ my $qtype_uc = uc $qtype;
+# print "Received query from $peerhost to ". $conn->{"sockhost"}. "\n";
+# $query->print;
+ $rcode = "NXDOMAIN";
+ for my $rec_str (@testzone) {
+ my($rrname,$rrttl,$rrclass,$rrtype,$rrdata) = split(' ',$rec_str,5);
+ if ($qclass_uc eq uc($rrclass) && lc($rrname) eq lc($qname)) {
+ $rcode = 'NOERROR';
+ if ($qtype_uc eq uc($rrtype) || $qtype_uc eq 'ANY') {
+ push(@ans, Net::DNS::RR->new(
+ join(' ', $qname, $rrttl, $qclass, $rrtype, $rrdata)));
+ }
+ }
+ }
+ # special DBL test case - numerical IP query handling
+ if ($qclass_uc eq 'IN' && $qname =~ /^[0-9.]+\.\Q$z\E\z/is) {
+ $rcode = 'NOERROR';
+ if ($qtype_uc eq 'A' || $qtype_uc eq 'ANY') {
+ push(@ans, Net::DNS::RR->new(join(' ',
+ $qname, '3600', $qclass, 'A', '127.0.1.255')));
+ }
+ if ($qtype_uc eq 'TXT' || $qtype_uc eq 'ANY') {
+ push(@ans, Net::DNS::RR->new(join(' ',
+ $qname, '3600', $qclass, 'TXT', '"No IP queries allowed"')));
+ }
+ }
+ return ($rcode, \@ans, \@auth, \@add);
+}
+
+sub dns_server($$) {
+ my($local_addr, $local_port) = @_;
+ my $ns = Net::DNS::Nameserver->new(
+ LocalAddr => $local_addr, LocalPort => $local_port,
+ ReplyHandler => \&reply_handler, Verbose => 0);
+ $ns or die "Cannot create a nameserver object";
+ $ns->main_loop;
+}
+
+# ---------------------------------------------------------------------------
+
+use Mail::SpamAssassin;
+my $spamassassin_obj;
+
+sub process_sample_urls(@) {
+ my(@url_list) = @_;
+ my($mail_obj, $per_msg_status, $spam_report);
+ $spamassassin_obj->timer_reset;
+
+ my $msg = <<'EOD';
+From: "DNSBL Testing" <ab...@example.org>
+To: someone@example.org
+Subject: test
+Date: Mon, 8 Mar 2010 15:10:44 +0100
+Message-Id: <te...@example.org>
+
+EOD
+ $msg .= $_."\n" for @url_list;
+
+ $mail_obj = $spamassassin_obj->parse($msg,0);
+ if ($mail_obj) {
+ local($1,$2,$3,$4,$5,$6); # avoid Perl 5.8.x bug, $1 can get tainted
+ $per_msg_status = $spamassassin_obj->check($mail_obj);
+ }
+ if ($per_msg_status) {
+ $spam_report = $per_msg_status->get_tag('REPORT');
+ $per_msg_status->finish;
+ }
+ if ($mail_obj) {
+ $mail_obj->finish;
+ }
+ $spam_report =~ s/\A(\s*\n)+//s;
+# print "\t$spam_report\n";
+ return $spam_report;
+}
+
+sub test_samples($$) {
+ my($patt_antipatt_list,$url_list_ref) = @_;
+ my $el = $patt_antipatt_list->[0];
+ shift @$patt_antipatt_list if @$patt_antipatt_list > 1; # last autorepeats
+ my($patt,$anti) = split(m{\s* / \s*}x, $el, 2);
+ %patterns = map { (" $_ ", $_) } split(' ',$patt);
+ %anti_patterns = map { (" $_ ", $_) } split(' ',$anti);
+ my $spam_report = process_sample_urls(@$url_list_ref);
+ clear_pattern_counters();
+ patterns_run_cb($spam_report);
+ my $status = ok_all_patterns();
+ printf("\nTest on %s failed:\n%s\n",
+ join(', ',@$url_list_ref), $spam_report) if !$status;
+}
+
+# detach a DNS server process
+my $pid = fork();
+defined $pid or die "Cannot fork: $!";
+if (!$pid) { # child
+ dns_server($dns_server_localaddr, $dns_server_localport);
+ exit;
+}
+
+# parent
+# print STDERR "Forked a DNS server process [$pid]\n";
+sleep 1;
+
+$spamassassin_obj = Mail::SpamAssassin->new({
+# rules_filename => "$prefix/t/log/test_rules_copy",
+# require_rules => 1,
+ rules_filename => "/dev/null",
+ site_rules_filename => "$prefix/t/log/localrules.tmp",
+ userprefs_filename => "$prefix/masses/spamassassin/user_prefs",
+ post_config_text => $local_conf,
+ dont_copy_prefs => 1,
+# debug => 'dns,async,uridnsbl',
+});
+ok($spamassassin_obj);
+$spamassassin_obj->compile_now; # try to preloaded most modules
+
+test_samples(
+ [q{ X_URIBL_Y_2A X_URIBL_Y_2B X_URIBL_Y_2C X_URIBL_Y_2D X_URIBL_Y_2E
+ X_URIBL_Y_2F X_URIBL_Y_2G X_URIBL_Y_ANY / X_URIBL_N_2E X_URIBL_N_2G
+ X_URIBL_N_3 X_URIBL_N_0A X_URIBL_N_0B X_URIBL_N_255A X_URIBL_N_255B }],
+ [qw( http://dbltest.com/ )]);
+
+test_samples(
+ [q{ X_URIBL_Y_2A X_URIBL_Y_2B X_URIBL_Y_2C X_URIBL_Y_2D X_URIBL_Y_2E
+ X_URIBL_Y_2F X_URIBL_Y_2G X_URIBL_Y_ANY X_URIBL_Y_3 / X_URIBL_N_3
+ X_URIBL_N_0A X_URIBL_N_0B X_URIBL_N_255A X_URIBL_N_255B }],
+ [qw( http://dbltest.com/ http://dbltest03.com/ http://dbltest19.com/
+ http://10.11.22.33/ )]);
+
+if ($pid) {
+ kill('TERM',$pid) or die "Cannot stop a DNS server [$pid]: $!";
+ waitpid($pid,0);
+ undef $pid;
+}
+
+END {
+ $spamassassin_obj->finish if $spamassassin_obj;
+ kill('KILL',$pid) if $pid; # ignoring status
+}
Propchange: spamassassin/trunk/t/dnsbl_subtests.t
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: spamassassin/trunk/t/dnsbl_subtests.t
------------------------------------------------------------------------------
svn:executable = *