#!/usr/bin/perl
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
# $Id: alias_manager.pl.in 12612 2016-01-01 01:48:29Z sikeda $
# L. Marcotte has written a version of alias_manager.pl that is LDAP enabled
# check the contrib. page for more information :
# http://sympa.org/contrib.html
# 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, 2015, 2016 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 .
# Modified to generate virtual alias files for Postfix virtual alias domains
# Elwyn Davies 4 April 2008
# Updated to alias_manager.pl from Sympa 6.12
# Felix Eckhofer 21 July 2013
# Updated to Sympa 6.2.16
# Peter Putzer 23 January 2016 and 11 March 2017
use lib split(/:/, $ENV{SYMPALIB} || ''), '/usr/share/sympa/lib';
use strict;
use warnings;
use English qw(-no_match_vars);
use Getopt::Long;
use Pod::Usage;
use Conf;
use Sympa::Constants;
use Sympa::Crash; # Show traceback.
use Sympa::Language;
use Sympa::LockedFile;
use Sympa::Log;
use Sympa::Template;
$ENV{'PATH'} = '';
my %options;
GetOptions(\%main::options, 'help|h');
if ($main::options{'help'}) {
pod2usage(0);
}
## Load Sympa.conf
unless (defined Conf::load()) {
printf STDERR
"Unable to load sympa configuration, file %s or one of the vhost robot.conf files contain errors. Exiting.\n",
Conf::get_sympa_conf();
exit 1;
}
my $log = Sympa::Log->instance;
$log->{level} = $Conf::Conf{'log_level'};
$log->openlog($Conf::Conf{'syslog'}, $Conf::Conf{'log_socket_type'});
my $tmp_alias_file = $Conf::Conf{'tmpdir'} . '/sympa_aliases.' . time;
my $default_domain;
my $virtual_domain = 0;
my $alias_wrapper =
Sympa::Constants::LIBEXECDIR . '/sympa_newaliases-wrapper';
my $path_to_queue = Sympa::Constants::LIBEXECDIR . '/queue';
my $path_to_bouncequeue = Sympa::Constants::LIBEXECDIR . '/bouncequeue';
my $lock_file = Sympa::Constants::PIDDIR() . '/alias_manager.lock';
my $lock_fh;
my ($operation, $listname, $domain, $file) = @ARGV;
if (($operation !~ /^(add|del)$/) || ($#ARGV < 2)) {
printf STDERR "Usage: $0 []\n";
exit(2);
}
$default_domain = $Conf::Conf{'domain'};
my $alias_file;
$alias_file = Conf::get_robot_conf($domain, 'sendmail_aliases')
|| Sympa::Constants::SENDMAIL_ALIASES;
$alias_file = $file if ($file);
$virtual_domain = 1 if ($alias_file =~ /virtual$/);
my $pt; # pattern type for alias matching
if ($virtual_domain != 0) {
$pt = 1;
} else {
$pt = 0;
}
unless (-w "$alias_file") {
print STDERR "Unable to access $alias_file\n";
exit(5);
}
my $language = Sympa::Language->instance;
$language->set_lang(Conf::get_robot_conf($domain, 'lang'),
$Conf::Conf{'lang'}, 'en');
my $data = {
'date' => $language->gettext_strftime('%d %b %Y', localtime time),
'list' => {
'domain' => $domain,
'domainescaped' => ($domain =~ s/\./\\\./gr),
'name' => $listname,
},
'robot' => $domain,
'default_domain' => $default_domain,
'is_default_domain' => ($domain eq $default_domain),
'is_virtual_domain' => ($virtual_domain != 0),
'return_path_suffix' =>
Conf::get_robot_conf($domain, 'return_path_suffix'),
};
my @aliases;
my $aliases_dump;
my $template = Sympa::Template->new($domain);
unless ($template->parse($data, 'list_aliases.tt2', \$aliases_dump)) {
print STDERR "Can't parse list_aliases.tt2\n";
exit 15;
}
@aliases = split /\n/, $aliases_dump;
unless (@aliases) {
print STDERR "No aliases defined\n";
exit(15);
}
if ($operation eq 'add') {
# Create a lock
unless ($lock_fh = Sympa::LockedFile->new($lock_file, 5, '+')) {
print STDERR "Can't lock $lock_file\n";
exit 14;
}
## Check existing aliases
if (already_defined($pt, @aliases)) {
printf STDERR "some alias already exist\n";
exit(13);
}
unless (open ALIAS, ">> $alias_file") {
print STDERR "Unable to append to $alias_file\n";
exit(5);
}
foreach (@aliases) {
print ALIAS "$_\n";
}
close ALIAS;
## Newaliases
unless ($file || $virtual_domain != 0) {
unless (system($alias_wrapper, "--domain=$domain") == 0) {
if ($? == -1) {
print STDERR "Failed to execute newaliases: $ERRNO\n";
} else {
printf STDERR "newaliases exited with status %d\n", ($? >> 8);
}
exit(6);
}
}
# Unlock
$lock_fh->close;
} elsif ($operation eq 'del') {
# Create a lock
unless ($lock_fh = Sympa::LockedFile->new($lock_file, 5, '+')) {
print STDERR "Can't lock $lock_file";
exit 14;
}
unless (open ALIAS, "$alias_file") {
print STDERR "Could not read $alias_file\n";
exit(7);
}
unless (open NEWALIAS, ">$tmp_alias_file") {
printf STDERR "Could not create $tmp_alias_file\n";
exit(8);
}
my @deleted_lines;
while (my $alias = ) {
my $left_side = '';
if ($pt == 0) {
$left_side = $1 if ($alias =~ /^([^\s:]+)[\s:]/);
} else {
$left_side = $1 if ($alias =~ /^([^\t ]+)[\t ]/);
$left_side = $1 if ($alias =~ /^(#[^\s:]+)[\s:]/);
}
my $to_be_deleted = 0;
foreach my $new_alias (@aliases) {
my $new_left_side = $1;
if ($pt == 0) {
$new_left_side = $1 if ($new_alias =~ /^([^\s:]+)[\s:]/);
} else {
$new_left_side = $1 if ($new_alias =~ /^([^\t ]+)[\t ]/);
$new_left_side = $1 if ($new_alias =~ /^(#[^\s:]+)[\s:]/);
}
next unless $new_left_side;
if ($left_side eq $new_left_side) {
push @deleted_lines, $alias;
$to_be_deleted = 1;
last;
}
}
unless ($to_be_deleted) {
## append to new aliases file
print NEWALIAS $alias;
}
}
close ALIAS;
close NEWALIAS;
if ($#deleted_lines == -1) {
print STDERR "No matching line in $alias_file\n";
exit(9);
}
## replace old aliases file
unless (open NEWALIAS, "$tmp_alias_file") {
print STDERR "Could not read $tmp_alias_file\n";
exit(10);
}
unless (open OLDALIAS, ">$alias_file") {
print STDERR "Could not overwrite $alias_file\n";
exit(11);
}
print OLDALIAS ;
close OLDALIAS;
close NEWALIAS;
unlink $tmp_alias_file;
## Newaliases
unless ($file || $virtual_domain != 0) {
unless (system($alias_wrapper, "--domain=$domain") == 0) {
if ($? == -1) {
print STDERR "Failed to execute newaliases: $ERRNO\n";
} else {
printf STDERR "newaliases exited with status %d\n", ($? >> 8);
}
exit(6);
}
}
# Unlock
$lock_fh->close;
} else {
print STDERR "Action $operation not implemented yet\n";
exit(2);
}
exit 0;
## Check if an alias is already defined
sub already_defined {
# pt is 'pattern type' - 0 for oridnary aliases, 1 for virtual regexp aliases
my ($pt, @aliases) = @_;
unless (open ALIAS, "$alias_file") {
printf STDERR "Could not read $alias_file\n";
exit(7);
}
my $left_side = '';
my $new_left_side = '';
while (my $alias = ) {
# skip comment
next if $alias =~ /^#/;
if ($pt == 0) {
$alias =~ /^([^\s:]+)[\s:]/;
$left_side = $1;
} else {
$alias =~ /^([^\t ]+)[ \t]/;
$left_side = $1;
}
next unless ($left_side);
foreach (@aliases) {
next unless ((($pt == 0) && ($_ =~ /^([^\s:]+)[\s:]/)) ||
(($pt == 1) && ($_ =~ /^([^\t ]+)[ \t]/)));
$new_left_side = $1;
if ($left_side eq $new_left_side) {
print STDERR "Alias already defined : $left_side\n";
return 1;
}
}
}
close ALIAS;
return 0;
}
__END__
=encoding utf-8
=head1 NAME
alias_manager, alias_manager.pl - Manage Sympa Aliases
=head1 SYNOPSIS
S B | B I I>
=head1 DESCRIPTION
Alias_manager is a program that helps in installing aliases for newly
created lists and deleting aliases for closed lists.
It is called by
L or L via the I.
Alias management is performed only if it was setup in F
(C configuration parameter).
Administrators using MTA functionalities to manage aliases (ie
virtual_regexp and transport_regexp with postfix) can disable alias
management by setting
C configuration parameter to B.
=head1 OPTIONS
=over 4
=item B I I
Add the set of aliases for the mailing list I in the
domain I.
=item B I I
Remove the set of aliases for the mailing list I in the
domain I.
=back
=head1 FILES
F sendmail aliases file.
=head1 DOCUMENTATION
The full documentation in HTML and PDF formats can be
found in L.
The mailing lists (with web archives) can be accessed at
http://listes.renater.fr/sympa/lists/informatique/sympa.
=head1 HISTORY
This program was originally written by:
=over 4
=item Serge Aumont
ComitE<233> RE<233>seau des UniversitE<233>s
=item Olivier SalaE<252>n
ComitE<233> RE<233>seau des UniversitE<233>s
=back
This manual page was initially written by
JE<233>rE<244>me Marant
for the Debian GNU/Linux system.
=head1 LICENSE
You may distribute this software under the terms of the GNU General
Public License Version 2. For more details see F file.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts and no Back-Cover Texts. A
copy of the license can be found under
L.
=head1 BUGS
Report bugs to Sympa bug tracker.
See L.
=head1 SEE ALSO
L, L, L, L.
=cut