summaryrefslogtreecommitdiff
path: root/localmkpostfixvirtual
diff options
context:
space:
mode:
authorJonas Smedegaard <dr@jones.dk>2006-08-22 15:36:21 +0000
committerJonas Smedegaard <dr@jones.dk>2006-08-22 15:36:21 +0000
commitbcc792c163e9f3c42fe1a500aaf2d3d9d2f1fe53 (patch)
treeb6632ddeec55ae2654f0506ca4258c77de0d560c /localmkpostfixvirtual
parent24c959704278a19ed9c2a4cc586f6a3d147dd39c (diff)
Complete rewrite in Perl.
Diffstat (limited to 'localmkpostfixvirtual')
-rwxr-xr-xlocalmkpostfixvirtual169
1 files changed, 93 insertions, 76 deletions
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 <dr@jones.dk>
+# Copyright 2001-2006 Jonas Smedegaard <dr@jones.dk>
#
-# $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 <uid>
#
-# 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");
+ }
+ }
+}