Mail-SpamAssassin
view release on metacpan or search on metacpan
sa-compile.raw view on Meta::CPAN
my $RE2C_BIN = '@@RE2C_BIN@@'; # substituted at 'make' time
use lib '@@INSTALLSITELIB@@'; # substituted at 'make' time
use Errno qw(EBADF);
use File::Spec;
use Config;
use POSIX qw(locale_h setsid sigprocmask _exit);
POSIX::setlocale(LC_TIME,'C');
BEGIN { # see comments in "spamassassin.raw" for doco
my @bin = File::Spec->splitpath($0);
my $bin = ($bin[0] ? File::Spec->catpath(@bin[0..1], '') : $bin[1])
|| File::Spec->curdir;
if (-e $bin.'/lib/Mail/SpamAssassin.pm'
|| !-e '@@INSTALLSITELIB@@/Mail/SpamAssassin.pm' )
{
my $searchrelative;
$searchrelative = 1; # disabled during "make install": REMOVEFORINST
if ($searchrelative && $bin eq '../' && -e '../blib/lib/Mail/SpamAssassin.pm')
{
unshift ( @INC, '../blib/lib' );
} else {
foreach ( qw(lib ../lib/site_perl
../lib/spamassassin ../share/spamassassin/lib))
{
my $dir = File::Spec->catdir( $bin, split ( '/', $_ ) );
if ( -f File::Spec->catfile( $dir, "Mail", "SpamAssassin.pm" ) )
{ unshift ( @INC, $dir ); last; }
}
}
}
}
use Mail::SpamAssassin;
use Mail::SpamAssassin::Util qw(untaint_var exit_status_str);
use Mail::SpamAssassin::Logger;
use Getopt::Long;
use File::Copy;
use File::Path;
use Pod::Usage;
use Data::Dumper;
our %opt;
Mail::SpamAssassin::Util::clean_path_in_taint_mode();
untaint_var( \%ENV );
Getopt::Long::Configure(
qw(bundling no_getopt_compat
permute no_auto_abbrev no_ignore_case)
);
GetOptions(
'list' => \$opt{'list'},
'sudo' => \$opt{'sudo'},
'quiet' => \$opt{'quiet'},
'keep-tmps' => \$opt{'keep-tmps'},
'configpath|config-file|config-dir|c|C=s' => \$opt{'configpath'},
'prefspath|prefs-file|p=s' => \$opt{'prefspath'},
'siteconfigpath=s' => \$opt{'siteconfigpath'},
'updatedir=s' => \$opt{'updatedir'},
'cf=s' => \@{$opt{'cf'}},
'debug|D:s' => \$opt{'debug'},
'help|h|?' => \$opt{'help'},
'version|V' => \$opt{'version'},
)
or usage( 0, "Unknown option!" );
if ( defined $opt{'help'} ) {
usage( 0, "For more information read the manual page" );
}
if ( defined $opt{'version'} ) {
print "SpamAssassin version " . Mail::SpamAssassin::Version() . "\n"
or die "error writing: $!";
exit 0;
}
# Check for some dependencies and provide useful error messages if they aren't
# present
eval("use ExtUtils::MakeMaker");
if ($@) {
print "$0 requires ExtUtils::MakeMaker for proper operation.\n"
or die "error writing: $!";
exit 1;
}
unless (qx($RE2C_BIN -V)) {
print "$0 requires $RE2C_BIN for proper operation.\n"
or die "error writing: $!";
exit 1;
}
sub usage {
my ( $exitval, $message ) = @_;
$exitval ||= 64;
if ($exitval == 0) {
print_version();
print("\n") or die "error writing: $!";
}
pod2usage(
-verbose => 0,
-message => $message,
-exitval => $exitval,
);
}
# set debug areas, if any specified (only useful for command-line tools)
if (defined $opt{'debug'}) {
$opt{'debug'} ||= 'all';
}
# at least info
$opt{'debug'} ||= 'info';
my $quiet = $opt{'quiet'} || 0;
# ensure the body-rule base extractor plugin is loaded, we use that
my $post_config = q(
loadplugin Mail::SpamAssassin::Plugin::BodyRuleBaseExtractor
).join("\n", @{$opt{'cf'}})."\n";
my $spamtest = Mail::SpamAssassin->new(
{
rules_filename => $opt{'configpath'},
site_rules_filename => $opt{'siteconfigpath'},
userprefs_filename => $opt{'prefspath'},
debug => $opt{'debug'},
local_tests_only => 1,
dont_copy_prefs => 1,
PREFIX => $PREFIX,
DEF_RULES_DIR => $DEF_RULES_DIR,
LOCAL_RULES_DIR => $LOCAL_RULES_DIR,
LOCAL_STATE_DIR => $LOCAL_STATE_DIR,
post_config_text => $post_config,
}
);
# appropriate BodyRuleBaseExtractor settings for rule2xs usage
$spamtest->{base_extract} = 1;
$spamtest->{bases_must_be_casei} = 1;
$spamtest->{bases_can_use_alternations} = 0;
$spamtest->{bases_can_use_quantifiers} = 0;
$spamtest->{bases_can_use_char_classes} = 0;
$spamtest->{bases_split_out_alternations} = 1;
$spamtest->{base_quiet} = $quiet;
if (defined $opt{'updatedir'}) {
$opt{'updatedir'} = Mail::SpamAssassin::Util::untaint_file_path($opt{'updatedir'});
}
else {
$opt{'updatedir'} = $spamtest->sed_path('__local_state_dir__/compiled/__perl_major_ver__/__version__');
}
my $installdir = $opt{'updatedir'};
if ((!defined $opt{'list'})
&& !$opt{'sudo'}
&& -d $installdir && !-w $installdir)
{
die "sa-compile: cannot write to $installdir, aborting\n";
}
$spamtest->{bases_cache_dir} = $spamtest->get_and_create_userstate_dir()
."/sa-compile.cache";
$spamtest->init(1);
my $conf = $spamtest->{conf};
# this actually extracts the base rules in the plugin, as a side-effect
my $res = $spamtest->lint_rules();
if ($res) {
die "sa-compile: not compiling; 'spamassassin --lint' check failed!\n";
}
if ( defined $opt{'list'} ) {
foreach my $ruletype (sort keys %{$conf->{base_orig}}) {
print dump_base_strings($ruletype);
}
}
else {
compile_base_strings();
}
$spamtest->finish();
# make sure we notice any write errors while flushing output buffer
close STDOUT or die "error closing STDOUT: $!";
close STDIN or die "error closing STDIN: $!";
exit;
sa-compile.raw view on Meta::CPAN
$has_rules
};
XSLoader::load '$modname', \$VERSION;
}
1;
fnord__END__
fnord=head1 NAME
$modname - Efficient string matching for regexps found in $FILE
fnord=head1 SYNOPSIS
use $modname;
...
my \$match = ${modname}::scan(\$string);
fnord=head1 DESCRIPTION
This module was created by SpamAssassin with the aid of re2xs, which uses re2c
to create an XS library capable of scanning through a bunch of regular
expressions as defined in F<$FILE>.
See C<sa-compile> for more details.
fnord=cut
EOT
$str =~ s/^fnord//gm;
print FILE $str or die "error writing to $PMFILE: $!";
close FILE or die "error closing $PMFILE: $!";
}
sub handle_fixup_error {
my ($strat, $regexp, $reason) = @_;
if ($strat) {
warn "skipped: $regexp: $strat";
}
}
##############################################################################
=head1 NAME
sa-compile - compile SpamAssassin ruleset into native code
=head1 SYNOPSIS
B<sa-compile> [options]
Options:
--list Output base string list to STDOUT
--sudo Use 'sudo' for privilege escalation
--keep-tmps Keep temporary files instead of deleting
-C path, --configpath=path, --config-file=path
Path to standard configuration dir
-p prefs, --prefspath=file, --prefs-file=file
Set user preferences file
--siteconfigpath=path Path for site configs
(default: @@PREFIX@@/etc/mail/spamassassin)
--updatedir=path Directory to place updates
(default: @@LOCAL_STATE_DIR@@/compiled/<perlversion>/@@VERSION@@)
--cf='config line' Additional line of configuration
-D, --debug [area=n,...] Print debugging messages
-V, --version Print version
-h, --help Print usage message
=head1 DESCRIPTION
sa-compile uses C<re2c> to compile the site-wide parts of the SpamAssassin
ruleset. No part of user_prefs or any files included from user_prefs can be
built into the compiled set.
This compiled set is then used by the
C<Mail::SpamAssassin::Plugin::Rule2XSBody> plugin to speed up
SpamAssassin's operation, where possible, and when that plugin is loaded.
C<re2c> can match strings much faster than perl code, by constructing a DFA to
match many simple strings in parallel, and compiling that to native object
code. Not all SpamAssassin rules are amenable to this conversion, however.
This requires C<re2c> (see C<https://re2c.org/>), and the C
compiler used to build Perl XS modules, be installed.
Note that running this, and creating a compiled ruleset, will have no
effect on SpamAssassin scanning speeds unless you also edit your C<v320.pre>
file and ensure this line is uncommented:
loadplugin Mail::SpamAssassin::Plugin::Rule2XSBody
Additionally, "sa-compile" will not restart "spamd" or otherwise cause a scanner to
reload the now-compiled ruleset automatically.
=head1 OPTIONS
=over 4
=item B<--list>
Output the extracted base strings to STDOUT, instead of generating
the C extension code.
=item B<--sudo>
Use C<sudo(8)> to run code as 'root' when writing files to the compiled-rules
storage area (which is C<@@LOCAL_STATE_DIR@@/compiled/@@PERL_MAJOR_VER@@/@@VERSION@@> by default).
=item B<--quiet>
Produce less diagnostic output. Errors will still be displayed.
=item B<--keep-tmps>
Keep temporary files after the script completes, instead of
deleting them.
=item B<-C> I<path>, B<--configpath>=I<path>, B<--config-file>=I<path>
Use the specified path for locating the distributed configuration files.
Ignore the default directories (usually C</usr/share/spamassassin> or similar).
=item B<--siteconfigpath>=I<path>
Use the specified path for locating site-specific configuration files. Ignore
the default directories (usually C</etc/mail/spamassassin> or similar).
=item B<--updatedir>
By default, C<sa-compile> will use the system-wide rules update directory:
@@LOCAL_STATE_DIR@@/compiled/@@PERL_MAJOR_VER@@/@@VERSION@@
If the updates should be stored in another location, specify it here.
Note that use of this option is not recommended; if sa-compile is placing the
compiled rules the wrong directory, you probably need to rebuild SpamAssassin
with different C<Makefile.PL> arguments, instead of overriding sa-compile's
runtime behaviour.
=item B<--cf='config line'>
Add additional lines of configuration directly from the command-line, parsed
after the configuration files are read. Multiple B<--cf> arguments can be
used, and each will be considered a separate line of configuration.
=item B<-p> I<prefs>, B<--prefspath>=I<prefs>, B<--prefs-file>=I<prefs>
Read user score preferences from I<prefs> (usually
C<$HOME/.spamassassin/user_prefs>) .
=item B<-D> [I<area,...>], B<--debug> [I<area,...>]
Produce debugging output. If no areas are listed, all debugging information is
printed. Diagnostic output can also be enabled for each area individually;
I<area> is the area of the code to instrument.
For more information about which areas (also known as channels) are
available, please see the documentation at
L<https://wiki.apache.org/spamassassin/DebugChannels>.
=item B<-h>, B<--help>
Print help message and exit.
=item B<-V>, B<--version>
Print sa-compile version and exit.
=back
=head1 SEE ALSO
Mail::SpamAssassin(3)
spamassassin(1)
spamd(1)
=head1 PREREQUISITES
C<Mail::SpamAssassin>
C<re2c>
C<Mail::SpamAssassin::Plugin::Rule2XSBody>
=head1 BUGS
See E<lt>https://bz.apache.org/SpamAssassin/E<gt>
=head1 AUTHORS
The Apache SpamAssassin(tm) Project E<lt>https://spamassassin.apache.org/E<gt>
=head1 LICENSE AND COPYRIGHT
SpamAssassin is distributed under the Apache License, Version 2.0, as
described in the file C<LICENSE> included with the distribution.
Copyright (C) 2015 The Apache Software Foundation
=cut
( run in 0.901 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )