#! /usr/bin/perl
# $Id:$

# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
# Copyright (c) 2011, 2012, 2013, 2014 GIP RENATER
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

use strict;
use warnings;
use lib qw(/usr/local/libdata/perl5/site_perl/Sympa);
use Getopt::Long;
use Pod::Usage;

use Conf;
use Log;

my %options;
unless ( GetOptions( \%options, 'domain=s', 'help|h' ) ) {
    pod2usage( -exitval => 1, -output => \*STDERR );
}
if ( $options{'help'} ) {
    pod2usage(0);
}
my $robot_id = $options{'domain'};

# Load configuration
my $sympa_conf_file = Sympa::Constants::CONFIG;
unless ( Conf::load( $sympa_conf_file ) ) {
    do_log( 'err', 'The configuration file %s contains error',
        $sympa_conf_file );
    exit 1;
}

do_openlog( $Conf{'syslog'}, $Conf{'log_socket_type'}, 'sympa_newaliases' );
Log::set_log_level( $Conf{'log_level'} );

my ( $aliases_file, $aliases_program, $aliases_db_type );
if ($robot_id) {
    unless ( Conf::valid_robot($robot_id) ) {
        do_log( 'err', 'robot %s does not exist', $robot_id );
        exit 1;
    }
    $aliases_file    = Conf::get_robot_conf( $robot_id, 'sendmail_aliases' );
    $aliases_program = Conf::get_robot_conf( $robot_id, 'aliases_program' );
    $aliases_db_type = Conf::get_robot_conf( $robot_id, 'aliases_db_type' );
} else {
    $aliases_file    = $Conf{'sendmail_aliases'};
    $aliases_program = $Conf{'aliases_program'};
    $aliases_db_type = $Conf{'aliases_db_type'};
}
if ( $aliases_file eq 'none' ) {
    exit 0;    # do nothing
} elsif ( !-e $aliases_file ) {
    do_log( 'err', 'The aliases file %s does not exist', $aliases_file );
    exit 1;
}
unless ( $aliases_db_type =~ /\A\w+\z/ ) {
    do_log( 'err', 'Invalid aliases_db_type "%s"', $aliases_db_type );
    exit 1;
}

if ( $aliases_program =~ m{\A/} ) {
    do_log( 'debug2', 'executing "%s %s"', $aliases_program, $aliases_file );

    exec $aliases_program, $aliases_file;
} elsif ( $aliases_program eq 'makemap' ) {
    do_log( 'debug2', 'executing "%s %s %s < %s"',
        q{/usr/sbin/makemap}, $aliases_db_type, $aliases_file, $aliases_file );

    unless ( open STDIN, '<', $aliases_file ) {
        do_log( 'err', 'Canot open $s', $aliases_file );
        exit 1;
    }
    exec q{/usr/sbin/makemap}, $aliases_db_type, $aliases_file;
} elsif ( $aliases_program eq 'newaliases' ) {
    do_log( 'debug2', 'executing "%s"',
        q{/usr/bin/newaliases } );

    # Some newaliases utilities e.g. with Postfix cannot take arguments.
    # OTOH if it may take arg, exec() must take separate one to avoid shell
    # metacharacters.
    if (q{}) {
        exec q{/usr/bin/newaliases}, q{};
    } else {
        exec q{/usr/bin/newaliases};
    }
} elsif ( $aliases_program eq 'postalias' ) {
    do_log( 'debug2', 'executing "%s %s:%s"',
        q{/usr/sbin/postalias}, $aliases_db_type, $aliases_file );

    exec q{/usr/sbin/postalias}, "$aliases_db_type:$aliases_file";
} elsif ( $aliases_program eq 'postmap' ) {
    do_log( 'debug2', 'executing "%s %s:%s"',
        q{/sbin/postmap}, $aliases_db_type, $aliases_file );

    exec q{/sbin/postmap}, "$aliases_db_type:$aliases_file";
} else {
    do_log( 'err', 'Invalid aliases_program "%s"', $aliases_program );
    exit 1;
}

my $errno = $!;
do_log( 'Cannot execute aliases_program "%s": %s', $aliases_program, $errno );
exit( $errno || 1 );

__END__

=encoding utf-8

=head1 NAME

sympa_newaliases, sympa_newaliases.pl - Alias database maintenance

=head1 SYNOPSIS

  sympa_newaliases.pl --domain=dom.ain

=head1 DESCRIPTION

sympa_newaliases is a program to maintain alias database.

It is typically called by
L<alias_manager(8)> via sympa_newaliases-wrapper,
then updates alias database.

=head1 OPTIONS

F<sympa_newaliases.pl> may run with following options.

=over

=item B<--domain=>I<domain>

Name of virtual robot on which aliases will be updated.

=item B<-h>, B<--help>

Print this help message.

=back

=head1 CONFIGURATION PARAMETERS

Following site configuration parameters in F</var/sympa/etc//sympa.conf> will be referred.
They may be overridden by robot.conf of each virtual robot.

=over

=item sendmail_aliases

Source text of alias database.

Default value is F</var/sympa/sympa_aliases>.

=item aliases_program

System command to update alias database.
Possible values are:

=over

=item C<makemap>

Sendmail makemap utility.

=item C<newaliases>

L<newaliases(1)> or compatible utility.

=item C<postalias>

Postfix L<postalias(1)> utility.

=item C<postmap>

Postfix L<postmap(1)> utility.

=item Full path

Full path to executable file.
File will be invoked with the value of C<sendmail_aliases> as an argument.

=back

Default value is C<newaliases>.

=item aliases_db_type

Type of alias database.
This is meaningful when value of C<aliases_program> parameter is
C<makemap>, C<postalias> or C<postmap>.

Possible values will be vary by system commands.
For example, C<postalias> and C<postmap> can support any of
C<btree>, C<cdb>, C<dbm>, C<hash> and C<sdbm>.

Default value is C<hash>.

=back

=head1 RETURN VALUE

Returns with exit code 0.
If invoked system command failed, returns with its exit code.
On other failures, returns with 1.

=head1 FILES

=over

=item F</var/sympa/etc//sympa.conf>

Sympa site configuration.

=item F</usr/local/libexec/sympa/sympa_newaliases-wrapper>

Set UID wrapper for sympa_newaliases.pl.

=back

=head1 AUTHOR

This program was initially written by
IKEDA Soji <ikeda@conversion.co.jp>.

=head1 SEE ALSO

L<alias_manager(8)>.

=cut
