#!/usr/local/bin/perl
#
$valid_users = "kroot,root,daemon";
$valid_group = "misnsm";
require "getopts.pl";
die("Usage: $0 -o owner -p passwd old-list new-list")
unless &Getopts("C:o:p:") && @ARGV == 2;
$oldlist = shift(@ARGV); $list = shift(@ARGV);
&squawk("list names must be different") if $oldlist eq $list;
$cf = $ENV{"MAJORDOMO_CF"} || "/etc/majordomo.cf";
$cf = $opt_C if $opt_C;
# NOT CHECKING THE PASSWORD HERE. This should have been done via
# MajorCool. If this is run via shell, then just do it.
# Read and execute the .cf file
die("$cf not readable; stopped") if ! -r $cf;
die("require of majordomo.cf failed $@") unless require "$cf";
# Go to the home directory specified by the .cf file
chdir("$homedir");
# All these should be in the standard PERL library
unshift(@INC, $homedir);
require "ctime.pl"; # To get MoY definitions for month abbrevs
require "majordomo_version.pl"; # What version of Majordomo is this?
require "majordomo.pl"; # all sorts of general-purpose Majordomo subs
require "shlock.pl"; # NNTP-style file locking
require "config_parse.pl"; # functions to parse the config files
# Here's where the fun begins...
# check to see if the cf file is valid
die("listdir not defined. Is majordomo.cf being included correctly?")
if !defined($listdir);
# where do we look for files, by default?
$filedir = $listdir if !defined($filedir);
$filedir_suffix = ".archive" if !defined($filedir_suffix);
#----------------------------------------------------------------------------
# 1.94 has this set in $CF already
$sendmail_command = "/usr/lib/sendmail" unless $sendmail_command;
# don't allow just anyone to run this command...
print "Validating permissions...\n";
&squawk("access denied") unless &is_user($valid_users,$valid_group);
# unbuffered stdout/stderr
select((select(STDOUT), $|=1)[$[]);
select((select(STDERR), $|=1)[$[]);
print "Checking for old list...\n";
&squawk("list '$oldlist' does not exist") unless -f "$listdir/$oldlist";
print "Verifying new list name...\n";
&squawk("list '$list' must be lowercase only") if $list =~ /[A-Z]+/;
&squawk("invalid characters in list '$list'") unless $list =~ /^[-\w]+$/;
&squawk("list '$list' already exists") if -f "$listdir/$list";
print "Checking for existing aliases...\n";
&squawk("address '$list' already exists")
unless system("$sendmail_command -bv $list >/dev/null");
#
# NOTE: depending on sendmail version, the above might
# need to be changed to an "if".
&squawk("cannot open listdir") unless opendir(DIR,$listdir);
print "Renaming $oldlist to $list...";
foreach $oldfile (grep(/^$oldlist(\.\w+)?$/, readdir(DIR))) {
local(*FILE, @data);
local($file) = $oldfile;
local($nostrings) =
($oldfile =~ /\.passwd$/ && -f "$listdir/MASTER.PASSWD");
#
$file =~ s/^$oldlist(\.\w+)?$/$list$1/;
#print "$oldfile -> $file...";
print ".";
if (-f "$listdir/$oldfile" && ! $nostrings) {
&lopen(FILE, "<", "$listdir/$oldfile");
@data = <FILE>;
&lreopen(FILE, ">", "$listdir/$oldfile");
foreach (@data) {
s/\b$oldlist\b/$list/;
print FILE;
}
&lclose(FILE);
}
rename("$listdir/$oldfile", "$listdir/$file");
}
print "\n";
if ($opt_o) {
print "Sending confirmation to '$opt_o'...\n";
&send_confirm;
}
if (-x "$homedir/mj_build_aliases") {
print "Starting alias rebuild...\n";
system("nohup $homedir/mj_build_aliases @ >/dev/null &");
}
print "Done.\n";
sub squawk {
local(@argv) = split('/',$0);
printf STDERR "%s: @_\n", $argv[$#argv];
exit(1);
}
### IS_USER(users, group)
# boolean: match current user against other users/group
# <users> can be single token or colon-separated list
# <group> can be name or gid
#
sub is_user {
local($users, $group) = @_[0,1];
local($valid);
$current_user = getlogin || (getpwuid($<))[0] || die "Unknown user";
#print "$current_user: ";
if ($users) {
foreach (split(',', $users)) {
#print "$_...";
if ($current_user eq $_) {
$valid = 1; last;
}
}
}
if ($group && ! $valid) {
#print "$group()...";
foreach (&group_members($group)) {
#print "$_...";
if ($_ eq $current_user) {
$valid = 1; last;
}
}
}
return $valid;
}
### GROUP_MEMBERS(group)
# list: return members of Unix group
# checks both primary (/etc/passwd) and supplementary (/etc/group)
# <group> can be name or gid
#
sub group_members {
local($target) = @_;
return unless $target;
local(@users);
if ($target =~ /[^\d]*/) {
# supplementary group, by name
local($name,$passwd,$gid,$members) = getgrnam($target);
$target = $gid;
@users = split(' ',$members);
}
else {
# supplementary group, by gid
local($name,$passwd,$gid,$members) = getgrgid($target);
@users = split(' ',$members);
}
# primary group, by gid
while (($user,$pass,$uid,$gid) = getpwent) {
push(@users, $user) if ($gid == $target);
}
return @users;
}
sub send_confirm {
&set_mailer($bounce_mailer ? $bounce_mailer : $mailer);
&set_mail_sender($whoami_owner);
&set_mail_from($whoami_owner);
&sendmail(MAIL, $opt_o, "$list: Majordomo list renamed");
print MAIL <<"EOF";
The Majordomo list called "$oldlist" has been renamed as per
password-validated request. The new name is "$list".
Each supporting file has been processed such that all data
(including passwords) which contained the old list name have
been changed to reflect the new list name.
If this list renaming is unexpected or otherwise incorrect,
please contact:
$whoami_owner
as soon as possible.
EOF
close(MAIL);
}
syntax highlighted by Code2HTML, v. 0.9.1