qpsmtpd/packaging/rpm/files/qpsmtpd-plugin-file_connection
2009-07-14 21:52:40 +01:00

185 lines
4.7 KiB
Perl

#!/usr/bin/perl
# $Id: file 478 2005-07-19 07:40:16Z aqua $
=head1 NAME
file_connection - Simple per session log-to-file logging for qpsmtpd
=head1 DESCRIPTION
The 'file_connection' logging plugin for qpsmtpd records qpsmtpd log messages into a
file (or a named pipe, if you prefer.)
The file is reopened for each connection. To facilitate automatic
logfile switching the filename can contain strftime conversion
specifiers, which are expanded immediately before opening the file. This
ensures that a single connection is never split across logfiles.
The list of supported conversion specifiers depends on the strftime
implementation of your C library. See strftime(3) for details.
Additionally, %i exands to a (hopefully) unique session-id.
=head1 CONFIGURATION
To enable the logging plugin, add a line of this form to the qpsmtpd plugins
configuration file:
=over
logging/file_connection [loglevel I<level>] I<path>
For example:
logging/file_connection loglevel LOGINFO /var/log/qpsmtpd/%Y-%m-%d
=back
Multiple instances of the plugin can be configured by appending :I<N> for any
integer(s) I<N>, to log to multiple files simultaneously, e.g. to log critical
errors and normally verbose logs elsewhere.
The following optional configuration setting can be supplied:
=over
=item loglevel I<loglevel>
The internal log level below which messages will be logged. The I<loglevel>
given should be chosen from this list. Priorities count downward (for example,
if LOGWARN were selected, LOGERROR, LOGCRIT and LOGEMERG messages would be
logged as well):
=over
=item B<LOGDEBUG>
=item B<LOGINFO>
=item B<LOGNOTICE>
=item B<LOGWARN>
=item B<LOGERROR>
=item B<LOGCRIT>
=item B<LOGALERT>
=item B<LOGEMERG>
=back
=back
The chosen I<path> should be writable by the user running qpsmtpd; it will be
created it did not already exist, and appended to otherwise.
=head1 AUTHOR
Peter J. Holzer <hjp@hjp.at>, based on a plugin by
Devin Carraway <qpsmtpd@devin.com>
=head1 LICENSE
Copyright (c) 2005, Devin Carraway.
This plugin is licensed under the same terms as the qpsmtpd package itself.
Please see the LICENSE file included with qpsmtpd for details.
=cut
use strict;
use warnings;
use IO::File;
#use Sys::Hostname;
use POSIX qw(strftime);
sub register {
my ($self, $qp, @args) = @_;
my %args;
$self->{_loglevel} = LOGWARN;
while (1) {
last if !@args;
if (lc $args[0] eq 'loglevel') {
shift @args;
my $ll = shift @args;
if (!defined $ll) {
warn "Malformed arguments to logging/file_connection plugin";
return;
}
if ($ll =~ /^(\d+)$/) {
$self->{_loglevel} = $1;
}
elsif ($ll =~ /^(LOG\w+)$/) {
$self->{_loglevel} = log_level($1);
defined $self->{_loglevel} or $self->{_loglevel} = LOGWARN;
}
}
else { last }
}
unless (@args && $args[0]) {
warn "Malformed arguments to syslog plugin";
return;
}
$self->{_logfile} = join(' ', @args);
$self->{_log_session_id_prefix} = sprintf("%08x%04x", time(), $$);
$self->{_log_session_id_counter} = 0;
$self->register_hook('logging', 'write_log');
$self->register_hook('pre-connection', 'open_log');
$self->open_log($qp);
}
sub open_log {
my ($self, $qp) = @_;
my $output = $self->{_logfile};
$self->{_log_session_id} =
$self->{_log_session_id_prefix} . "." .
++$self->{_log_session_id_counter};
$output =~ s/%i/$self->{_log_session_id}/;
$output = strftime($output, localtime);
#print STDERR "open_log: output=$output, uid=$>\n";
if ($output =~ /^\s*\|(.*)/) {
unless ($self->{_f} = new IO::File "|$1") {
warn "Error opening log output to command $1: $!";
return;
}
} elsif ($output =~ /^(.*)/) { # detaint
unless ($self->{_f} = new IO::File ">>$1") {
warn "Error opening log output to path $1: $!";
return;
}
}
$self->{_f}->autoflush(1);
return DECLINED;
}
sub write_log {
my ($self, $txn, $trace, $hook, $plugin, @log) = @_;
return DECLINED if $trace > $self->{_loglevel};
return DECLINED if defined $plugin and $plugin eq $self->plugin_name;
$self->open_log unless($self->{_f});
my $f = $self->{_f};
print STDERR "no open file\n" unless (defined $f);
print $f join(" ",
strftime("%Y-%m-%dT%H:%M:%S%z", localtime), $self->{_log_session_id},
(defined $plugin ? " $plugin plugin:" :
defined $hook ? " running plugin ($hook):" : ""),
@log), "\n";
return DECLINED;
}
# vi: tabstop=4 shiftwidth=4 expandtab: