Mail-SpamAssassin
view release on metacpan or search on metacpan
spamd/spamd.raw view on Meta::CPAN
# make sure not to enter this socket into @listen_sockets,
# otherwise exit handlers would unlink it!
die "spamd: already running on $path, exiting\n";
}
else {
dbg("spamd: removing stale socket file $path");
unlink $path;
}
}
if (not -d (File::Spec->splitpath($path))[1]) {
die "spamd: directory for $path does not exist, exiting\n";
}
my %socket = (
Local => $path,
Type => &SOCK_STREAM,
Listen => &SOMAXCONN,
);
dbg("spamd: creating UNIX socket:\n" . join("\n", map { " $_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
my $server_unix = IO::Socket::UNIX->new(%socket);
# sanity check! cf. bug 3490
if (not $server_unix or not -S $path) {
unless ($server_unix) {
dbg "spamd: socket path might have been truncated due to system limits\n";
die "spamd: could not create UNIX socket on $path: $!\n";
}
my $hostpath = $server_unix->hostpath();
if ($hostpath ne $path) {
warn "spamd: socket path was truncated at position " . length($hostpath) . "\n";
warn "spamd: leaving stale socket at $hostpath\n" if -S $hostpath;
die "spamd: path length for UNIX socket on $path exceeds system limit, exiting\n";
}
else {
die "spamd: could not find newly-created UNIX socket on $path: $!\n";
}
}
my $mode = $opt{socketmode};
if ($mode) {
$mode = oct $mode;
} else {
$mode = 0666; # default
}
my $owner = $opt{socketowner};
my $group = $opt{socketgroup};
if ($owner || $group) {
my $uid = -1;
my $gid = -1;
if ($owner) {
my ($login,$pass,$puid,$pgid) = getpwnam($owner)
or die "spamd: $owner not in passwd database\n";
$uid = $puid;
}
if ($group) {
my ($name,$pass,$ggid,$members) = getgrnam($group)
or die "spamd: $group not in group database\n";
$gid = $ggid;
}
if (!chown $uid, $gid, $path) {
die "spamd: could not chown $path to $uid/$gid: $!";
}
}
if (!chmod $mode, $path) { # make sure everybody can talk to it
die "spamd: could not chmod $path to $mode: $!";
}
push(@listen_sockets, { specs => $socket_specs,
path => $path,
socket => $server_unix,
fd => $server_unix->fileno }) if $server_unix;
1;
}
sub server_sock_setup_inet {
my($socket_specs, $addr, $port, $ssl) = @_;
$have_inet4 || $have_inet6
or warn "spamd: neither the PF_INET (IPv4) nor the PF_INET6 (IPv6) ".
"protocol families seem to be available, pushing our luck anyway\n";
my $ai_family = &AF_UNSPEC; # defaults to any address family (i.e. both)
if ($have_inet6 && (!$have_inet4 || $opt{'force_ipv6'})) {
$ai_family = &AF_INET6;
} elsif ($have_inet4 && (!$have_inet6 || $opt{'force_ipv4'})) {
$ai_family = &AF_INET;
}
my($error, @addresses);
if (!defined $addr || lc $addr eq 'localhost') { # loopback interface
push(@addresses, '::1')
if $ai_family == &AF_UNSPEC || $ai_family == &AF_INET6;
push(@addresses, '127.0.0.1')
if $ai_family == &AF_UNSPEC || $ai_family == &AF_INET;
} elsif ($addr eq '*' || $addr eq '') { # any address
push(@addresses, '::')
if $ai_family == &AF_UNSPEC || $ai_family == &AF_INET6;
push(@addresses, '0.0.0.0')
if $ai_family == &AF_UNSPEC || $ai_family == &AF_INET;
} else {
($error, @addresses) = ip_or_name_to_ip_addresses($addr, $ai_family);
}
die "spamd: invalid address for a listen socket: \"$socket_specs\": $error\n"
if $error;
die "spamd: no valid address for a listen socket: \"$socket_specs\"\n"
if !@addresses;
dbg("spamd: attempting to listen on IP addresses: %s, port %d",
join(', ',@addresses), $port);
my(@diag_succ, @diag_fail);
for my $adr (@addresses) {
my %sockopt = (
LocalAddr => $adr,
LocalPort => $port,
Type => &SOCK_STREAM,
Proto => 'tcp',
ReuseAddr => 1,
Listen => &SOMAXCONN,
);
$sockopt{V6Only} = 1 if $io_socket_module_name eq 'IO::Socket::IP'
&& IO::Socket::IP->VERSION >= 0.09;
( run in 2.180 seconds using v1.01-cache-2.11-cpan-71847e10f99 )