diff --git a/backend/GNUmakefile.in b/backend/GNUmakefile.in
index 0920c92f4fe38a2eecda3fb55e05dda27bc3d425..e5c818c4d1a3e5a624f78671db89385b8466f599 100644
--- a/backend/GNUmakefile.in
+++ b/backend/GNUmakefile.in
@@ -13,9 +13,9 @@ UNIFIED         = @UNIFIED_BOSS_AND_OPS@
 include $(OBJDIR)/Makeconf
 
 BIN_SCRIPTS	= moduserinfo newgroup newmmlist editexp editimageid \
-		  editnodetype
+		  editnodetype editsitevars
 WEB_BIN_SCRIPTS = webmoduserinfo webnewgroup webnewmmlist webeditimageid \
-		  webeditnodetype
+		  webeditnodetype webeditsitevars
 WEB_SBIN_SCRIPTS= 
 LIBEXEC_SCRIPTS	= $(WEB_BIN_SCRIPTS) $(WEB_SBIN_SCRIPTS)
 
diff --git a/backend/editsitevars.in b/backend/editsitevars.in
new file mode 100644
index 0000000000000000000000000000000000000000..c69d4172881e2f413dc78f2269f610364cae0909
--- /dev/null
+++ b/backend/editsitevars.in
@@ -0,0 +1,282 @@
+#!/usr/bin/perl -wT
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2000-2007 University of Utah and the Flux Group.
+# All rights reserved.
+#
+use English;
+use strict;
+use Getopt::Std;
+use XML::Simple;
+use Data::Dumper;
+
+#
+# Back-end script to edit site variables.
+#
+sub usage()
+{
+    print("Usage: editsitevars [-v] <xmlfile>\n");
+    exit(-1);
+}
+my $optlist = "dv";
+my $debug   = 0;
+my $verify  = 0;	# Check data and return status only. 
+
+#
+# Configure variables
+#
+my $TB		= "@prefix@";
+my $TBOPS       = "@TBOPSEMAIL@";
+my $TBAUDIT	= "@TBAUDITEMAIL@";
+
+#
+# Untaint the path
+#
+$ENV{'PATH'} = "$TB/bin:$TB/sbin:/bin:/usr/bin:/usr/bin:/usr/sbin";
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+
+#
+# Turn off line buffering on output
+#
+$| = 1;
+
+#
+# Load the Testbed support stuff.
+#
+use lib "@prefix@/lib";
+use libdb;
+use libtestbed;
+use User;
+use Project;
+
+# Protos
+sub fatal($);
+sub UserError(;$);
+sub escapeshellarg($);
+
+#
+# Parse command arguments. Once we return from getopts, all that should be
+# left are the required arguments.
+#
+my %options = ();
+if (! getopts($optlist, \%options)) {
+    usage();
+}
+if (defined($options{"d"})) {
+    $debug = 1;
+}
+if (defined($options{"v"})) {
+    $verify = 1;
+}
+if (@ARGV != 1) {
+    usage();
+}
+my $xmlfile  = shift(@ARGV);
+
+#
+# Map invoking user to object. 
+# If invoked as "nobody" we are coming from the web interface and the
+# current user context is "implied" (see tbauth.php3).
+#
+my $this_user;
+
+if (getpwuid($UID) ne "nobody") {
+    $this_user = User->ThisUser();
+
+    if (! defined($this_user)) {
+	fatal("You ($UID) do not exist!");
+    }
+    fatal("You must have admin privledges to edit site variables.")
+	if (!$this_user->IsAdmin());
+}
+else {
+    #
+    # Check the filename when invoked from the web interface; must be a
+    # file in /tmp.
+    #
+    if ($xmlfile =~ /^([-\w\.\/]+)$/) {
+	$xmlfile = $1;
+    }
+    else {
+	fatal("Bad data in pathname: $xmlfile");
+    }
+
+    # Use realpath to resolve any symlinks.
+    my $translated = `realpath $xmlfile`;
+    if ($translated =~ /^(\/tmp\/[-\w\.\/]+)$/) {
+	$xmlfile = $1;
+    }
+    else {
+	fatal("Bad data in translated pathname: $xmlfile");
+    }
+
+    # The web interface (and in the future the xmlrpc interface) sets this.
+    $this_user = User->ImpliedUser();
+
+    if (! defined($this_user)) {
+	fatal("Cannot determine implied user!");
+    }
+}
+
+#
+# These are the fields that we allow to come in from the XMLfile.
+#
+my $SLOT_OPTIONAL	= 0x1;	# The field is not required.
+my $SLOT_REQUIRED	= 0x2;  # The field is required and must be non-null.
+my $SLOT_ADMINONLY	= 0x4;  # Only admins can set this field.
+#
+# XXX We should encode all of this in the DB so that we can generate the
+# forms on the fly, as well as this checking code.
+#
+my %xmlfields =
+    # XML Field Name        DB slot name         Flags             Default
+    ("name"		=> ["name",		$SLOT_REQUIRED],
+     "value"		=> ["value",		$SLOT_OPTIONAL],
+     "reset"		=> ["reset",		$SLOT_OPTIONAL]);
+
+#
+# Must wrap the parser in eval since it exits on error.
+#
+my $xmlparse = eval { XMLin($xmlfile,
+			    VarAttr => 'name',
+			    ContentKey => '-content',
+			    SuppressEmpty => undef); };
+fatal($@)
+    if ($@);
+
+#
+# Process and dump the errors (formatted for the web interface).
+# We should probably XML format the errors instead but not sure I want
+# to go there yet.
+#
+my %errors = ();
+
+#
+# Make sure all the required arguments were provided.
+#
+my $key;
+foreach $key (keys(%xmlfields)) {
+    my (undef, $required, undef) = @{$xmlfields{$key}};
+
+    $errors{$key} = "Required value not provided"
+	if ($required & $SLOT_REQUIRED  &&
+	    ! exists($xmlparse->{'attribute'}->{"$key"}));
+}
+UserError()
+    if (keys(%errors));
+
+#
+# We build up an array of arguments to reference as we check
+# the attributes.
+#
+my %editsitevars_args = ();
+
+foreach $key (keys(%{ $xmlparse->{'attribute'} })) {
+    my $value = $xmlparse->{'attribute'}->{"$key"}->{'value'};
+
+    if ($debug) {
+	print STDERR "User attribute: '$key' -> '$value'\n";
+    }
+
+    $errors{$key} = "Unknown attribute"
+	if (!exists($xmlfields{$key}));
+
+    my ($dbslot, $required, $default) = @{$xmlfields{$key}};
+
+    if ($required & $SLOT_REQUIRED) {
+	# A slot that must be provided, so do not allow a null value.
+	if (!defined($value)) {
+	    $errors{$key} = "Must provide a non-null value";
+	    next;
+	}
+    }
+    if ($required & $SLOT_OPTIONAL) {
+	# Optional slot. If value is null skip it. Might not be the correct
+	# thing to do all the time?
+	if (!defined($value)) {
+	    next
+		if (!defined($default));
+	    $value = $default;
+	}
+    }
+    if ($required & $SLOT_ADMINONLY) {
+	# Admin implies optional, but thats probably not correct approach.
+	$errors{$key} = "Administrators only"
+	    if (! $this_user->IsAdmin());
+    }
+	
+    # Now check that the value is legal.
+    if (! TBcheck_dbslot($value, "sitevariables", 
+			 $dbslot, TBDB_CHECKDBSLOT_ERROR)) {
+	$errors{$key} = TBFieldErrorString();
+	next;
+    }
+
+    $editsitevars_args{$dbslot} = $value;
+}
+UserError()
+    if (keys(%errors));
+
+#
+# Now do special checks.
+#
+
+if (!exists($editsitevars_args{"value"}) && 
+    !exists($editsitevars_args{"reset"})) {
+    UserError("Site Var: Must give a new value, or reset it to default.");
+}
+if (exists($editsitevars_args{"value"}) && 
+    exists($editsitevars_args{"reset"})) {
+    UserError("Site Var: Can't both give a new value, and reset to default.");
+}
+
+exit(0)
+    if ($verify);
+
+#
+# Now safe to set the site variable value.
+#
+my $name = $editsitevars_args{"name"};
+my $value = exists($editsitevars_args{"reset"}) ? "NULL" :
+    "'" . escapeshellarg($editsitevars_args{"value"}) . "'";
+
+DBQueryFatal("UPDATE sitevariables ".
+	     "SET value=$value ".
+	     "WHERE name='$name'");
+exit(0);
+
+
+sub fatal($)
+{
+    my ($mesg) = @_;
+
+    print STDERR "*** $0:\n".
+	         "    $mesg\n";
+    # Exit with negative status so web interface treats it as system error.
+    exit(-1);
+}
+
+sub UserError(;$)
+{
+    my ($mesg) = @_;
+
+    if (keys(%errors)) {
+	foreach my $key (keys(%errors)) {
+	    my $val = $errors{$key};
+	    print "${key}: $val\n";
+	}
+    }
+    print "$mesg\n"
+	if (defined($mesg));
+
+    # Exit with positive status so web interface treats it as user error.
+    exit(1);
+}
+
+sub escapeshellarg($)
+{
+    my ($str) = @_;
+
+    $str =~ s/[^[:alnum:]]/\\$&/g;
+    return $str;
+}
diff --git a/configure b/configure
index 725c8ead1e0cd4d4b92a30ddc561c62e6c5c4946..3c33e5433dfafb67674339a84aa8cb45952ce521 100755
--- a/configure
+++ b/configure
@@ -2429,6 +2429,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
 	account/quotamail account/mkusercert account/newproj account/newuser \
 	backend/GNUmakefile backend/moduserinfo backend/newgroup \
 	backend/newmmlist backend/editexp backend/editimageid backend/editnodetype \
