diff --git a/db/genelists.in b/db/genelists.in index 8119f5f0df355a18892b87a3f1f1300acb4958fb..00c5de977cada0cc81ecb7e0f4ac2b1b9cfcf81d 100644 --- a/db/genelists.in +++ b/db/genelists.in @@ -1,13 +1,16 @@ #!/usr/bin/perl -wT use Fcntl ':flock'; use English; +use Getopt::Std; sub usage() { - print STDOUT "Usage: genelists\n". - "Generate the email list files after things change\n"; + print STDOUT "Usage: genelists [-a] [-n uid]\n". + "Generate the email list files after things change.\n". + "Use the -a option to generate lists for all projects.\n". + "Use the -n option to generate lists for a new user.\n"; exit(-1); } -my $optlist = ""; +my $optlist = "an:"; # Configure variables my $TB = "@prefix@"; @@ -15,13 +18,15 @@ my $TBOPS = "@TBOPSEMAIL@"; my $USERS = "@USERNODE@"; my $TBACTIVE = "@TBACTIVEARCHIVE@"; my $TBALL = "@TBUSERSARCHIVE@"; +my $PROJROOT = "/proj"; # Note no -n option. We redirect stdin from the new exports file below. my $SSH = "$TB/bin/sshtb -l root $USERS"; my $PROG = "/usr/testbed/sbin/genelists.proxy"; my $lockfile = "/var/tmp/testbed_genelists_lockfile"; my $tempfile = "/var/tmp/testbed_genelists_tempfile"; -my $userlist; +my $newuser; +my $allprojects; my $d = 0; # @@ -42,7 +47,7 @@ if ($EUID != 0) { " Must be root! Maybe its a development version?\n"); } # XXX Hacky! -if ($TB ne "/usr/testbed") { +if (1 && $TB ne "/usr/testbed") { die("*** $0:\n". " Wrong version. Maybe its a development version?\n"); } @@ -53,7 +58,33 @@ if ($TB ne "/usr/testbed") { $ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/usr/local/bin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; -if (@ARGV != 0) { +# +# Parse command arguments. Once we return from getopts, all that should +# left are the required arguments. +# +%options = (); +if (! getopts($optlist, \%options)) { + usage(); +} +if (@ARGV) { + usage(); +} +if (defined($options{"a"})) { + $allprojects = 1; +} +if (defined($options{"n"})) { + $newuser = $options{"n"}; + # + # Untaint. + # + if ($newuser =~ /^([-\w]+)$/) { + $newuser = $1; + } + else { + die("Tainted argument $newuser!\n"); + } +} +if (defined($newuser) && defined($allprojects)) { usage(); } @@ -71,6 +102,7 @@ while (flock(LOCK, LOCK_EX|LOCK_NB) == 0) { foreach my $active ( 0, 1 ) { my $progarg; + my $userlist; if ($active) { print "Getting Active Users\n" if $d; @@ -84,8 +116,8 @@ foreach my $active ( 0, 1 ) { DBFatal("Getting Active Users!"); } $userlist = "$TBOPS\n". - "$TBACTIVE\n"; - $progarg = "-active"; + "$TBACTIVE"; + $progarg = "emulab-active-users"; } else { print "Getting All Users\n" if $d; @@ -96,9 +128,66 @@ foreach my $active ( 0, 1 ) { DBFatal("Getting Users!"); } $userlist = "$TBOPS\n". - "$TBALL\n"; - $progarg = "-all"; + "$TBALL"; + $progarg = "emulab-users"; } + genelist($query_result, $userlist, $progarg); +} + +# +# Regen project lists. Either all the lists, or just the projects +# that "newuser" is a member of. +# +if (defined($newuser) || defined($allprojects)) { + my $proj_result; + + if (defined($newuser)) { + $proj_result = + DBQueryFatal("select pid from group_membership ". + "where uid='$newuser' and pid=gid"); + } + else { + $proj_result = + DBQueryFatal("select pid from projects"); + } + + while (($pid) = $proj_result->fetchrow_array) { + print "Getting project members for $pid\n" if $d; + + my $query_result = + DBQueryFatal("SELECT distinct u.usr_email from ". + " group_membership as p ". + "left join users as u on u.uid=p.uid ". + "where p.pid='$pid' and p.pid=p.gid and ". + " p.trust!='none' ". + "order by u.usr_email"); + + if ($query_result->numrows) { + my $archive = "$PROJROOT/$pid/$pid-users.mail"; + + # + # This would be nice, but will not work since the mailer daemon + # cannot access files in /proj/$pid. + # + if (0 && ! -e $archive) { + open(ARCHIVE, ">>$archive") or + fatal("Could not create $archive: $!"); + close(ARCHIVE); + + chmod(0666, "$archive") or + fatal("Could not chmod(666) $archive: $!"); + } + genelist($query_result, undef, "$pid-users"); + } + } +} + +# +# Generate and fire over a list. +# +sub genelist($$$) +{ + my($query_result, $inituserlist, $progarg) = @_; open(LIST,"> $tempfile") || fatal("Couldn't open $tempfile: $!\n"); @@ -106,21 +195,18 @@ foreach my $active ( 0, 1 ) { print LIST "#\n"; print LIST "# WARNING! THIS FILE IS AUTOGENERATED. DO NOT EDIT!\n"; print LIST "#\n"; + if (defined($inituserlist)) { + print LIST "$inituserlist\n"; + } for ($i = 0; $i < $query_result->numrows; $i++) { - $user_email = ($query_result->fetchrow_array())[0]; + my $user_email = ($query_result->fetchrow_array())[0]; if (! defined($user_email)) { next; } - if ($userlist) { - $userlist .= "$user_email\n"; - } - else { - $userlist = "$user_email\n"; - } + print LIST "$user_email\n"; + print "$user_email\n" if $d; } - print LIST $userlist; - print $userlist if $d; close(LIST); # diff --git a/db/genelists.proxy.in b/db/genelists.proxy.in index 526e6d8e332c7a963277e812764ec6bbdaaa62a2..34d942f6e589a6afc8eecaff837dcf17a6626733 100644 --- a/db/genelists.proxy.in +++ b/db/genelists.proxy.in @@ -5,13 +5,15 @@ use Fcntl ':flock'; # # Insert new version of testbed emails lists into place on operations node. # The single argument indicates which list is being piped into the script -# from the control node. +# from the control node. We create a new alias in the aliases file as well. # -# usage: genelists.proxy [-all | -active] +# NB: We do not prune dead lists yet. +# +# usage: genelists.proxy # sub usage() { - print STDOUT "Usage: genelists.proxy [-all | -active]\n". - "Generate the email list files after things change\n"; + print STDOUT "Usage: genelists.proxy \n". + "Generate email list file after things change!\n"; exit(-1); } @@ -20,17 +22,19 @@ sub usage() { # my $TBOPS = "@TBOPSEMAIL@"; -my $maildir = "/etc/mail/lists"; -my $tempfile = "$maildir/tempfile.$$"; -my $alllist = "$maildir/testbed-users"; -my $activelist = "$maildir/testbed-active-users"; +my $maildir = "/etc/mail"; +my $listdir = "$maildir/lists"; +my $tempfile = "$listdir/tempfile.$$"; +my $aliasfile = "$maildir/aliases"; +my $listname; my $thelist; # # We don't want to run this script unless its the real version. # if ($UID != 0) { - die("Must be root!"); + die("*** $0:\n". + " Must be root!\n"); } # un-taint path @@ -46,15 +50,21 @@ $| = 1; use lib "@prefix@/lib"; use libtestbed; -if (@ARGV != 1 || ($ARGV[0] ne "-all" && $ARGV[0] ne "-active")) { +if (@ARGV != 1) { usage(); } -if ($ARGV[0] eq "-active") { - $thelist = $activelist; +$listname = $ARGV[0]; + +# +# Untaint the arguments. +# +if ($listname =~ /^([-\@\w]+)$/) { + $listname = $1; } else { - $thelist = $alllist; + die("Tainted argument $listname!\n"); } +$thelist = "$listdir/$listname"; # # Take our input and write it to the temp file. @@ -73,12 +83,32 @@ chmod(0644, $tempfile); system("/bin/mv $tempfile $thelist") == 0 || fatal("Could not move $tempfile to $thelist: $!"); +# +# See if the aliases exists in the alias file. If not, append it and +# rebuild with newaliases. +# +if (system("egrep -q -s '^${listname}:' $aliasfile")) { + print "Adding new alias $listname to aliases file\n"; + + open(ALIASES, ">>$aliasfile") or + fatal("opening $aliasfile to append new alias: $!"); + + printf ALIASES "%-24s%s\n", "${listname}:", ":include:${thelist}"; + + close(ALIASES) or + fatal("Could not close $aliasfile after modification: $!"); + + system("newaliases") == 0 or + fatal("Could not rebuild the aliases database!"); +} + exit(0); sub fatal { local($msg) = $_[0]; SENDMAIL($TBOPS, "genelists.proxy failure", $msg); - die($msg); + die("*** $0:\n". + " $msg\n"); } diff --git a/tbsetup/mkacct.in b/tbsetup/mkacct.in index 27dbe557efb1620d81e74bfa0e5f04ed6fe7ed93..49d1388826cead0accfa35f957efc2b54418b11f 100755 --- a/tbsetup/mkacct.in +++ b/tbsetup/mkacct.in @@ -177,7 +177,7 @@ $UID = $EUID; # this command must be run when EUID==UID==0 because its a setuid # PERL script. # -system("$GENELISTS"); +system("$GENELISTS -n $user"); # # Make user on local. We don't give them a password since they are not