#!/usr/bin/env perl

	##these are the files that need to be staged on the remote machine
$config = "condor_config.glidein";
@DAEMONS = ( "condor_master", "condor_startd", "condor_starter",
			 "condor_starter.std", "condor_pvmd", "condor_starter.pvm" );


if ( ( $error = parse_command_line() )
		|| ( $error = gather_info() ) )
{
	print STDERR "$error\n";
	exit( 1 );
}

foreach $CONTACT ( @CONTACTS ) {
	if ( host_info() ) {
		next;
	}

	if ( !$runonly ) {
		if ( $error = do_remote_setup() ) {
			print STDERR "Error: $error\n";
			exit( 2 );
		}
	}
	if ( !$setuponly ) {
		if ( do_submit() ) {
			print STDERR "Error: condor_submit failed.\n";
			exit( 3 );
		}
	}
}

exit( 0 );

## END OF PROGRAM

sub do_submit() {

	if ( $arch =~ /linux/ ) {
		$mail_arch = "/usr/bin/mail";
	}
	elsif ( $arch =~ /solaris/ ) {
		$mail_arch = "/usr/ucb/mail";
	}
	elsif ( $arch =~ /irix/ ) {
		$mail_arch = "/usr/sbin/mailx";
	}
	else {
		$mail_arch = "/bin/mail";
	}
	$GLOBUSRSL = "";
	if ( $queue ) {
		$GLOBUSRSL .= "(queue=$queue)";
	}
	if ( $project ) {
		$GLOBUSRSL .= "(project=$project)";
	}
	if ( $globus_run_time ) {
		$GLOBUSRSL .= "(maxTime=$globus_run_time)";
	}
	if ( $memory ) {
		$GLOBUSRSL .= "(maxMemory=$memory)";
	}
	if ( $cpucount > 1 ) {
			##claim N cpus, but only run one copy of the program
		$GLOBUSRSL .= "(count=$cpucount)(jobtype=single)";
	}

	$GLOBUSENV .= "CONDOR_CONFIG=$basedir/$config;";
	$GLOBUSENV .= "_condor_CONDOR_HOST=$CONDOR_HOST;";

	chomp( $my_hostname = `$G_HOSTNAME` );
	$GLOBUSENV .= "_condor_GLIDEIN_HOST=$my_hostname;";

	$GLOBUSENV .= "_condor_LOCAL_DIR=$localdir;";
	$GLOBUSENV .= "_condor_SBIN=$archdir;";

	$GLOBUSENV .= "_condor_CONDOR_ADMIN=$condor_admin;";

		##if submitting to Condor scheduler under Globus, don't want "queue <n>"
		##starting <n> copies, EACH asking for <n> CPUs, that would give us
		## <n>**2 CPUs....
	if ( $CONTACT =~ /condor/ ) {
		$GLOBUSENV .= "_condor_NUM_CPUS=1;";
	}
	else {
		$GLOBUSENV .= "_condor_NUM_CPUS=$cpucount;";
	}
	$GLOBUSENV .= "_condor_UID_DOMAIN=$UID_DOMAIN;";
	$GLOBUSENV .= "_condor_FILESYSTEM_DOMAIN=$UID_DOMAIN;";
	$GLOBUSENV .= "_condor_MAIL=$mail_arch;";
	if ( $idle_time != 0 ) {
		$GLOBUSENV .= "_condor_STARTD_NOCLAIM_SHUTDOWN=" . ($idle_time * 60) . ";";
	}
	if ( $memory ) {
		$kmem = $memory * 1024;
		$GLOBUSENV .= "_condor_MEMORY=$kmem;";
	}
	if ( $anybody ) {
		$GLOBUSENV .= "_condor_START=True;";
	}
	else {
		$GLOBUSENV .= "_condor_START_owner=$ENV{'LOGNAME'};";
	}
	if ( $vmcount != $cpucount ) {
		$GLOBUSENV .= "_condor_VIRTUAL_MACHINE_TYPE_1=1/$vmcount;";
		$GLOBUSENV .= "_condor_NUM_VIRTUAL_MACHINES_TYPE_1=$vmcount;";
	}

		##Condor has trouble determining ARCH on some
		##high-performance HP-UX machines because they have a
		##minimal OS install.  So, set the ARCH here if we
		##know it.
	if ( $arch =~ /hppa2/ ) {
		$GLOBUSENV .= "_condor_ARCH=HPPA2;";
	}
	elsif ( $arch =~ /hppa1/ ) {
		$GLOBUSENV .= "_condor_ARCH=HPPA1;";
	}

	chomp( $skipauth = `$CONFIGVAL SKIP_AUTHENTICATION 2>/dev/null` );
	if ( $skipauth ne "" ) {
		$GLOBUSENV .= "_condor_SKIP_AUTHENTICATION=$skipauth;";
	}

	if ( $master_run_time ) {
		$GLOBUSENV .= "_condor_DaemonStopTime=DaemonStartTime+(${master_run_time}*60);";
	}

	chop $GLOBUSENV;

	$arguments = "-dyn -f";
	if ( $master_run_time ) {
		$arguments .= " -r $master_run_time";
	}

		##Escape '$' in submit file entries
	$archdir =~ s/\$/\$(DOLLAR)/g;
	$GLOBUSRSL =~ s/\$/\$(DOLLAR)/g;
	$GLOBUSENV =~ s/\$/\$(DOLLAR)/g;

		##generate condor_submit description file
	if ( $gen_submit ) {
		open( SUBMIT, ">submit.glidein" );
	} else {
		open( SUBMIT, "|$submit" );
	}
	print SUBMIT <<"EOF";
Universe = Globus

Executable = $archdir/condor_master

Arguments = $arguments

Environment = ${GLOBUSENV}

Transfer_Executable = False

GlobusRSL = ${GLOBUSRSL}

GlobusScheduler = $CONTACT
Queue

EOF
	close( SUBMIT );
	if ( $gen_submit ) {
		return 0;
	} else {
		return ($?);
	}
}


