Commit 3e05832d authored by Leigh B. Stoller's avatar Leigh B. Stoller

The Big group thing!

parent a1f22169
...@@ -1047,7 +1047,8 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -1047,7 +1047,8 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \ tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \ tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \ tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs \ tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tip/GNUmakefile \ tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \ tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \ tmcd/netbsd/GNUmakefile \
......
...@@ -169,7 +169,8 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -169,7 +169,8 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \ tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \ tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \ tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs \ tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tip/GNUmakefile \ tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \ tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \ tmcd/netbsd/GNUmakefile \
......
...@@ -39,11 +39,13 @@ use libtestbed; ...@@ -39,11 +39,13 @@ use libtestbed;
# We don't want to run this script unless its the real version. # We don't want to run this script unless its the real version.
# #
if ($EUID != 0) { if ($EUID != 0) {
die("Must be root! Maybe its a development version?\n"); die("*** $0:\n".
" Must be root! Maybe its a development version?\n");
} }
# XXX Hacky! # XXX Hacky!
if ($TB ne "/usr/testbed") { if ($TB ne "/usr/testbed") {
die("Wrong version. Maybe its a development version?\n"); die("*** $0:\n".
" Wrong version. Maybe its a development version?\n");
} }
# #
...@@ -76,7 +78,8 @@ foreach my $active ( 0, 1 ) { ...@@ -76,7 +78,8 @@ foreach my $active ( 0, 1 ) {
# All active users on the testbed # All active users on the testbed
if (! ($query_result = if (! ($query_result =
DBQuery("SELECT DISTINCT u.usr_email from experiments as e ". DBQuery("SELECT DISTINCT u.usr_email from experiments as e ".
"left join proj_memb as p on e.pid=p.pid ". "left join group_membership as p ".
" on e.pid=p.pid and p.pid=p.gid ".
"left join users as u on u.uid=p.uid ". "left join users as u on u.uid=p.uid ".
"where u.status='active' order by u.usr_email"))) { "where u.status='active' order by u.usr_email"))) {
DBFatal("Getting Active Users!"); DBFatal("Getting Active Users!");
......
This diff is collapsed.
...@@ -41,17 +41,20 @@ my @nodes= (); ...@@ -41,17 +41,20 @@ my @nodes= ();
if ($debug) { print "Expt '$eid', proj '$pid'\n"; } if ($debug) { print "Expt '$eid', proj '$pid'\n"; }
# #
# Make sure the user is a member of the correct project, and that the # Experiment must exist.
# experiment exists #
if (!ExpState($pid,$eid)) {
die "There is no experiment $eid in project $pid\n";
}
#
# User must have permission to modify the experiment.
# #
if ($UID) { if ($UID) {
if (!ProjMember($pid)) { if (!TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_MODIFY)) {
die "You are not a member of project $pid\n"; die("*** You not have permission to allocate nodes in $pid/$eid!\n");
} }
} }
if (!ExpState($pid,$eid)) {
die "There is no experiment $eid in project $pid\n";
}
###################################################################### ######################################################################
# Step 1 - Make a list of nodes to reserve # Step 1 - Make a list of nodes to reserve
......
...@@ -261,7 +261,7 @@ int main(int argc, char *argv[]) ...@@ -261,7 +261,7 @@ int main(int argc, char *argv[])
{ {
int userdir = 0; /* ~userdir flag */ int userdir = 0; /* ~userdir flag */
uid_t uid; /* user information */ uid_t uid; /* user information */
gid_t gid; /* target group placeholder */ gid_t gid, primary_gid; /* target group placeholder */
char *target_uname; /* target user name */ char *target_uname; /* target user name */
char *target_gname; /* target group name */ char *target_gname; /* target group name */
char *target_homedir; /* target home directory */ char *target_homedir; /* target home directory */
...@@ -411,6 +411,7 @@ int main(int argc, char *argv[]) ...@@ -411,6 +411,7 @@ int main(int argc, char *argv[])
* Save these for later since initgroups will hose the struct * Save these for later since initgroups will hose the struct
*/ */
uid = pw->pw_uid; uid = pw->pw_uid;
primary_gid = pw->pw_gid;
actual_uname = strdup(pw->pw_name); actual_uname = strdup(pw->pw_name);
target_homedir = strdup(pw->pw_dir); target_homedir = strdup(pw->pw_dir);
...@@ -441,6 +442,30 @@ int main(int argc, char *argv[]) ...@@ -441,6 +442,30 @@ int main(int argc, char *argv[])
exit(108); exit(108);
} }
#ifdef TESTBED
{
int groups[NGROUPS], ngroups, i;
ngroups = NGROUPS;
getgrouplist(actual_uname, primary_gid, groups, &ngroups);
if (ngroups == NGROUPS) {
log_err("emerg: failed to getgroups (%ld: %s)\n", gid, cmd);
exit(109);
}
for (i = 0; i < ngroups; i++) {
if (groups[i] == gid)
break;
}
if (i == ngroups)
groups[ngroups++] = gid;
if (((setgid(primary_gid)) != 0) ||
(setgroups(ngroups, groups) != 0)) {
log_err("emerg: failed to setgid (%ld: %s)\n", gid, cmd);
exit(109);
}
}
#else
/* /*
* Change UID/GID here so that the following tests work over NFS. * Change UID/GID here so that the following tests work over NFS.
* *
...@@ -451,6 +476,7 @@ int main(int argc, char *argv[]) ...@@ -451,6 +476,7 @@ int main(int argc, char *argv[])
log_err("emerg: failed to setgid (%ld: %s)\n", gid, cmd); log_err("emerg: failed to setgid (%ld: %s)\n", gid, cmd);
exit(109); exit(109);
} }
#endif
/* /*
* setuid() to the target user. Error out on fail. * setuid() to the target user. Error out on fail.
......
...@@ -19,12 +19,14 @@ USERBINS = os_load node_reboot nscheck node_update savelogs ...@@ -19,12 +19,14 @@ USERBINS = os_load node_reboot nscheck node_update savelogs
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \ SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \ batch_daemon exports_setup reload_daemon sched_reserve \
console_reset db2ns bwconfig frisbeelauncher console_reset db2ns bwconfig frisbeelauncher group-update \
rmgroup
LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \ LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \
os_setup mkexpdir console_setup webnscheck webreport \ os_setup mkexpdir console_setup webnscheck webreport \
webstartexp webendexp webbatchexp webkillbatchexp \ webstartexp webendexp webbatchexp webkillbatchexp \
assign_wrapper ptopgen webnodeupdate assign_wrapper ptopgen webnodeupdate webgroupupdate \
webrmgroup
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \ LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm
...@@ -68,6 +70,8 @@ post-install: ...@@ -68,6 +70,8 @@ post-install:
chmod u+s $(INSTALL_LIBEXECDIR)/mkprojdir chmod u+s $(INSTALL_LIBEXECDIR)/mkprojdir
chown root $(INSTALL_LIBEXECDIR)/rmproj chown root $(INSTALL_LIBEXECDIR)/rmproj
chmod u+s $(INSTALL_LIBEXECDIR)/rmproj chmod u+s $(INSTALL_LIBEXECDIR)/rmproj
chown root $(INSTALL_SBINDIR)/rmgroup
chmod u+s $(INSTALL_SBINDIR)/rmgroup
chown root $(INSTALL_LIBEXECDIR)/mkacct-ctrl chown root $(INSTALL_LIBEXECDIR)/mkacct-ctrl
chmod u+s $(INSTALL_LIBEXECDIR)/mkacct-ctrl chmod u+s $(INSTALL_LIBEXECDIR)/mkacct-ctrl
chown root $(INSTALL_LIBEXECDIR)/rmacct-ctrl chown root $(INSTALL_LIBEXECDIR)/rmacct-ctrl
...@@ -78,6 +82,8 @@ post-install: ...@@ -78,6 +82,8 @@ post-install:
chmod u+s $(INSTALL_SBINDIR)/exports_setup chmod u+s $(INSTALL_SBINDIR)/exports_setup
chown root $(INSTALL_BINDIR)/savevlans chown root $(INSTALL_BINDIR)/savevlans
chmod u+s $(INSTALL_BINDIR)/savevlans chmod u+s $(INSTALL_BINDIR)/savevlans
chown root $(INSTALL_SBINDIR)/group-update
chmod u+s $(INSTALL_SBINDIR)/group-update
chown root $(INSTALL_LIBEXECDIR)/console_setup chown root $(INSTALL_LIBEXECDIR)/console_setup
chmod u+s $(INSTALL_LIBEXECDIR)/console_setup chmod u+s $(INSTALL_LIBEXECDIR)/console_setup
chown root $(INSTALL_BINDIR)/node_reboot chown root $(INSTALL_BINDIR)/node_reboot
......
...@@ -54,6 +54,7 @@ my $dirname; ...@@ -54,6 +54,7 @@ my $dirname;
# #
my $eid; my $eid;
my $pid; my $pid;
my $gid;
my $logname; my $logname;
my $nsfile; my $nsfile;
my $user_name = "Testbed Operations"; my $user_name = "Testbed Operations";
...@@ -209,11 +210,12 @@ sub dosomething($$) ...@@ -209,11 +210,12 @@ sub dosomething($$)
{ {
my($dowhat) = shift; my($dowhat) = shift;
my(%exphash) = @_; my(%exphash) = @_;
my($uid, $gid, $row, $query_result); my($unix_uid, $unix_gid, $row, $query_result);
# Global vars # Global vars
$eid = $exphash{'eid'}; $eid = $exphash{'eid'};
$pid = $exphash{'pid'}; $pid = $exphash{'pid'};
$gid = $exphash{'gid'};
print "Doing a '$dowhat' to batch experiment $pid/$eid\n"; print "Doing a '$dowhat' to batch experiment $pid/$eid\n";
...@@ -277,19 +279,19 @@ sub dosomething($$) ...@@ -277,19 +279,19 @@ sub dosomething($$)
# Figure out the unix uid/gid that the experiment configuration is # Figure out the unix uid/gid that the experiment configuration is
# going to run as. # going to run as.
# #
(undef,undef,$uid) = getpwnam($creator) or (undef,undef,$unix_uid) = getpwnam($creator) or
fatal("No such user $creator"); fatal("No such user $creator");
(undef,undef,$gid) = getgrnam($pid) or (undef,undef,$unix_gid) = getgrnam($gid) or
fatal("No such group $pid"); fatal("No such group $gid");
# #
# Change the ownership of the log file before we flip. # Change the ownership of the log file before we flip.
# #
chown($uid, $gid, $logname); chown($unix_uid, $unix_gid, $logname);
# Flip to the user. We never flip back. # Flip to the user. We never flip back.
$EGID = $GID = $gid; $EGID = $GID = $unix_gid;
$EUID = $UID = $uid; $EUID = $UID = $unix_uid;
$ENV{'USER'} = $creator; $ENV{'USER'} = $creator;
if ($dowhat eq "start") { if ($dowhat eq "start") {
...@@ -323,15 +325,16 @@ sub startexp($) ...@@ -323,15 +325,16 @@ sub startexp($)
# #
$query_result = $query_result =
DBQueryFatal("insert into experiments ". DBQueryFatal("insert into experiments ".
"(eid, pid, expt_created, expt_name, ". "(eid, pid, gid, expt_created, expt_name, ".
"expt_head_uid, expt_expires, state, batchmode) ". "expt_head_uid, expt_expires, state, batchmode) ".
"VALUES ('$eid', '$pid', '$rightnow', '$longname', ". "VALUES ('$eid', '$pid', '$gid', '$rightnow', ".
"'$creator', '$expires', 'new', 1)"); " '$longname', ".
" '$creator', '$expires', 'new', 1)");
# #
# Try to start the experiment. If it fails, the experiment is gone. # Try to start the experiment. If it fails, the experiment is gone.
# #
system("$startexp -b $logname $pid $eid $nsfile"); system("$startexp -b $logname -g $gid $pid $eid $nsfile");
$exit_status = $? >> 8; $exit_status = $? >> 8;
$running = 1; $running = 1;
if ($exit_status) { if ($exit_status) {
......
...@@ -5,8 +5,6 @@ use Getopt::Std; ...@@ -5,8 +5,6 @@ use Getopt::Std;
# #
# Create a batch experiment. # Create a batch experiment.
# #
# usage: batchexp <batchfile>
#
sub usage() sub usage()
{ {
print STDOUT "Usage: batchexp <batchfile>\n"; print STDOUT "Usage: batchexp <batchfile>\n";
...@@ -29,7 +27,7 @@ use libtestbed; ...@@ -29,7 +27,7 @@ use libtestbed;
my $tbbindir = "$TB/bin/"; my $tbbindir = "$TB/bin/";
my $batchdir = "$TB/batch"; my $batchdir = "$TB/batch";
my $parser = "/usr/testbed/libexec/ns2ir/parse.tcl"; my $parser = "$TB/libexec/ns2ir/parse.tcl";
my $projroot = "/proj"; my $projroot = "/proj";
my $dirname; my $dirname;
...@@ -74,19 +72,21 @@ else { ...@@ -74,19 +72,21 @@ else {
# #
my $eid; my $eid;
my $pid; my $pid;
my $gid;
my $dbuid;
my $longname; my $longname;
my $expires; my $expires;
my $webnsfile; my $webnsfile;
parse_batchfile($tempfile) or parse_batchfile($tempfile) or
fatal("Could not parse batchfile $tempfile"); fatal("*** Could not parse batchfile $tempfile");
# #
# Sanity check a few things. # Sanity check a few things.
# #
if (!defined($eid) || !defined($pid) || !defined($longname) || if (!defined($eid) || !defined($pid) || !defined($longname) ||
!defined($expires) || !defined($webnsfile)) { !defined($expires) || !defined($webnsfile)) {
fatal("Batchfile is incomplete!"); fatal("*** Batchfile is incomplete!");
} }
$nsfile = "$eid.ns"; $nsfile = "$eid.ns";
...@@ -96,50 +96,33 @@ $nsfile = "$eid.ns"; ...@@ -96,50 +96,33 @@ $nsfile = "$eid.ns";
$dirname = "$batchdir/$pid-$eid"; $dirname = "$batchdir/$pid-$eid";
mkdir($dirname, 0775) or mkdir($dirname, 0775) or
fatal("Could not mkdir $dirname: $!"); fatal("*** Could not mkdir $dirname: $!");
chdir($dirname) or chdir($dirname) or
fatal("Could not chdir to $dirname: $!"); fatal("*** Could not chdir to $dirname: $!");
# #
# Copy in the batch file. Web script is responsible for removing the # Copy in the batch file. Web script is responsible for removing the
# original. # original.
# #
if (system("/bin/cp", "$tempfile", "batchfile")) { if (system("/bin/cp", "$tempfile", "batchfile")) {
fatal("Could not copy $tempfile to $dirname"); fatal("*** Could not copy $tempfile to $dirname");
} }
# #
# Now a bunch of DB checks. # Verify user and get his DB uid.
#
# First off, get some user information.
# #
$query_result = if (! UNIX2DBUID($UID, \$dbuid)) {
DBQuery("SELECT uid from users WHERE unix_uid='$EUID'"); fatal("*** You do not exist in the Emulab Database!");
if ($query_result->numrows < 1) {
fatal("Go Away! You do not exist in the Emulab Database.");
} }
@row = $query_result->fetchrow_array();
$uid = $row[0];
# #
# Make sure UID is allowed to create experiments in this project. # Make sure UID is allowed to create experiments in this project.
# #
$query_result = if (!TBAdmin($UID) &&
DBQuery("SELECT trust from proj_memb WHERE uid='$uid' and pid='$pid'"); !TBProjAccessCheck($dbuid, $pid, $gid, TB_PROJECT_CREATEEXPT)) {
fatal("*** You do not have permission to create experiments ".
if ($query_result->numrows == 0) { "in project $pid";
fatal("Go Away! You are not a member of project $pid!");
}
@row = $query_result->fetchrow_array();
$trust = $row[0];
if ($trust ne "local_root" &&
$trust ne "group_root") {
fatal("Go Away! You are not a trusted member of project $pid!");
} }
# #
...@@ -150,7 +133,7 @@ $query_result = ...@@ -150,7 +133,7 @@ $query_result =
"WHERE eid='$eid' and pid='$pid'"); "WHERE eid='$eid' and pid='$pid'");
if ($query_result->numrows) { if ($query_result->numrows) {
fatal("Experiment $eid in project $pid already exists!"); fatal("*** Experiment $eid in project $pid already exists!");
} }
$query_result = $query_result =
...@@ -158,21 +141,21 @@ $query_result = ...@@ -158,21 +141,21 @@ $query_result =
"WHERE eid='$eid' and pid='$pid'"); "WHERE eid='$eid' and pid='$pid'");
if ($query_result->numrows) { if ($query_result->numrows) {
fatal("Batch experiment $eid in project $pid already exists!"); fatal("*** Batch experiment $eid in project $pid already exists!");
} }
# #
# Now we can get the NS file! # Now we can get the NS file!
# #
if (system("/bin/cp", "$webnsfile", "$nsfile")) { if (system("/bin/cp", "$webnsfile", "$nsfile")) {
fatal("Could not copy $webnsfile to $dirname/$nsfile"); fatal("*** Could not copy $webnsfile to $dirname/$nsfile");
} }
# Run parse in impotent mode on the NS file. This has no effect but # Run parse in impotent mode on the NS file. This has no effect but
# will display any errors. # will display any errors.
if (system("$parser -n -a $nsfile") != 0) { if (system("$parser -n -a $nsfile") != 0) {
fatal("NS Parse failed!"); fatal("*** NS Parse failed!");
} }
# #
...@@ -185,10 +168,10 @@ $created = DBDateTime(); ...@@ -185,10 +168,10 @@ $created = DBDateTime();
# is looking for batch experiments to run. Easy race avoidance. # is looking for batch experiments to run. Easy race avoidance.
# #
DBQueryFatal("INSERT INTO batch_experiments ". DBQueryFatal("INSERT INTO batch_experiments ".
"(eid, pid, created, expires, ". "(eid, pid, gid, created, expires, ".
" name, creator_uid, status) ". " name, creator_uid, status) ".
"VALUES ('$eid', '$pid', '$created', '$expires', ". "VALUES ('$eid', '$pid', '$gid', '$created', '$expires', ".
"'$longname', '$uid', 'new')"); "'$longname', '$dbuid', 'new')");
exit 0; exit 0;
...@@ -224,6 +207,10 @@ sub parse_batchfile() ...@@ -224,6 +207,10 @@ sub parse_batchfile()
$pid = $1; $pid = $1;
next; next;
} }
if ($_ =~ /^GID:\s+([-\@\w.]*)/) {
$gid = $1;
next;
}
if ($_ =~ /^name:\s+([-\@\w. ]*)/) { if ($_ =~ /^name:\s+([-\@\w. ]*)/) {
$longname = $1; $longname = $1;
next; next;
......
...@@ -50,7 +50,8 @@ my @nodes = @ARGV; ...@@ -50,7 +50,8 @@ my @nodes = @ARGV;
# nodes are specified since this script always does the right thing. # nodes are specified since this script always does the right thing.
# #
if ($EUID != 0) { if ($EUID != 0) {
die("Must be root! Maybe its a development version?\n"); die("*** $0:\n".
" Must be root! Maybe its a development version?\n");
} }
# #
...@@ -83,7 +84,12 @@ foreach my $node (@nodes) { ...@@ -83,7 +84,12 @@ foreach my $node (@nodes) {
} }
else { else {
$db_result = $db_result =
DBQueryFatal("select pid from reserved where node_id='$node'"); DBQueryFatal("select g.unix_name from groups as g ".
"left join experiments as e ".
" on g.pid=e.pid and g.gid=e.gid ".
"left join reserved as r ".
" on e.pid=r.pid and e.eid=r.eid ".
"where r.node_id='$node'");
} }
if ($db_result->numrows > 0) { if ($db_result->numrows > 0) {
@row = $db_result->fetchrow_array(); @row = $db_result->fetchrow_array();
......
#!/usr/bin/perl -w #!/usr/bin/perl -w
use English;
# This is a very simple program that convers the virt_* tables in the DB # This is a very simple program that convers the virt_* tables in the DB
# into a NS file. Not the original NS file, but a NS file that, if parsed # into a NS file. Not the original NS file, but a NS file that, if parsed
...@@ -16,17 +17,18 @@ if ($#ARGV != 1) { ...@@ -16,17 +17,18 @@ if ($#ARGV != 1) {
($pid,$eid) = @ARGV; ($pid,$eid) = @ARGV;
# #
# Make sure they have access to the experiment # Make sure the experiment exists
# #
if ((!TBAdmin()) && (!ProjMember($pid))) { if (!ExpState($pid,$eid)) {
die "You are not a member of project %pid"; die "There is no experiment $eid in project $pid\n";
} }
# #
# Make sure the experiment exists # Make sure they have access to the experiment
# #
if (!ExpState($pid,$eid)) { if (!TBAdmin($UID) &&
die "There is no experiment $eid in project $pid\n"; !TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_READINFO)) {
die("*** You do not have permission to access this experiment!\n");
} }
print "source tb_compat.tcl\n"; print "source tb_compat.tcl\n";
......
...@@ -106,15 +106,12 @@ if (! UserDBInfo($user_login, \$user_name, \$user_email)) { ...@@ -106,15 +106,12 @@ if (! UserDBInfo($user_login, \$user_name, \$user_email)) {
} }
# #
# Verify that this person is allowed to end the experiment. Must be # Verify that this person is allowed to end the experiment.
# in the project membership table, or must be an admin type. Note that # Note that any script down the line has to do an admin check also.
# any script down the line has to do an admin check also.
# #
if ($EUID && !TBAdmin($EUID) && if ($EUID && !TBAdmin($EUID) &&
ProjMember($pid, $user_login) != PROJMEMBERTRUST_ROOT) { !TBExptAccessCheck($user_login, $pid, $eid, TB_EXPT_DESTROY)) {
print STDOUT "You do not have permission to end this experiment!\n";
print STDOUT "Go Away! You do not have permission to end experiments ".
"in project $pid\n";
exit(1); exit(1);
} }
...@@ -314,6 +311,12 @@ sub fatal($) ...@@ -314,6 +311,12 @@ sub fatal($)
print STDOUT $mesg; print STDOUT $mesg;
#
# Kill this for convenience later.
#
DBQueryWarn("update experiments set expt_terminating=NULL ".
"WHERE eid='$eid' and pid='$pid'");
# #
# In batch mode, exit without sending the email. # In batch mode, exit without sending the email.
#