# HG changeset patch # User Heiko Schlittermann # Date 1366475778 -7200 # Node ID f3c6f1f69e7d20db4406a40ee021f12895fcaeb9 # Parent 044834f7b19f9161148bfb523c22058707c95bee migration to perlish Build.PL diff -r 044834f7b19f -r f3c6f1f69e7d .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Apr 20 18:36:18 2013 +0200 @@ -0,0 +1,3 @@ +syntax: glob +_build/ +blib/ diff -r 044834f7b19f -r f3c6f1f69e7d Build.PL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Build.PL Sat Apr 20 18:36:18 2013 +0200 @@ -0,0 +1,14 @@ +use strict; +use warnings; +use Module::Build; + +Module::Build->new( + module_name => "exiacl", + dist_name => "exiacl", + dist_version => "1.2.1", + dist_author => "Heiko Schlittermann ", + dist_abstract => "check exim acl", + requires => { + "AppConfig" => 0, + }, +)->create_build_script; diff -r 044834f7b19f -r f3c6f1f69e7d MANIFEST --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MANIFEST Sat Apr 20 18:36:18 2013 +0200 @@ -0,0 +1,98 @@ +.hg/00changelog.i +.hg/branch +.hg/branch.cache +.hg/branchheads.cache +.hg/cache/tags +.hg/dirstate +.hg/hgrc +.hg/last-message.txt +.hg/patches/.hg/00changelog.i +.hg/patches/.hg/dirstate +.hg/patches/.hg/last-message.txt +.hg/patches/.hg/requires +.hg/patches/.hg/store/00changelog.i +.hg/patches/.hg/store/00manifest.i +.hg/patches/.hg/store/data/.hgignore.i +.hg/patches/.hg/store/data/series.i +.hg/patches/.hg/store/data/use-build-pl.i +.hg/patches/.hg/store/fncache +.hg/patches/.hg/store/undo +.hg/patches/.hg/tags.cache +.hg/patches/.hg/undo.branch +.hg/patches/.hg/undo.desc +.hg/patches/.hg/undo.dirstate +.hg/patches/.hgignore +.hg/patches/series +.hg/patches/status +.hg/patches/use-build-pl +.hg/requires +.hg/store/00changelog.i +.hg/store/00manifest.i +.hg/store/data/.hgignore.i +.hg/store/data/.hgsigs.i +.hg/store/data/.hgtags.i +.hg/store/data/.perltidyrc.i +.hg/store/data/_makefile.i +.hg/store/data/bin/exiacl.i +.hg/store/data/debian/_r_e_a_d_m_e._debian.i +.hg/store/data/debian/changelog.i +.hg/store/data/debian/compat.i +.hg/store/data/debian/control.i +.hg/store/data/debian/copyright.i +.hg/store/data/debian/cron.d.ex.i +.hg/store/data/debian/dirs.i +.hg/store/data/debian/docs.i +.hg/store/data/debian/emacsen-install.ex.i +.hg/store/data/debian/emacsen-remove.ex.i +.hg/store/data/debian/emacsen-startup.ex.i +.hg/store/data/debian/exiacl-default.ex.i +.hg/store/data/debian/exiacl.doc-base._e_x.i +.hg/store/data/debian/init.d.ex.i +.hg/store/data/debian/manpage.1.ex.i +.hg/store/data/debian/manpage.sgml.ex.i +.hg/store/data/debian/manpage.xml.ex.i +.hg/store/data/debian/menu.ex.i +.hg/store/data/debian/postinst.ex.i +.hg/store/data/debian/postrm.ex.i +.hg/store/data/debian/preinst.ex.i +.hg/store/data/debian/prerm.ex.i +.hg/store/data/debian/rules.i +.hg/store/data/debian/watch.ex.i +.hg/store/data/exiacl.i +.hg/store/data/exiacl.man8.i +.hg/store/data/exiacl.pl.i +.hg/tags.cache +.hg/undo.branch +.hg/undo.desc +.hg/undo.dirstate +.hgignore +.hgsigs +.hgtags +.perltidyrc +bin/exiacl +Build.PL +debian/changelog +debian/compat +debian/control +debian/copyright +debian/cron.d.ex +debian/dirs +debian/docs +debian/emacsen-install.ex +debian/emacsen-remove.ex +debian/emacsen-startup.ex +debian/exiacl-default.ex +debian/exiacl.doc-base.EX +debian/init.d.ex +debian/manpage.1.ex +debian/manpage.sgml.ex +debian/manpage.xml.ex +debian/menu.ex +debian/postinst.ex +debian/postrm.ex +debian/preinst.ex +debian/prerm.ex +debian/README.Debian +debian/rules +debian/watch.ex +MANIFEST This list of files diff -r 044834f7b19f -r f3c6f1f69e7d Makefile --- a/Makefile Wed Oct 20 23:38:51 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -# © Heiko Schlittermann -# $Id$ -# $URL$ - -SCRIPTS = exiacl -MANPAGES = exiacl.8 -CLEANFILES = $(SCRIPTS) $(MANPAGES) -p = exiacl - -prefix = /usr/local -bindir = $(prefix)/bin - -ifndef DESTDIR - STOW := $(shell which stow 2>/dev/null) -else - STOW := -endif - -# use stow if found -ifdef STOW - override prefix := $(prefix)/stow/exiacl -endif - - -.PHONY: all install clean uninstall - -all: $(SCRIPTS) $(MANPAGES) - -install: all - install -d $(bindir) - install -m 0755 $(SCRIPTS) $(bindir) -ifdef STOW - stow -d $(prefix)/.. -vR $(p) -endif - -clean: - @-rm -fv $(CLEANFILES) - -uninstall: - stow -d $(stowdir) -vD $(p) - rm -rf $(stowdir)/$(p) - - -%: %.pl - @perl -c $< - @cp -vf $< $@ - @chmod -w+x $@ - -%.8: %.man8 - pod2man --name $(basename $<) --section 8 --center "exim" $< >$@ - - -# vim:sts=4 sw=4 aw ai sm list: diff -r 044834f7b19f -r f3c6f1f69e7d bin/exiacl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/exiacl Sat Apr 20 18:36:18 2013 +0200 @@ -0,0 +1,284 @@ +#! /usr/bin/perl +# © Heiko Schlittermann +use constant USAGE => << '#'; +!ME! [options] [-- exim native options] + + --[no]log show the log output [!$Cf->log!] + --[no]debug show debug output [!$Cf->debug!] + + --from=s from: [!$Cf->from!] + --to=s to: [!$Cf->to!] + (comma separated) + + --Helo=s HELO [!$Cf->Helo!] + --From=s MAIL FROM: [!$Cf->From!] + --To=s RCPT TO: [!$Cf->To!] + (comma separated) + + --src=s src ip/name [!$Cf->src!] + --dst=s dst ip/name [!$Cf->dst!] + + --au user (-oMai) [!$Cf->oMai!] + --aa authenticator (-oMaa) [!$Cf->oMaa!] + + --exim=s exim binary [!$Cf->exim!] + --config=s exim config file [!$Cf->config!] + + --[no]callout [!$Cf->callout!] + + Environment used: $EXIM [!$ENV{EXIM}!] + $EXIM_CONF [!$ENV{EXIM_CONF}!] + + mail data is read from STDIN unless it's connected to terminal. + + Source: https://keller.schlittermann.de/hg/exiacl + +# + +use strict; +use warnings; +use AppConfig; +use IPC::Open3; +use IO::Select; +use Socket; +use File::Basename; + +our $VERSION = "1.2"; + +sub exim_option($); +sub read_exim($;$); +sub write_exim($@); +sub addr(@); +sub hostname() { chomp (my $h = `hostname -f`); return $h; } + +sub which($) { (map { -x "$_/$_[0]" && "$_/$_[0]" || () } split /:/, $ENV{PATH})[0] } +sub findExim() { $ENV{EXIM} || which("exim") || which("exim4") || undef } +sub guessConfig() { $_ = findExim(); qx/$_ "-bV"/ =~ /^Configuration.*\sis\s+(\S+)/mi and return $1 } + +use constant ME => basename $0; +use constant HOSTNAME => hostname; + +my $Cf = new AppConfig ( + { CASE => 1 }, + + log => { ARGS => "!", DEFAULT => 1 }, + debug => { ARGS => "!", DEFAULT => 0 }, + + from => { ARGS => "=s" }, + to => { ARGS => "=s" }, + + Helo => { ARGS => "=s", ALIAS => "ehlo" }, + From => { ARGS => "=s" }, + To => { ARGS => "=s" }, + + src => { ARGS => "=s", DEFAULT => "172.20.1.8" }, + dst => { ARGS => "=s" }, # exim primary_hostname + + au => { ARGS => "=s" }, + aa => { ARGS => "=s" }, + + exim => { ARGS => "=s", DEFAULT => findExim() }, + config => { ARGS => "=s", DEFAULT => guessConfig(), ALIAS => "C" }, + + callout => { ARGS => "!", DEFAULT => 1 }, + help => { ARGS => "!" }, + +) or die; + + $Cf->exim or die "No exim binary found\n"; + $Cf->dst(addr(exim_option("primary_hostname"))); + #$Cf->getopt(qw(pass_through no_ignore_case)) or die $@; + $Cf->getopt(qw(no_ignore_case)) or die $@; + + $Cf->From($Cf->from) unless $Cf->From; + $Cf->To($Cf->to) unless $Cf->To; + + $Cf->Helo(map { (my $x = $_) =~ s/[<>]//g; $x } (split/@/, $Cf->from||"")[1] || HOSTNAME) + unless $Cf->Helo; + $Cf->dst(addr(HOSTNAME)) unless $Cf->dst; + + $Cf->aa("LOGIN") unless $Cf->aa || !$Cf->au; + + + +MAIN: { + die "Config file for exim not readable ".$Cf->config.": $!\n" if not -r $Cf->config; + + + my ($w, $r); + my @cmd = ($Cf->exim, + -C => $Cf->config, + -oMi => addr($Cf->dst), + ($Cf->au ? (-oMai => $Cf->au) : ()), + ($Cf->aa ? (-oMaa => $Cf->aa) : ()), + ($Cf->callout? "-bhc" : "-bh" ) => addr($Cf->src), + @ARGV); # remaining args are exim native + + if ($Cf->help) { + ($_ = USAGE) =~ s/!(.*?)!/eval $1||""/egs; + print; exit; + } + + $@ = ""; + foreach (qw/from to src dst/) { + $Cf->get($_) or $@ = join " ", $@, $_; + } + die ME.": Missing values: $@\n" if $@; + + # my $s = new IO::Select; + + print "**> @cmd\n"; + + $SIG{PIPE} = sub { exit }; + my $pid = open3($w, $r, undef, @cmd) or die "Can't run @cmd: $!\n"; + + + read_exim $r; + write_exim $w, "EHLO ".$Cf->Helo."\n"; + read_exim $r; + write_exim $w, "MAIL FROM: ".$Cf->From."\n"; + read_exim $r; + + foreach my $rcpt (split /\s*,\s*/, $Cf->To) { + write_exim $w, "RCPT TO: $rcpt\n"; + read_exim $r, "5"; + } + write_exim $w, "DATA\n"; + read_exim $r; + write_exim $w, "From: ".$Cf->from."\n"; + write_exim $w, "To: ".$Cf->to."\n"; + write_exim $w, "Subject: Test\n"; + + if (not -t STDIN) { + write_exim $w, "\n"; + while (<>) { + write_exim $w, $_; + } + } + + write_exim $w, "\n.\n"; + read_exim $r; + write_exim $w, "QUIT\n"; + + +} + +sub read_exim($;$) { + my $fh = shift; + my $oh_my_dear = shift || "54"; + while (<$fh>) { + /^\d\d\d/ and print("< $_") and next; + /^LOG/ and print and next if $Cf->log; + print and next if $Cf->debug; + } continue { + last if /^\d\d\d\s/; + } + exit if defined and /^[$oh_my_dear]/; +} + +sub write_exim($@) { + my $fh = shift; + print "> ", @_; + print $fh @_; +} + + +{ + my %opts; +sub exim_option($) { + my $opt = shift; + my $exim = $Cf->exim; + if (!%opts) { + %opts = map { chomp; /^(.*?)\s*=\s*(.*)/ ? ($1, $2) : (/no_(.*)/ ? ($1, 0) : ($_, 1)) } grep !/^\s*$/, `$exim -bP`; + } + $opts{$opt} +} } + + +sub addr(@) { + map { inet_ntoa scalar gethostbyname $_ } @_; +} + +# vim:sts=4 sw=4 aw ai sm: +=head1 NAME + +exiacl - exim acl tester + +=head1 SYNOPSIS + +B [options] B<-f>|B<--from>=I B<-t>|B<--to>=I [-- I<>] + +=head1 DESCRIPTION + +This tools tests the exim acl, B performing callouts. + +=head1 OPTIONS + +=over + +=item B<-f>|B<--from> I + +The mail address of the sender. (no default) + +=item B<-l>|B<--[no]log> + +Show the log output to stdout. (default: yes) + +=item B<-l>|B<--debug>=I + +Call Exim with some debug options. (e.g. C<-d-all+route>). + +=item B<--Helo>=I + +Use the specified HELO when talking to Exim (default: current hostname) + +=item B<--From>=I + +The envelope-from for the SMTP dialog. (no default) + +=item B<--To>=I[,I...] + +The recipients address. You may use more than once addresse, if they're +comma separated. (no default) + +=item B<--src>=I + +The source IP address. (default: some random private address) + +=item B<--dst>=I + +The destination IP address. This you'll need if you've an Exim running +on more then one interface. (default: IP of the current host) + +=item B<--au>=I + +Username for authentication. (no default) + +=item B<--aa>=I + +The authenticator to be used (plain, ....). (no default) + +=item B<--exim>=I + +The path to the exim binary to be called. (default: exim, but see +L below) + +=item B<--config>=I + +The config file to be used. (default: /etc/exim/exim.conf, but see +L below). + +=item B<--[no]callout> + +Do callouts (not do not). (default: do callouts) + +=back + +=head1 ENVIRONMENT + +B is used to refer to the exim binary to be called. And +B is the default configuration file. + +=head1 AUTHOR + +Heiko Schlittermann L diff -r 044834f7b19f -r f3c6f1f69e7d debian/rules --- a/debian/rules Wed Oct 20 23:38:51 2010 +0200 +++ b/debian/rules Sat Apr 20 18:36:18 2013 +0200 @@ -25,6 +25,7 @@ configure: configure-stamp configure-stamp: dh_testdir + perl Build.PL --installdirs=vendor --destdir=$(r) touch configure-stamp @@ -32,14 +33,14 @@ build-stamp: configure-stamp dh_testdir - $(MAKE) prefix=$(r)/usr + ./Build touch $@ clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp - -$(MAKE) clean + -./Build distclean dh_clean @@ -50,8 +51,7 @@ dh_installdirs # Add here commands to install the package into debian/exiacl. - install -d $(r)/usr/bin - $(MAKE) install DESTDIR=$(r) prefix=$(r)/usr + ./Build fakeinstall # Build architecture-independent files here. diff -r 044834f7b19f -r f3c6f1f69e7d exiacl.man8 --- a/exiacl.man8 Wed Oct 20 23:38:51 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -=head1 NAME - -exiacl - exim acl tester - -=head1 SYNOPSIS - -B [options] B<-f>|B<--from>=I B<-t>|B<--to>=I [-- I<>] - -=head1 DESCRIPTION - -This tools tests the exim acl, B performing callouts. - -=head1 OPTIONS - -=over - -=item B<-f>|B<--from> I - -The mail address of the sender. (no default) - -=item B<-l>|B<--[no]log> - -Show the log output to stdout. (default: yes) - -=item B<-l>|B<--debug>=I - -Call Exim with some debug options. (e.g. C<-d-all+route>). - -=item B<--Helo>=I - -Use the specified HELO when talking to Exim (default: current hostname) - -=item B<--From>=I - -The envelope-from for the SMTP dialog. (no default) - -=item B<--To>=I[,I...] - -The recipients address. You may use more than once addresse, if they're -comma separated. (no default) - -=item B<--src>=I - -The source IP address. (default: some random private address) - -=item B<--dst>=I - -The destination IP address. This you'll need if you've an Exim running -on more then one interface. (default: IP of the current host) - -=item B<--au>=I - -Username for authentication. (no default) - -=item B<--aa>=I - -The authenticator to be used (plain, ....). (no default) - -=item B<--exim>=I - -The path to the exim binary to be called. (default: exim, but see -L below) - -=item B<--config>=I - -The config file to be used. (default: /etc/exim/exim.conf, but see -L below). - -=item B<--[no]callout> - -Do callouts (not do not). (default: do callouts) - -=back - -=head1 ENVIRONMENT - -B is used to refer to the exim binary to be called. And -B is the default configuration file. - -=head1 AUTHOR - -Heiko Schlittermann L diff -r 044834f7b19f -r f3c6f1f69e7d exiacl.pl --- a/exiacl.pl Wed Oct 20 23:38:51 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -#! /usr/bin/perl -# © Heiko Schlittermann -use constant USAGE => << '#'; -!ME! [options] [-- exim native options] - - --[no]log show the log output [!$Cf->log!] - --[no]debug show debug output [!$Cf->debug!] - - --from=s from: [!$Cf->from!] - --to=s to: [!$Cf->to!] - (comma separated) - - --Helo=s HELO [!$Cf->Helo!] - --From=s MAIL FROM: [!$Cf->From!] - --To=s RCPT TO: [!$Cf->To!] - (comma separated) - - --src=s src ip/name [!$Cf->src!] - --dst=s dst ip/name [!$Cf->dst!] - - --au user (-oMai) [!$Cf->oMai!] - --aa authenticator (-oMaa) [!$Cf->oMaa!] - - --exim=s exim binary [!$Cf->exim!] - --config=s exim config file [!$Cf->config!] - - --[no]callout [!$Cf->callout!] - - Environment used: $EXIM [!$ENV{EXIM}!] - $EXIM_CONF [!$ENV{EXIM_CONF}!] - - mail data is read from STDIN unless it's connected to terminal. - - Source: https://keller.schlittermann.de/hg/exiacl - -# - - -use strict; -use warnings; -use AppConfig; -use IPC::Open3; -use IO::Select; -use Socket; -use File::Basename; - -our $VERSION = "1.2"; - -sub exim_option($); -sub read_exim($;$); -sub write_exim($@); -sub addr(@); -sub hostname() { chomp (my $h = `hostname -f`); return $h; } - -sub which($) { (map { -x "$_/$_[0]" && "$_/$_[0]" || () } split /:/, $ENV{PATH})[0] } -sub findExim() { $ENV{EXIM} || which("exim") || which("exim4") || undef } -sub guessConfig() { $_ = findExim(); qx/$_ "-bV"/ =~ /^Configuration.*\sis\s+(\S+)/mi and return $1 } - -use constant ME => basename $0; -use constant HOSTNAME => hostname; - -my $Cf = new AppConfig ( - { CASE => 1 }, - - log => { ARGS => "!", DEFAULT => 1 }, - debug => { ARGS => "!", DEFAULT => 0 }, - - from => { ARGS => "=s" }, - to => { ARGS => "=s" }, - - Helo => { ARGS => "=s", ALIAS => "ehlo" }, - From => { ARGS => "=s" }, - To => { ARGS => "=s" }, - - src => { ARGS => "=s", DEFAULT => "172.20.1.8" }, - dst => { ARGS => "=s" }, # exim primary_hostname - - au => { ARGS => "=s" }, - aa => { ARGS => "=s" }, - - exim => { ARGS => "=s", DEFAULT => findExim() }, - config => { ARGS => "=s", DEFAULT => guessConfig(), ALIAS => "C" }, - - callout => { ARGS => "!", DEFAULT => 1 }, - help => { ARGS => "!" }, - -) or die; - - $Cf->exim or die "No exim binary found\n"; - $Cf->dst(addr(exim_option("primary_hostname"))); - #$Cf->getopt(qw(pass_through no_ignore_case)) or die $@; - $Cf->getopt(qw(no_ignore_case)) or die $@; - - $Cf->From($Cf->from) unless $Cf->From; - $Cf->To($Cf->to) unless $Cf->To; - - $Cf->Helo(map { (my $x = $_) =~ s/[<>]//g; $x } (split/@/, $Cf->from||"")[1] || HOSTNAME) - unless $Cf->Helo; - $Cf->dst(addr(HOSTNAME)) unless $Cf->dst; - - $Cf->aa("LOGIN") unless $Cf->aa || !$Cf->au; - - - -MAIN: { - die "Config file for exim not readable ".$Cf->config.": $!\n" if not -r $Cf->config; - - - my ($w, $r); - my @cmd = ($Cf->exim, - -C => $Cf->config, - -oMi => addr($Cf->dst), - ($Cf->au ? (-oMai => $Cf->au) : ()), - ($Cf->aa ? (-oMaa => $Cf->aa) : ()), - ($Cf->callout? "-bhc" : "-bh" ) => addr($Cf->src), - @ARGV); # remaining args are exim native - - if ($Cf->help) { - ($_ = USAGE) =~ s/!(.*?)!/eval $1||""/egs; - print; exit; - } - - $@ = ""; - foreach (qw/from to src dst/) { - $Cf->get($_) or $@ = join " ", $@, $_; - } - die ME.": Missing values: $@\n" if $@; - - # my $s = new IO::Select; - - print "**> @cmd\n"; - - $SIG{PIPE} = sub { exit }; - my $pid = open3($w, $r, undef, @cmd) or die "Can't run @cmd: $!\n"; - - - read_exim $r; - write_exim $w, "EHLO ".$Cf->Helo."\n"; - read_exim $r; - write_exim $w, "MAIL FROM: ".$Cf->From."\n"; - read_exim $r; - - foreach my $rcpt (split /\s*,\s*/, $Cf->To) { - write_exim $w, "RCPT TO: $rcpt\n"; - read_exim $r, "5"; - } - write_exim $w, "DATA\n"; - read_exim $r; - write_exim $w, "From: ".$Cf->from."\n"; - write_exim $w, "To: ".$Cf->to."\n"; - write_exim $w, "Subject: Test\n"; - - if (not -t STDIN) { - write_exim $w, "\n"; - while (<>) { - write_exim $w, $_; - } - } - - write_exim $w, "\n.\n"; - read_exim $r; - write_exim $w, "QUIT\n"; - - -} - -sub read_exim($;$) { - my $fh = shift; - my $oh_my_dear = shift || "54"; - while (<$fh>) { - /^\d\d\d/ and print("< $_") and next; - /^LOG/ and print and next if $Cf->log; - print and next if $Cf->debug; - } continue { - last if /^\d\d\d\s/; - } - exit if defined and /^[$oh_my_dear]/; -} - -sub write_exim($@) { - my $fh = shift; - print "> ", @_; - print $fh @_; -} - - -{ - my %opts; -sub exim_option($) { - my $opt = shift; - my $exim = $Cf->exim; - if (!%opts) { - %opts = map { chomp; /^(.*?)\s*=\s*(.*)/ ? ($1, $2) : (/no_(.*)/ ? ($1, 0) : ($_, 1)) } grep !/^\s*$/, `$exim -bP`; - } - $opts{$opt} -} } - - -sub addr(@) { - map { inet_ntoa scalar gethostbyname $_ } @_; -} - -# vim:sts=4 sw=4 aw ai sm: