Mail-MIMEDefang

 view release on metacpan or  search on metacpan

Makefile.PL  view on Meta::CPAN

#!/usr/bin/env perl
# =============================================================================
# Makefile.PL  -  MIMEDefang
#
# Supported options:
#
#   SENDMAIL=/path/to/sendmail        Path to sendmail binary      [auto-detect]
#   DEFANGUSER=login                  MIMEDefang run-as user       [defang]
#   MILTERINC=/path/to/milter/inc     Milter header directory      [auto-detect]
#   MILTERLIB=/path/to/milter/lib     Milter library directory     [auto-detect]
#   SPOOLDIR=/var/spool/MIMEDefang    Spool directory
#   QUARANTINEDIR=/var/spool/MD-Quarantine
#   CONFSUBDIR=mail                   Subdirectory under sysconfdir
#   SYSCONFDIR=/etc                   System configuration root
#   ENABLE_EMBEDDED_PERL=1|0          Build embedded Perl interpreter  [1]
#   ENABLE_POLL=0|1                   Use poll(2) instead of select(2) [0]
#   ENABLE_DEBUGGING=0|1              Enable syslog debug messages     [0]
#   ENABLE_ANTI_VIRUS=1|0             Probe for AV scanners            [1]
#   ENABLE_CHECK_PERL_MODULES=1|0     Verify Perl deps at build time   [1]
#   ENABLE_PTHREAD_FLAG=0|1           Pass -pthread to the C compiler  [0]
#   IPHEADER=0|1                      Install IP-header config file    [0]
# =============================================================================

use strict;
use warnings;
use 5.008009;

use Config;
use ExtUtils::MakeMaker;
use File::Spec;
use File::Basename qw(dirname);
use POSIX          qw(uname);

# ---------------------------------------------------------------------------
# Version
# ---------------------------------------------------------------------------
my $VERSION;
{
    my $pm = 'modules/lib/Mail/MIMEDefang.pm';
    if (open my $fh, '<', $pm) {
        while (<$fh>) {
            if (/^\s*our\s+\$VERSION\s*=\s*['"]([^'"]+)['"]\s*;/) {
                $VERSION = $1;
                last;
            }
        }
        close $fh;
    }
    die "Cannot determine version from $pm\n" unless defined $VERSION;
}

# Split "3.7-rc1" -> base "3.7" and prerelease "rc1".
# RPM forbids hyphens in Version:; the prerelease part goes into Release:.
my ($BASE_VERSION, $PRERELEASE) = ($VERSION =~ /^([^-]+)(?:-(.+))?$/);
$BASE_VERSION //= $VERSION;
$PRERELEASE   //= '';

# ---------------------------------------------------------------------------
# AV scanner table  (binary => template token)
# Keys must match the @TOKEN@ names used in mimedefang.pl.in
# ---------------------------------------------------------------------------
my @AV_SCANNERS = (
    [ clamscan   => 'CLAMSCAN'   ],
    [ clamdscan  => 'CLAMDSCAN'  ],
    [ clamd      => 'CLAMD'      ],
    [ uvscan     => 'NAI'        ],  # NAI/McAfee uvscan
    [ sweep      => 'SOPHOS'     ],  # Sophos sweep
    [ trend      => 'TREND'      ],
    [ AvpLinux   => 'AVP'        ],  # Kaspersky AvpLinux
    [ aveclient  => 'AVP5'       ],  # Kaspersky AVP5
    [ kavscanner => 'KAVSCANNER' ],
    [ antivir    => 'HBEDV'      ],  # H+BEDV / Avira antivir
    [ vascan     => 'VEXIRA'     ],  # Vexira vascan
    [ bdc        => 'BDC'        ],  # BitDefender
    [ fsav       => 'FSAV'       ],

Makefile.PL  view on Meta::CPAN

    } else {
        my $found;
        for my $p (qw(
            /usr/sbin/sendmail
            /usr/lib/sendmail
            /usr/local/sbin/sendmail
        )) {
            if (-x $p) { $found = $p; last }
        }
        $found // '/usr/sbin/sendmail';
    }
};
print "Sendmail binary      : $SENDMAILPROG\n";

