#!/usr/bin/perl -w
# ====================================================================
# Copyright (c) 1999, MeepZor Consulting.
# All rights reserved.
#
# The use and distribution of this code or document is
# governed by the latest version of the MeepZor Consulting
# Licence (MCL), which may be found on the Internet at
# .
#
#
# mklist: Majordomo utility to make a new list
#
# $Id: mklist,v 1.13 2001/04/19 12:45:47 coar Exp $
#
# See the MANIFEST file for package information.
#
# A required file is "template-list.config", which is a Majordomo
# list configuration file with special placeholders in it. The
# placeholders, and with what they're replaced when the real .config file
# is created, are:
#
# @@PASSWORD@@
# The password for list management, specified with -p
#
# @@OWNER@@
# The email address of the list owner, specified with -o
#
# @@HOST@@
# The name of the mailing-list host (used in From addresses and
# administrative notices). Specified manually with -H or derived
# from the current hostname.
#
# @@LNAME-H@@
# The listname as consumable by humans (i.e., with case preserved),
# specified by -n
#
# @@LNAME-M@@
# The listname as consumable by Majordomo (i.e., converted to all
# lowercase). Derived from @@LNAME-H@@
#
# @@DNAME-H@@
# The human-consumable name of the digest list, formed from the value
# of the -n option with "-Digest" appended
#
# @@DNAME-M@@
# The Majordomo-usable name of the digest list; @@DNAME-H@@ lowercased
#
# If digesting is going to be done, "template-digest.config" is also
# required. The placeholders have the same meanings. The -T switch
# tells mklist where the template files can be found.
#
# All lists are archived with -M by default, in the .archive
# subdirectory under the lists directory.
#
# See the usage() function at the end of this script for a description of
# all of the switches and their meanings.
#
use Getopt::Long;
use Sys::Hostname;
Getopt::Long::Configure("bundling");
#
# Pre-set the option scalars so Perl won't gritch about them only being
# used once.
#
%opt = ();
$opts = join("", @ARGV);
foreach (split(//, "dhnopDFHLMNPSTvVW")) {
$opt{$_} = "";
}
GetOptions(\%opt,
"description|d=s" => \$opt{'d'},
"help|h" => \$opt{'h'},
"list-name|n=s" => \$opt{'n'},
"owner|o=s" => \$opt{'o'},
"password|p=s" => \$opt{'p'},
"verbose|v" => \$opt{'v'},
"config-file|C=s" => \$opt{'C'},
"digest|D" => \$opt{'D'},
"force|F" => \$opt{'F'},
"host|H=s" => \$opt{'H'},
"list-directory|L=s" => \$opt{'L'},
"majordomo-home|M=s" => \$opt{'M'},
"no-action|N" => \$opt{'N'},
"alias-prefix|P=s" => \$opt{'P'},
"save|S" => \$opt{'S'},
"template-directory|T=s" => \$opt{'T'},
"very-verbose|V" => \$opt{'V'},
"digest-work|W=s" => \$opt{'W'}
);
$opt{'h'} = $opt{'h'} || ($opts eq "") || (join("", %opt) eq "");
if ($opt{'h'}) {
&usage();
exit 0;
}
#
# Check to see if we have a saved-settings file, and load the values
# if so.
#
%sticky_settings = ('-H' => &hostname(),
'-L' => '/usr/local/mail/lists',
'-M' => '/usr/local/mail/majordomo',
'-P' => '',
'-T' => '/usr/local/mail',
'-W' => '/usr/local/mail/digests'
);
$HOME = $ENV{'HOME'};
print "$0: checking for a .mklistrc file\n" if ($opt{'V'});
$file = (-f "./.mklistrc") ? "./.mklistrc" : "$HOME/.mklistrc";
if (open(RC, $file)) {
print "$0: loading saved settings: "
if ($opt{'v'} || $opt{'V'});
my(@opts) = ;
close(RC);
foreach (@opts) {
chomp;
if ($_ =~ m:^\s*-([A-Z])\s+(.*):) {
$sticky_settings{"-$1"} = $2;
}
}
print "done.\n"
if ($opt{'v'} || $opt{'V'});
if ($opt{'V'}) {
print "$0: current sticky settings:\n";
foreach (sort(keys(%sticky_settings))) {
print " $_ = " . $sticky_settings{$_} . "\n";
}
}
}
@errors = ();
$sticky_settings{'-H'} = $HOST = $opt{'H'} || $sticky_settings{'-H'};
$sticky_settings{'-L'} = $LDIR = $opt{'L'} || $sticky_settings{'-L'};
$sticky_settings{'-M'} = $MDIR = $opt{'M'} || $sticky_settings{'-M'};
$sticky_settings{'-P'} = $PFIX = $opt{'P'} || $sticky_settings{'-P'};
$sticky_settings{'-T'} = $TDIR = $opt{'T'} || $sticky_settings{'-T'};
$sticky_settings{'-W'} = $DDIR = $opt{'W'} || $sticky_settings{'-W'};
$list_has_digest = $opt{'D'};
#
# Deal with the name of the list. If it's a digest, the user should
# specify the name of the actual list, not the digest name.
#
if ($opt{'S'} && ($opt{'d'} || $opt{'n'} || $opt{'o'} || $opt{'p'})) {
push(@errors, "-S may not be combined with -d, -n, -o, or -p");
}
elsif ($opt{'S'}) {
print "$0: saving sticky settings: "
if ($opt{'v'} || $opt{'V'});
open(RC, ">$HOME/.mklistrc") || die("Can't create $HOME/.mklistrc");
print RC "#\n# .mklistrc -- settings for mklist's sticky options\n#\n";
foreach (sort(keys(%sticky_settings))) {
print RC "$_ " . $sticky_settings{$_} . "\n";
}
print "done.\n"
if ($opt{'v'} || $opt{'V'});
exit(0);
}
if ((! $opt{'n'}) && (! $opt{'S'})) {
push(@errors, "-n must specify the name of the list");
}
elsif ($opt{'n'}) {
$lname_h = $dname_h = $opt{'n'};
$dname_h .= ($lname_h =~ /[A-Z]/) ? "-Digest" : "-digest";
$lname_m = lc($lname_h);
$dname_m = lc($dname_h);
chdir("$LDIR");
if (! $opt{'F'}) {
push(@errors, "subscriber file $lname_m exists")
if (-e "$lname_m");
push(@errors, "config file ${lname_m}.config exists")
if (-e "${lname_m}.config");
push(@errors, "introduction file ${lname_m}.intro exists")
if (-e "${lname_m}.intro");
push(@errors, "information file ${lname_m}.config exists")
if (-e "${lname_m}.info");
push(@errors, "archive directory ${lname_m}.archive exists")
if (-e "${lname_m}.archive");
}
}
$description = $opt{'d'};
if ((! $description) && (! $opt{'S'})){
push(@errors, "-d must specify up to 50 characters of description");
}
if (length($description) > 50) {
push(@errors, "-d is too long; no more than 50 characters");
}
$password = $opt{'p'};
if ((! $password) && (! $opt{'S'})) {
push(@errors, "-p must specify a password");
}
$owner = $opt{'o'};
if ((! $owner) && (! $opt{'S'})) {
push(@errors, "-o must specify a (possibly local) email address for "
. "the list owner");
}
if ($#errors >= 0) {
print STDERR "$0: ", join("\n$0: ", @errors), "\n";
exit 1;
}
#
# Right; if we've gotten this far, we're ready to go. We have at least one
# list to set up, so let's do it.
#
$list_type = "list";
$dname_h = $lname_h;
$dname_h .= ($lname_h =~ /[A-Z]/) ? "-Digest" : "-digest";
$dname_m = lc($dname_h);
#
# Create the 'welcome to the list' and 'here's what the list is about
# in case you want to join' description files.
#
&mkintro(0);
&mkinfo(0);
#
# Create a blank subscriber file (do nothing if it already exists, since that
# means we're just normalising the control files).
#
system("touch $LDIR/$lname_m");
#
# Create the list's configuration file from the template and our
# settings.
#
&mkconfig("$TDIR/template-list.config", "$LDIR/${lname_m}.config");
#
# Create the list's archive directory.
#
mkdir("$LDIR/${lname_m}.archive", 0755);
#
# Create a file containing the various alias entries for easy addition
# to the /etc/aliases file.
#
&mkalii(0);
#
# Now, if this list doesn't have a digest, we're all done. Otherwise
# we need to adjust our variables and create the digest-list info too.
#
exit 0 if (! $list_has_digest);
#
# Heigh-ho, time to make the digest.
#
$list_type = "digest";
$tmp = $dname_h;
$dname_h = $lname_h;
$lname_h = $tmp;
$tmp = $dname_m;
$dname_m = $lname_m;
$lname_m = $tmp;
$description = "Digests of the $dname_h list";
#
# Make the blurb files.
#
&mkintro(1);
&mkinfo(1);
#
# Now the subscriber list.
#
system("touch $LDIR/$lname_m");
#
# Now create the config file from the digest template.
#
&mkconfig("$TDIR/template-digest.config", "$LDIR/${lname_m}.config");
#
# Create the digest working directory.
#
mkdir("$DDIR/${lname_m}", 0755);
#
# Create the list's archive directory. This is where the digests are
# archived for later retrieval.
#
mkdir("$LDIR/${lname_m}.archive", 0755);
#
# Create a file containing the various alias entries for easy addition
# to the /etc/aliases file.
#
&mkalii(1);
#
# Create a file containing the cron definition for the digestification.
#
open CRON, ">$LDIR/${lname_m}.cron";
print CRON "0 21 * * * ",
"echo \"mkdigest $lname_m ${lname_h}-Subscribers $password\" ",
"| mail Majordomo\@Localhost\n";
close CRON;
#
# All done!
#
exit 0;
#
# Create a file containing the various alii needed for Majordomo
# to manage this mailing list. The user has to add these to the
# appropriate system alias file, but this is to make it easy.
#
sub mkalii {
my($digest) = @_;
my($cfgfile) = $opt{'C'} ? " -C $opt{'C'}" : "";
printf STDERR ("$0: creating ${lname_m}.alii:")
if ($opt{'V'});
open ALII, ">${lname_m}.alii";
print ALII <${lname_m}.virtuser";
print VIRTUSER <$CONFIG")
or die("$0: Can't open new config file '$CONFIG'");
while () {
s:\@\@HOST\@\@:$HOST:g;
s:\@\@LNAME-H\@\@:$lname_h:g;
s:\@\@LNAME-M\@\@:$lname_m:g;
s:\@\@DNAME-H\@\@:$dname_h:g;
s:\@\@DNAME-M\@\@:$dname_m:g;
s:\@\@DESCRIPTION\@\@:$description:g;
s:\@\@PASSWORD\@\@:$password:g;
print CONFIG $_;
}
close TEMPLATE;
close CONFIG;
}
#
# Create a blank intro file, which gets sent to new subscribers.
#
sub mkintro {
my($digest) = @_;
open INTRO, ">${lname_m}.intro";
print INTRO <${lname_m}.info";
print INFO <