sub gather_info() {
		##ensure the needed condor programs are avail...
	chomp( $submit = `which condor_submit` );
	chomp( $CONFIGVAL = `which condor_config_val` );
	chomp( $STATUS = `which condor_status` );
	if ( ! ( -x $CONFIGVAL && -x $STATUS && -x $submit ) ) {
		return( "cannot find programs \"condor_config_val\" or "
				. "\"condor_status\" or \"condor_submit\" needed for setup" );
	}

	if ( !defined( $condor_admin ) ) {
		chomp( $condor_admin = getlogin() . '@' . `$CONFIGVAL UID_DOMAIN`);
	}

	chomp( $CONDOR_HOST = `$CONFIGVAL CONDOR_HOST` );

	#set CONDOR_VERSION
	$TMP = `$STATUS -master -format "%s" CondorVersion $CONDOR_HOST`;
		#if we get a blank response because the collector isn't running
		#a master in the same pool, try our master...
	if ( $? != 0 || !($TMP =~ /\S/) ) {
			$HOST = $ENV{'HOST'};
			$TMP = `$STATUS -master -format "%s" CondorVersion $HOST`;
			if ( $? != 0 ) {
				$TMP = "";
			}
	}
	( $_, $CONDOR_VERSION, $_) = split( / *[$: ]+/, $TMP );
	if ( $CONDOR_VERSION eq "" ) {
		return( "Can't determine Condor version.\n" );
	}

	#Find out where the glidein tarball server is
	chomp( $SERVER_NAME = `$CONFIGVAL GLIDEIN_SERVER_NAME` );
	if ( $SERVER_NAME eq "" ) {
	    return( "Error, GLIDEIN_SERVER_NAME needs to be defined in the Condor config file" );
	}
	chomp( $SERVER_DIR = `$CONFIGVAL GLIDEIN_SERVER_DIR` );
	if ( $SERVER_DIR eq "" ) {
	    return( "Error, GLIDEIN_SERVER_DIR needs to be defined in the Condor config file" );
	}

		##if archdir was specified on command line
	if ( defined( $ARCHDIR ) ) {
		$archdir = $ARCHDIR;
	}

		## globus programs
	chomp( $G_RUN = `which globusrun 2>/dev/null` );
	if ( ! -x $G_RUN ) {
	    return( "Error, cannot find globusrun" );
	}
	chomp( $G_INFO = `which grid-proxy-info 2>/dev/null` );
	if ( ! -x $G_INFO ) {
	    return( "Error, cannot find grid-proxy-info" );
	}
	chomp( $G_SEARCH = `which grid-info-search 2>/dev/null` );
	if ( ! -x $G_SEARCH ) {
	    return( "Error, cannot find grid-info-search" );
	}
	chomp( $G_HOSTNAME = `which globus-hostname 2>/dev/null` );
	if ( ! -x $G_HOSTNAME ) {
	    return( "Error, cannot find globus-hostname" );
	}

	if ( silently( "$G_INFO -exists" ) ) {
		return( "$NAME needs a valid grid proxy. (Re)run grid-proxy-init." );
	}
	if ( silently( "$G_INFO -exists -hours 4" ) ) {
		return( "Your grid proxy expires in less than four hours.\n"
			. "Rerun grid-proxy-init." );
	}

		##also, ensure GLOBUS_LOCATION and HOME are set in ENV
	if ( !defined( $ENV{'HOME'} ) ) {
		return( "$NAME: $HOME not in your ENV" );
	}
	if ( !defined( $ENV{'GLOBUS_LOCATION'} ) )
	{
		return( "$NAME: GLOBUS_LOCATION "
			. "must be defined in your ENV" );
	}

	return( 0 );
}

