Commit ffa8eaf3 authored by Jonathon Duerig's avatar Jonathon Duerig

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents 1ec74da3 ff170013
event/trafgen/tg2.0
.merge-build
......@@ -117,3 +117,25 @@ check: $(TESTS)
fi \
done
endif
ifeq ($(MERGE_BUILD),1)
.PRECIOUS: ${SRCDIR}/*
#
# I really want to say something like:
# ${TESTBED_SRCDIR}/.merged: $(wildcard ${OBJDIR}/${MERGE_BUILD_SANDBOX}/${SUBDIR}/*)
# but that causes problems if one the prereq. has a rule for it (such
# as when both GNUmakefile and GNUmakefile.in exist in the source tree),
# thus I do the equivalent manually
#
newest=$(shell ls -rtd "${OBJDIR}/${MERGE_BUILD_SANDBOX}/${SUBDIR}/"* "${TESTBED_SRCDIR}/.merged" | tail -n 1)
ifneq ($(newest),${TESTBED_SRCDIR}/.merged)
${TESTBED_SRCDIR}/.merged:
cd ${TESTBED_SRCDIR} && utils/merge-build sync
.PHONY: ${TESTBED_SRCDIR}/.merged
else
${TESTBED_SRCDIR}/.merged:
endif
${SRCDIR}/*: ${TESTBED_SRCDIR}/.merged
endif
......@@ -91,4 +91,7 @@ STANDALONE_CLEARINGHOUSE = @STANDALONE_CLEARINGHOUSE@
NODE_USAGE_SUPPORT = @NODE_USAGE_SUPPORT@
MERGE_BUILD = @MERGE_BUILD@
MERGE_BUILD_SANDBOX = @MERGE_BUILD_SANDBOX@
EXP_VIS_SUPPORT = @EXP_VIS_SUPPORT@
......@@ -158,6 +158,10 @@ if (@ARGV < 1) {
my $orgunit = shift(@ARGV);
my $uuid = (@ARGV ? shift(@ARGV) : undef);
# Moved before uuid generation. Might be a race, might not.
TBScriptLock("mkusercert") == 0 or
fatal("Could not get the lock!");
# Generate/confirm uuid
if (!defined($uuid)) {
$uuid = NewUUID();
......@@ -176,9 +180,6 @@ if (!defined($email)) {
chdir("$WORKDIR") or
fatal("Could not chdir to $WORKDIR: $!");
TBScriptLock("mkusercert") == 0 or
fatal("Could not get the lock!");
#
# Need an index file, which is the openssl version of the DB.
#
......
......@@ -44,11 +44,24 @@ $(INSTALL_APACHE_CONFIG)/%: %
# This could (should?) be done with configure, but apache port might
# not be installed when we configure our software.
#
# XXX ugh, do the same thing to detect php5...
#
httpd.conf.fixed: httpd.conf
-@cp httpd.conf httpd.conf.fixed
@if [ -x /usr/local/libexec/apache/mod_auth_mysql.so ]; then \
sed -i "" -e '/^LoadModule auth_mysql/s/libauth/mod_auth/' httpd.conf.fixed; \
echo "Updated httpd.conf"; \
echo "Updated httpd.conf for auth_mysql"; \
fi
@if [ -x /usr/local/libexec/apache/libphp5.so ]; then \
sed -i "" -e 's/php4/php5/g' httpd.conf.fixed; \
echo "Updated httpd.conf for php5"; \
fi
httpd.conf-ops.fixed: httpd.conf-ops
-@cp httpd.conf-ops httpd.conf-ops.fixed
@if [ true -o -x /usr/local/libexec/apache/libphp5.so ]; then \
sed -i "" -e 's/php4/php5/g' httpd.conf-ops.fixed; \
echo "Updated httpd.conf-ops for php5"; \
fi
install-dirs:
......@@ -82,8 +95,8 @@ endif
install: install-dirs install-scripts httpd.conf.fixed
$(INSTALL_DATA) httpd.conf.fixed $(INSTALL_APACHE_CONFIG)/httpd.conf
control-install: install-dirs install-scripts httpd.conf-ops
$(INSTALL_DATA) httpd.conf-ops $(INSTALL_APACHE_CONFIG)/httpd.conf
control-install: install-dirs install-scripts httpd.conf-ops.fixed
$(INSTALL_DATA) httpd.conf-ops.fixed $(INSTALL_APACHE_CONFIG)/httpd.conf
else
install-scripts install control-install:
@echo "Cannot install Apache config in dev tree"
......
......@@ -428,18 +428,7 @@ DocumentRoot "@prefix@/www"
<Directory @prefix@>
Order allow,deny
deny from all
allow from 155.99.212.
allow from 155.98.60.
allow from 69.59.212.104
allow from 18.31.0.114
allow from 18.31.0.144
allow from 24.254.69.120
# Jay's machines.
allow from 207.173.21.122
allow from 207.173.21.123
allow from 207.173.21.126
# Tim Stack
allow from 66.219.220.49
</Directory>
<Directory @prefix@/webglimpse>
......
......@@ -305,7 +305,7 @@ float find_link_resolutions(resolution_vector &resolutions, pvertex pv,
// Check only whether the dest interface is fixed - this is the
// last link in a multi-hop path
SDEBUG(cerr << " intraswitch: finding second link (" << ")" << endl;)
if (!find_best_link(dest_pv,*switch_it,vlink,second,flipped,
if (!find_best_link(dest_pv,*switch_it,vlink,second,!flipped,
false,true)) {
// No link to this switch
SDEBUG(cerr << " intraswitch failed - no link second" <<
......@@ -389,7 +389,7 @@ float find_link_resolutions(resolution_vector &resolutions, pvertex pv,
if (second_link) {
// Check only whether the dest interface is fixed - this is the
// last link in a multi-hop path
if (!find_best_link(dest_pv,*dest_switch_it,vlink,second,flipped,
if (!find_best_link(dest_pv,*dest_switch_it,vlink,second,!flipped,
false,true)) {
// No link to tshis switch
SDEBUG(cerr << " interswitch failed - no second link" << endl;)
......@@ -521,6 +521,7 @@ void resolve_link(vvertex vv, pvertex pv, tb_vnode *vnode, tb_pnode *pnode,
if (dest_vv == vv) {
dest_vv = source(edge,VG);
SDEBUG(cerr << " dest_vv is backwards" << endl);
}
/*
......@@ -1508,14 +1509,14 @@ bool find_best_link(pvertex pv,pvertex switch_pv,tb_vlink *vlink,
// XXX: Not 100% sure it's better to do this inside find_best_link rather
// than in the caller
// if (flipped) {
// // If the endpoints are flipped, then we need to flip our notion of
// // which ones need to be compared.
// bool tmp = check_src_iface;
// check_src_iface = check_dst_iface;
// check_dst_iface = tmp;
// SDEBUG(cerr << " find_best_link: flipping interface comparisons" << endl;)
// }
if (flipped) {
// If the endpoints are flipped, then we need to flip our notion of
// which ones need to be compared.
bool tmp = check_src_iface;
check_src_iface = check_dst_iface;
check_dst_iface = tmp;
SDEBUG(cerr << " find_best_link: flipping interface comparisons" << endl;)
}
SDEBUG(cerr << " find_best_link: fix_src_iface = " <<
vlink->fix_src_iface << " check_src_iface = " << check_src_iface
......
......@@ -286,7 +286,7 @@ foreach $key (keys(%{ $xmlparse->{'attribute'} })) {
}
}
$newosid_args{$key} = $value;
$newosid_args{$dbslot} = $value;
}
UserError()
if (keys(%errors));
......
This diff is collapsed.
......@@ -813,6 +813,28 @@ if test "$TBMAINSITE" = 1; then
FANCYBANNER=1
fi
#
# Merge build
#
MERGE_BUILD=0
MERGE_BUILD_SANDBOX=
if test -e "$srcdir/.merge-build"; then
merge_sandbox=`grep source-tree "$srcdir/.merge-build" | cut -d' ' -f2`
merge_tree=`grep merge-tree "$srcdir/.merge-build" | cut -d' ' -f2`
if test "$srcdir" -ef "$srcdir/$merge_sandbox/$merge_tree"; then
MERGE_BUILD=1
MERGE_BUILD_SANDBOX=$srcdir/$merge_sandbox
echo "#/bin/sh" > sync
echo >> sync
echo "cd \"$srcdir\"" >> sync
echo "utils/merge-build sync" >> sync
chmod +x sync
echo "Merge-build enabled"
fi
fi
AC_SUBST(MERGE_BUILD)
AC_SUBST(MERGE_BUILD_SANDBOX)
outfiles="$outfiles Makeconf GNUmakefile \
assign/GNUmakefile \
named/GNUmakefile firewall/GNUmakefile \
......@@ -935,6 +957,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tmcd/linux9/GNUmakefile tmcd/linux9/supfile \
tmcd/fedora/GNUmakefile tmcd/fedora/supfile \
tmcd/linux-sg/GNUmakefile tmcd/ubuntu7/GNUmakefile \
tmcd/ubuntu10/GNUmakefile \
tmcd/freebsd5/GNUmakefile tmcd/freebsd5/supfile \
tmcd/freebsd6/GNUmakefile tmcd/freebsd6/supfile tmcd/freebsd6/netif-emulab \
tmcd/freebsd7/GNUmakefile tmcd/freebsd7/supfile tmcd/freebsd7/netif-emulab \
......
......@@ -118,7 +118,8 @@ my $EXPT_RESOURCESHOSED = 0;
"v2pmap" => ["node_id", "vname"],
"linkdelays" => ["node_id", "vlan", "vnode"],
"traces" => ["node_id", "idx"],
"portmap" => undef);
"portmap" => undef,
"bridges" => ["node_id", "bridx", "iface"]);
# These are slots in the node table that need to be restored.
my @nodetable_fields = ("def_boot_osid",
......@@ -4230,6 +4231,20 @@ sub SetPortRange($$)
DBQueryWarn("unlock tables");
return ($newlow, $newhigh);
}
sub GetPortRange($)
{
my ($self) = @_;
my $idx = $self->idx();
my $query_result =
DBQueryWarn("select low,high from ipport_ranges where exptidx=$idx");
return undef
if (!defined($query_result) || !$query_result->numrows);
my ($low,$high) = $query_result->fetchrow_array();
return ($low, $high);
}
#
# Reserve all of the shared BW we need. The vinterfaces table has
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2007-2009 University of Utah and the Flux Group.
# Copyright (c) 2007-2010 University of Utah and the Flux Group.
# All rights reserved.
#
package Lan;
......@@ -1389,6 +1389,22 @@ sub GetNodeIface($$$)
return 0;
}
#
# Get the Interface structure.
#
sub GetInterface($)
{
my ($self) = @_;
my $node;
my $iface;
require Interface;
return -1
if ($self->GetNodeIface(\$node, \$iface));
return Interface->LookupByIface($node, $iface);
}
############################################################################
#
......@@ -2584,7 +2600,8 @@ sub ExperimentVLans($$$)
DBQueryWarn("select l.lanid from lans as l ".
"left join lan_attributes as la on ".
" la.lanid=l.lanid and la.attrkey='class' ".
"where l.type='vlan' and l.exptidx='$exptidx' and ".
"where (l.type='vlan' or l.type='wire') ".
" and l.exptidx='$exptidx' and ".
" (la.attrvalue='Experimental' or ".
" la.attrvalue is null)");
return -1
......
......@@ -291,8 +291,12 @@ sub Create($$$$)
print STDERR "*** No virtnode_capacity for $type! Using zero.\n";
$virtnode_capacity = 0;
}
if ($isremote) {
$osid = 0;
if ($typeinfo->isswitch()) {
$osid = "NULL";
$opmode = "ALWAYSUP";
}
elsif ($isremote) {
$osid = "NULL";
$opmode = "";
if (defined($typeinfo->default_osid())) {
......@@ -330,7 +334,7 @@ sub Create($$$$)
}
}
else {
$osid = 0;
$osid = "NULL";
$opmode = "";
}
$state = $STATE_INITIAL;
......@@ -370,7 +374,7 @@ sub Create($$$$)
" phys_nodeid='$node_id', role='$role', ".
" priority=$priority, " .
" eventstate='$state', op_mode='$opmode', " .
" def_boot_osid='$osid', " .
" def_boot_osid=$osid, " .
" inception=now(), uuid=$uuid, ".
" state_timestamp=unix_timestamp(NOW()), " .
" op_mode_timestamp=unix_timestamp(NOW())")) {
......
#
# This is the definitions file for Weibin on Emulab.Net.
#
. defs-default
TBOPSEMAIL=wbsun@flux.utah.edu
TBLOGSEMAIL=wbsun@flux.utah.edu
TBWWWEMAIL=wbsun@flux.utah.edu
TBAPPROVALEMAIL=wbsun@flux.utah.edu
TBAUDITEMAIL=wbsun@flux.utah.edu
TBSTATEDEMAIL=wbsun@cs.utah.edu
TBTESTSUITEEMAIL=wbsun@cs.utah.edu
WWW=www.emulab.net/dev/wbsun
THISHOMEBASE=Wbsun.Emulab.Net
......@@ -37,6 +37,14 @@ if [ ! -d $dir/iperf-$version/src ]; then
echo "ERROR: iperf-fetch.sh: tar failed"
exit 1
}
# XXX hack to deal with relative paths...argh!
case $srcdir in
/*)
;;
*)
srcdir="../$srcdir"
;;
esac
cd iperf-$version && patch -p0 < $srcdir/iperf-patch || {
echo "ERROR: iperf-fetch.sh: patch failed"
exit 1
......
......@@ -40,6 +40,15 @@ if [ ! -d $dir/rude-$version/src ]; then
if [ -d rude -a ! -d rude-$version ]; then
mv rude rude-$version
fi
# XXX hack to deal with relative paths...argh!
case $srcdir in
/*)
;;
*)
srcdir="../$srcdir"
;;
esac
cd rude-$version && patch -p0 < $srcdir/rude-patch || {
echo "ERROR: rude-fetch.sh: patch failed"
exit 1
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2008 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -1767,7 +1767,7 @@ parse_configfile(char *filename)
while (fgets(buf, sizeof(buf), fp)) {
int cc = strlen(buf);
if (buf[cc-1] == '\n')
buf[cc-1] = (char) NULL;
buf[cc-1] = '\0';
if (!strncmp(buf, "UID=", 4)) {
if (user) {
......@@ -1896,7 +1896,7 @@ parse_configfile_env(char *filename)
FILE *file;
if (buf[cc-1] == '\n')
buf[cc-1] = (char) NULL;
buf[cc-1] = '\0';
if (isops)
bp = buf;
......
......@@ -42,16 +42,16 @@ PFLAGS = -pthread
PFLAGS += -DDEBUG
PFLAGS += -O2 -g -Wall
PFLAGS += -I. -I${OBJDIR} -I$(SRCDIR)/../lib -I$(TESTBED_SRCDIR)/lib/libtb
PFLAGS += -L/usr/local/lib -lpubsub_r -lm
PFLAGS += -L/usr/local/lib -lpubsub_r -ltb -lm
PLDFLAGS += -L$(OBJDIR)/lib -L$(OBJDIR)/lib/libtb -L../lib
PLIBS = -levent_r -ltb -lcrypto
PLIBS += -L/usr/local/lib -lpubsub_r -lm
PLIBS += -L/usr/local/lib -lpubsub_r -ltb -lm
PLDFLAGS += $(LDSTATIC)
LDFLAGS += -L$(OBJDIR)/lib -L$(OBJDIR)/lib/libtb -L../lib
LIBS = -levent -ltb -lcrypto
LIBS += -L/usr/local/lib -lpubsub -lm
LIBS += -L/usr/local/lib -lpubsub -ltb -lm
LDFLAGS += $(LDSTATIC)
# Deal with the presence/absence of kerberos in the linux ssl library
......@@ -89,7 +89,7 @@ evproxyplab-debug: evproxyplab.o ../lib/libevent.a ../lib/event.h
version0_gateway: version0_gateway.c
$(CC) $(CFLAGS) $(PLDFLAGS) -pthread -o $@ $< -L/usr/local/lib \
-lpubsub_r -lm
-lpubsub_r -ltb -lm
eventping-debug: eventping.o
$(CC) $(LDFLAGS) -o $@ eventping.o -pthread $(LIBS)
......
......@@ -207,6 +207,7 @@ main(int argc, char **argv)
static char notify_debug_string[2*BUFSIZ];
#if 0
static int
pubsub_notify_traverse_debug(void *arg, char *name,
pubsub_type_t type, pubsub_value_t value,
......@@ -258,6 +259,7 @@ pubsub_notify_traverse_debug(void *arg, char *name,
return 1;
}
#endif
static void
pubsub_callback(pubsub_handle_t *handle,
......
......@@ -819,8 +819,8 @@ sub stateTransition($$) {
objname => $node);
next;
};
(/^$TBPOWERCYCLE$/) && do {
handleCommand($node,$TBPOWERCYCLE);
(/^$TBREBOOT$/ || /^$TBPOWERCYCLE$/) && do {
handleCommand($node,$trig);
next;
};
/^RELOADOLDMFS$/ && do {
......@@ -1010,8 +1010,7 @@ sub handleCtrlEvent($$) {
}
my $cmd = "$nodereboot -r $optarg $node";
debug("$cmd\n");
system("date 2>&1 >> $rebootlog");
system("$cmd 2>&1 >> $rebootlog &") and
system("(date; $cmd) >>$rebootlog 2>&1 &") and
notify("$PXEWAKEUP retry: ".
"Command '$cmd' failed, error $?: $!\n");
......@@ -1084,6 +1083,7 @@ sub handleCommand($$;$$) {
debug("Checking rebooting: $node, $nodes{$node}, ".
"$nodes{$node}{state}, $nodes{$node}{noretry}\n");
if (($nodes{$node}{state} ne TBDB_NODESTATE_ISUP) &&
($nodes{$node}{state} ne TBDB_NODESTATE_TBFAILED) &&
(!$nodes{$node}{noretry}) ) {
# This node shouldn't be rebooted now...
# XXX Send feedback here somehow!
......@@ -1102,14 +1102,11 @@ sub handleCommand($$;$$) {
info("Rebooting nodes: $nodelist\n");
# Permissions were checked in order to send the message,
# so we don't need to do any fancy stuff here.
my $cmd = "$nodereboot -r $nodelist";
my $redir = " 2>&1 >> $rebootlog &";
debug("$cmd $redir\n");
system("date $redir");
system($cmd.$redir) and
notify("$params/$command: ".
"Command '$cmd' failed, error $?: $!\n");
debug("$cmd\n");
system("(date; $cmd) >>$rebootlog 2>&1 &") and
notify("$params/$command: ".
"Command '$cmd' failed, error $?: $!\n");
# Set up a timeout, so we retry if we don't get SHUTDOWN in time
foreach $node (@nodes) {
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2007 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -209,7 +209,7 @@ main(int argc, char **argv)
if ((bp = strchr(temp, '/')) == NULL)
fatal("Malformed pid/eid: %s", myeid);
*bp++ = (char) NULL;
*bp++ = '\0';
sprintf(keyfilebuf, "/proj/%s/exp/%s/tbdata/eventkey",
temp, bp);
......@@ -292,7 +292,7 @@ main(int argc, char **argv)
* XXX For now, uppercase the strings, and remove trailing _.
*/
if (argc) {
buf[0] = (char) NULL;
buf[0] = '\0';
while (argc) {
if (strlen(*argv) + strlen(buf) >= sizeof(buf)-2)
fatal("Too many event argument strings!");
......@@ -309,8 +309,8 @@ main(int argc, char **argv)
bp++;
}
if (*(bp-1) == '_')
*(bp-1) = (char) NULL;
*bp++ = (char) NULL;
*(bp-1) = '\0';
*bp++ = '\0';
sprintf(&buf[strlen(buf)], "%s=%s ", *argv, bp);
}
......
......@@ -46,7 +46,6 @@ my $FRISADDR = '@FRISEBEEMCASTADDR@';
#
# Fixed paths for clients
#
my $PROJROOT = "@PROJROOT_DIR@";
my $GROUPROOT = "@GROUPSROOT_DIR@";
my $USERROOT = "@USERSROOT_DIR@";
my $SCRATCHROOT = "@SCRATCHROOT_DIR@";
......@@ -94,7 +93,6 @@ my $SYSLOG_CONF = "/etc/syslog.conf";
my $NEWSYSLOG_CONF = "/etc/newsyslog.conf";
my $INETD_CONF = "/etc/inetd.conf";
my $PROTOUSER = "elabman";
my $PROTOUSER_KEY = "$TOP_SRCDIR/install/elabman_dsa.pub";
my $ROOT_PRIVKEY = "/root/.ssh/id_rsa";
my $ROOT_PUBKEY = "$ROOT_PRIVKEY.pub";
......@@ -111,7 +109,6 @@ my $DHCPD_TEMPLATE = "/usr/local/etc/dhcpd.conf.template";
my $DHCPD_LEASES = "/var/db/dhcpd.leases";
my $DHCPD_MAKECONF = "$PREFIX/sbin/dhcpd_makeconf";
my $BATCHEXP = "$PREFIX/bin/batchexp";
my $WAP = "$PREFIX/sbin/withadminprivs";
my $NAMED_SETUP = "$PREFIX/sbin/named_setup";
my $ADDPUBKEY = "$PREFIX/sbin/addpubkey";
my $TBACCT = "$PREFIX/sbin/tbacct";
......@@ -153,10 +150,6 @@ my $TFTPD_PKG = "emulab-tftp-hpa-0.48";
# XXX temporary for perl DBD mysql access
my $P5DBD_PKG = "p5-DBD-mysql50-3.0002";
# XXX temporary until fix dependencies in emulab-boss package
my $PYM2_PKG = "py25-m2crypto-0.19.1";
# XXX temporary until someone extracts their head from the dark regions
my $EASYINSTALL = "/usr/local/bin/easy_install";
#
# Named pid file.
......@@ -255,7 +248,12 @@ else {
#
my $BOSS_PORT = "emulab-boss-1.8";
if ($FBSD_MAJOR > 4) {
if ($FBSD_MAJOR > 6) {
if ($FBSD_MAJOR > 7) {
# XXX someday...
$BOSS_PORT = "emulab-boss-4.0";
} elsif ($FBSD_MAJOR == 7 && $FBSD_MINOR > 2) {
$BOSS_PORT = "emulab-boss-3.1";
} elsif ($FBSD_MAJOR == 7) {
$BOSS_PORT = "emulab-boss-3.0";
} elsif ($FBSD_MAJOR == 6 && $FBSD_MINOR > 2) {
$BOSS_PORT = "emulab-boss-2.1";
......@@ -263,7 +261,26 @@ if ($FBSD_MAJOR > 4) {
$BOSS_PORT = "emulab-boss-2.0";
}
}
my $PHP4_PORT = "php4-extensions-1.0";
# PHP5 is the only alternative at the moment and only for newer OSes
my $PHP_VERSION = 4;
my $PHP_PORT = "php4-extensions-1.0";
if ($FBSD_MAJOR > 7 || ($FBSD_MAJOR == 7 && $FBSD_MINOR > 2)) {
$PHP_VERSION = 5;
$PHP_PORT = "php5-extensions-1.3";
}
#
# Version dependent python-fu
#
my $PYM2_PKG = "py25-m2crypto-0.19.1";
my $PY_VER = "python2.5";
if ($FBSD_MAJOR > 7 || ($FBSD_MAJOR == 7 && $FBSD_MINOR > 2)) {
$PYM2_PKG = "py26-m2crypto-0.20";
$PY_VER = "python2.6";
}
# XXX temporary until someone extracts their head from the dark regions
my $EASYINSTALL = "/usr/local/bin/easy_install";
#
# XXX keep 4.x ElabInElab install limping along...
......@@ -447,15 +464,19 @@ Phase "ports", "Installing ports", sub {
ExecQuietFatal("$ENV PKG_PATH=$packagedir $PKG_ADD $BOSS_PORT");
};
if ($FBSD_MAJOR > 4) {
Phase "php4", "Installing php4 package", sub {
if (!ExecQuiet("$PKG_INFO -e $PHP4_PORT")) {
PhaseSkip("Port already installed");
Phase "php", "Installing php${PHP_VERSION} package", sub {
if (!ExecQuiet("$PKG_INFO -e $PHP_PORT")) {