diff --git a/GNUmakefile.in b/GNUmakefile.in
index 01fee0ea13745e31571a252ec5de0de6de73a59e..8b6c8255a80de59e20c4b14213ab84f7c304f28c 100644
--- a/GNUmakefile.in
+++ b/GNUmakefile.in
@@ -156,6 +156,7 @@ install-mkdirs:
 	-mkdir -p $(INSTALL_TOPDIR)/log/mysql
 	-mkdir -p $(INSTALL_TOPDIR)/etc
 	-mkdir -p $(INSTALL_TOPDIR)/www
+	-mkdir -p $(INSTALL_TOPDIR)/suidbin
 	-mkdir -p $(INSTALL_TOPDIR)/ssl
 	-chmod 770 $(INSTALL_TOPDIR)/ssl
 ifeq ($(STANDALONE_CLEARINGHOUSE),0)
diff --git a/GNUmakerules b/GNUmakerules
index c9872858f1823e4ad094d3e07094f0df4afa160b..f332d0ae147e53d231453e6bf27413318d3de60f 100644
--- a/GNUmakerules
+++ b/GNUmakerules
@@ -1,6 +1,6 @@
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2000-2011 University of Utah and the Flux Group.
+# Copyright (c) 2000-2012 University of Utah and the Flux Group.
 # All rights reserved.
 
 # Get rid of a bunch of nasty built-in implicit rules,
@@ -36,21 +36,43 @@ $(INSTALL_ETCDIR)/%: %
 	-mkdir -p $(INSTALL_ETCDIR)
 	$(INSTALL_DATA) $< $@
 
-$(addprefix $(INSTALL_SBINDIR)/, $(SETUID_SBIN_SCRIPTS)): $(INSTALL_SBINDIR)/%: %
+$(addprefix $(INSTALL_SBINDIR)/, $(SETUID_SBIN_PROGS)): $(INSTALL_SBINDIR)/%: %
 	echo "Installing (setuid) $<"
 	-mkdir -p $(INSTALL_SBINDIR)
 	$(SUDO) $(INSTALL) -o root -m 4755 $< $@
 
-$(addprefix $(INSTALL_BINDIR)/, $(SETUID_BIN_SCRIPTS)): $(INSTALL_BINDIR)/%: %
+$(addprefix $(INSTALL_BINDIR)/, $(SETUID_BIN_PROGS)): $(INSTALL_BINDIR)/%: %
 	echo "Installing (setuid) $<"
 	-mkdir -p $(INSTALL_BINDIR)
 	$(SUDO) $(INSTALL) -o root -m 4755 $< $@
 
-$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_LIBX_SCRIPTS)): $(INSTALL_LIBEXECDIR)/%: %
+$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_LIBX_PROGS)): $(INSTALL_LIBEXECDIR)/%: %
 	echo "Installing (setuid) $<"
 	-mkdir -p $(INSTALL_LIBEXECDIR)
 	$(SUDO) $(INSTALL) -o root -m 4755 $< $@
 
+$(addprefix $(INSTALL_SBINDIR)/, $(SETUID_SBIN_SCRIPTS)): $(INSTALL_SBINDIR)/%: % $(INSTALL_SUIDDIR)/%
+	echo "Installing (link to wrapper) $<"
+	-mkdir -p $(INSTALL_SBINDIR)
+	-rm -f $@
+	ln -s $(INSTALL_LIBEXECDIR)/runsuid $@
+
+$(addprefix $(INSTALL_BINDIR)/, $(SETUID_BIN_SCRIPTS)): $(INSTALL_BINDIR)/%: % $(INSTALL_SUIDDIR)/%
+	echo "Installing (link to wrapper) $<"
+	-mkdir -p $(INSTALL_BINDIR)
+	-rm -f $@
+	ln -s $(INSTALL_LIBEXECDIR)/runsuid $@
+
+$(addprefix $(INSTALL_LIBEXECDIR)/, $(SETUID_LIBX_SCRIPTS)): $(INSTALL_LIBEXECDIR)/%: % $(INSTALL_SUIDDIR)/%
+	echo "Installing (link to wrapper) $<"
+	-mkdir -p $(INSTALL_LIBEXECDIR)
+	-rm -f $@
+	ln -s $(INSTALL_LIBEXECDIR)/runsuid $@
+
+$(INSTALL_SUIDDIR)/%: %
+	echo "Installing (real script) $<"
+	-mkdir -p $(INSTALL_SUIDDIR)
+	$(INSTALL_PROGRAM) $< $@	
 
 CFLAGS += $(LOCALCFLAGS)
 
diff --git a/Makeconf.in b/Makeconf.in
index 9be77e898be2ce3d8a91569fe95e91b0d2e09761..7f25588ccffd2eb2ab581cd77e2bb8780037e996 100644
--- a/Makeconf.in
+++ b/Makeconf.in
@@ -62,6 +62,7 @@ INSTALL_LIBEXECDIR = @libexecdir@
 INSTALL_ETCDIR  = @sysconfdir@
 INSTALL_INCDIR  = @includedir@
 INSTALL_WWWDIR	= @exec_prefix@/www
+INSTALL_SUIDDIR = @exec_prefix@/suidbin
 INSTALL_RCDIR	= @INSTALL_RCDIR@
 INSTALL_APACHE_CONFIG = @INSTALL_APACHE_CONFIG@
 
diff --git a/clientside/event/trafgen/tg.patch b/clientside/event/trafgen/tg.patch
index a8d4da85dbe17fbc723ddf2ec5d4e0144843dc68..3510419e17875cfbf1e7810856d515896dda8df4 100644
--- a/clientside/event/trafgen/tg.patch
+++ b/clientside/event/trafgen/tg.patch
@@ -1,6 +1,6 @@
 diff -ru dist/tg2.0/src/tg/config.h tg2.0/src/tg/config.h
---- dist/tg2.0/src/tg/config.h	Thu Jan 24 16:30:09 2002
-+++ tg2.0/src/tg/config.h	Wed Aug 25 14:37:32 2004
+--- dist/tg2.0/src/tg/config.h	2002-01-24 16:30:09.000000000 -0700
++++ tg2.0/src/tg/config.h	2012-03-21 16:54:20.000000000 -0600
 @@ -14,7 +14,7 @@
  
  /* Maximum packet buffer size.						*/
@@ -11,9 +11,28 @@ diff -ru dist/tg2.0/src/tg/config.h tg2.0/src/tg/config.h
  /* Maximum value from random-number generator.				*/
  
 diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
---- dist/tg2.0/src/tg/log.c	Thu Jan 24 16:30:09 2002
-+++ tg2.0/src/tg/log.c	Wed Aug 25 14:37:32 2004
-@@ -268,6 +268,11 @@
+--- dist/tg2.0/src/tg/log.c	2002-01-24 16:30:09.000000000 -0700
++++ tg2.0/src/tg/log.c	2012-03-21 16:58:39.000000000 -0600
+@@ -23,7 +23,6 @@
+ #include <sys/utsname.h> 
+ #include <sys/param.h>
+ #include <errno.h>
+-#include <utmp.h>
+ 
+ #include "config.h"
+ #include "distribution.h"
+@@ -31,6 +30,10 @@
+ #include "decode.h"
+ #include "log.h"
+ 
++/* XXX utmp.h is defunct */
++#define UT_NAMESIZE 32
++#define UT_HOSTSIZE 256
++
+ /* Type definitions local to this file.					*/
+ 
+ #define FPRINTF		(void) fprintf
+@@ -268,6 +271,11 @@
  	char		*cp = buf;
  	char		ctl;
  