sub usage() {
		#print out the command line options
	print STDERR "Usage: $NAME [options] [<globus contact>]\n";
	print STDERR "\tWhere <globus contact> is of form:\n";
	print STDERR "\t<hostname> | <hostname>/jobmanager-<scheduler> | <full contact string>\n";

print STDERR "	Valid options:\n"
. "   -basedir <name>         Use <name> as remote base directory\n"
. "                            [default: \$(HOME)/Condor_glidein]\n"
. "   -archdir <name>         Specify remote dir for daemon executables\n"
. "                            [default is built from system config info]\n"
. "   -localdir <name>        Use <name> as remote base for log/execute dirs\n"
. "                            [default on remote host: <basedir>/local]\n"
. "   -contactfile <file>     Specify file from which to read Globus contacts\n"
. "   -setuponly|-runonly     Setup and exit  |  No setup, just run\n"
. "   -forcesetup             During setup, force copying of files\n"
. "   -queue <queue>          Queue to use on Globus scheduler\n"
. "   -project <project>      Project to use on Globus resource\n"
. "   -memory <Mbytes>        Amount of memory to request\n"
. "   -count <CPU count>      Number of CPUs to request [default=1]\n"
. "   -vms <VM count>         Number of virtual machines to split up\n"
. "                            allocated resources into [default=<CPU count>]\n"
. "   -runtime <mins>         Maximum run time on Globus resource\n"
. "   -idletime <mins>        Remote daemons exit gracefully after <mins>\n"
. "                            without running a Condor job [default=20]\n"
. "   -anybody                Allow any user to run jobs on your glideins\n"
. "   -admin <email address>  Who to email with problems [default=<you>]\n"
. "   -genconfig              Generate condor_config.glidein\n"
. "   -useconfig <file>       Use the specifed config file\n"
. "   -gensubmit              Generate submit.glidein\n"
. "   -edg                    Use EDG MDS schema to query GRIS\n"
. "   -help                   Print this usage, see documentation for info\n";
}