# --- Milter includes and library -------------------------------------------
my $MILTERINC = do {
    my @candidates = grep { $_ ne '' } (
        opt('MILTERINC', ''),
        '/usr/include/libmilter',
        '/usr/local/include/libmilter',
        '/usr/include/sendmail',
        '/usr/local/include/sendmail',
    );
    my $found;
    for my $d (@candidates) {
        if (-f File::Spec->catfile($d, 'libmilter', 'mfapi.h') ||
            -f File::Spec->catfile($d, 'mfapi.h')) {
            $found = $d; last;
        }
    }
    $found or die <<END;
ERROR: Cannot find milter header (libmilter/mfapi.h).
       Install sendmail-devel / libmilter-dev, or pass MILTERINC=/path
END
};

my $MILTERLIB = do {
    my @candidates = grep { $_ ne '' } (
        opt('MILTERLIB', ''),
        '/usr/lib',   '/usr/lib64',
        '/usr/local/lib', '/usr/local/lib64',
    );
    my $found;
    for my $d (@candidates) {
        if (-f File::Spec->catfile($d, 'libmilter.a')  ||
            -f File::Spec->catfile($d, 'libmilter.so') ||
            glob(File::Spec->catfile($d, 'libmilter.so.*'))) {
            $found = $d; last;
        }
    }
    $found or die <<END;
ERROR: Cannot find libmilter.
       Install sendmail-devel / libmilter-dev, or pass MILTERLIB=/path
END
};

print "Milter include dir   : $MILTERINC\n";
print "Milter library dir   : $MILTERLIB\n";

# --- Feature flags ---------------------------------------------------------
my $ENABLE_EMBEDDED_PERL     = opt('ENABLE_EMBEDDED_PERL',     1);
my $ENABLE_POLL              = opt('ENABLE_POLL',              0);
my $ENABLE_DEBUGGING         = opt('ENABLE_DEBUGGING',         0);
my $ENABLE_ANTI_VIRUS        = opt('ENABLE_ANTI_VIRUS',        1);
my $ENABLE_CHECK_PERL_MODULES= opt('ENABLE_CHECK_PERL_MODULES',1);
my $ENABLE_PTHREAD_FLAG      = opt('ENABLE_PTHREAD_FLAG',      0);

# --- Required Perl module check --------------------------------------------
if ($ENABLE_CHECK_PERL_MODULES) {
    print "\nChecking required Perl modules:\n";
    my $all_ok = 1;
    for my $mod (sort keys %REQUIRED_MODULES) {
        my $minver = $REQUIRED_MODULES{$mod};
        my $ok;
        eval "use $mod" . ($minver ? " $minver" : '') . '; $ok = 1';
        printf "  %-35s %s\n", $mod, $ok ? 'ok' : 'MISSING';
        $all_ok = 0 unless $ok;
    }
    die "\nERROR: One or more required Perl modules are missing.\n"
      . "       Install them from CPAN, then re-run perl Makefile.PL\n"
      unless $all_ok;

    # Syslog: need at least one
    print "\nChecking syslog Perl module (need one of):\n";
    my $have_syslog = 0;
    for my $mod (@SYSLOG_MODULES) {
        my $ok;
        eval "use $mod; \$ok = 1";
        printf "  %-35s %s\n", $mod, $ok ? 'found' : 'not found';
        $have_syslog = 1 if $ok;
    }
    warn "\nWARNING: Neither Unix::Syslog nor Sys::Syslog is installed.\n"
       . "         MIMEDefang will not be able to log to syslog.\n"
       unless $have_syslog;
}

# AnyEvent optional module check
{
    print "\nChecking optional Perl modules (async I/O - required for md_async_* functions):\n";
    my $all_async_ok = 1;
    for my $mod (qw(AnyEvent AnyEvent::DNS AnyEvent::Socket)) {
        my $ok;
        eval "use $mod; \$ok = 1";
        printf "  %-35s %s\n", $mod, $ok ? 'found' : 'not found';
        $all_async_ok = 0 unless $ok;
    }
    unless ($all_async_ok) {
        warn "\nNOTE: One or more AnyEvent modules are missing.\n"
           . "      md_async_* functions will not be available.\n"
           . "      Install with: cpanm AnyEvent\n";
    }
}