@@ -25,7 +44,7 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	/* Encode record type.						*/
  
  	*cp++ = LOGTYPE_ACCEPT;
-@@ -326,6 +331,11 @@
+@@ -326,6 +334,11 @@
  	char		*cp = buf;
  	char		ctl;
  
@@ -37,7 +56,7 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	/* Encode record type.						*/
  
  	*cp++ = LOGTYPE_ERROR;
-@@ -391,6 +401,11 @@
+@@ -391,6 +404,11 @@
  	char		*cp = buf;
  	char		ctl;
  
@@ -49,7 +68,7 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	/* Encode record type.						*/
  
  	*cp++ = LOGTYPE_RX;
-@@ -459,6 +474,11 @@
+@@ -459,6 +477,11 @@
  	char		*cp = buf;
  	char		ctl;
  
@@ -61,7 +80,7 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	/* Encode record type.						*/
  
  	*cp++ = LOGTYPE_SETUP;
-@@ -510,6 +530,11 @@
+@@ -510,6 +533,11 @@
  	char		*cp = buf;
  	char		ctl;
  
@@ -73,7 +92,7 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	/* Encode record type.						*/
  
  	*cp++ = LOGTYPE_TEARDOWN;
-@@ -568,6 +593,11 @@
+@@ -568,6 +596,11 @@
  	char		*cp = buf;
  	char		ctl;
  
@@ -85,7 +104,7 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	/* Encode record type.						*/
  
  	*cp++ = LOGTYPE_TX;
-@@ -717,6 +747,10 @@
+@@ -717,6 +750,10 @@
  
  	extern FILE	*log_fp;
  	
@@ -97,8 +116,8 @@ diff -ru dist/tg2.0/src/tg/log.c tg2.0/src/tg/log.c
  	  (void) fclose (log_fp);
  
 diff -ru dist/tg2.0/src/tg/prot_dgram.c tg2.0/src/tg/prot_dgram.c
---- dist/tg2.0/src/tg/prot_dgram.c	Thu Jan 24 16:30:10 2002
-+++ tg2.0/src/tg/prot_dgram.c	Wed Aug 25 14:37:32 2004
+--- dist/tg2.0/src/tg/prot_dgram.c	2002-01-24 16:30:10.000000000 -0700
++++ tg2.0/src/tg/prot_dgram.c	2012-03-21 16:54:20.000000000 -0600
 @@ -198,6 +198,22 @@
  	for (;;)
  		{
@@ -167,8 +186,8 @@ diff -ru dist/tg2.0/src/tg/prot_dgram.c tg2.0/src/tg/prot_dgram.c
  	}
  
 diff -ru dist/tg2.0/src/tg/prot_stream.c tg2.0/src/tg/prot_stream.c
---- dist/tg2.0/src/tg/prot_stream.c	Thu Jan 24 16:30:10 2002
-+++ tg2.0/src/tg/prot_stream.c	Wed Aug 25 14:37:32 2004
+--- dist/tg2.0/src/tg/prot_stream.c	2002-01-24 16:30:10.000000000 -0700
++++ tg2.0/src/tg/prot_stream.c	2012-03-21 16:54:20.000000000 -0600
 @@ -147,6 +147,22 @@
  	for (;;)
  		{
@@ -241,8 +260,8 @@ diff -ru dist/tg2.0/src/tg/prot_stream.c tg2.0/src/tg/prot_stream.c
  	return (result);
  	}
 diff -ru dist/tg2.0/src/tg/prot_tcp.c tg2.0/src/tg/prot_tcp.c
---- dist/tg2.0/src/tg/prot_tcp.c	Thu Jan 24 16:30:10 2002
-+++ tg2.0/src/tg/prot_tcp.c	Wed Aug 25 14:37:32 2004
+--- dist/tg2.0/src/tg/prot_tcp.c	2002-01-24 16:30:10.000000000 -0700
++++ tg2.0/src/tg/prot_tcp.c	2012-03-21 16:54:20.000000000 -0600
 @@ -93,6 +93,12 @@
  
  #endif /* QOSDEBUG */
@@ -312,8 +331,8 @@ diff -ru dist/tg2.0/src/tg/prot_tcp.c tg2.0/src/tg/prot_tcp.c
  			{
  			(void)close(sfd);
 diff -ru dist/tg2.0/src/tg/prot_test.c tg2.0/src/tg/prot_test.c
---- dist/tg2.0/src/tg/prot_test.c	Thu Jan 24 16:30:10 2002
-+++ tg2.0/src/tg/prot_test.c	Wed Aug 25 14:37:32 2004
+--- dist/tg2.0/src/tg/prot_test.c	2002-01-24 16:30:10.000000000 -0700
++++ tg2.0/src/tg/prot_test.c	2012-03-21 16:54:20.000000000 -0600
 @@ -447,6 +447,7 @@
  
  	if (!test_get_packets(prtab, fd, endtout))
@@ -323,8 +342,8 @@ diff -ru dist/tg2.0/src/tg/prot_test.c tg2.0/src/tg/prot_test.c
  		}
  	else
 diff -ru dist/tg2.0/src/tg/prot_udp.c tg2.0/src/tg/prot_udp.c
---- dist/tg2.0/src/tg/prot_udp.c	Thu Jan 24 16:30:10 2002
-+++ tg2.0/src/tg/prot_udp.c	Wed Aug 25 14:37:32 2004
+--- dist/tg2.0/src/tg/prot_udp.c	2002-01-24 16:30:10.000000000 -0700
++++ tg2.0/src/tg/prot_udp.c	2012-03-21 16:54:20.000000000 -0600
 @@ -47,7 +47,7 @@
  
  /* Apply QOS parameters to an existing fd.                              */
@@ -380,8 +399,8 @@ diff -ru dist/tg2.0/src/tg/prot_udp.c tg2.0/src/tg/prot_udp.c
  			{
  			    (void)close(sfd);
 diff -ru dist/tg2.0/src/tg/tg.y tg2.0/src/tg/tg.y
---- dist/tg2.0/src/tg/tg.y	Thu Jan 24 16:30:10 2002
-+++ tg2.0/src/tg/tg.y	Tue Oct  5 16:53:50 2004
+--- dist/tg2.0/src/tg/tg.y	2002-01-24 16:30:10.000000000 -0700
++++ tg2.0/src/tg/tg.y	2012-03-21 16:54:20.000000000 -0600
 @@ -133,7 +133,11 @@
  char                    *version = "2.0";	/* TG program version.	*/
  char			*ofile = NULL;
diff --git a/clientside/tmcc/common/config/rc.mkelab b/clientside/tmcc/common/config/rc.mkelab
index 644e97fe97ed3b949f2fc23706db77d651fc9bd5..524911983ea13e8da6e1ac13b1b44b5f1c151b92 100755
--- a/clientside/tmcc/common/config/rc.mkelab
+++ b/clientside/tmcc/common/config/rc.mkelab
@@ -528,7 +528,7 @@ sub doboot()
 	$emulabconfig{OPS_PKG}      = "emulab-ops-3.1";
 	$emulabconfig{BOSS_PKG}     = "emulab-boss-3.1";
     }