sub parse_command_line() {
		#parse command line options
	($NAME = $0) =~ s/.*\///; ## strip off directory path...
	$idle_time = 20;
	$cpucount = 1;
	$vmcount = 0;
	$basedir = '$(HOME)/Condor_glidein';
	##don't set default archdir because it is built below from pool version, arch
	$localdir = "";
	$use_config = "";
	chomp( $username = `whoami` );

	use Getopt::Long;
	$RESULT = GetOptions(
		"basedir=s" => \$basedir,
		"archdir=s" => \$ARCHDIR,
		"localdir=s" => \$localdir,
		"contactfile=s" => \$contactfile,
		"setuponly" => \$setuponly,
		"runonly" => \$runonly,
		"forcesetup" => \$force_setup,
		"queue=s" => \$queue,
		"project=s" => \$project,
		"memory=i" => \$memory,
		"count=i" => \$cpucount,
		"vms=i" => \$vmcount,
		"runtime=i" => \$globus_run_time,
		"idletime=i" => \$idle_time,
		"anybody" => \$anybody,
		"admin=s" => \$condor_admin,
		"genconfig" => \$gen_config,
		"useconfig=s" => \$use_config,
		"gensubmit" => \$gen_submit,
		"edg" => \$edg_mds_schema,
		"help" => \$help );
	if ( !$RESULT ) {
		usage();
		exit( 1 );
	}

	if ( $vmcount == 0 ) {
		$vmcount = $cpucount;
	} elsif ( $cpucount % $vmcount ) {
		return( "ERROR: $NAME --vms must be a factor of --count");
	}

	if ( $localdir eq "" ) {
		$localdir = "$basedir/local";
	}

	if ( $setuponly && $runonly ) {
		return( "ERROR: $NAME --setuponly and --runonly are mutually exclusive");
	}

	if ( ! $force_setup ) {
		$force_setup = 0;
	}

	if ( $globus_run_time ) {
		if ( $globus_run_time > 0 ) {
			# Tell the master to shutdown a minute before the Globus limit
			$master_run_time = $globus_run_time - 1;
		} else {
			return( "ERROR: $NAME --runtime must be positive" );
		}
	}

	if ( $help ) {
		print STDERR "Add a remote node to your local Condor pool\n";
		print STDERR "For detailed help, see the condor documentation "
			. "concerning condor_glidein\n\n";
		usage();
		exit( 0 );
	}

	if ( $contactfile ) {
		open( CONTACTS, "< $contactfile" );
		@CONTACTS = <CONTACTS>;
	}
	else {
		push( @CONTACTS, join( ' ', @ARGV ) );
	}
	chomp( @CONTACTS );

	if ( $#ARGV == -1 ) {
	    print "No resource specified\n";
	    exit( -1 );
	}

	if ( $gen_config ) {
		gen_main_config($config);
		exit( 0 );
	}

	return( 0 );
}

sub silently {
		#get rid of unsightly output from system commands
		#expects a list compatible with system()
	if ( $pid = fork() ) {
		#parent
		waitpid $pid, 0;
	}
	else {
		#child
		close STDOUT;
		close STDERR;
		open( STDOUT, ">/dev/null" );
		open( STDERR, ">/dev/null" );
		exec( @_ );
	}
	return $?;
}

sub gen_main_config {
	my $filename = shift(@_);
	##generate the config files
	open( CONDOR_CONFIG, ">$filename");
	print CONDOR_CONFIG <<"EOF";

	LOG = \$(LOCAL_DIR)/log
	EXECUTE = \$(LOCAL_DIR)/execute
	HOSTALLOW_ADMINISTRATOR = \$(HOSTNAME), \$(GLIDEIN_HOST)

	MAIL = /bin/mail
	DAEMON_LIST = MASTER, STARTD
	MASTER_ADDRESS_FILE = \$(LOG)/.master_address
	MASTER = \$(SBIN)/condor_master
	MASTER_LOG = \$(LOG)/MasterLog
	STARTD = \$(SBIN)/condor_startd
	STARTER = \$(SBIN)/condor_starter

	STARTER_PVM = \$(SBIN)/condor_starter.pvm
	STARTER_STD = \$(SBIN)/condor_starter.std
	STARTER_LIST = STARTER, STARTER_STD, STARTER_PVM

	ALTERNATE_STARTER_1 = \$(SBIN)/condor_starter.pvm
	PVMD = \$(SBIN)/condor_pvmd

	USE_NFS = False
	USE_CKPT_SERVER = False
	NEGOTIATOR_HOST	= \$(CONDOR_HOST)
	COLLECTOR_HOST = \$(CONDOR_HOST)

	LOCK = \$(LOG)
	STARTD_LOG = \$(LOG)/StartdLog
	STARTER_LOG = \$(LOG)/StarterLog

	STARTD_DEBUG = D_COMMAND

	SUSPEND = False
	CONTINUE = True
	PREEMPT = False
	WANT_VACATE = False
	WANT_SUSPEND = True
	SUSPEND_VANILLA = False
	WANT_SUSPEND_VANILLA = True
	KILL = False
	UPDATE_INTERVAL = 20
	IS_GLIDEIN = True
	STARTD_EXPRS = IS_GLIDEIN, START, DaemonStopTime

	PREEN_INTERVAL = 0
EOF
	close CONDOR_CONFIG;
}