# Mail::BIMI optional module check
{
    print "\nChecking optional Perl module (BIMI validation):\n";
    my $ok;
    eval "use Mail::BIMI 3; \$ok = 1";
    printf "  %-35s %s\n", 'Mail::BIMI >= 3', $ok ? 'found' : 'not found';
    unless ($ok) {
        warn "\nNOTE: Mail::BIMI >= 3 is not installed.\n"

Makefile.PL  view on Meta::CPAN

# MIME::Tools version advisory
{
    my $mt_ver = eval { require MIME::Tools; $MIME::Tools::VERSION } // 'unknown';
    print "\nMIME::Tools version  : $mt_ver\n";
    if ($mt_ver ne 'unknown') {
        warn "WARNING: MIME::Tools >= 5.412 is strongly recommended (found $mt_ver)\n"
            if $mt_ver + 0 < 5.412;
    }
}

# --- DEFANGUSER existence check -------------------------------------------
{
    my $uid = getpwnam($DEFANGUSER);
    unless (defined $uid) {
        print "\nNote: The MIMEDefang user '$DEFANGUSER' does not seem to exist.\n";
        print "      Please create this user before running 'make install'.\n";
    }
}

# --- AV scanner detection --------------------------------------------------
my %AV_PATHS;
print "\nAV scanner detection:\n";
if (!$ENABLE_ANTI_VIRUS) {
    print "  (disabled by ENABLE_ANTI_VIRUS=0)\n";
    for my $pair (@AV_SCANNERS) {
        $AV_PATHS{ $pair->[1] } = '/bin/false';
    }
} else {
    for my $pair (@AV_SCANNERS) {
        my ($prog, $key) = @$pair;
        my $path = find_in_path($prog);
        $AV_PATHS{$key} = $path // '/bin/false';
        printf "  %-20s %s\n", $prog, ($path ? $path : 'not found');
    }
}

# --- C compiler (needed by probes below) -----------------------------------
my $CC = $Config{cc} // 'cc';
my $INSTALL_PROGRAM = $Config{install_program} // 'install';
my $INSTALL_DATA = $Config{install_data} // 'install';
my $MAN3EXT = $Config{man3ext} // '3';

# --- clock_gettime(CLOCK_MONOTONIC) probe ----------------------------------
my $HAVE_CLOCK_MONOTONIC = probe_clock_monotonic();
print "\nclock_gettime(CLOCK_MONOTONIC): " . ($HAVE_CLOCK_MONOTONIC ? 'yes' : 'no') . "\n";

# --- inet_ntop probe --------------------------------------------------------
my $HAVE_INET_NTOP = probe_inet_ntop();
print "inet_ntop             : " . ($HAVE_INET_NTOP ? 'yes' : 'no') . "\n";

# --- socklen probe --------------------------------------------------------
my $HAVE_SOCKLEN_T = probe_socklen();
print "socklen_t             : " . ($HAVE_SOCKLEN_T ? 'yes' : 'no') . "\n";

# --- libresolv probe -------------------------------------------------------
my $HAVE_LIBRESOLV = probe_libresolv();
print "libresolv             : " . ($HAVE_LIBRESOLV ? 'yes' : 'no (using libc)') . "\n";

# --- Embedded Perl C/LD flags ----------------------------------------------
my ($EMBPERL_CFLAGS, $EMBPERL_LDFLAGS) = ('', '');
if ($ENABLE_EMBEDDED_PERL) {
    chomp($EMBPERL_CFLAGS  = `$PERL -MExtUtils::Embed -e ccopts  2>/dev/null`);
    chomp($EMBPERL_LDFLAGS = `$PERL -MExtUtils::Embed -e ldopts  2>/dev/null`);
    print "Embedded Perl        : enabled\n";
} else {
    print "Embedded Perl        : disabled\n";
}

# Base CFLAGS: use the compiler's defaults plus mandatory defines
my $CFLAGS = join(' ',
    '-I.',
    "-I$MILTERINC",
    "-std=c89 -D_BSD_SOURCE -D_DEFAULT_SOURCE",
    ($ENABLE_DEBUGGING         ? '-DENABLE_DEBUGGING'    : ()),
    ($ENABLE_POLL              ? '-DUSE_POLL'             : ()),
    ($ENABLE_PTHREAD_FLAG      ? '-pthread'               : ()),
    ($HAVE_CLOCK_MONOTONIC     ? '-DHAVE_CLOCK_MONOTONIC' : ()),
    ($ENABLE_EMBEDDED_PERL     ? ('-DEMBED_PERL', $EMBPERL_CFLAGS) : ()),
);

my $LDFLAGS_MILTER  = "-L$MILTERLIB -lmilter";
my $LDFLAGS_PTHREAD = $ENABLE_PTHREAD_FLAG ? '-lpthread' : '';
my $LDFLAGS_EMBPERL = $ENABLE_EMBEDDED_PERL ? $EMBPERL_LDFLAGS : '';
my $LDFLAGS_COMMON  = join(' ', ($HAVE_LIBRESOLV ? '-lresolv' : ()),
                            $LDFLAGS_PTHREAD, $LDFLAGS_EMBPERL);

my $HAVE_MILTER = probe_milter($CC, $CFLAGS);
print "\nmilter.h: " . ($HAVE_MILTER ? 'found' : 'not found') . "\n";

print "\nCC                   : $CC\n";
print "CFLAGS (extra)       : $CFLAGS\n\n";

# --- Write config.h --------------------------------------------------------
write_config_h(
    DEFANGUSER        => $DEFANGUSER,
    SPOOLDIR          => $SPOOLDIR,
    QUARANTINEDIR     => $QUARANTINEDIR,
    CONFDIR           => $CONFDIR,
    SENDMAILPROG      => $SENDMAILPROG,
    VERSION           => $VERSION,
    MIMEDEFANG_PL     => $MIMEDEFANG_PL,
    HAVE_CLOCK_MONOTONIC => $HAVE_CLOCK_MONOTONIC,
    HAVE_INET_NTOP    => $HAVE_INET_NTOP,
    HAVE_SOCKLEN_T    => $HAVE_SOCKLEN_T,
    HAVE_MILTER       => $HAVE_MILTER,
    ENABLE_DEBUGGING  => $ENABLE_DEBUGGING,
    ENABLE_POLL       => $ENABLE_POLL,
    WITH_EMBEDDED_PERL=> $ENABLE_EMBEDDED_PERL,
);

# ---------------------------------------------------------------------------
# Substitution map for .in template files
# ---------------------------------------------------------------------------
my %SUBST = (
    PERL             => $PERL,
    VERSION          => $VERSION,
    PACKAGE          => 'mimedefang',
    DEFANGUSER       => $DEFANGUSER,
    SPOOLDIR         => $SPOOLDIR,
    QUARANTINEDIR    => $QUARANTINEDIR,
    CONFSUBDIR       => $CONFSUBDIR,
    SYSCONFDIR       => $SYSCONFDIR,
    CONFDIR          => $CONFDIR,
    IPHEADER         => $IPHEADER,
    SENDMAILPROG     => $SENDMAILPROG,
    MILTERINC        => $MILTERINC,
    MILTERLIB        => $MILTERLIB,
    CC               => $CC,
    CFLAGS           => $CFLAGS,
    INSTALL_PROGRAM  => $INSTALL_PROGRAM,
    INSTALL_DATA     => $INSTALL_DATA,
    (map { (uc("PERLINSTALL$_") => $perl_vars{$_}) } keys %perl_vars),
    %AV_PATHS,
);

# ---------------------------------------------------------------------------
# WriteMakefile
# ---------------------------------------------------------------------------

# Collect .in source files, excluding autoconf templates that are not processed here
my @IN_FILES = grep { $_ !~ m{\b(Makefile|config\.h)\.in$} }
               map  { chomp; $_ }
               `find . -name '*.in' -not -path './.git/*' 2>/dev/null`;
my @GENERATED_FILES = map { (my $f = $_) =~ s/\.in$//; $f } @IN_FILES;

# Perl modules live under modules/lib/
my @PM_FILES = map { chomp; $_ } `find modules/lib -name '*.pm' 2>/dev/null`;
my %PM = map {
    my $dest = $_;
    $dest =~ s{^modules/lib/}{};   # strip the local lib/ prefix
    my $install_path = File::Spec->catfile('$(INST_LIB)', $dest);
    ($_ => $install_path)
} @PM_FILES;

my %install_overrides =
    map  { $_ => $ARGS{$_} }
    grep { /^INSTALL/ && exists $ARGS{$_} }
    keys %ARGS;

WriteMakefile(
    NAME             => 'Mail::MIMEDefang',
    INSTALLDIRS      => ($ARGS{INSTALLDIRS} // 'site'),
    %install_overrides,
    DISTNAME         => "Mail-MIMEDefang",
    VERSION          => $VERSION,
    MIN_PERL_VERSION => '5.008009',
    AUTHOR           => 'The McGrail Foundation <https://mimedefang.org>',
    ABSTRACT         => 'E-mail filtering with Sendmail Milter',

Makefile.PL  view on Meta::CPAN

);

# ---------------------------------------------------------------------------
# MY package overrides
# ---------------------------------------------------------------------------

{
    package MY;

    # Pure-Perl: suppress all XS/dynamic-loading rules.
    sub dlsyms      { '' }
    sub dynamic_bs  { '' }
    sub dynamic_lib { '' }
    sub dynamic     { "dynamic ::\n\t\$(NOECHO) \$(NOOP)\n" }

    sub c_o {
        return <<'MAKE';
.c.o:
	$(MD_CC) $(MD_CFLAGS) -c -o $@ $<
MAKE
    }

    # postamble: add rules for C binaries, .in processing, and extra install
    sub postamble {
        my $self = shift;

        # ----------------------------------------------------------------
        # List every .in file as a dependency of "all" so "make" processes
        # them automatically.
        # ----------------------------------------------------------------
        my $generated = join(' ', @GENERATED_FILES);

        # ----------------------------------------------------------------
        # Per-target object lists and link flags
        # ----------------------------------------------------------------
        my $md_objs = join(' ', qw(
            mimedefang.o
            drop_privs.o
            dynbuf.o
            gen_id.o
            milter_cap.o
            rm_r.o
            syslog-fac.o
            utils.o
        ));
        my $md_ldflags = '$(MD_LDFLAGS_MILTER) $(MD_LDFLAGS_COMMON)';

        # mimedefang-multiplexor
        my @mux_obj_list = qw(
            mimedefang-multiplexor.o
            drop_privs.o
            dynbuf.o
            event.o
            event_tcp.o
            gen_id.o
            notifier.o
            rm_r.o
            syslog-fac.o
            utils.o
        );
        push @mux_obj_list, 'embperl.o', 'xs_init.o' if $ENABLE_EMBEDDED_PERL;
        my $mux_objs = join(' ', @mux_obj_list);
        my $mux_ldflags = '$(MD_LDFLAGS_COMMON)';

        # md-mx-ctrl
        my $ctrl_objs = join(' ', qw(
            md-mx-ctrl.o
            dynbuf.o
            utils.o
        ));
        my $ctrl_ldflags = '$(MD_LDFLAGS_COMMON)';

        # Substitute @TOKEN@ placeholders in all .in templates at perl Makefile.PL time.
        # This avoids relying on make pattern rules, which differ between GNU make and BSD make.
        my %subst = (
            PERL               => $PERL,
            PERLINSTALLSITELIB => $perl_vars{installsitelib},
            VERSION            => $VERSION,
            PACKAGE            => 'mimedefang',
            DEFANGUSER         => $DEFANGUSER,
            SPOOLDIR           => $SPOOLDIR,
            QUARANTINEDIR      => $QUARANTINEDIR,
            QDIR               => $QUARANTINEDIR,
            CONFDIR            => $CONFDIR,
            CONFDIR_EVAL       => $CONFDIR,
            SYSCONFDIR         => $SYSCONFDIR,
            CONFSUBDIR         => $CONFSUBDIR,
            IPHEADER           => $IPHEADER,
            SENDMAILPROG       => $SENDMAILPROG,
            MILTERINC          => $MILTERINC,
            MILTERLIB          => $MILTERLIB,
            CC                 => $CC,
            MIMEDEFANG_PL      => $MIMEDEFANG_PL,
            %AV_PATHS,
        );
        for my $mdfile (@IN_FILES) {
            open my $in, '<', $mdfile or do { warn "Cannot open $mdfile: $!\n"; next };
            local $/;
            my $content = <$in>;
            close $in;
            $content =~ s{\@([A-Z0-9_]+)\@}{ exists $subst{$1} ? $subst{$1} : '/bin/false' }ge;
            (my $outf = $mdfile) =~ s/\.in$//;
            open my $out, '>', $outf or do { warn "Cannot write $outf: $!\n"; next };
            print $out $content;
            close $out;
            my $mode = (stat $mdfile)[2] & 0777;
            chmod $mode, $outf;
        }

        # Generate xs_init.c for embedded Perl support
        if ($ENABLE_EMBEDDED_PERL) {
            print "Generating xs_init.c for embedded Perl...\n";
            system($PERL, '-MExtUtils::Embed', '-e', 'xsinit', '--', '-o', 'xs_init.c') == 0
                or warn "WARNING: Failed to generate xs_init.c\n";
        }

        # ----------------------------------------------------------------
        # Extra install targets (spool dirs, config, man pages, scripts)
        # ----------------------------------------------------------------
        return <<MAKE;

# ============================================================
# Generated files from .in templates (created by perl Makefile.PL)
# ============================================================
all :: $generated c_binaries pod2man

# ============================================================
# C binaries
# ============================================================
c_binaries: mimedefang mimedefang-multiplexor md-mx-ctrl

mimedefang: $md_objs
\t\$(MD_CC) -o \$\@ $md_objs $md_ldflags

mimedefang-multiplexor: $mux_objs
\t\$(MD_CC) -o \$\@ $mux_objs $mux_ldflags

md-mx-ctrl: $ctrl_objs
\t\$(MD_CC) -o \$\@ $ctrl_objs $ctrl_ldflags

# ============================================================
# pod2man: generate man pages from POD in scripts and modules
# ============================================================
pod2man: mimedefang-release.8 script/mimedefang-util.1 md_module_manpages

mimedefang-release.8: mimedefang-release.pl
\t\$(FULLPERL) "-MExtUtils::Command::MM" -e pod2man "--" --section=8 --perm_rw=644 \\
\t\t--center="mimedefang-release Documentation" \\
\t\t--name="mimedefang-release" \\
\t\t--release=\$(MD_VERSION) \\
\t\tmimedefang-release.pl mimedefang-release.8

script/mimedefang-util.1: script/mimedefang-util
\t\$(FULLPERL) "-MExtUtils::Command::MM" -e pod2man "--" --section=1 --perm_rw=644 \\
\t\t--center="MIMEDefang Documentation" \\
\t\t--release=\$(MD_VERSION) \\
\t\tscript/mimedefang-util script/mimedefang-util.1

md_module_manpages:
\t\$(MKPATH) modules/man
\t\$(FULLPERL) "-MExtUtils::Command::MM" -e pod2man "--" --section=3 --perm_rw=644 \\
\t\t--center="Mail::MIMEDefang Documentation" \\
\t\t--name="Mail::MIMEDefang" \\
\t\t--release=\$(MD_VERSION) \\
\t\tmodules/lib/Mail/MIMEDefang.pm "modules/man/Mail::MIMEDefang.$MAN3EXT"
\t\$(FULLPERL) "-MExtUtils::Command::MM" -e pod2man "--" --section=3 --perm_rw=644 \\
\t\t--center="Mail::MIMEDefang::Actions Documentation" \\
\t\t--name="Mail::MIMEDefang::Actions" \\
\t\t--release=\$(MD_VERSION) \\
\t\tmodules/lib/Mail/MIMEDefang/Actions.pm "modules/man/Mail::MIMEDefang::Actions.$MAN3EXT"
\t\$(FULLPERL) "-MExtUtils::Command::MM" -e pod2man "--" --section=3 --perm_rw=644 \\

Makefile.PL  view on Meta::CPAN


sub probe_socklen {
    my $tmpdir = File::Spec->tmpdir();
    my $src    = File::Spec->catfile($tmpdir, "conftest_inet_$$.c");
    my $exe    = File::Spec->catfile($tmpdir, "conftest_inet_$$");
    open my $fh, '>', 'tst.c' or die $!;
    print $fh <<'C';
#include <sys/types.h>
#include <sys/socket.h>

int
main (void)
{
socklen_t x;
  ;
  return 0;
}
C
    close $fh;
    my $rc = system("$CC -o $exe $src 2>/dev/null") == 0;
    unlink $src, $exe;
    return $rc ? 1 : 0;
}

sub probe_libresolv {
    my $tmpdir = File::Spec->tmpdir();
    my $src    = File::Spec->catfile($tmpdir, "conftest_resolv_$$.c");
    my $exe    = File::Spec->catfile($tmpdir, "conftest_resolv_$$");
    open my $fh, '>', $src or return 0;
    print $fh <<'C';
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
int main(void) { res_init(); return 0; }
C
    close $fh;
    my $rc = system("$CC -o $exe $src -lresolv 2>/dev/null") == 0;
    unlink $src, $exe;
    return $rc ? 1 : 0;
}

# Write config.h from the collected values.
sub write_config_h {
    my %v = @_;
    open my $fh, '>', 'config.h' or die "Cannot write config.h: $!\n";
    print $fh "/* config.h - generated by perl Makefile.PL - do not edit */\n\n";
    print $fh '#define VERSION           "' . $v{VERSION}      . "\"\n";
    print $fh '#define DEFANG_USER       "' . $v{DEFANGUSER}   . "\"\n";
    print $fh '#define SPOOLDIR          "' . $v{SPOOLDIR}     . "\"\n";
    print $fh '#define QUARANTINEDIR     "' . $v{QUARANTINEDIR}. "\"\n";
    print $fh '#define CONFDIR           "' . $v{CONFDIR}      . "\"\n";
    print $fh '#define SENDMAIL_PROG     "' . $v{SENDMAILPROG} . "\"\n";
    print $fh "#ifndef HAVE_CLOCK_MONOTONIC\n#define HAVE_CLOCK_MONOTONIC\n#endif\n" if $v{HAVE_CLOCK_MONOTONIC};
    print $fh '#define MIMEDEFANG_PL     "' . $v{MIMEDEFANG_PL} . "\"\n";
    print $fh "#define HAVE_UNISTD_H 1\n";
    print $fh "#ifndef HAVE_INET_NTOP\n#define HAVE_INET_NTOP\n#endif\n"   if $v{HAVE_INET_NTOP};
    print $fh "#define HAVE_SOCKLEN_T\n"       if not $v{HAVE_SOCKLEN_T};
    print $fh "#define HAVE_MILTER\n"           if $v{HAVE_MILTER};
    print $fh "#ifndef ENABLE_DEBUGGING\n#define ENABLE_DEBUGGING\n#endif\n" if $v{ENABLE_DEBUGGING};
    print $fh "#ifndef USE_POLL\n#define USE_POLL\n#endif\n"                 if $v{ENABLE_POLL};
    print $fh "#ifndef EMBED_PERL\n#define EMBED_PERL\n#endif\n" if $v{WITH_EMBEDDED_PERL};
    print $fh "#define STDC_HEADERS 1\n";
    close $fh;
    print "config.h written.\n";
}



( run in 2.306 seconds using v1.01-cache-2.11-cpan-0b58ddf2af1 )