From bcc792c163e9f3c42fe1a500aaf2d3d9d2f1fe53 Mon Sep 17 00:00:00 2001 From: Jonas Smedegaard Date: Tue, 22 Aug 2006 15:36:21 +0000 Subject: Complete rewrite in Perl. --- localmkpostfixvirtual | 169 +++++++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 76 deletions(-) (limited to 'localmkpostfixvirtual') diff --git a/localmkpostfixvirtual b/localmkpostfixvirtual index e6eed13..3014382 100755 --- a/localmkpostfixvirtual +++ b/localmkpostfixvirtual @@ -1,9 +1,9 @@ -#!/bin/sh +#!/usr/bin/perl -wT # # /usr/local/sbin/localmkpostfixvirtual -# Copyright 2001-2002 Jonas Smedegaard +# Copyright 2001-2006 Jonas Smedegaard # -# $Id: localmkpostfixvirtual,v 1.21 2006-08-13 23:57:44 jonas Exp $ +# $Id: localmkpostfixvirtual,v 1.22 2006-08-22 15:36:21 jonas Exp $ # # Generate virtual file for postfix # @@ -34,81 +34,98 @@ # Suggestion: Add mailgroup users like this: # adduser --system --no-create-home --group --disabled-password # -# TODO: reuse getent requests (drastically improves speed) -# TODO: Write command "members" as internal code -# -get_fullname_field() { getent passwd $1 | awk -F: '{print $5}' | awk -F, '{print $1}'; } -get_roomnumber_field() { getent passwd $1 | awk -F: '{print $5}' | awk -F, '{print $2}'; } -get_other_field() { getent passwd $1 | awk -F: '{print $5}' | awk -F, '{print $5}'; } -get_groups() { groups $1 | sed -e 's/^.*: //' -e "s/\( \+\|^\)$1\( \+\|$\)/\1/"; } -get_domain() { echo $1 | egrep "^@[\.[:alnum:]-]+$" | sed -e 's/@//'; } -get_account() { echo $1 | egrep "^([\.[:alnum:]_-]+|\+)@($mailgroup|$maildomain)?$" | sed -e 's/@.*//'; } -sort_u() { for x in $@; do echo $x; done | sort -u; } +use strict; + +use User::pwent; +use User::grent; +#use Data::Dumper; + +my (%username, %fullname, %office, %workphone, %homephone, %other); +my (%username_by_gid, %addresshints, %domains); -print_accounts() { - uid=$1 - maildomain=$2 - pre_text=$3 - post_fallback_text=$4 +while (my $pw = getpwent()) { - test -n "$pre_text" && echo "$pre_text" - uid_seen="" - joker_seen="" - for mailaccountchunk in `get_other_field $uid`; do - for mailaccount in `get_account $mailaccountchunk`; do - case $mailaccount in - '+') - if [ -z "$joker_seen" ]; then - echo "@$maildomain $uid" - joker_seen="$uid" - else - echo "#WARNING: Catch-all for $maildomain already set to $joker_seen: `get_fullname_field $uid`" - fi - ;; - *) - echo "$mailaccount@$maildomain $uid" - ;; - esac - uid_seen=1 - done - done - test -n "$post_fallback_text" -a -z "$uid_seen" && echo "$post_fallback_text" - echo + $username_by_gid{$pw->gid} = $pw->name; + ($fullname{$pw->name}, $office{$pw->name}, $workphone{$pw->name}, $homephone{$pw->name}, $other{$pw->name}) = split /\s*,\s*/, $pw->gecos; + if (defined($other{$pw->name})) { + @{$addresshints{$pw->name}} = grep {/^([\.[:alnum:]_-]+|\+)?@([\.[:alnum:]_-]+)?$/} split /\s+/, $other{$pw->name}; + } +#DEBUG: ($pw->name eq "annette") and print STDERR Dumper(@{$addresses{$pw->name}}); } -loop="" -if [ $# -lt 1 ]; then - mailgroups="`members maildomains`" -else - mailgroups="$@" -fi -for mailgroup in $mailgroups; do - for maildomainchunk in `get_other_field $mailgroup`; do - for maildomain in `get_domain $maildomainchunk`; do - if [ $loop ]; then - echo - echo "##################################################################" - echo - fi - loop=true - print_accounts root "$maildomain" "$maildomain VIRTUAL" "postmaster@$maildomain root" - mailgroupowners="" - mailusers="" - mailgroupgroups="`get_roomnumber_field $mailgroup`" - test -z "$mailgroupgroups" && mailgroupgroups="$mailgroup" - for mailgroupgroup in $mailgroupgroups; do - mailgroupowners="$mailgroupowners `members -p "$mailgroupgroup"`" - mailusers="$mailusers `members -s "$mailgroupgroup"`" - done - # Do mailgroup owners (and don't warn if there's no addresses attached) - for mailgroupowner in `sort_u $mailgroupowners`; do - print_accounts $mailgroupowner "$maildomain" "# `get_fullname_field "$mailgroupowner"` (`get_groups "$mailgroupowner"`)" "" - done - # Do secondary mailgroup members - for mailuser in `sort_u $mailusers`; do - print_accounts "$mailuser" "$maildomain" "# `get_fullname_field "$mailuser"` (`get_groups "$mailuser"`)" "#WARNING: No addresses for $mailuser" - done - done - done -done +my (%owner, %members, %groups); + +while (my $gr = getgrent()) { + + $owner{$gr->name} = $username_by_gid{$gr->gid}; + $members{$gr->name} = $gr->members; + foreach my $member (@{$members{$gr->name}}) { + push @{$groups{$member}}, $gr->name; + } +} + +sub print_accounts($$$$) { + my ($username, $mailgroup, $maildomain, $pre_text, $post_fallback_text) = @_; + + ($pre_text) && print $pre_text . "\n"; + my $user_seen; + my $joker_seen; +#DEBUG: print STDERR "$mailgroup $maildomain\n"; +#DEBUG: ($username eq "annette") and print STDERR Dumper(@{$addresshints{$username}}); + my @localparthints = @{$addresshints{$username}}; + my @localparts = grep {s/(.+)@($mailgroup|$maildomain)?$/$1/} @localparthints; + foreach my $localpart (@localparts) { + for ($localpart) { + if (/^\+$/) { + if (!$joker_seen) { + print "\@$maildomain $username\n"; + $joker_seen = $username; + } else { + print "#WARNING: Catch-all for $maildomain already set to $joker_seen!"; + } + } else { + print "$localpart\@$maildomain $username\n"; + } + } + $user_seen++; + } + print $post_fallback_text . "\n" if ($post_fallback_text && !$user_seen); + print "\n"; +} + +my $loop; +my @mailgroups = @ARGV ? @ARGV : @{$members{'maildomains'}}; +foreach my $mailgroup (@mailgroups) { + if (not defined(@{$addresshints{$mailgroup}})) { + print STDERR "W: Skipping empty mailgroup \"$mailgroup\"."; + next; + } + my @maildomainhints = @{$addresshints{$mailgroup}}; + my @maildomains = grep {s/^@(.+)/$1/} @maildomainhints; + foreach my $maildomain (@maildomains) { + my (@mailgroupowners, @mailusers); + my @mailgroupgroups = split / +/, $office{$mailgroup}; + push @mailgroupgroups, $mailgroup unless (@mailgroupgroups); + foreach my $mailgroupgroup (@mailgroupgroups) { + push @mailgroupowners, $owner{$mailgroupgroup} if ($owner{$mailgroupgroup}); + push @mailusers, @{$members{$mailgroupgroup}}; + } + my @mailgroupowners_sorted = sort @mailgroupowners; + my @mailusers_sorted = sort @mailusers; +#DEBUG: print STDERR Dumper(@mailusers); die; + if ($loop) { + print "\n##################################################################\n\n"; + } + $loop++; + &print_accounts('root', $mailgroup, $maildomain, "$maildomain VIRTUAL", "postmaster\@$maildomain root"); + # Do mailgroup owners (and don't warn if there's no addresses attached) + foreach my $mailgroupowner (@mailgroupowners_sorted) { + &print_accounts($mailgroupowner, $mailgroup, $maildomain, '# ' . $fullname{$mailgroupowner} . ' (' . join(' ', @{$groups{$mailgroupowner}}) . ')'); + } + # Do secondary mailgroup members + foreach my $mailuser (@mailusers_sorted) { + &print_accounts($mailuser, $mailgroup, $maildomain, '# ' . $fullname{$mailuser} . ' (' . join(' ', @{$groups{$mailuser}}) . ')', "#WARNING: No addresses for $mailuser"); + } + } +} -- cgit v1.2.3