sub host_info() 
{
		##get rid of everything following '#' in contact entries
	$CONTACT =~ s/#.*//;

	if ( ( $CONTACT eq "" ) || !defined( $CONTACT ) ) {
		return( 1 );
	}

	$GLOBUSHOST = $CONTACT;
	$GLOBUSHOST =~ s/[:\/].*//;

	$UID_DOMAIN = $GLOBUSHOST;
	$UID_DOMAIN =~ s/[^\.]*\.//;

	if ( $edg_mds_schema ) {

		#The remote machine is an EDG Compute Element. Use the EDG MDS
		#schema to query the GRIS server there. We're looking for the
		#architecture of the Compute Element.
		open( QUERY, "$G_SEARCH -x -h $GLOBUSHOST -p 2135 -b 'mds-vo-name=local,o=grid' '(objectclass=MdsComputer)' Mds-Cpu-vendor Mds-Computer-platform Mds-Os-name Mds-Os-release|" );
		@QUERY = <QUERY>;
		if ( !close( QUERY ) ) {
			print STDERR "Error querying GRIS on $GLOBUSHOST\n";
			return( 1 );
		}

		#Currently, the EDG MDS schema doesn't advertise anything that lets
		#us find a jobmanager service & queue that'll run immediately for
		#the setup phase, so we'll just try "jobmanager-fork".
		$CONTACT_SETUP_QUEUE = "unknown";
		$CONTACT_SETUP = $CONTACT;
		if ( grep( /jobmanager/, $CONTACT_SETUP ) ) {
			$CONTACT_SETUP =~ s|/[^:]*|/jobmanager-fork|;
		} elsif ( grep( /:/, $CONTACT_SETUP ) < 2 ) {
			$CONTACT_SETUP .= "/jobmanager-fork";
		} else {
			$CONTACT_SETUP =~ s|(:[^:]*)|\1/jobmanager-fork|;
		}

		#Search the query results for the architecture of the resource the
		#user wants to glidein to. In EDG land, there's only one
		#architecture for a given Compute Element (a front-end machine
		#running Globus and all it's associated back-end nodes).
		@SEARCH1 = grep( /^Mds-Computer-platform:/, @QUERY );
		@SEARCH2 = grep( /^Mds-Cpu-vendor:/, @QUERY );
		@SEARCH3 = grep( /^Mds-Os-name:/, @QUERY );
		@SEARCH4 = grep( /^Mds-Os-release:/, @QUERY );
		my $cputype = "";
		my $manufacturer = "";
		my $osname = "";
		my $osversion = "";
		if ( $#SEARCH1 >= 0 ) {
			chomp( $cputype = $SEARCH1[0] );
			$cputype =~ s/Mds-Computer-platform: //;
			chomp( $manufacturer = $SEARCH2[0] );
			$manufacturer =~ s/Mds-Cpu-vendor: //;
			chomp( $osname = $SEARCH3[0] );
			$osname =~ s/Mds-Os-name: //;
			chomp( $osversion = $SEARCH4[0] );
			$osversion =~ s/Mds-Os-release: //;
			if ( $osname =~ /[Ll]inux/ ) {
				$osversion =~ s/(\d+\.\d+)\..*/\1/;
			}
			if ( $manufacturer =~ /GenuineIntel/ ) {
				$manufacturer = "pc";
			}
			if ( $manufacturer =~ /AuthenticAMD/ ) {
				$manufacturer = "pc";
			}
		}

		if ( $cputype eq "" || $manufacturer eq "" || $osname eq "" ||
			 $osversion eq "" ) {
			print STDERR "Can't find architecture info on $GLOBUSHOST\n";
			return( 1 );
		}

		$arch = "${CONDOR_VERSION}-${cputype}-${manufacturer}-${osname}-${osversion}";

	} else {

		#Query the GRIS server on the globus machine using the Globus MDS
		#schema. We're looking for two
		#things: which jobmanager/queue will run jobs immediately (for
		#setup), and the architecture of the jobmanager the user wants to
		#run on (not necessarily the same as the machine we're talking to).
		open( QUERY, "$G_SEARCH -x -h $GLOBUSHOST -p 2135 -b 'mds-vo-name=local,o=grid' '(|(objectclass=MdsServiceGram)(objectclass=MdsGramJobQueue))' Mds-Software-deployment Mds-Gram-Job-Queue-dispatchtype Mds-Computer-isa Mds-Computer-manufacturer Mds-Os-name Mds-Os-release|" );
		@QUERY = <QUERY>;
		if ( !close( QUERY ) ) {
			print STDERR "Error querying GRIS on $GLOBUSHOST\n";
			return( 1 );
		}

		#Search the query results for an "Immediate" jobmanager/queue
		@SEARCH1 = grep( /^dn: Mds-Job-Queue-name=/, @QUERY );
		@SEARCH2 = grep( /^Mds-Gram-Job-Queue-dispatchtype:/, @QUERY );
		my $queue = "";
		my $service = "";
		for ( $i = 0; $i <= $#SEARCH1; $i++ ) {
			if ( grep( /Immediate/, $SEARCH2[$i] ) > 0 ) {
				chomp( $queue = $SEARCH1[$i] );
				$queue =~ s/^dn: Mds-Job-Queue-name=([^,]*),.*$/\1/;
				chomp( $service = $SEARCH1[$i] );
				$service =~ s/^.*Mds-Software-deployment=([^,]*),.*$/\1/;
				last;
			}
		}

		if ( $queue eq "" || $service eq "" ) {
			print STDERR "Can't find immediate jobmanager on $GLOBUSHOST\n";
			return( 1 );
		}

		$CONTACT_SETUP_QUEUE = $queue;
		$CONTACT_SETUP = $CONTACT;
		if ( grep( /jobmanager/, $CONTACT_SETUP ) ) {
			$CONTACT_SETUP =~ s|/[^:]*|/$service|;
		} elsif ( grep( /:/, $CONTACT_SETUP ) < 2 ) {
			$CONTACT_SETUP .= "/$service";
		} else {
			$CONTACT_SETUP =~ s|(:[^:]*)|\1/$service|;
		}

		#Search the query results for the architecture of the jobmanager
		#the user wants to glidein to.
		my $jobmanager;
		if ( grep( /jobmanager/, $CONTACT ) ) {
			$jobmanager = $CONTACT;
			$jobmanager =~ s|^[^/]*/([^:]*).*|\1|;
		} else {
			$jobmanager = "jobmanager";
		}
		@SEARCH1 = grep( /^Mds-Software-deployment:/, @QUERY );
		@SEARCH2 = grep( /^Mds-Computer-isa:/, @QUERY );
		@SEARCH3 = grep( /^Mds-Computer-manufacturer:/, @QUERY );
		@SEARCH4 = grep( /^Mds-Os-name:/, @QUERY );
		@SEARCH5 = grep( /^Mds-Os-release:/, @QUERY );
		my $cputype = "";
		my $manufacturer = "";
		my $osname = "";
		my $osversion = "";
		for ( $i = 0; $i <= $#SEARCH1; $i++ ) {
			if ( grep( /$jobmanager/, $SEARCH1[$i] ) > 0 ) {
				chomp( $cputype = $SEARCH2[$i] );
				$cputype =~ s/Mds-Computer-isa: //;
				chomp( $manufacturer = $SEARCH3[$i] );
				$manufacturer =~ s/Mds-Computer-manufacturer: //;
				chomp( $osname = $SEARCH4[$i] );
				$osname =~ s/Mds-Os-name: //;
				chomp( $osversion = $SEARCH5[$i] );
				$osversion =~ s/Mds-Os-release: //;
				if ( $osname =~ /[Ll]inux/ ) {
					$osversion =~ s/(\d+\.\d+)\..*/\1/;
				}
				last;
			}
		}

		if ( $cputype eq "" || $manufacturer eq "" || $osname eq "" ||
			 $osversion eq "" ) {
			print STDERR "Can't find jobmanager info on $GLOBUSHOST\n";
			return( 1 );
		}

		$arch = "${CONDOR_VERSION}-${cputype}-${manufacturer}-${osname}-${osversion}";

	}

	if ( $? != 0 || $arch eq "" ) {
		print STDERR "Error contacting resource $CONTACT_SETUP\n";
		return( 1 );
	}

	if ( !defined( $ARCHDIR ) || $ARCHDIR eq "" ) {
		$archdir = "$basedir/$arch";
	}

	return( 0 );
}

