#!/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 = ; &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 # can be single token or colon-separated list # 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) # 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); }