#!/usr/bin/perl -w use English; require Mysql; # # A library of useful DB stuff. Mostly things that get done a lot. # Saves typing. # # # Configure variables # my $TB = "@prefix@"; my $DBNAME = "@TBDBNAME@"; my $TBOPS = "@TBOPSEMAIL@"; # # Set up for querying the database. # my $DB = Mysql->connect("localhost", $DBNAME, "script", "none"); # # Record last DB error string. # my $DBErrorString = ""; # # Test admin status. Optional argument is the UID to test. If not provided, # then test the current UID. # # usage: TBAdmin([int uid]); # returns 1 if an admin type. # returns 0 if a mere user. # sub TBAdmin(;$) { my($uid) = @_; if (!defined($uid)) { $uid = $UID; } my ($name) = getpwuid($uid) or die "$uid not in passwd file\n"; my $query_result = DBquery("select admin from users where uid='$name'"); my @row = $query_result->fetchrow_array(); if ($row[0] == 1) { return 1; } return 0; } # # Check access permission to a list of nodes. First argument is a *reference* to # a single node, or a list of nodes. Second argument is optional uid, defaults # to the current uid. # # usage: NodeAccessCheck(array or scalar \@nodelist, [int uid]) # returns 1 if the uid is allowed to muck with all the nodes. # returns 0 if the uid is not allowed to muck with at least one of the nodes. # sub NodeAccessCheck($;$) { my($list, $uid) = @_; my(@nodelist); if (!defined($uid)) { $uid = $UID; } if (ref($list) eq "ARRAY") { @nodelist = @$list; } elsif (ref($list) eq "SCALAR") { @nodelist = ($$list); } if (!defined(@nodelist) || scalar(@nodelist) == 0) { die("NodeAccessCheck:\n". " First parameter should be a reference to a node (scalar), ". "or a list of nodes!\n"); } # # Admin types can do anything to any node. So can Root. # if ($uid == 0 || TBAdmin($uid)) { return 1; } my ($name) = getpwuid($uid) or die "$uid not in passwd file\n"; # # Check to make sure that mere user is allowed to muck with nodes. # foreach my $node (@$nodelist) { my $query_result = DBquery("select reserved.node_id from reserved ". "left join proj_memb on ". "reserved.pid=proj_memb.pid and reserved.node_id='$node' ". "where proj_memb.uid='$name'"); if ($query_result == 0 || $query_result->numrows == 0) { return 0; } } return 1; } # # Check project membership. First argument is the project to check. # Second argument is optional uid, defaults to the current uid. # # usage: ProjMember(char *pid, [int uid]) # returns 1 if the uid is a member of pid. # returns 0 if the uid is not a member of pid. # sub ProjMember($;$) { my($pid, $uid) = @_; if (!defined($uid)) { $uid = $UID; } my ($name) = getpwuid($uid) or die "$uid not in passwd file\n"; my $query_result = DBquery("select * from proj_memb where uid='$name' and pid='$pid'"); if ($query_result == 0 || $query_result->numrows == 0) { return 0; } return 1; } # # Issue a DB query. Argument is a string. Returns the actual query object, so # it is up to the caller to test it. I would not for one moment view this # as encapsulation of the DB interface. I'm just tired of typing the same # silly stuff over and over. # # usage: DBQuery(char *str) # returns the query object result. # # Sets $DBErrorString is case of error; saving the original query string and # the error string from the DB module. Use DBFatal (below) to print/email # that string, and then exit. # sub DBQuery($) { my($query) = $_[0]; my($result); $result = $DB->query($query); if (! $result) { $DBErrorString = " Query: $query\n". " Error: " . $DB->errstr . "\n"; } return $result; } # # Same as above, but die on error. # sub DBQueryFatal($) { my($query) = $_[0]; my($result); $result = DBQuery($query); if (! $result) { DBFatal("DB Query failed"); } return $result; } # # Die and send email after a failed DB query. First argument is the error # message to display. The contents of $DBErrorString is also printed. # # usage: DBFatal(char *message) # sub DBFatal($) { my($message) = $_[0]; my($text, $progname); # # Must taint check $PROGRAM_NAME cause it comes from outside. # if ($PROGRAM_NAME =~ /^([-\w.\/]+)$/) { $progname = $1; } else { $progname = "Tainted"; } $text = "In TB script: $progname\n\n $message\n" . "$DBErrorString"; print STDERR "$text\n"; system("echo \"$text\" | /usr/bin/mail ". "-s 'TESTBED: DBFatal - $message' \"$TBOPS\""); exit(-1); } 1;