sub do_remote_setup() {
	my $DAEMONS = join( ' ', @DAEMONS );

	my $remotedir = "/tmp";

	# Why are we changing directories at all???
	my $oldcwd = `pwd`;
	chomp($oldcwd);

	if ( $use_config ne "" ) {
		`cp $use_config $remotedir/$config`;
		chdir $remotedir;
	} else {
		chdir $remotedir;
		gen_main_config($config);
	}

	if ( ! -f $config ) {
		return( "Couldn't create Condor config file" );
	}

	$REM_SETUP = "/tmp/remote_setup.glidein.$$";
	open( REM_SETUP, ">$REM_SETUP" );
	print REM_SETUP<<"EOF";

	BASEDIR=\$1
	ARCHDIR=\$2
	ARCH=\$3
	LOCALDIR=\$4
	GASS_SERVER=\$5
	TARBALL_SERVER=\$6
	FORCE=\$7

	CONFIG=\$BASEDIR/$config

	for newdir in \$BASEDIR \$ARCHDIR \$LOCALDIR; do
		if [ ! -d \$newdir ];
			then \$GLOBUS_SH_MKDIR \$newdir;
		fi
		if [ ! -d \$newdir ];
			then echo "ERROR mkdir \$newdir"
			exit 1;
		fi
	done

	if [ \$FORCE -ne 0 -o ! -f \$CONFIG ];
		then \$GLOBUS_LOCATION/bin/globus-url-copy \$GASS_SERVER/$config file:\$BASEDIR/$config 
	fi

	cd \$ARCHDIR
	GETFILES=0
	for needexec in $DAEMONS; do
		if [ ! -f \$needexec ];
			then GETFILES=1;
		fi
	done
	if [ \$FORCE -ne 0 -o \$GETFILES -ne 0 ]; then
		\$GLOBUS_LOCATION/bin/globus-url-copy \$TARBALL_SERVER/\$ARCH.tar.gz file:\$ARCHDIR/\$ARCH.tar.gz;
		if [ \$? != 0 -o ! -f \$ARCHDIR/\$ARCH.tar.gz ]; then
			echo "Error: unable to retrieve \$TARBALL_SERVER/\$ARCH.tar.gz"
			exit 1;
		fi

		\$GLOBUS_SH_GZIP -d \$ARCH.tar.gz;
		\$GLOBUS_SH_TAR xf \$ARCH.tar;
		\$GLOBUS_SH_RM -f \$ARCH.tar;
	fi

	exit 0;

EOF
	close( REM_SETUP );
	$SYSTEM = "$G_RUN -s -r '$CONTACT_SETUP' '&(executable=\$(GLOBUS_LOCATION)/bin/globus-sh-exec)(arguments=\$(GLOBUSRUN_GASS_URL)$REM_SETUP $basedir $archdir $arch $localdir \$(GLOBUSRUN_GASS_URL)$remotedir gsiftp://$SERVER_NAME$SERVER_DIR $force_setup)(queue=$CONTACT_SETUP_QUEUE)'";

	$err = system( $SYSTEM );

	unlink( "$remotedir/$config" );
	unlink( $REM_SETUP );

	chdir $oldcwd;

	if ( $err ) {
		return( "running setup script on remote machine" );
	}

	return( 0 );
}
