Author: vetinari
Date: Thu Sep 20 10:18:17 2007
New Revision: 791

Added:
   contrib/vetinari/config_ini

Log:
config_ini: new plugin for -forkserver and -prefork, 
  reads an .ini file with the qpsmtpd config, re-read only if changed on disk 


Added: contrib/vetinari/config_ini
==============================================================================
--- (empty file)
+++ contrib/vetinari/config_ini Thu Sep 20 10:18:17 2007
@@ -0,0 +1,137 @@
+#! perl
+
+=head1 NAME
+
+config_ini - (another) example plugin how to use the "config" hook
+
+=head1 DESCRIPTION
+
+B<config_ini> reads a config.ini and returns the section for the requested
+config to qpsmtpd, if found.
+
+It only reads the config if it has changed on disk, instead of reading every
+small file each time it's requested. Reading of the config is done in the 
+C<pre-connection> hook, so it will only work with qpsmtpd flavours supporting
+this hook (C<-forkserver>, C<-prefork>).
+
+This (like any config hook plugin) plugin should be 
+the first plugin in the F<config/plugins> file.
+
+The B<config_ini> plugin can be given an (optional) argument: the name of the
+F<config.ini> file, default is C</etc/qpsmtpd/config.ini>.
+
+The F<config.ini> is standard ini format, comments start with C<#>. Example:
+
+ [me]
+ my.host.name
+ [IP]
+ 0
+ [badhelo]
+ aol.com
+ yahoo.com
+  
+ [badrcptto_patterns]
+ # Format is pattern\s+Response
+ # Don't forget to anchor the pattern if required
+ !       Sorry, bang paths not accepted here
+ @.*@    Sorry, multiple at signs not accepted here
+ %       Sorry, percent hack not accepted here 
+ [logging]
+ logging/warn 9
+ [loglevel]
+ # Log levels
+ # LOGDEBUG   = 7
+ # LOGINFO    = 6
+ # LOGNOTICE  = 5
+ # LOGWARN    = 4
+ # LOGERROR   = 3
+ # LOGCRIT    = 2
+ # LOGALERT   = 1
+ # LOGEMERG   = 0
+ 4
+ [require_resolvable_fromhost]
+ 1
+ # EOF
+
+=cut
+
+my %config = ();
+
+sub register {
+    my ($self,$qp,@args) = @_;
+    unless (@args) {
+        @args = ("/etc/qpsmtpd/config.ini");
+        $self->log(LOGDEBUG, "Using default file /etc/qpsmtpd/config.ini");
+    }
+
+    die "too many arguments to config_ini plugin"
+      if (@args > 1);
+    
+    $self->{_config_ini_file} = $args[0];
+
+    ($self->{_config_ini_time},%config) = $self->read_ini();
+    die "failed to read config file $args[0]"
+      unless $self->{_config_ini_time};
+}
+
+sub read_ini {
+    my $self = shift;
+    my $file = $self->{_config_ini_file};
+    my %conf = ();
+
+    open CFG, $file
+      or $self->log(LOGWARN, "Failed to open $file: $!"), return (0, ());
+    my ($time)  = (stat(CFG))[9] || 0;
+    my $section = undef;
+
+    while (<CFG>) {
+        # skip comments and empty lines:
+        next if /^\s*#/;
+        next if /^\s*$/;
+        chomp; 
+        if (/^\s*\[([^\]]+)\]\s*$/) {
+            $section = lc $1;
+        } else {
+            next unless defined $section;
+            push @{$conf{$section}}, $_;
+        }
+    }
+    close CFG;
+    return ($time, %conf);
+}
+
+sub hook_pre_connection {
+    my $self = shift;
+    my ($time) = (stat($self->{_config_ini_file}))[9];
+    my %tmp = (); 
+    if ($time > $self->{_config_ini_time}) {
+        $self->log(
+                   LOGINFO, 
+                   "$time > " . $self->{_config_ini_time} . ", re-reading "
+                   . $self->{_config_ini_file}
+                  );
+
+        ($time, %tmp) = $self->read_ini();
+
+        # if ($time && (keys %tmp >= keys %config)) {
+        if ($time && keys(%tmp)) {
+            %config = %tmp;
+            $self->{_config_ini_time} = $time;
+        } 
+        else {
+            $self->log(LOGWARN, "no values in config found, ignoring");
+        }
+    }
+    return (DECLINED);
+}
+
+sub hook_config {
+    my ($self,$txn,$value) = @_;
+    $value = lc $value;
+    # $self->log(LOGDEBUG, "config_ini: '$value'");
+    return (OK, @{$config{$value}})
+      if exists $config{$value};
+    return (DECLINED);
+}
+
+# vim: ts=4 sw=4 expandtab syn=perl

Reply via email to