|
1 # © 2006,2007 Heiko Schlittermann <hs@schlittermann.de> |
|
2 # $Id$ |
|
3 # $URL$ |
|
4 |
|
5 use strict; |
|
6 use warnings; |
|
7 use BerkeleyDB; |
|
8 |
|
9 my %DEFAULT = ( |
|
10 delay => 600, |
|
11 db => "seen.db", |
|
12 ); |
|
13 |
|
14 sub unseen($;$$); |
|
15 |
|
16 sub getDBDir(); |
|
17 sub findExim(;$); |
|
18 sub getDefault() { %DEFAULT }; |
|
19 |
|
20 # Usage: |
|
21 # ${perl{unseen}{$sender_host_address}} |
|
22 # ${perl{unseen}{$sender_host_address}{600}} |
|
23 # ${perl{unseen}{$sender_host_address}{600}{seen.db}} |
|
24 # ${perl{unseen}{$sender_host_address}{600}{/some/dir/seen.db}} |
|
25 # |
|
26 # record structure: key: item\0 |
|
27 # value: timestamp(creation) timestamp(usage)\0 |
|
28 # (This way we're compatible with ${lookup{...}dbm{...}}) |
|
29 sub unseen($;$$) { |
|
30 my ($item, $delay, $db) = @_; |
|
31 $item .= "\0"; |
|
32 $delay = $DEFAULT{delay} unless defined $delay; |
|
33 $db = $DEFAULT{db} unless defined $db; |
|
34 |
|
35 my $now = time(); |
|
36 my $umask; |
|
37 my $rc; |
|
38 |
|
39 $db = getDBDir() . "/$db" unless $db =~ /^\//; |
|
40 |
|
41 $umask = umask 0077 if !-f $db; |
|
42 |
|
43 my %h; tie %h, "BerkeleyDB::Hash", |
|
44 -Filename => $db, |
|
45 -Flags => DB_CREATE |
|
46 or die; |
|
47 |
|
48 umask $umask if defined $umask; |
|
49 |
|
50 if (not exists $h{$item}) { |
|
51 $h{$item} = "$now $now\0"; |
|
52 $rc = "yes"; |
|
53 } else { |
|
54 my $created = (split " ", $h{$item})[0]; |
|
55 if ($now - $created < $delay) { $rc = "yes" } |
|
56 else { |
|
57 $rc = "no"; |
|
58 $h{$item} = "$created $now\0"; |
|
59 } |
|
60 } |
|
61 untie %h; |
|
62 return $rc; |
|
63 } |
|
64 |
|
65 # Get the directory where we could store the database file(s) |
|
66 # If we're running under exim it's easy, otherwise we've to find exim |
|
67 # and then ask... |
|
68 sub getDBDir() { |
|
69 my $spooldir; |
|
70 eval { $spooldir = Exim::expand_string('$spool_directory') }; |
|
71 if (not defined $spooldir) { |
|
72 my $exim = findExim(); |
|
73 chomp($spooldir = `$exim -be '\$spool_directory'`); |
|
74 die "Can't find spooldir" if not defined $spooldir; |
|
75 } |
|
76 return "$spooldir/db"; |
|
77 } |
|
78 |
|
79 sub findExim(;$) { |
|
80 my $path = shift || $ENV{PATH}; |
|
81 my $exim; |
|
82 foreach (split /:/, $ENV{PATH}) { |
|
83 -x ($exim = "$_/exim") and return $exim; |
|
84 -x ($exim = "$_/exim4") and return $exim; |
|
85 } |
|
86 return undef; |
|
87 } |
|
88 |
|
89 1; |
|
90 |
|
91 # vim:aw: |