-    elsif ($FBSD_VERSION >= 8.2) {
+    elsif ($FBSD_VERSION >= 8.2 && $FBSD_VERSION < 9.0) {
 	$emulabconfig{FS_PKG_DIR} = "/share/freebsd/8.2/packages";
 	$emulabconfig{FS_PKG_DIR} .= ".elvincompat"
 	    if ($emulabconfig{"CONFIG_ELVIN"});
@@ -540,6 +540,18 @@ sub doboot()
 	$emulabconfig{PACKAGE_TARBALL} = "FreeBSD-8.2-packages.tar.gz";
 	$emulabconfig{PGENI_PKG}    = "emulab-protogeni-2.0";
     }
+    elsif ($FBSD_VERSION >= 9.0) {
+	$emulabconfig{FS_PKG_DIR} = "/share/freebsd/9.0/packages";
+	$emulabconfig{FS_PKG_DIR} .= ".elvincompat"
+	    if ($emulabconfig{"CONFIG_ELVIN"});
+	$emulabconfig{OPS_PKG_DIR}  = $emulabconfig{FS_PKG_DIR};
+	$emulabconfig{BOSS_PKG_DIR} = $emulabconfig{FS_PKG_DIR};
+	$emulabconfig{FS_PKG}       = "emulab-fs-5.0";
+	$emulabconfig{OPS_PKG}      = "emulab-ops-5.0";
+	$emulabconfig{BOSS_PKG}     = "emulab-boss-5.0";
+	$emulabconfig{PACKAGE_TARBALL} = "FreeBSD-9.0-packages.tar.gz";
+	$emulabconfig{PGENI_PKG}    = "emulab-protogeni-2.0";
+    }
     if (exists($emulabconfig{"PACKAGE_TARBALL"})) {
 	$emulabconfig{FS_PKG_DIR}   = "$TBDIR/packages";
 	$emulabconfig{OPS_PKG_DIR}  = $emulabconfig{FS_PKG_DIR};
diff --git a/install/installvars.pm.in b/install/installvars.pm.in
index c5862dc199bf19903c88252949e0b9942d2c8622..9003f5ab46a283d69d3d10bce801f5ddc8045dc1 100644
--- a/install/installvars.pm.in
+++ b/install/installvars.pm.in
@@ -40,7 +40,11 @@ $BOSS_PORT = "emulab-boss-1.8";
 $OPS_PORT  = "emulab-ops-1.4"; 
 $FS_PORT   = "emulab-fs-1.4";
 if ($FBSD_MAJOR > 4) {
-    if ($FBSD_MAJOR > 7) {
+    if ($FBSD_MAJOR > 8) {
+	$BOSS_PORT = "emulab-boss-5.0";
+	$OPS_PORT = "emulab-ops-5.0";
+	$FS_PORT = "emulab-fs-5.0";
+    } elsif ($FBSD_MAJOR > 7) {
 	$BOSS_PORT = "emulab-boss-4.0";
 	$OPS_PORT = "emulab-ops-4.0";
 	$FS_PORT = "emulab-fs-4.0";
@@ -68,10 +72,11 @@ $PHP_VERSION = 4;
 $PHP_PORT = "php4-extensions-1.0";
 if ($FBSD_MAJOR > 7 || ($FBSD_MAJOR == 7 && $FBSD_MINOR > 2)) {
     $PHP_VERSION = 5;
-    if ($FBSD_MAJOR > 7) {
+    if ($FBSD_MAJOR > 8) {
+	$PHP_PORT = "php5-extensions-1.6";
+    } elsif ($FBSD_MAJOR > 7) {
 	$PHP_PORT = "php5-extensions-1.4";
-    }
-    else {
+    } else {
 	$PHP_PORT = "php5-extensions-1.3";
     }
 }
@@ -94,7 +99,10 @@ $SELFLOAD_PATCH		= "$main::TOP_SRCDIR/patches/SelfLoader.patch";
 #
 $PYM2_PKG = "py25-m2crypto-0.19.1";
 $PY_VER   = "python2.5";
-if ($FBSD_MAJOR > 7 || ($FBSD_MAJOR == 7 && $FBSD_MINOR > 2)) {
+if ($FBSD_MAJOR > 8) {
+    $PYM2_PKG = "py27-m2crypto-0.21.1";
+    $PY_VER = "python2.7";
+} elsif ($FBSD_MAJOR > 7 || ($FBSD_MAJOR == 7 && $FBSD_MINOR > 2)) {
     $PYM2_PKG = "py26-m2crypto-0.20";
     $PY_VER = "python2.6";
 }
diff --git a/install/phases/sperl b/install/phases/sperl
index 76675f14cf30a02c4644ad405e18da997d8e52a7..b93315a97afd00e1308b61bbe6a2fbad97ccd0ba 100755
--- a/install/phases/sperl
+++ b/install/phases/sperl
@@ -5,6 +5,7 @@ use strict;
 use libinstall;
 use installvars;
 
+my $PERL     = "/usr/bin/perl";
 my $SUIDPERL = "/usr/bin/suidperl";
 
 sub Install($$$)
@@ -16,6 +17,17 @@ sub Install($$$)
 	if ($isupdate);
 
     Phase "perl", "Checking for setuid perl", sub {
+	#
+	# See if suidperl is supported. Perl 5.12 and beyond don't have it.
+	#
+	if (-x $PERL) {
+	    my $vstr = `$PERL -v | grep version`;
+	    if ($vstr =~ /This is perl 5, version (\d+),/) {
+		if (int($1) >= 12) {
+		    PhaseSkip("Not used");
+		}
+	    }
+	}
 	Phase "sperl", "Checking for sperl", sub {
 	    if (ExecQuiet("$PKG_INFO -L -x perl-5 | fgrep -q -s sperl") == 0) {
 		PhaseSkip("Perl is okay");
diff --git a/install/ports/emulab-boss/Makefile b/install/ports/emulab-boss/Makefile
index c27722cab7e920f75a2ae63e7b970d5f1afe37a6..226f8536560114c20835720e302a01dfdfbc4ae5 100644
--- a/install/ports/emulab-boss/Makefile
+++ b/install/ports/emulab-boss/Makefile
@@ -24,7 +24,9 @@ MAINTAINER=	testbed-ops@flux.utah.edu
 # We must make sure PERL is built with this.
 #
 .MAKEFLAGS+=	ENABLE_SUIDPERL=yes
-.if (${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
+.if ${PORTVERSION} == "5.0"
+.MAKEFLAGS+=	PERL_VERSION=5.12.4 PERL_VER=5.12.4 PERL_ARCH=mach
+.elif (${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
 .MAKEFLAGS+=	PERL_VERSION=5.10.1 PERL_VER=5.10.1 PERL_ARCH=mach
 .elif ${PORTVERSION} == "3.0"
 .MAKEFLAGS+=	PERL_VERSION=5.10.0 PERL_VER=5.10.0 PERL_ARCH=mach
@@ -48,7 +50,7 @@ MAINTAINER=	testbed-ops@flux.utah.edu
 # agrees with what is in the emulab-ops and emulab-php* metaports.
 #
 .MAKEFLAGS+=	-DWITH_APACHE
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 .MAKEFLAGS+=	APACHE_PORT=www/apache22
 .MAKEFLAGS+=	WITH_SUEXEC=yes
 .else
@@ -73,7 +75,7 @@ MAINTAINER=	testbed-ops@flux.utah.edu
 .if (${PORTVERSION} == "1.7" || ${PORTVERSION} == "2.0")
 BUILD_DEPENDS=	\
 	${LOCALBASE}/lib/perl5/site_perl/${PERL_VER}/${PERL_ARCH}/Mysql.pm:${PORTSDIR}/databases/p5-DBD-mysql50
-.elif (${PORTVERSION} == "4.0")
+.elif (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 # back to a standard p5-DBD-mysql50 install
 BUILD_DEPENDS=	\
 	${LOCALBASE}/lib/perl5/site_perl/${PERL_VER}/${PERL_ARCH}/DBD/mysql.pm:${PORTSDIR}/databases/p5-DBD-mysql50 \
@@ -97,7 +99,7 @@ LIB_DEPENDS+= lthread.[236]:${PORTSDIR}/devel/linuxthreads
 LIB_DEPENDS+= xerces-c.27:${PORTSDIR}/textproc/xerces-c2
 .endif
 .if ${OSMAJOR} >= 7
-LIB_DEPENDS+= xmlrpc.9:${PORTSDIR}/net/xmlrpc-c
+LIB_DEPENDS+= xmlrpc:${PORTSDIR}/net/xmlrpc-c
 .endif
 
 #
@@ -148,7 +150,7 @@ RUN_DEPENDS+=	\
 	mysqlhotcopy:${PORTSDIR}/databases/mysql50-scripts
 
 # apache related ports
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 RUN_DEPENDS+=	\
 	${LOCALBASE}/libexec/apache22/mod_ssl.so:${PORTSDIR}/${APACHE_PORT} \
 	${LOCALBASE}/libexec/apache22/mod_fastcgi.so:${PORTSDIR}/www/mod_fastcgi
@@ -159,7 +161,8 @@ RUN_DEPENDS+=	\
 .endif
 
 # m2crypto port
-.if (${PORTVERSION} == "3.0" || ${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
+.if (${PORTVERSION} == "3.0" || ${PORTVERSION} == "3.1" || \
+     ${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 # must handle patching of m2crypto when the port is built
 RUN_DEPENDS+=	\
 	${PYTHON_PKGNAMEPREFIX}m2crypto>0:${PORTSDIR}/misc/emulab-py-m2crypto
@@ -170,7 +173,7 @@ RUN_DEPENDS+=	\
 .endif
 
 # dhcpd port
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 RUN_DEPENDS+=	\
 	dhcpd:${PORTSDIR}/net/isc-dhcp42-server
 .elif (${PORTVERSION} == "3.1" || ${PORTVERSION} == "3.0")
@@ -182,7 +185,7 @@ RUN_DEPENDS+=	\
 .endif
 
 # misc. old vs. new port stuff
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 RUN_DEPENDS+=	\
 	autoconf:${PORTSDIR}/devel/autoconf \
 	libtool:${PORTSDIR}/devel/libtool
diff --git a/install/ports/emulab-boss/Makefile.emulab b/install/ports/emulab-boss/Makefile.emulab
index da9544580f18d170de35616b0b806899a544d049..b3cb0bd1b596969bb988053a83089aec41734e94 100644
--- a/install/ports/emulab-boss/Makefile.emulab
+++ b/install/ports/emulab-boss/Makefile.emulab
@@ -7,6 +7,9 @@
 OSMAJOR!= /usr/bin/uname -r | /usr/bin/sed -e 's/\..*//'
 OSMINOR!= /usr/bin/uname -r | /usr/bin/sed -e 's/[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/'
 
+.if ${OSMAJOR} > 8
+EMULAB_PORTVERSION=	5.0
+.else
 .if ${OSMAJOR} > 7
 EMULAB_PORTVERSION=	4.0
 .else
@@ -28,12 +31,20 @@ EMULAB_PORTVERSION=	1.7
 .  endif
 . endif
 .endif
+.endif
 
 #
 # Select PHP and Apache versions
 # Fix up some port diffs
 #
-.if ${EMULAB_PORTVERSION} == "4.0"
+.if ${EMULAB_PORTVERSION} == "5.0"
+PHP_VER=	5
+PERL_VER=	5.12.4
+PYTHON_DEFAULT_VERSION=python2.7
+APACHE_PORT=	www/apache22
+BOOST_PORT=	devel/boost-all
+P5SNMP_PORT=	misc/p5-SNMP
+.elif ${EMULAB_PORTVERSION} == "4.0"
 PHP_VER=	5
 PERL_VER=	5.10.1
 APACHE_PORT=	www/apache22
diff --git a/install/ports/emulab-fs/Makefile b/install/ports/emulab-fs/Makefile
index 0e8f8bc121bcbab9f9bd9fee810b5bd75f0f89b7..7d0d62bec7aca6d20873fe1f552db7e772e6e3e9 100644
--- a/install/ports/emulab-fs/Makefile
+++ b/install/ports/emulab-fs/Makefile
@@ -18,21 +18,13 @@ COMMENT=	"Meta-port for an Emulab fs node"
 
 MAINTAINER=	testbed-ops@flux.utah.edu
 
-#
-# Select PHP and Apache versions
-# Fix up some port diffs
-#
-.if ${PORTVERSION} == "3.1"
-PHP_VER=	5
-.else
-PHP_VER=	4
-.endif
-
 #
 # We must make sure PERL is built with this.
 #
 .MAKEFLAGS+=	ENABLE_SUIDPERL=yes
-.if (${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
+.if ${PORTVERSION} == "5.0"
+.MAKEFLAGS+=	PERL_VERSION=5.12.4 PERL_VER=5.12.4 PERL_ARCH=mach
+.elif (${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
 .MAKEFLAGS+=	PERL_VERSION=5.10.1 PERL_VER=5.10.1 PERL_ARCH=mach
 .elif ${PORTVERSION} == "3.0"
 .MAKEFLAGS+=	PERL_VERSION=5.10.0 PERL_VER=5.10.0 PERL_ARCH=mach
@@ -56,7 +48,7 @@ RUN_DEPENDS= gmake:${PORTSDIR}/devel/gmake \
 	sudo:${PORTSDIR}/security/sudo \
 	rsync:${PORTSDIR}/net/rsync \
 
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 RUN_DEPENDS+= \
 	smbd:${PORTSDIR}/net/samba36
 .else
diff --git a/install/ports/emulab-ops/Makefile b/install/ports/emulab-ops/Makefile
index 77cabdf226ba784866259f225911280da6fb0ffb..a3de84618a99c50ee0e2ff429fba8e58e3c51d9e 100644
--- a/install/ports/emulab-ops/Makefile
+++ b/install/ports/emulab-ops/Makefile
@@ -28,7 +28,9 @@ MAINTAINER=	testbed-ops@flux.utah.edu
 # We must make sure PERL is built with this.
 #
 .MAKEFLAGS+=	ENABLE_SUIDPERL=yes
-.if (${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
+.if ${PORTVERSION} == "5.0"
+.MAKEFLAGS+=	PERL_VERSION=5.12.4 PERL_VER=5.12.4 PERL_ARCH=mach
+.elif (${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
 .MAKEFLAGS+=	PERL_VERSION=5.10.1 PERL_VER=5.10.1 PERL_ARCH=mach
 .elif ${PORTVERSION} == "3.0"
 .MAKEFLAGS+=	PERL_VERSION=5.10.0 PERL_VER=5.10.0 PERL_ARCH=mach
@@ -52,7 +54,7 @@ MAINTAINER=	testbed-ops@flux.utah.edu
 # agrees with what is in the emulab-ops and emulab-php* metaports.
 #
 .MAKEFLAGS+=	-DWITH_APACHE
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 .MAKEFLAGS+=	APACHE_PORT=www/apache22
 .MAKEFLAGS+=	WITH_SUEXEC=yes
 .else
@@ -77,7 +79,7 @@ MAINTAINER=	testbed-ops@flux.utah.edu
 .if (${PORTVERSION} == "1.4" || ${PORTVERSION} == "2.0")
 BUILD_DEPENDS=	\
 	${LOCALBASE}/lib/perl5/site_perl/${PERL_VER}/${PERL_ARCH}/Mysql.pm:${PORTSDIR}/databases/p5-DBD-mysql50
-.elif (${PORTVERSION} == "4.0")
+.elif (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 # back to a standard p5-DBD-mysql50 install
 BUILD_DEPENDS=	\
 	${LOCALBASE}/lib/perl5/site_perl/${PERL_VER}/${PERL_ARCH}/DBD/mysql.pm:${PORTSDIR}/databases/p5-DBD-mysql50 \
@@ -98,7 +100,7 @@ LIB_DEPENDS+= mhash.2:${PORTSDIR}/security/mhash \
 	mysqlclient.15:${PORTSDIR}/databases/mysql50-client
 .endif
 .if ${OSMAJOR} >= 7
-LIB_DEPENDS+= xmlrpc.9:${PORTSDIR}/net/xmlrpc-c
+LIB_DEPENDS+= xmlrpc:${PORTSDIR}/net/xmlrpc-c
 .endif
 
 .if defined(ELVIN_COMPAT)
@@ -126,7 +128,7 @@ RUN_DEPENDS+= ${LOCALBASE}/libexec/elvind:${PORTSDIR}/misc/elvind
 .endif
 
 # apache related ports
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 RUN_DEPENDS+=	\
 	${LOCALBASE}/libexec/apache22/mod_ssl.so:${PORTSDIR}/${APACHE_PORT} \
 	${LOCALBASE}/libexec/apache22/mod_fastcgi.so:${PORTSDIR}/www/mod_fastcgi
@@ -137,7 +139,8 @@ RUN_DEPENDS+=	\
 .endif
 
 # m2crypto port
-.if (${PORTVERSION} == "3.0" || ${PORTVERSION} == "3.1" || ${PORTVERSION} == "4.0")
+.if (${PORTVERSION} == "3.0" || ${PORTVERSION} == "3.1" || \
+     ${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 # must handle patching of m2crypto when the port is built
 # also needs swig to install!
 RUN_DEPENDS+=	\
@@ -150,7 +153,7 @@ RUN_DEPENDS+=	\
 .endif
 
 # misc. old vs. new port stuff
-.if ${PORTVERSION} == "4.0"
+.if (${PORTVERSION} == "4.0" || ${PORTVERSION} == "5.0")
 RUN_DEPENDS+=	\
 	autoconf:${PORTSDIR}/devel/autoconf \
 	libtool:${PORTSDIR}/devel/libtool
diff --git a/install/ports/emulab-protogeni/Makefile b/install/ports/emulab-protogeni/Makefile
index 34f867ae1ed231d0142081b4d3a1a5d28bf2ede1..741770eeb1fc74f7ba6f8ee2ac1a6cd4717af75a 100644
--- a/install/ports/emulab-protogeni/Makefile
+++ b/install/ports/emulab-protogeni/Makefile
@@ -2,38 +2,27 @@
 # Date created:         21 July 2009
 # Whom:                 stoller@flux.utah.edu
 
-# Need the major version number to figure out to do.
-OSMAJOR!= /usr/bin/uname -r | /usr/bin/sed -e 's/\..*//'
-OSMINOR!= /usr/bin/uname -r | /usr/bin/sed -e 's/[0-9][0-9]*\.\([0-9][0-9]*\).*/\1/'
+.include "../emulab-boss/Makefile.emulab"
 
-PORTNAME=	emulab-protogeni
-PORTVERSION=	1.0
-.if ${OSMAJOR} >= 8
+# XXX deal with out-of-sync-edness of meta ports
+.if ${EMULAB_PORTVERSION} == "5.0"
+PORTVERSION=	3.0
+.elif ${EMULAB_PORTVERSION} == "4.0"
 PORTVERSION=	2.0
 .else
-.if ${OSMAJOR} >= 7
-.if ${OSMINOR} >= 3
 PORTVERSION=	1.1
 .endif
-.endif
-.endif
+
+PORTNAME=	emulab-protogeni
 CATEGORIES=	misc
 MASTER_SITES=	#none
 DISTFILES=	#none
 EXTRACT_ONLY=	#none
 COMMENT=	"Meta-port for a protogeni site"
 
-MAINTAINER=	stoller@cs.utah.edu
+MAINTAINER=	testbed-ops@flux.utah.edu
 
-# XXX this crap should not be needed!
-.if ${PORTVERSION} != "1.0"
-PHP_VER=	5
-PERL_VER=	5.10.1
 .MAKEFLAGS+=	WITH_OPENSSL_BASE=yes
-.else
-PHP_VER=	4
-.MAKEFLAGS+=	WITH_OPENSSL_PORT=yes
-.endif
 
 #
 # We set this so that the mysql server port doesn't do name resolution
@@ -56,7 +45,7 @@ PHP_VER=	4
 # Various ports need to agree on what version of apache. Make sure this
 # agrees with what is in the emulab-ops and emulab-php4 metaports.
 #
-.if ${PORTVERSION} == "2.0"
+.if ${PORTVERSION} != "1.1"
 .MAKEFLAGS+=	APACHE_PORT=www/apache22
 .else
 .MAKEFLAGS+=	APACHE_PORT=www/apache13-modssl
diff --git a/install/ports/emulab-py-m2crypto/distinfo b/install/ports/emulab-py-m2crypto/distinfo
index bf997f52d6bfbfc467c02eb2ed0bff9959bf44c8..382000755fd0a474583ee0d00876f66f5e58ad11 100644
--- a/install/ports/emulab-py-m2crypto/distinfo
+++ b/install/ports/emulab-py-m2crypto/distinfo
@@ -4,3 +4,5 @@ SIZE (python/M2Crypto-0.19.1.tar.gz) = 390933
 MD5 (python/M2Crypto-0.20.tar.gz) = 43a4d958a6c892a37ca02ffcc650b66b
 SHA256 (python/M2Crypto-0.20.tar.gz) = bec1a55cd5e4d88bb87f066c83a0ad42391e0e436b2d6b1edb7259c918e4b55f
 SIZE (python/M2Crypto-0.20.tar.gz) = 412877
+SHA256 (python/M2Crypto-0.21.1.tar.gz) = 25b94498505c2d800ee465db0cc1aff097b1615adc3ac042a1c85ceca264fc0a
+SIZE (python/M2Crypto-0.21.1.tar.gz) = 413563
diff --git a/install/ports/emulab-tftp-hpa/Makefile b/install/ports/emulab-tftp-hpa/Makefile
index 650a6009d73c24b3d4ca98835a81907d7f50eace..2b7f6cc21cf02f952e3e6eb058f975d11b78774d 100644
--- a/install/ports/emulab-tftp-hpa/Makefile
+++ b/install/ports/emulab-tftp-hpa/Makefile
@@ -9,7 +9,7 @@ PORTNAME=	tftp-hpa
 PORTVERSION=	0.48
 #CATEGORIES=	net
 CATEGORIES=	misc
-MASTER_SITES=	ftp://www.kernel.org/pub/software/network/tftp/
+MASTER_SITES=	http://www.emulab.net/distributions/
 PKGNAMEPREFIX=	emulab-
 DISTNAME=	${PORTNAME}-${PORTVERSION}
 
diff --git a/install/ports/net-snmp4/Makefile b/install/ports/net-snmp4/Makefile
index 2ca81395d72690a919b19fe3044ee2a879745afd..f268fa8ca21ae3ffe308d9c5b19b8b4230a9b92b 100644
--- a/install/ports/net-snmp4/Makefile
+++ b/install/ports/net-snmp4/Makefile
@@ -1,5 +1,7 @@
 #
 # This port has been "expired" from the official FreeBSD ports tree.
+# Note: removed "snmpnetstat" from BIN= as it causes install to fail.
+#       I don't think we need it so I didn't track the failure down.
 #
 # New ports collection makefile for:	ucd-snmp
 # Date created:				26 June 1996
@@ -84,7 +86,7 @@ MLINKS=		snmptrap.1 snmpinform.1 \
 		snmp_sess_api.3 snmp_sess_send.3 \
 		snmp_sess_api.3 snmp_sess_session.3 \
 		snmp_sess_api.3 snmp_sess_timeout.3
-BIN=		snmpbulkwalk snmpget snmpgetnext snmpnetstat snmpset \
+BIN=		snmpbulkwalk snmpget snmpgetnext snmpset \
 		snmpstatus snmptest snmptranslate snmptrap snmpwalk
 SBIN=		snmpd snmptrapd
 
diff --git a/install/ports/net-snmp4/files/patch-agent-emulab b/install/ports/net-snmp4/files/patch-agent-emulab
new file mode 100644
index 0000000000000000000000000000000000000000..669488ed083d22658a24733895c6f932dae3d58c
--- /dev/null
+++ b/install/ports/net-snmp4/files/patch-agent-emulab
@@ -0,0 +1,24 @@
+--- agent/agent_read_config.c.orig	2003-05-06 09:09:24.000000000 -0600
++++ agent/agent_read_config.c		2012-03-19 09:18:30.000000000 -0600
+@@ -5,6 +5,9 @@
+ #include <config.h>
+ 
+ #include <sys/types.h>
++#ifdef HAVE_SYS_PARAM_H
++#include <sys/param.h>
++#endif
+ #if HAVE_STDLIB_H
+ #include <stdlib.h>
+ #endif
+--- agent/snmp_vars.c.orig	2002-08-29 02:35:51.000000000 -0600
++++ agent/snmp_vars.c		2012-03-19 09:18:12.000000000 -0600
+@@ -41,6 +41,9 @@
+ #include <stdlib.h>
+ #endif
+ #include <sys/types.h>
++#ifdef HAVE_SYS_PARAM_H
++#include <sys/param.h>
++#endif
+ #include <stdio.h>
+ #include <fcntl.h>
+ 
diff --git a/install/ports/ports-install b/install/ports/ports-install
index 9f999d79c9eeb8711b2ae29118f5d11eea8acb48..9161e5ce49378845ad0d6905684477a0700b4467 100644
--- a/install/ports/ports-install
+++ b/install/ports/ports-install
@@ -7,7 +7,7 @@
 PORTSDIR=${PORTSDIR:-/usr/ports}
 PORTSUBDIR=misc
 SRCDIR=`dirname $0`
-PORTS="emulab-boss emulab-fs emulab-ops emulab-tftp-hpa p5-GD-old p5-DBD-mysql50-old ulsshxmlrpcpp emulab-iperf emulab-php4 emulab-php5 emulab-py-m2crypto emulab-mailman emulab-pubsub emulab-clrhouse emulab-protogeni p5-IO-EventMux p5-IO-EventMux-Socket-MsgHdr p5-Privileges-Drop p5-RPC-Async p5-SNMP"
+PORTS="emulab-boss emulab-fs emulab-ops emulab-tftp-hpa net-snmp4 p5-GD-old p5-DBD-mysql50-old ulsshxmlrpcpp emulab-iperf emulab-php4 emulab-php5 emulab-py-m2crypto emulab-mailman emulab-pubsub emulab-clrhouse emulab-protogeni p5-IO-EventMux p5-IO-EventMux-Socket-MsgHdr p5-Privileges-Drop p5-RPC-Async p5-SNMP"
 
 EPORTS="elvind libelvin emulab-pubsub-elvincompat"
 EPATCH=ports-elvin.patch
diff --git a/install/ports/ulsshxmlrpcpp/Makefile b/install/ports/ulsshxmlrpcpp/Makefile
index d582cee8a2aae16047780e5e1e3974a6c25362a6..ae4f829638eaa3e9d88fc44a68e89c58e9a1f653 100644
--- a/install/ports/ulsshxmlrpcpp/Makefile
+++ b/install/ports/ulsshxmlrpcpp/Makefile
@@ -3,7 +3,7 @@
 # Whom:                 ricci@cs.utah.edu
 
 PORTNAME=	ulsshxmlrpcpp
-PORTVERSION=	0.1.2
+PORTVERSION=	0.1.3
 CATEGORIES=	misc
 MASTER_SITES=	http://www.emulab.net/distributions/
 
diff --git a/install/ports/ulsshxmlrpcpp/distinfo b/install/ports/ulsshxmlrpcpp/distinfo
index 51aabe2e145ca3af244d4b0c115f33af76c5d98b..01d3aad2a141c7f6d00a2ce5ec2fa9a57bf2f07c 100644
--- a/install/ports/ulsshxmlrpcpp/distinfo
+++ b/install/ports/ulsshxmlrpcpp/distinfo
@@ -1,3 +1,3 @@
-SHA256 (ulsshxmlrpcpp-0.1.2.tar.gz) = c88d693b4c5f3b9e1f71051dacce8da95ed259aaf7219626cc7145262dc672d2
-MD5 (ulsshxmlrpcpp-0.1.2.tar.gz) = 60f9e02c35bba1965608c61168244243
-SIZE (ulsshxmlrpcpp-0.1.2.tar.gz) = 866631
+SHA256 (ulsshxmlrpcpp-0.1.3.tar.gz) = c6385a86c8ba55b0b62870cc360a4eab0e15c7d2f73d99f6b014d2e1e0324f41
+MD5 (ulsshxmlrpcpp-0.1.3.tar.gz) = 79ce3f52b7a452427b600ec63ef37a62
+SIZE (ulsshxmlrpcpp-0.1.2.tar.gz) = 871357
diff --git a/ipod/GNUmakefile.in b/ipod/GNUmakefile.in
index b579009e78ad5f1234d1822a8ebda80f50565b3b..5c83c9dc98d402c67caa5f8a0c394f700a1a13e3 100644
--- a/ipod/GNUmakefile.in
+++ b/ipod/GNUmakefile.in
@@ -1,6 +1,6 @@
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2000-2002, 2006 University of Utah and the Flux Group.
+# Copyright (c) 2000-2012 University of Utah and the Flux Group.
 # All rights reserved.
 #
 SRCDIR		= @srcdir@
@@ -12,9 +12,12 @@ include $(OBJDIR)/Makeconf
 
 all: ipod apod
 
+# These binaries installed setuid, with sudo. 
+SETUID_SBIN_PROGS    = ipod
+
 # These scripts installed setuid, with sudo. 
 SETUID_BIN_SCRIPTS   = 
-SETUID_SBIN_SCRIPTS  = ipod apod
+SETUID_SBIN_SCRIPTS  = apod
 SETUID_LIBX_SCRIPTS  =
 
 include $(TESTBED_SRCDIR)/GNUmakerules
diff --git a/security/GNUmakefile.in b/security/GNUmakefile.in
index b0023c35c48f1c62ae67ea7c02f18621a09c5e72..5c04b776f09dfb6163c3cc8ab25b04feebba9841 100644
--- a/security/GNUmakefile.in
+++ b/security/GNUmakefile.in
@@ -1,6 +1,6 @@
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2000-2011 University of Utah and the Flux Group.
+# Copyright (c) 2000-2012 University of Utah and the Flux Group.
 # All rights reserved.
 #
 
@@ -11,13 +11,13 @@ SUBDIR		= security
 
 include $(OBJDIR)/Makeconf
 
-BINS		= suexec
+BINS		= suexec runsuid
 SBINS		= genlastlog lastlog_daemon
 
 # These scripts installed setuid, with sudo. 
 SETUID_BIN_SCRIPTS   = 
-SETUID_SBIN_SCRIPTS  = 
-SETUID_LIBX_SCRIPTS  = suexec
+SETUID_SBIN_SCRIPTS  =
+SETUID_LIBX_PROGS    = suexec runsuid
 
 #
 # Force dependencies on the scripts so that they will be rerun through
@@ -36,6 +36,9 @@ suexec:		suexec.c suexec.h
 		-DSAFE_PATH='"$(prefix)/libexec:/usr/local/bin:/usr/bin:/bin"'\
 		-o suexec $<
 
+runsuid:	runsuid.c ${OBJDIR}/config.h
+	$(CC) $(CFLAGS) -I${OBJDIR} -o runsuid $<
+
 genlastlog:	genlastlog.c
 	$(CC) $(CFLAGS) -I/usr/local/include -I$(TESTBED_LIBSRCDIR)/libtb \
 		-DTBDBNAME='"$(TBDBNAME)"' \
diff --git a/security/checkenv.pl b/security/checkenv.pl
new file mode 100755
index 0000000000000000000000000000000000000000..44e116070163ffce69aa5b90e03ca85a7b53c56b
--- /dev/null
+++ b/security/checkenv.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/perl
+
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2012 University of Utah and the Flux Group.
+# All rights reserved.
+#
+
+#
+# Check the callers environment including IDs.
+# A simple test script for the runsuid suid wrapper.
+#
+
+use English;
+
+my %OENV = %ENV;
+
+# un-taint path ala emulab scripts
+$ENV{'PATH'} = '/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin';
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+
+my $subUID = `/usr/bin/id -ru`; chomp($subUID);
+my $subEUID = `/usr/bin/id -u`; chomp($subEUID);
+my $subGID = `/usr/bin/id -rg`; chomp($subGID);
+my $subEGID = `/usr/bin/id -g`; chomp($subEGID);
+
+print "ARGs:\n";
+foreach my $arg (@ARGV) {
+    print "  '$arg'\n";
+}
+print "IDs:\n";
+print "  UID = $UID\n";
+print "  EUID = $EUID\n";
+print "  GID = $GID\n";
+print "  EGID = $EGID\n";
+print "  subshell-UID = $UID\n";
+print "  subshell-EUID = $EUID\n";
+print "  subshell-GID = $GID\n";
+print "  subshell-EGID = $EGID\n";
+
+my @envstrs = `/usr/bin/env`;
+my %subENV = ();
+foreach (@envstrs) {
+    if (/^([^=]+)=(.*)$/) {
+	$subENV{$1} = $2;
+    }
+}
+
+print "Environment:\n";
+foreach my $var (sort keys %OENV) {
+    print "  $var=$OENV{$var}\n";
+}
+
+print "Subshell environment:\n";
+foreach my $var (sort keys %subENV) {
+    print "  $var=$ENV{$var}\n";
+}
+
+exit(0);
diff --git a/security/genlastlog.c b/security/genlastlog.c
index 81bebe393ebc0242b6df5f944ea81d18d3e287ba..3035c2d5903e3d3692f7f0c89595cba7ecd79be8 100644
--- a/security/genlastlog.c
+++ b/security/genlastlog.c
@@ -45,7 +45,6 @@
 #include <stdio.h>
 #include <time.h>
 #include <sys/types.h>
-#include <utmp.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
diff --git a/security/runsuid.c b/security/runsuid.c
new file mode 100644
index 0000000000000000000000000000000000000000..1273853b562ea09c3f910f4b21bd22287e8f4799
--- /dev/null
+++ b/security/runsuid.c
@@ -0,0 +1,166 @@
+/*
+ * EMULAB-COPYRIGHT
+ * Copyright (c) 2012 University of Utah and the Flux Group.
+ * All rights reserved.
+ */
+
+/*
+ * Replacement for suid perl. Installed setuid, and just execs the
+ * script/binary in the magic directory with the same name as us.
+ * We run the script/binary with the following constraints:
+ *
+ * EUID is 0, UID is not changed.
+ * GID and EGID list is not changed.
+ * Path is set to a standard value
+ * A couple of environment variables are purged.
+ *
+ * The latter two are not things that suidperl would do, but is something
+ * that our scripts routinely do.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include "config.h"
+
+#define SUIDDIR	TBROOT "/suidbin/"
+
+char *safepath[] = {
+	TBROOT "/bin",
+	TBROOT "/sbin",
+	"/bin",
+	"/sbin",
+	"/usr/bin",
+	"/usr/sbin",
+	"/usr/local/bin",
+	"/usr/local/sbin"
+};
+
+char *badvars[] = {
+	"IFS=", "CDPATH=", "ENV=", "BASH_ENV="
+};
+
+static int debug = 1;
+
+static void
+sanedir(char *dir)
+{
+	struct stat sb;
+
+	if (stat(dir, &sb) != 0) {
+		perror(dir);
+		exit(1);
+	}
+	if (sb.st_uid != 0 ||
+	    !S_ISDIR(sb.st_mode) || (sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+		fprintf(stderr, "%s: must be root-owned, unwritable dir\n",
+			SUIDDIR);
+		exit(1);
+	}
+}
+
+static char **
+saneenviron(char **oenvp, char *path)
+{
+	int i, ni, j;
+	char **nenvp;
+	int havepath = 0;
+
+	for (i = 0; oenvp != NULL && oenvp[i] != NULL; i++)
+		if (!strncmp(oenvp[i], "PATH=", 5))
+			havepath++;
+	if (!havepath)
+		i++;
+
+	nenvp = calloc(i, sizeof(char *));
+	if (nenvp == NULL)
+		return NULL;
+
+	for (i = ni = 0; oenvp != NULL && oenvp[i] != NULL; i++) {
+		for (j = 0; j < sizeof(badvars)/sizeof(badvars[0]); j++)
+			if (!strncmp(oenvp[i], badvars[j], strlen(badvars[j])))
+				break;
+		if (j < sizeof(badvars)/sizeof(badvars[0]))
+			continue;
+		if (!strncmp(oenvp[i], "PATH=", 5)) {
+			nenvp[ni++] = path;
+			continue;
+		}
+		nenvp[ni++] = oenvp[i];
+	}
+	if (!havepath)
+		nenvp[ni] = path;
+
+	return nenvp;
+}
+
+int
+main(int argc, char **argv)
+{
+	char *cp, *name = argv[0];
+	char *exepath, *path, **envp;
+	int i, len;
+	extern char **environ;
+
+#if 0
+	if (getuid()) {
+		fprintf(stderr, "%s: not running as root; not suid?\n", name);
+		exit(1);
+	}
+#endif
+
+	/* Check the state of the SUIDDIR */
+	sanedir(SUIDDIR);
+
+	if ((cp = strrchr(name, '/')) == NULL)
+		cp = name;
+	else
+		cp++;
+
+	assert(strlen(cp) > 0);
+	if ((exepath = malloc(strlen(SUIDDIR) + strlen(cp) + 1)) == NULL) {
+	nomem:
+		fprintf(stderr, "%s: no memory!\n", name);
+		exit(2);
+	}
+	strcpy(exepath, SUIDDIR);
+	strcat(exepath, cp);
+
+	len = 0;
+	for (i = 0; i < sizeof(safepath)/sizeof(safepath[0]); i++)
+		len += strlen(safepath[i]) + 1;
+	if ((path = malloc(5+len)) == NULL)
+		goto nomem;
+	strcpy(path, "PATH=");
+	cp = path + 5;
+	for (i = 0; i < sizeof(safepath)/sizeof(safepath[0]); i++) {
+		strcpy(cp, safepath[i]);
+		cp += strlen(safepath[i]);
+		*cp++ = ':';
+	}
+	if (cp != path)
+		*--cp = '\0';
+
+	if ((envp = saneenviron(environ, path)) == NULL)
+		goto nomem;
+
+	argv[0] = exepath;
+
+	if (debug) {
+		printf("Command: '%s'\n", exepath);
+		printf("Args:\n");
+		for (i = 0; argv[i] != NULL; i++)
+			printf("  '%s'\n", argv[i]);
+		if (envp) {
+			printf("Env:\n");
+			for (i = 0; envp[i] != NULL; i++)
+				printf("  '%s'\n", envp[i]);
+		}
+		exit(0);
+	}
+
+	execve(exepath, argv, envp);
+	perror(exepath);
+}
diff --git a/security/sudoers.in b/security/sudoers.in
new file mode 100644
index 0000000000000000000000000000000000000000..c6ab93bb7becebb2956169c3fc70f3b9694ef5d9
--- /dev/null
+++ b/security/sudoers.in
@@ -0,0 +1,46 @@
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2012 University of Utah and the Flux Group.
+# All rights reserved.
+#
+
+#
+# Emulab sudoers file. Serves double duty:
+#
+#  * Allows members of the wheel group to sudo without a password
+#
+#  * Replaces "suidperl" allowing any user to run a script in the
+#    /usr/testbed/suidbin directory as root.
+#
+# For the latter, we clamp down on the environment of the user.
+# suidperl just changed the effective uid to root and left all groups
+# and the environment the same. We clean out the environment, including
+# setting a default path.
+#
+# XXX we do not actually use this config right now since preserve_groups
+# loses the primary group in the resulting group list. Emulab needs all
+# the groups to be unchanged.
+#
+
+# setuid perl scripts
+Cmnd_Alias	SPERL = @prefix@/suidbin/
+
+Defaults	!env_reset
+Defaults	!syslog, logfile="/var/log/sudo.log"
+
+# attempt to preserve suidperl behavior
+Defaults!SPERL	env_reset, stay_setuid, preserve_groups, !set_logname
+# need the following if !env_reset
+#Defaults!SPERL env_delete="IFS CDPATH ENV BASH_ENV", !set_home
+# need the following if env_reset
+Defaults!SPERL	secure_path="@prefix@/bin:@prefix@/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
+
+# set to !logfile to turn off logging of sudo scripts
+Defaults!SPERL	logfile="/var/log/sudo-scripts.log"
+
+root		ALL = (ALL) ALL
+%wheel		ALL = (ALL) NOPASSWD: ALL
+
+# To implement suid perl scripts
+ALL		ALL = (root) NOPASSWD: SPERL
+
diff --git a/sensors/GNUmakefile.in b/sensors/GNUmakefile.in
index 5c1a51d9a1f784e9372c1f7768dc4070dc0d802c..aa2bcc69a571f237b15fd0b5c11a0d15279bb1ff 100644
--- a/sensors/GNUmakefile.in
+++ b/sensors/GNUmakefile.in
@@ -1,6 +1,6 @@
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2002-2011 University of Utah and the Flux Group.
+# Copyright (c) 2002-2012 University of Utah and the Flux Group.
 # All rights reserved.
 #
 SRCDIR		= @srcdir@
@@ -13,15 +13,21 @@ ISMAINSITE	= @TBMAINSITE@
 include $(OBJDIR)/Makeconf
 
 SUBDIRS	= powermon
-ifeq ($(ISMAINSITE),1)
-SUBDIRS += nfstrace
-endif
 
 SYSTEM            := $(shell uname -s)
 
 ifeq ($(SYSTEM),FreeBSD)
 FBSDVERSION   := $(shell uname -v | sed -e 's/FreeBSD \([0-9]\).*/FreeBSD\1/')
 
+ifeq ($(ISMAINSITE),1)
+# XXX nfstrace broke on FBSD 8 and above right now (uses linuxthreads)
+ifneq ($(FBSDVERSION),FreeBSD8)
+ifneq ($(FBSDVERSION),FreeBSD9)
+SUBDIRS += nfstrace
+endif
+endif
+endif
+
 # XXX not on FreeBSD 5/6 til I get a chance to fix it
 ifeq ($(FBSDVERSION),FreeBSD4)
 SUBDIRS += and 
diff --git a/tools/whol/GNUmakefile.in b/tools/whol/GNUmakefile.in
index 47b1b800cacb82aa3df71a1b82e24f3c2a875c4f..9eb5643939baa0a9c2928bc015c3c7c9033a0152 100644
--- a/tools/whol/GNUmakefile.in
+++ b/tools/whol/GNUmakefile.in
@@ -1,6 +1,6 @@
 #
 # EMULAB-COPYRIGHT
-# Copyright (c) 2005, 2006 University of Utah and the Flux Group.
+# Copyright (c) 2005-2012 University of Utah and the Flux Group.
 # All rights reserved.
 #
 
@@ -11,9 +11,12 @@ SUBDIR          = tools/whol
 
 include $(OBJDIR)/Makeconf
 
+# These binaries installed setuid, with sudo. 
+SETUID_SBIN_PROGS    = whol
+
 # These scripts installed setuid, with sudo. 
 SETUID_BIN_SCRIPTS   = 
-SETUID_SBIN_SCRIPTS  = whol
+SETUID_SBIN_SCRIPTS  =
 SETUID_LIBX_SCRIPTS  =
 
 all: whol