You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by qu...@apache.org on 2005/04/21 01:18:07 UTC
svn commit: r162089 [2/2] - in /spamassassin/branches/logger: ./ lib/Mail/
lib/Mail/SpamAssassin/ lib/Mail/SpamAssassin/BayesStore/
lib/Mail/SpamAssassin/Conf/ lib/Mail/SpamAssassin/Locker/
lib/Mail/SpamAssassin/Logger/ lib/Mail/SpamAssassin/Message/
lib/Mail/SpamAssassin/Plugin/ masses/ spamd/
Modified: spamassassin/branches/logger/spamd/spamd.raw
URL: http://svn.apache.org/viewcvs/spamassassin/branches/logger/spamd/spamd.raw?rev=162089&r1=162088&r2=162089&view=diff
==============================================================================
--- spamassassin/branches/logger/spamd/spamd.raw (original)
+++ spamassassin/branches/logger/spamd/spamd.raw Wed Apr 20 16:18:05 2005
@@ -41,10 +41,10 @@
use Mail::SpamAssassin::NetSet;
use Mail::SpamAssassin::SubProcBackChannel;
use Mail::SpamAssassin::SpamdForkScaling qw(:pfstates);
+use Mail::SpamAssassin::Logger qw(:DEFAULT log_message);
use Getopt::Long;
use Pod::Usage;
-use Sys::Syslog qw(:DEFAULT setlogsock);
use POSIX qw(:sys_wait_h);
use POSIX qw(setsid sigprocmask);
use Errno;
@@ -63,6 +63,13 @@
BEGIN {
eval { require Time::HiRes };
Time::HiRes->import(qw(time)) unless $@;
+ # redirect __WARN__ and __DIE__
+ $SIG{__WARN__} = sub {
+ log_message("warn", $_[0]);
+ };
+ $SIG{__DIE__} = sub {
+ log_message("error", $_[0]) if $_[0] !~ /\bin eval\b/;
+ };
}
my %resphash = (
@@ -85,9 +92,6 @@
EX_TIMEOUT => 79, # read timeout
);
-*dbg = \&Mail::SpamAssassin::dbg;
-
-
sub print_version {
printf("%s version %s\n", "SpamAssassin Server", Mail::SpamAssassin::Version());
printf(" running on Perl %s\n", join(".", map { $_||=0; $_*1 } ($] =~ /(\d)\.(\d{3})(\d{3})?/)));
@@ -233,8 +237,8 @@
if (defined $opt{'debug'}) {
$opt{'debug'} ||= 'all';
}
-Mail::SpamAssassin::_init_debugger($opt{'debug'});
-
+# turn on debugging facilities as soon as possible
+Mail::SpamAssassin::Logger::add_facilities($opt{'debug'});
# bug 2228: make the values of (almost) all parameters which accept file paths
# absolute, so they are still valid after daemonize()
@@ -373,122 +377,24 @@
$log_socket = 'file';
}
-my $already_done_syslog_failure_warning;
-my $syslog_disabled;
-my $syslog_consecutive_failures = 0;
-my $syslog_failure_threshold = 10;
-
-# Logging via syslog is requested. Falling back to INET and then STDERR
-# if opening a UNIX socket fails.
+# Logging via syslog is requested.
if ($log_socket ne 'file' && $log_facility ne 'null') {
- dbg("logger: trying to connect to syslog/${log_socket}...\n");
- eval {
- defined( setlogsock($log_socket) ) || die $!;
-
- # The next call is required to actually open the socket.
- openlog_for_spamd();
- syslog( 'debug', "%s", "spamd starting" );
- };
- my $err = $@;
- chomp($err);
-
- # Solaris sometimes doesn't support UNIX-domain syslog sockets apparently;
- # same is true for perl 5.6.0 build on an early version of Red Hat 7!
- # In that case we try it with INET.
- if ( $err and $log_socket ne 'inet' ) {
- dbg("logger: connection to syslog/${log_socket} failed: $err\n"
- . "trying to connect to syslog/inet...");
- eval {
- defined( setlogsock('inet') ) || die $!;
- openlog_for_spamd();
- syslog( 'debug', "%s", "spamd starting, 2nd try" );
- syslog( 'debug', "%s", "failed to setlogsock(${log_socket}): $err" );
- syslog( 'debug', "%s",
- "falling back to inet (you might want to use --syslog-socket=inet)" );
- };
- $log_socket = 'inet' unless $@;
- }
-
- # fall back to stderr if all else fails
- if ($@) {
- dbg("logger: failed to setlogsock(${log_socket}): $err\n"
- . "reporting logs to stderr");
- $log_facility = 'stderr';
- }
- else {
- dbg("logger: successfully connected to syslog/${log_socket}");
+ if (Mail::SpamAssassin::Logger::add(method => 'syslog',
+ socket => $log_socket,
+ facility => $log_facility))
+ {
+ Mail::SpamAssassin::Logger::remove('stderr');
}
}
-
-# The user wants to log to some file -- open it on STDLOG. Falling back to STDERR
-# if opening the file fails.
-elsif ( $log_facility eq 'file' ) {
- unless ( open( STDLOG, ">>$log_file" ) ) {
- warn "failed to open logfile ${log_file}: $!\n"
- . "reporting logs to stderr\n";
- $log_facility = 'stderr';
+# Otherwise, the user wants to log to some file.
+elsif ($log_facility eq 'file') {
+ if (Mail::SpamAssassin::Logger::add(method => 'file',
+ filename => $log_file))
+ {
+ Mail::SpamAssassin::Logger::remove('stderr');
}
}
-# Either one of the above failed ot logging to STDERR is explicitly requested --
-# make STDLOG a dup so we don't have to handle so many special cases later on.
-if ( $log_facility eq 'stderr' ) {
- open( STDLOG, ">&STDERR" ) || die "Can't duplicate stderr: $!\n";
- $log_socket = 'file';
-}
-
-dbg("logger: enabled with:\n"
- . "\tfacility: ${log_facility}\n"
- . "\tsocket: ${log_socket}\n"
- . "\toutput: "
- . (
- $log_facility eq 'file' ? ${log_file}
- : $log_facility eq 'stderr' ? 'stderr'
- : $log_facility eq 'null' ? 'debug'
- : 'syslog'
- )
-);
-
-# Don't duplicate log messages in debug mode.
-if ( $log_facility eq 'stderr' and $Mail::SpamAssassin::DEBUG ) {
- dbg("logger: facility stderr disabled: already debugging to stderr.");
- $log_facility = 'null';
-}
-
-# Either above or at the command line all logging was disabled (--syslog=null).
-if ( $log_facility eq 'null' ) {
- $log_socket = 'none';
-}
-
-# Close the logfile on exit.
-END {
- close(STDLOG) if (defined $log_socket && $log_socket eq 'file');
-}
-
-# The code above was quite complicated. Make sure everything fits together.
-# These combinations are allowed:
-# * socket = file
-# ^ ^-> facility = stderr
-# '---> facility = file
-# * socket = none
-# ^-> facility = null
-# * socket = (unix|inet|...)
-# --> facility = (mail|daemon|...)
-die "fatal: internal error while setting up logging: values don't match:\n"
- . "\targuments:\n"
- . "\t\t--syslog=$opt{'syslog'} --syslog-socket=$opt{'syslog-socket'}\n"
- . "\tvalues:\n"
- . "\t\tfacility: ${log_facility}\n"
- . "\t\tsocket: ${log_socket}\n"
- . "\t\tfile: ${log_file}\n"
- . "\tplease report to http://bugzilla.spamassassin.org -- thank you\n"
- if ( $log_socket eq 'file'
- and ( $log_facility ne 'stderr' and $log_facility ne 'file' ) )
- or ( ( $log_facility eq 'stderr' or $log_facility eq 'file' )
- and $log_socket ne 'file' )
- or ( $log_socket eq 'none' and $log_facility ne 'null' )
- or ( $log_facility eq 'null' and $log_socket ne 'none' );
-
### End initialization of logging ##########################
# REIMPLEMENT: if $log_socket is none, fall back to log_facility 'stderr'.
@@ -668,7 +574,7 @@
die "spamd already running on $path, exiting\n";
}
else {
- dbg("daemon: removing stale socket file $path");
+ dbg("spamd: removing stale socket file $path");
unlink $path;
}
}
@@ -678,7 +584,7 @@
Type => SOCK_STREAM,
Listen => SOMAXCONN,
);
- dbg("daemon: creating UNIX socket:\n" . join("\n", map { "\t$_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
+ dbg("spamd: creating UNIX socket:\n" . join("\n", map { "\t$_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
$server = new IO::Socket::UNIX(%socket)
|| die "Could not create UNIX socket on $path: $! ($@)\n";
@@ -730,7 +636,7 @@
SSL_key_file => $opt{'server-key'},
SSL_cert_file => $opt{'server-cert'}
);
- dbg("daemon: creating SSL socket:\n" . join("\n", map { "\t$_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
+ dbg("spamd: creating SSL socket:\n" . join("\n", map { "\t$_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
$server = new IO::Socket::SSL(%socket)
|| die "Could not create SSL socket on $addr:$port: $! ($@)\n";
}
@@ -743,7 +649,7 @@
ReuseAddr => 1,
Listen => SOMAXCONN
);
- dbg("daemon: creating INET socket:\n" . join("\n", map { "\t$_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
+ dbg("spamd: creating INET socket:\n" . join("\n", map { "\t$_: " . (defined $socket{$_} ? $socket{$_} : "(undef)") } sort keys %socket));
$server = new IO::Socket::INET(%socket)
|| die "Could not create INET socket on $addr:$port: $! ($@)\n";
}
@@ -823,10 +729,8 @@
# log server started, but processes watching the log to wait for connect
# should wait until they see the pid, after signal handlers are in place
# FIXME: two calls are one too much
-dbg("info: server started on $listeninfo (running version "
- . Mail::SpamAssassin::Version() . ")" );
-logmsg("server started on $listeninfo (running version "
- . Mail::SpamAssassin::Version() . ")" );
+info("spamd: server started on $listeninfo (running version "
+ . Mail::SpamAssassin::Version() . ")" );
my $remote_port;
@@ -873,7 +777,7 @@
# leave Client fds active, and do not kill children; they can still
# service clients until they exit. But restart the listener anyway.
# And close the logfile, so the new instance can reopen it.
- close(STDLOG) if $log_facility eq 'file';
+ Mail::SpamAssasin::Logger::close();
chdir($ORIG_CWD)
|| die "spamd restart failed: chdir failed: ${ORIG_CWD}: $!\n";
exec( $ORIG_ARG0, @ORIG_ARGV );
@@ -907,7 +811,7 @@
## PARENT
$children{$pid} = 1;
- logmsg("server successfully spawned child process, pid $pid");
+ info("spamd: server successfully spawned child process, pid $pid");
$backchannel->setup_backchannel_parent_post_fork($pid);
if ($scaling) {
$scaling->add_child($pid);
@@ -965,7 +869,7 @@
$orders = $scaling->wait_for_orders(); # and sleep...
if ($orders != PFORDER_ACCEPT) {
- logmsg("unknown order: $orders");
+ info("spamd: unknown order: $orders");
}
}
@@ -974,7 +878,7 @@
my $evalret = eval { accept_a_conn(); };
if (!defined ($evalret)) {
- logmsg("error: $@ $!, continuing");
+ warn("spamd: error: $@ $!, continuing");
if ($client) { $client->close(); } # avoid fd leaks
}
elsif ($evalret == -1) {
@@ -987,7 +891,7 @@
$) = "$( $("; # change eGID
$> = $<; # change eUID
if ( $> != $< and $> != ( $< - 2**32 ) ) {
- logmsg("fatal: return setuid failed");
+ warn("spamd: fatal: return setuid failed");
die; # make it fatal to avoid security breaches
}
}
@@ -1018,7 +922,7 @@
if ($err) {
if ($err =~ /__alarm__/) {
- logmsg("copy_config timeout, respawning child process after ".
+ warn("spamd: copy_config timeout, respawning child process after ".
($i+1)." messages");
exit; # so that the master spamd can respawn
@@ -1048,11 +952,11 @@
return 0;
}
elsif ( $! == 0 && $opt{'ssl'} ) {
- logmsg( "SSL failure: " . &IO::Socket::SSL::errstr() );
+ warn("spamd: SSL failure: " . &IO::Socket::SSL::errstr());
return 0;
}
else {
- logmsg("accept failed: $!");
+ warn("spamd: accept failed: $!");
return -1;
}
}
@@ -1068,11 +972,11 @@
my $remote_hostname;
my $remote_hostaddr;
- if ( $opt{'socketpath'} ) {
+ if ($opt{'socketpath'}) {
$remote_hostname = 'localhost';
$remote_hostaddr = '127.0.0.1';
$remote_port = $opt{'socketpath'};
- logmsg( "got connection over " . $opt{'socketpath'} );
+ info("spamd: got connection over " . $opt{'socketpath'});
}
else {
my ( $port, $ip ) = sockaddr_in( $client->peername );
@@ -1083,11 +987,11 @@
$remote_port = $port;
my $msg = "connection from ${remote_hostname} [${remote_hostaddr}] at port ${port}";
- if ( ip_is_allowed($remote_hostaddr) ) {
- logmsg($msg);
+ if (ip_is_allowed($remote_hostaddr)) {
+ info("spamd: $msg");
}
else {
- logmsg("unauthorized " . $msg);
+ warn("spamd: unauthorized $msg");
$client->close;
return 0;
}
@@ -1127,9 +1031,7 @@
# in that case.
if (/SKIP SPAMC\/(.*)/) {
- logmsg( "skipped large message in "
- . sprintf( "%3d", time - $start )
- . " seconds." );
+ info(sprintf("spamd: skipped large message in %3d seconds", time - $start));
}
# It might be a CHECK message, meaning that we should just check
@@ -1200,24 +1102,20 @@
}
sub handle_setuid_to_user {
-
- if ( $spamtest->{paranoid} ) {
- logmsg("PARANOID: still running as root, closing connection.");
- die;
- }
- logmsg( "Still running as root: user not specified with -u, "
- . "not found, or set to root. Fall back to nobody." );
- my ( $uid, $gid ) = ( getpwnam('nobody') )[ 2, 3 ];
+ if ($spamtest->{paranoid}) {
+ die("spamd: in paranoid mode, still running as root: closing connection");
+ }
+ warn("spamd: still running as root: user not specified with -u, "
+ . "not found, or set to root, falling back to nobody" );
+ my ($uid, $gid) = (getpwnam('nobody'))[2,3];
$uid =~ /^(\d+)$/ and $uid = $1; # de-taint
$gid =~ /^(\d+)$/ and $gid = $1; # de-taint
$) = "$gid $gid"; # eGID
$> = $uid; # eUID
- if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) {
- logmsg("fatal: setuid to nobody failed");
- die;
+ if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
+ die("spamd: fatal error: setuid to nobody failed");
}
-
}
sub parse_body {
@@ -1299,14 +1197,13 @@
$msgid ||= "(unknown)";
$current_user ||= "(unknown)";
- logmsg( ( $method eq 'PROCESS' ? "processing" : "checking" )
- . " message $msgid"
- . ( $rmsgid ? " aka $rmsgid" : "" )
- . " for ${current_user}:$>"
- . "." );
+ info("spamd: " . ($method eq 'PROCESS' ? "processing" : "checking")
+ . " message $msgid"
+ . ( $rmsgid ? " aka $rmsgid" : "" )
+ . " for ${current_user}:$>");
# Check length if we're supposed to.
- if ( defined $expected_length && $actual_length != $expected_length ) {
+ if (defined $expected_length && $actual_length != $expected_length) {
protocol_error(
"(Content-Length mismatch: Expected $expected_length bytes, got $actual_length bytes)"
);
@@ -1400,8 +1297,8 @@
my $scantime = sprintf( "%.1f", time - $start_time );
- logmsg( "$was_it_spam ($msg_score/$msg_threshold) for $current_user:$> in"
- . " $scantime seconds, $actual_length bytes." );
+ info("spamd: $was_it_spam ($msg_score/$msg_threshold) for $current_user:$> in"
+ . " $scantime seconds, $actual_length bytes." );
# add a summary "result:" line, based on mass-check format
my @extra;
@@ -1426,8 +1323,8 @@
my $score = $status->get_score();
my $tests = join(",", sort(grep(length,$status->get_names_of_tests_hit())));
- logmsg( sprintf("result: %s %2d - %s %s", $yorn, $score,
- $tests, join(",", @extra) ));
+ info(sprintf("spamd: result: %s %2d - %s %s", $yorn, $score,
+ $tests, join(",", @extra)));
$status->finish(); # added by jm to allow GC'ing
$mail->finish();
@@ -1498,11 +1395,10 @@
$forget = 1;
}
- logmsg($learn_type_desc
+ info("spamd: $learn_type_desc"
. " message $msgid"
. ( $rmsgid ? " aka $rmsgid" : "" )
- . " for ${current_user}:$>"
- . ".");
+ . " for ${current_user}:$>");
# Check length if we're supposed to.
if (defined $expected_length && $actual_length != $expected_length) {
@@ -1526,8 +1422,8 @@
my $scantime = sprintf( "%.1f", time - $start_time );
- logmsg("$learn_type_desc_past message for $current_user:$> in"
- . " $scantime seconds, $actual_length bytes.");
+ info("spamd: $learn_type_desc_past message for $current_user:$> in"
+ . " $scantime seconds, $actual_length bytes");
$status->finish(); # added by jm to allow GC'ing
$mail->finish();
return 1;
@@ -1658,23 +1554,23 @@
sub protocol_error {
my ($err) = @_;
my $resp = "EX_PROTOCOL";
- syswrite( $client, "SPAMD/1.0 $resphash{$resp} Bad header line: $err\r\n" );
- logmsg("bad protocol: header error: $err");
+ syswrite($client, "SPAMD/1.0 $resphash{$resp} Bad header line: $err\r\n");
+ info("spamd: bad protocol: header error: $err");
}
sub service_unavailable_error {
my ($err) = @_;
my $resp = "EX_UNAVAILABLE";
- syswrite( $client,
- "SPAMD/1.0 $resphash{$resp} Service Unavailable: $err\r\n" );
- logmsg("service unavailable: $err");
+ syswrite($client,
+ "SPAMD/1.0 $resphash{$resp} Service Unavailable: $err\r\n");
+ info("spamd: service unavailable: $err");
}
sub service_timeout {
my ($err) = @_;
my $resp = "EX_TIMEOUT";
print $client "SPAMD/1.0 $resphash{$resp} Timeout: $err\r\n";
- logmsg("timeout: $err");
+ info("spamd: timeout: $err");
}
###########################################################################
@@ -1685,7 +1581,7 @@
my $dn = $ident_username || 'NONE'; # display name
dbg("ident: ident_username = $dn, spamc_username = $username\n");
if ( !defined($ident_username) || $username ne $ident_username ) {
- logmsg( "fatal: ident username ($dn) does not match "
+ info("spamd: fatal: ident username ($dn) does not match "
. "spamc username ($username)" );
return 0;
}
@@ -1706,15 +1602,14 @@
else {
$userid = $username;
}
- my ( $name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc ) =
- getpwnam($userid);
-
- if ( !$spamtest->{'paranoid'} && !defined($uid) ) {
+ my ($name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc) =
+ getpwnam($userid);
- #if we are given a username, but can't look it up,
- #Maybe NIS is down? lets break out here to allow
- #them to get 'defaults' when we are not running paranoid.
- logmsg("handle_user: unable to find user '$userid'!");
+ if (!$spamtest->{'paranoid'} && !defined($uid)) {
+ # if we are given a username, but can't look it up, maybe name
+ # services are down? let's break out here to allow them to get
+ # 'defaults' when we are not running paranoid
+ info("spamd: handle_user unable to find user: $userid\n");
return 0;
}
@@ -1726,11 +1621,11 @@
$) = "$gid $gid"; # change eGID
$> = $uid; # change eUID
if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) {
- logmsg("fatal: setuid to $username failed");
- die; # make it fatal to avoid security breaches
+ # make it fatal to avoid security breaches
+ die("spamd: fatal error: setuid to $username failed");
}
else {
- logmsg("info: setuid to $username succeeded");
+ info("spamd: setuid to $username succeeded");
}
}
@@ -1799,7 +1694,7 @@
$prefsfile = $dir . '/user_prefs';
# Log that the default configuration is being used for a user.
- logmsg("Using default config for $username: $prefsfile");
+ info("spamd: using default config for $username: $prefsfile");
}
if ( -f $prefsfile ) {
@@ -1850,15 +1745,14 @@
sub handle_user_setuid_with_sql {
my $username = shift;
- my ( $name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc ) =
- getpwnam($username);
+ my ($name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc) =
+ getpwnam($username);
- if ( !$spamtest->{'paranoid'} && !defined($uid) ) {
-
- #if we are given a username, but can't look it up,
- #Maybe NIS is down? lets break out here to allow
- #them to get 'defaults' when we are not running paranoid.
- logmsg("handle_user() -> unable to find user [$username]!\n");
+ if (!$spamtest->{'paranoid'} && !defined($uid)) {
+ # if we are given a username, but can't look it up, maybe name
+ # services are down? let's break out here to allow them to get
+ # 'defaults' when we are not running paranoid
+ info("spamd: handle_user unable to find user: $username\n");
return 0;
}
@@ -1868,26 +1762,26 @@
if ($setuid_to_user) {
$) = "$gid $gid"; # change eGID
$> = $uid; # change eUID
- if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) {
- logmsg("fatal: setuid to $username failed");
- die; # make it fatal to avoid security breaches
+ if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
+ # make it fatal to avoid security breaches
+ die("spamd: fatal error: setuid to $username failed");
}
else {
- logmsg("info: setuid to $username succeeded, reading scores from SQL.");
+ info("spamd: setuid to $username succeeded, reading scores from SQL");
}
}
- my $spam_conf_dir = $dir . '/.spamassassin'; #needed for Bayes, etc.
- if ( !-d $spam_conf_dir ) {
- if ( mkdir $spam_conf_dir, 0700 ) {
- logmsg("info: created $spam_conf_dir for $username.");
+ my $spam_conf_dir = $dir . '/.spamassassin'; # needed for Bayes, etc.
+ if (! -d $spam_conf_dir) {
+ if (mkdir $spam_conf_dir, 0700) {
+ info("spamd: created $spam_conf_dir for $username");
}
else {
- logmsg("info: failed to create $spam_conf_dir for $username.");
+ info("spamd: failed to create $spam_conf_dir for $username");
}
}
- unless ( $spamtest->load_scoreonly_sql($username) ) {
+ unless ($spamtest->load_scoreonly_sql($username)) {
return 0;
}
@@ -1897,37 +1791,36 @@
sub handle_user_setuid_with_ldap {
my $username = shift;
- my ( $name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc ) =
- getpwnam($username);
-
- if ( !$spamtest->{'paranoid'} && !defined($uid) ) {
+ my ($name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc) =
+ getpwnam($username);
- #if we are given a username, but can't look it up,
- #Maybe NIS is down? lets break out here to allow
- #them to get 'defaults' when we are not running paranoid.
- logmsg("handle_user() -> unable to find user [$username]!\n");
+ if (!$spamtest->{'paranoid'} && !defined($uid)) {
+ # if we are given a username, but can't look it up, maybe name
+ # services are down? let's break out here to allow them to get
+ # 'defaults' when we are not running paranoid
+ info("spamd: handle_user unable to find user: $username\n");
return 0;
}
if ($setuid_to_user) {
$) = "$gid $gid"; # change eGID
$> = $uid; # change eUID
- if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) {
- logmsg("fatal: setuid to $username failed");
- die; # make it fatal to avoid security breaches
+ if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
+ # make it fatal to avoid security breaches
+ die("spamd: fatal error: setuid to $username failed");
}
else {
- logmsg("info: setuid to $username succeeded, reading scores from LDAP.");
+ info("spamd: setuid to $username succeeded, reading scores from LDAP");
}
}
- my $spam_conf_dir = $dir . '/.spamassassin'; #needed for Bayes, etc.
- if ( !-d $spam_conf_dir ) {
- if ( mkdir $spam_conf_dir, 0700 ) {
- logmsg("info: created $spam_conf_dir for $username.");
+ my $spam_conf_dir = $dir . '/.spamassassin'; # needed for Bayes, etc.
+ if (! -d $spam_conf_dir) {
+ if (mkdir $spam_conf_dir, 0700) {
+ info("spamd: created $spam_conf_dir for $username");
}
else {
- logmsg("info: failed to create $spam_conf_dir for $username.");
+ info("spamd: failed to create $spam_conf_dir for $username");
}
}
@@ -1942,14 +1835,14 @@
# Parse user scores, creating default .cf if needed:
if ( !-r $cf_file && !$spamtest->{'dont_copy_prefs'} ) {
- logmsg("Creating default_prefs [$cf_file]");
+ info("spamd: creating default_prefs: $cf_file");
# If vpopmail config enabled then pass virtual homedir onto
# create_default_prefs via $userdir
$spamtest->create_default_prefs( $cf_file, $username, $userdir );
- if ( !-r $cf_file ) {
- logmsg("Couldn't create readable default_prefs for [$cf_file]");
+ if (! -r $cf_file) {
+ info("spamd: failed to create readable default_prefs: $cf_file");
}
}
}
@@ -1971,140 +1864,9 @@
$SIG{PIPE} = 'IGNORE';
}
-sub logmsg {
- my $msg = join ( " ", @_ );
- $msg =~ s/[\r\n]+$//; # remove any trailing newlines
- $msg =~ s/[\x00-\x1f]/_/g; # replace all other control chars with underscores
-
- dbg("log: $msg\n");
-
- # log to file:
- # bug 1360 <http://bugzilla.spamassassin.org/show_bug.cgi?id=1360>
- # enable logging to a file via --syslog=file or --syslog=/path/to/file
- # log to STDERR:
- # bug 605 <http://bugzilla.spamassassin.org/show_bug.cgi?id=605>
- # more efficient for daemontools if --syslog=stderr is used
- if ( $log_socket eq 'file' ) {
- logmsg_file ($msg);
- }
-
- # log to syslog (if logging isn't disabled completely via 'null')
- elsif ( $log_socket ne 'none' ) {
- logmsg_syslog ($msg);
- }
-}
-
-sub logmsg_file {
- my $msg = shift;
- my @date = reverse( ( gmtime(time) )[ 0 .. 5 ] );
- $date[0] += 1900;
- $date[1] += 1;
- syswrite(
- STDLOG,
- sprintf(
- "%04d-%02d-%02d %02d:%02d:%02d [%s] %s: %s\n",
- @date, $$, 'i', $msg
- )
- );
-}
-
-sub logmsg_syslog {
- my $msg = shift;
-
- return if $syslog_disabled;
-
- # install a new handler for SIGPIPE -- this signal has been
- # found to occur with syslog-ng after syslog-ng restarts.
- local $SIG{'PIPE'} = sub {
- $main::SIGPIPE_RECEIVED++;
- # force a log-close. trap possible die() calls
- eval { closelog(); };
- };
-
- # important: do not call syslog() from the SIGCHLD handler
- # child_handler(). otherwise we can get into a loop if syslog()
- # forks a process -- as it does in syslog-ng apparently! (bug 3625)
- $main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER = 1; #{
- eval { syslog( 'info', "%s", $msg ); };
- $main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER = 0; #}
-
- if ($@) {
- if (check_syslog_sigpipe($msg)) {
- # dealt with
- }
- else {
- warn "syslog() failed: $@"; # includes a \n
-
- # only write this warning once. it gets annoying fast
- if (!$already_done_syslog_failure_warning) {
- warn "try using --syslog-socket={unix,inet} or --syslog=file\n";
- $already_done_syslog_failure_warning = 1;
- }
- }
- syslog_incr_failure_counter();
- }
- else {
- $syslog_consecutive_failures = 0;
- check_syslog_sigpipe($msg); # check for SIGPIPE anyway (bug 3625)
- }
-
- $SIG{PIPE} = 'IGNORE'; # this may have been reset (bug 4026)
-}
-
-sub check_syslog_sigpipe {
- my ($msg) = @_;
-
- if (!$main::SIGPIPE_RECEIVED) {
- return 0; # didn't have a SIGPIPE
- }
-
- eval {
- # SIGPIPE received when writing to syslog -- close and reopen
- # the log handle, then try again.
- closelog();
- openlog_for_spamd();
- syslog( 'debug', "%s", "syslog reopened" );
- syslog( 'info', "%s", $msg );
-
- # now report what happend
- $msg = "SIGPIPE received, reopening log socket";
- dbg("log: $msg");
- syslog( 'warning', "%s", $msg );
-
- # if we've received multiple sigpipes, logging is probably
- # still broken.
- if ( $main::SIGPIPE_RECEIVED > 1 ) {
- warn "logging failure: multiple SIGPIPEs received\n";
- $syslog_disabled = 1;
- }
-
- $main::SIGPIPE_RECEIVED = 0;
- return 1;
- };
-
- if ($@) { # something died? that's not good.
- syslog_incr_failure_counter();
- }
-}
-
-# NOTE: wrap calls to this in eval{ }!!
-sub openlog_for_spamd {
- openlog( 'spamd', 'cons,pid,ndelay', $log_facility );
-}
-
-sub syslog_incr_failure_counter {
- if (++$syslog_consecutive_failures > $syslog_failure_threshold) {
- warn "syslog() failed ".$syslog_consecutive_failures
- ." times in a row, disabled\n";
- $syslog_disabled = 1;
- return 1;
- }
- return 0;
-}
-
sub kill_handler {
my ($sig) = @_;
- logmsg("server killed by SIG$sig, shutting down");
+ info("spamd: server killed by SIG$sig, shutting down");
$server->close;
if (defined($opt{'pidfile'})) {
@@ -2145,9 +1907,9 @@
if ($sock) { $sock->close(); }
}
- unless ($main::INHIBIT_LOGGING_IN_SIGCHLD_HANDLER) {
- logmsg("handled cleanup of child pid $pid ".
- (defined $sig) ? "due to SIG$sig" : "");
+ unless ($$Mail::SpamAssassin::Logger::LOG_SA{INHIBIT_LOGGING_IN_SIGCHLD_HANDLER}) {
+ info("spamd: handled cleanup of child pid $pid " .
+ (defined $sig) ? "due to SIG$sig" : "");
}
}
@@ -2156,13 +1918,13 @@
sub restart_handler {
my ($sig) = @_;
- logmsg("server hit by SIG$sig, restarting");
+ info("spamd: server hit by SIG$sig, restarting");
$SIG{CHLD} = 'DEFAULT'; # we're going to kill our children
foreach (keys %children) {
kill 'INT' => $_;
my $pid = waitpid($_, 0);
- logmsg("child $pid killed successfully");
+ info("spamd: child $pid killed successfully");
}
%children = ();
@@ -2175,26 +1937,26 @@
unlink($opt{'socketpath'}) || warn "Can't unlink $opt{'socketpath'}: $!\n";
}
- dbg("info: Server socket closed");
+ info("spamd: server socket closed");
}
$got_sighup = 1;
}
sub daemonize {
-
# Pretty command line in ps
- $0 = join (' ', $ORIG_ARG0, @ORIG_ARGV) unless $Mail::SpamAssassin::DEBUG;
+ $0 = join (' ', $ORIG_ARG0, @ORIG_ARGV) unless would_log("dbg");
- # Be a nice daemon and chdir() to the root so we don't block any unmount attempts
+ # be a nice daemon and chdir to the root so we don't block any
+ # unmount attempts
chdir '/' or die "Can't chdir to /: $!\n";
- # Redirect all warnings to logmsg()
- $SIG{__WARN__} = sub { logmsg( $_[0] ); };
-
# Redirect in and out to the bit bucket
open STDIN, "</dev/null" or die "Can't read from /dev/null: $!\n";
open STDOUT, ">/dev/null" or die "Can't write to /dev/null: $!\n";
+ # Remove the stderr logger
+ Mail::SpamAssassin::Logger::remove('stderr');
+
# Here we go...
defined( my $pid = fork ) or die "Can't fork: $!\n";
exit if $pid;
@@ -2203,7 +1965,7 @@
# Now we can redirect the errors, too.
open STDERR, '>&STDOUT' or die "Can't duplicate stdout: $!\n";
- dbg("daemon: successfully daemonized");
+ dbg("spamd: successfully daemonized");
}
sub set_allowed_ip {
@@ -2234,7 +1996,7 @@
my $tmpsadir = File::Spec->catdir( $tmphome, ".spamassassin" );
- dbg("daemon: Preloading modules with HOME=$tmphome");
+ dbg("spamd: Preloading modules with HOME=$tmphome");
mkdir( $tmphome, 0700 ) or die "fatal: Can't create $tmphome: $!";
mkdir( $tmpsadir, 0700 ) or die "fatal: Can't create $tmpsadir: $!";