+	backend/editsitevars \
 	tbsetup/GNUmakefile tbsetup/console_setup tbsetup/spewlogfile \
 	tbsetup/spewrpmtar tbsetup/gentopofile tbsetup/power_sgmote.pm \
 	tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
diff --git a/configure.in b/configure.in
index 78230730aa97bdefa0049cea66df719341ea48cc..a2f954815fb07b639b9dc0cca86a98a99e0ae50d 100755
--- a/configure.in
+++ b/configure.in
@@ -809,6 +809,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
 	account/quotamail account/mkusercert account/newproj account/newuser \
 	backend/GNUmakefile backend/moduserinfo backend/newgroup \
 	backend/newmmlist backend/editexp backend/editimageid backend/editnodetype \
+	backend/editsitevars \
 	tbsetup/GNUmakefile tbsetup/console_setup tbsetup/spewlogfile \
 	tbsetup/spewrpmtar tbsetup/gentopofile tbsetup/power_sgmote.pm \
 	tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
diff --git a/sql/database-fill.sql b/sql/database-fill.sql
index da646eceb2604051006aff8d3588bd16a37fa569..63f8f8029285c5315d4bb3833b0ce6dbf77dc0fb 100644
--- a/sql/database-fill.sql
+++ b/sql/database-fill.sql
@@ -897,6 +897,12 @@ REPLACE INTO table_regex VALUES ('os_info','op_mode','text','regex','^[-\\w]*$',
 REPLACE INTO table_regex VALUES ('os_info','nextosid','text','redirect','os_info:osid',0,0,NULL);
 REPLACE INTO table_regex VALUES ('os_info','reboot_waittime','int','redirect','default:int',0,2000,NULL);
 
+REPLACE INTO table_regex VALUES ('sitevariables','name','text','regex','^[\\w\\/]+$',1,255,NULL);
+REPLACE INTO table_regex VALUES ('sitevariables','value','text','redirect','default:text',0,0,NULL);
+REPLACE INTO table_regex VALUES ('sitevariables','reset','text','redirect','default:boolean',0,0,NULL);
+REPLACE INTO table_regex VALUES ('sitevariables','defaultvalue','text','redirect','default:text',0,0,NULL);
+REPLACE INTO table_regex VALUES ('sitevariables','description','text','redirect','default:text',0,0,NULL);
+
 --
 -- Dumping data for table `testsuite_preentables`
 --
diff --git a/www/editsitevars.php3 b/www/editsitevars.php3
index cd682bcf9eaa11f648495058429afe960c02a73a..3749b0946c516d07ac758dc18ee967d7da6a505d 100644
--- a/www/editsitevars.php3
+++ b/www/editsitevars.php3
@@ -23,20 +23,108 @@ if (! $isadmin) {
 }
 
 #
-# Verify Page agruments.
+# Verify page arguments.
 #
-$optargs = OptionalPageArguments("edit",       PAGEARG_STRING,
-				 "name",       PAGEARG_STRING,
-				 "value",      PAGEARG_ANYTHING,
+$optargs = OptionalPageArguments(# Edit greenballs pull up an Edit subform.
+				 "edit",       PAGEARG_STRING,
+				 "formfields", PAGEARG_ARRAY,
+				 # Edit has three submit buttons.
 				 "defaulted",  PAGEARG_STRING,
 				 "edited",     PAGEARG_STRING,
 				 "canceled",   PAGEARG_STRING);
 
-if (isset($edit)) {
+function SPIT_MSGS($message, $errors)
+{
+    if ($message !== "") {
+	echo "<H3>$message</H3>\n";
+    }
+
+    if ($errors) {
+	echo "<table class=nogrid
+                     align=center border=0 cellpadding=6 cellspacing=0>
+              <tr>
+                 <th align=center colspan=2>
+                   <font size=+1 color=red>
+                      &nbsp;Oops, please fix the following errors!&nbsp;
+                   </font>
+                 </td>
+              </tr>\n";
+
+	while (list ($name, $text) = each ($errors)) {
+	    echo "<tr>
+                     <td align=right>
+                       <font color=red>$name:&nbsp;</font></td>
+                     <td align=left>
+                       <font color=red>$text</font></td>
+                  </tr>\n";
+	}
+	echo "</table><br>\n";
+    }
+}
+
+function SPITFORM($message, $errors) {
+    SPIT_MSGS($message, $errors);
+
+    echo "<table>
+	  <tr>
+	    <th>&nbsp;Name&nbsp;</th>
+	    <th>&nbsp;Value&nbsp;</th>
+	    <th><font size='-1'>Edit</font></th>
+	    <th>&nbsp;Default Value&nbsp;</th>
+	    <th>&nbsp;Description&nbsp;</th> 
+	  </tr>";
 
     $result = DBQueryFatal("SELECT name, value, defaultvalue, description ".
 			   "FROM sitevariables ".
-			   "WHERE name='$edit'");
+			   "ORDER BY name");
+
+    while ($row = mysql_fetch_row($result)) {
+	$name         = $row[0];
+	$value        = $row[1];
+	$defaultvalue = $row[2];
+	$description  = $row[3];
+	$cginame      = urlencode($name);
+
+	echo "<tr><td>&nbsp;<b>$name</b>&nbsp;</td>\n";
+
+	echo "<td>&nbsp;";
+	if (isset($value)) {
+	    if (0 != strcmp($value, "")) {
+		$wrapped_value = wordwrap($value, 30, "<br />", 1);
+		echo "<code>$wrapped_value</code>&nbsp;</td>";
+	    } else {
+		echo "<font color='#00B040'><i>empty string</i></font>&nbsp;</td>";	
+	    }
+	} else {
+	    echo "<font color='#00B040'><i>default</i></font>&nbsp;</td>";
+	}
+	echo "<td align=center>";
+	echo "&nbsp;<a href='editsitevars.php3?edit=$cginame'>";
+	echo "<img border='0' src='greenball.gif' /></a>";
+	echo "&nbsp;</td>";
+
+	echo "<td nowrap='1'>&nbsp;";
+	if (0 != strcmp($defaultvalue, "")) {
+	    echo "<code>$defaultvalue</code>&nbsp;</td>";
+	} else {
+	    echo "<font color='#00B040'><i>empty string</i></font>&nbsp;</td>";	
+	}
+
+	echo "<td>&nbsp;$description&nbsp;</td></tr>\n";
+    }
+
+    echo "</table>";
+}
+
+# The "Edit" greenball column displays an edit subform for individual vars.
+function SPIT_SUBFORM($formfields, $message, $errors)
+{
+    SPIT_MSGS($message, $errors);
+
+    $name = $formfields["name"];
+    $result = DBQueryFatal("SELECT name, value, defaultvalue, description ".
+			   "FROM sitevariables ".
+			   "WHERE name='$name'");
 
     if ($row = mysql_fetch_row($result)) {
 	$name         = $row[0];
@@ -46,7 +134,10 @@ if (isset($edit)) {
 
 	echo "<center>";
 	echo "<form action='editsitevars.php3' method='post'>";
-	echo "<input type='hidden' name='name' value='$name'></input>";
+
+	echo "<input type='hidden' name=\"formfields[name]\"
+		     value=\"" . $formfields["name"] . "\">";
+
 	echo "<table><tr><th colspan=2>";
 	echo "Editing site variable '<b>$name</b>':";
 	echo "</th></tr><tr><td>";
@@ -59,116 +150,168 @@ if (isset($edit)) {
 	    echo "<font color='#00B040'><i>Empty String</i></font>";	    
 	}
 	echo "</td></tr><tr><td>&nbsp;</td><td>";
-	echo "<input type='submit' name='defaulted' value='Reset to Default Value'></input>";
+
+	echo "<input type='submit' name='defaulted' ".
+	     "       value='Reset to Default Value'></input>";
+
 	echo "</td></tr><tr><td>";
 	echo "<b>New value:</b></td><td>";
-	echo "<input size='60' type='text' name='value' value='$value'></input>";
+	echo "<input size='60' type='text'
+		     name=\"formfields[value]\"
+		     value=\"" . $value . "\">";
 	echo "</td></tr><tr><td>&nbsp;</td><td>";
-	echo "<input type='submit' name='edited' value='Change to New Value'></input>";
+
+	echo "<input type='submit' name='edited'
+	    	     value='Change to New Value'></input>";
 	echo "&nbsp;";
-	echo "<input type='submit' name='canceled' value='Cancel'></input>";
+
+	echo "<input type='submit' name='canceled'
+		     value='Cancel'>";
+
 	echo "</td></tr></table>";
 	echo "</form>";
 	echo "</center>";
-
-    } else {
-	TBERROR("Couldn't find variable '$edit'!");
     }
-
-    PAGEFOOTER();
-    return;
 }
 
-if (isset($edited)) {
-    $value = addslashes("$value");
-    
-    DBQueryFatal("UPDATE sitevariables ".
-		 "SET value='$value' ".
-		 "WHERE name='$name'");
-
-    echo "<h3>'$name' changed.</h3>";
-    echo "<form action='editsitevars.php3' method='get'>";
-    echo "<input type='submit' name='yadda' value='Return to list'></input>";
-    echo "</form>";
-    PAGEFOOTER();
-    return;
-}
+#
+# Accumulate error reports for the user, e.g.
+#    $errors["Key"] = "Msg";
+# Required page args may need to be checked early.
+$errors  = array();
 
-if (isset($defaulted)) {
-    DBQueryFatal("UPDATE sitevariables ".
-		 "SET value=NULL ".
-		 "WHERE name='$name'");
+# Show an optional status message.
+$message = "";
 
-    echo "<h3>'$name' reset to default.</h3>";
-    echo "<form action='editsitevars.php3' method='get'>";
-    echo "<input type='submit' name='yadda' value='Return to list'></input>";
-    echo "</form>";
+#
+#  On first load, just display current values.
+#
+if (!isset($edit) && 
+    !isset($edited) && !isset($defaulted) && !isset($canceled)) {
+    SPITFORM(0, $errors);
     PAGEFOOTER();
     return;
 }
 
-if (isset($canceled)) {
-    echo "<h3>Operation canceled.</h3>";
-    echo "<form action='editsitevars.php3' method='get'>";
-    echo "<input type='submit' name='yadda' value='Return to list'></input>";
-    echo "</form>";
-    PAGEFOOTER();
-    return;
+# The "Edit" greenball column displays an edit subform for individual vars.
+if (isset($edit)) {
+    if (!TBSiteVarExists($edit)) {
+	USERERROR("Couldn't find variable '$edit'!", 1);
+    }
+    else {
+	$formfields["name"] = $edit;
+	SPIT_SUBFORM($formfields, $message, $errors);
+	PAGEFOOTER();
+	return;
+    }
 }
 
-$result = DBQueryFatal("SELECT name, value, defaultvalue, description ".
-		       "FROM sitevariables ".
-		       "ORDER BY name");
-
-echo "<table>
-      <tr>
-        <th>&nbsp;Name&nbsp;</th>
-        <th>&nbsp;Value&nbsp;</th>
-        <th><font size='-1'>Edit</font></th>
-        <th>&nbsp;Default Value&nbsp;</th>
-        <th>&nbsp;Description&nbsp;</th> 
-      </tr>";
- 
-while ($row = mysql_fetch_row($result)) {
-    $name         = $row[0];
-    $value        = $row[1];
-    $defaultvalue = $row[2];
-    $description  = $row[3];
-    $cginame      = urlencode($name);
-
-    echo "<tr><td>&nbsp;<b>$name</b>&nbsp;</td>\n";
-
-    echo "<td>&nbsp;";
-    if (isset($value)) {
-	if (0 != strcmp($value, "")) {
-	    $wrapped_value = wordwrap($value, 30, "<br />", 1);
-	    echo "<code>$wrapped_value</code>&nbsp;</td>";
-	} else {
-	    echo "<font color='#00B040'><i>empty string</i></font>&nbsp;</td>";	
-	}
-    } else {
-	echo "<font color='#00B040'><i>default</i></font>&nbsp;</td>";
-    }
-    echo "<td align=center>";
-    echo "&nbsp;<a href='editsitevars.php3?edit=$cginame'>";
-    echo "<img border='0' src='greenball.gif' /></a>";
-    echo "&nbsp;</td>";
-
-    echo "<td nowrap='1'>&nbsp;";
-    if (0 != strcmp($defaultvalue, "")) {
-	echo "<code>$defaultvalue</code>&nbsp;</td>";
-    } else {
-	echo "<font color='#00B040'><i>empty string</i></font>&nbsp;</td>";	
+#
+# Build up argument array to pass along.
+#
+$args = array();
+$name = "";
+if (isset($formfields["name"]) && $formfields["name"] != "") {
+    $name = $formfields["name"];
+}
+
+# Actions for the Edit subform.
+$do_change = 0;
+if (isset($canceled)) {		# Action for the Cancel submit button.
+    $message = "Operation canceled.";
+}
+elseif (isset($edited)) {	# Action for the "Change to new value" button.
+    if (isset($formfields["value"]) && $formfields["value"] != "") {
+	$args["value"] = $value = $formfields["value"];
     }
+    $message = "Setting '$name' to '$value'.";
+    $do_change = 1;
+}
+elseif (isset($defaulted)) {	# Action for "Reset to Default value" button.
+    $message = "Resetting '$name' to default.";
+    $do_change = 1;
+    $args["reset"] = "1";
+}
 
-    echo "<td>&nbsp;$description&nbsp;</td></tr>\n";
+if ($do_change) {
+    $result = SetSiteVar($name, $args, $errors);
 }
 
-echo "</table>";
+# Respit the form to see the result.
+SPITFORM($message, $errors);
 
 #
 # Standard Testbed Footer
 # 
 PAGEFOOTER();
-?>
+return;
 			
+#
+# Edit site variables.  (No class for them at present.)
+function SetSiteVar($name, $args, &$errors) {
+    global $suexec_output, $suexec_output_array;
+
+    #
+    # Generate a temporary file and write in the XML goo.
+    #
+    $xmlname = tempnam("/tmp", "editsitevars");
+    if (! $xmlname) {
+	TBERROR("Could not create temporary filename", 0);
+	$errors[] = "Transient error(1); please try again later.";
+	return null;
+    }
+    if (! ($fp = fopen($xmlname, "w"))) {
+	TBERROR("Could not open temp file $xmlname", 0);
+	$errors[] = "Transient error(2); please try again later.";
+	return null;
+    }
+
+    # Add these. Maybe caller should do this?
+    $args["name"] = $name;
+
+    fwrite($fp, "<sitevar>\n");
+    foreach ($args as $name => $value) {
+	fwrite($fp, "<attribute name=\"$name\">");
+	fwrite($fp, "  <value>" . htmlspecialchars($value) . "</value>");
+	fwrite($fp, "</attribute>\n");
+    }
+    fwrite($fp, "</sitevar>\n");
+    fclose($fp);
+    chmod($xmlname, 0666);
+
+    $retval = SUEXEC("nobody", "nobody", "webeditsitevars $xmlname",
+		     SUEXEC_ACTION_IGNORE);
+
+    if ($retval) {
+	if ($retval < 0) {
+	    $errors[] = "Transient error(3); please try again later.";
+	    SUEXECERROR(SUEXEC_ACTION_CONTINUE);
+	}
+	else {
+	    # unlink($xmlname);
+	    if (count($suexec_output_array)) {
+		for ($i = 0; $i < count($suexec_output_array); $i++) {
+		    $line = $suexec_output_array[$i];
+		    if (preg_match("/^([-\w]+):\s*(.*)$/",
+				   $line, $matches)) {
+			$errors[$matches[1]] = $matches[2];
+		    }
+		    else
+			$errors[] = $line;
+		}
+	    }
+	    else
+		$errors[] = "Transient error(4); please try again later.";
+	}
+	return null;
+    }
+
+    # There are no return value(s) to parse at the end of the output.
+
+    # Unlink this here, so that the file is left behind in case of error.
+    # We can then create the sitevar by hand from the xmlfile, if desired.
+    unlink($xmlname);
+    return true;
+}
+
+?>