#!/usr/bin/perl

##**************************************************************
##
## Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
## University of Wisconsin-Madison, WI.
## 
## Licensed under the Apache License, Version 2.0 (the "License"); you
## may not use this file except in compliance with the License.  You may
## obtain a copy of the License at
## 
##    http://www.apache.org/licenses/LICENSE-2.0
## 
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
##**************************************************************



###########################################################################
#
#  This is condor_configure. It performs initial installation of the Condor
#  software and/or subsequent re-configuration(s).
#
#  You shouldn't need to edit this script at all.
#
#  condor_configure by Carey Kireyev <ckireyev@cs.wisc.edu> 3/19/03
#  (loosely based on 
#     condor_install by Derek Wright <wright@cs.wisc.edu> 2/19/98)
#
###########################################################################

# Set some global settings
umask 0022;			# default file creation permissions
use strict;			# restrict unsafe constructs
use warnings;		# warn about bad things
use Cwd;

require 5.006;		# Perl version for function prototypes

# Library modules
use Text::Wrap;		# line wrapping to form simple paragraphs
use Getopt::Long;	# "long" command line options parser

my $Program; ($Program = $0) =~ s|.*/||;    # This program name.

my @Options =
(
 {
	 short => "--install[=<path/to/release_dirs>]",
	 long => <<END_OPT_INSTALL,
Perform installation of Condor files and initial configuration as a
working personal Condor. (if type or "central manager" are not
specified).  If this is an upgrade to an existing installation
directory, the existing config files and local directory will be
preserved.
The default behavior of "condor_install" is "--install=.".
END_OPT_INSTALL
 },
 {
	 short => "--prefix=<path> ",
	 long => <<END_OPT_PREFIX,
Specifies the installation directory (the root of Condor installation).
This is the same as --install-dir=<path>.
END_OPT_PREFIX
 },
 {
	 short => "--install-dir=<path> ",
	 long => <<END_OPT_INSTALL_DIR,
Specifies the installation directory (the root of Condor installation).
This is the same as --prefix=<path>.
END_OPT_INSTALL_DIR
 },
 {
	 short => "--local-dir=<path>",
	 long => <<END_OPT_LOCAL_DIR,
Sets the local directory at the specified location (if one does not
exist there).  Moves log,spool,execute directories there from the old
local directory applicable).
END_OPT_LOCAL_DIR
 },
 {
	 short => "--make-personal-condor",
	 long => <<END_OPT_MAKE_PERSONAL_CONDOR,
Creates a personal Condor (i.e. a 1-node pool running on local machine).
END_OPT_MAKE_PERSONAL_CONDOR
 },
 {
	 short => "--bosco",
	 long => <<END_OPT_BOSCO,
Install BOSCO, a personal Condor that submits jobs to remote batch systems.
END_OPT_BOSCO
 },
 {
	 short => "--type=<[submit],[execute],[manager]> ",
	 long => <<END_OPT_TYPE,
Determines which role(s) the machine will perform in a pool (which
translates to which daemons will run). In the case of a personal
Condor this value is automatically forced to be
\"submit,execute,manager\".
END_OPT_TYPE
 },
 {
	 short => "--central-manager=<host>",
	 long => <<END_OPT_CENTRAL_MANAGER,
Connect to existing pool with Central manager on <host>. 
END_OPT_CENTRAL_MANAGER
 },
 {
	 short => "--credd",
	 long => <<END_OPT_CREDD,
Configure credential manager daemon.
END_OPT_CREDD
 },
 {
	 short => "--owner=<user>",
	 long => <<END_OPT_OWNER,
Run Condor daemons as specified user (can be either ID or
username). (Only applicable when condor_configure is run by root,
otherwise the current user is assumed).  Changes ownership of
log,spool,execute directories to specified user, and instructs Condor
system to run as that user (by setting CONDOR_IDS in the config file).
You may not select 'root' or any other account with uid 0 for this purpose.
END_OPT_OWNER
 },
 {
	 short => "--maybe-daemon-owner",
	 long => <<END_OPT_MAYBE_DAEMON_OWNER,
If --owner is not specified and no appropriate user can be found to
run Condor, then this option will allow the daemon user to be
selected. This option is rarely needed by users but can be useful for
scripts that invoke condor_configure to install Condor.
END_OPT_MAYBE_DAEMON_OWNER
 },
 {
	 short => "--install-log=<file>",
	 long => <<END_OPT_INSTALL_LOG,
Save information about the installation in the specified file. This is
normally only needed when condor_configure is called by a higher-level
script, not when invoked by a person.
END_OPT_INSTALL_LOG
 },
 {
	 short => "--overwrite",
	 long => <<END_OPT_OVERWRITE,
Always overwrite the contents of the 'sbin' directory in the
installation directory.  By default, Condor will not install if it
finds an existing 'sbin' directory.  If condor finds a 'sbin' directory
in the installation directory, You must specify --overwrite
or --backup to tell condor what to do.
END_OPT_OVERWRITE
 },
 {
	 short => "--env-scripts-dir=<dir>",
	 long => <<END_OPT_ENV_SCRIPTS_DIR
Condor will create simple scripts that can be sourced by
sh and csh shells to update the PATH and set the CONDOR_CONFIG environtment
variables.  This option allows you to specify in what directory to write
them.  By default, these will be created in the root of the installation
directory.
END_OPT_ENV_SCRIPTS_DIR
 },
 {
	 short => "--no-env-scripts",
	 long => <<END_OPT_NO_ENV_SCRIPTS
By default, Condor will create simple scripts that can be sourced by
sh and csh shells to update the PATH and set the CONDOR_CONFIG environtment
variables.  This option prevents Condor from creating these scripts.
END_OPT_NO_ENV_SCRIPTS
 },
 {
	 short => "--ignore-missing-libs",
	 long => <<END_OPT_IGNORE_MISSING_LIBS,
By default, Condor will not install if prerequisite libraries
are detected as missing (this would cause the Condor programs to be unable
to run).  This option tells Condor to install even if it detects
missing libraries.
END_OPT_IGNORE_MISSING_LIBS
 },
 {
	 short => "--force",
	 long => <<END_OPT_FORCE,
Enable --overwrite and --ignore-missing-libs options
END_OPT_FORCE
 },
 {
	 short => "--backup",
	 long => <<END_OPT_BACKUP,
Always backup the 'sbin' directory in the installation directory.  By
default, Condor will not install if it finds an existing 'sbin'
directory.  If condor finds a 'sbin' directory in the installation
directory, You must specify --overwrite or --backup to tell condor
what to do.
END_OPT_BACKUP
 },
 {
	 short => "--verbose",
	 long => <<END_OPT_VERBOSE,
Print more information.
END_OPT_VERBOSE
 },
 {
	 short => "--usage",
	 long => <<END_OPT_USAGE,
Prints out short usage and exits.
END_OPT_USAGE
 },
 {
	 short => "--help",
	 long => <<END_OPT_HELP,
Prints out this screen and exits.
END_OPT_HELP
 },
 );

# For parsing command line options (&GetOptions)
my (
	$opt_release_dir,				# --install= directory
	$opt_prefix_dir,
	$opt_sbin_rename,
	$opt_local_dir,
	$opt_make_personal_condor,
	$opt_bosco,
	$opt_type,
	$opt_central_manager,
	$opt_credd,
	$opt_owner,
	$opt_maybe_daemon_owner,
	$opt_install_log,
	$opt_verbose,
	$opt_overwrite,
	$opt_ignore_missing_libs,
	$opt_test_missing_libs,
	$opt_force,
	$opt_backup,
	$opt_env_scripts_dir,
	$opt_disable_env_scripts,
	);


my ($owner, $release_dir, $local_dir, $local_config_file, $config_file, $cm, $type);
my ($who, $host, $fullhost, $domain);
my $no_config_modify=0;
my %comment_hash;
my @allparams;
my @metaknobs = ();
my $knobcount = 0;
my %daemon_list = (MASTER => 1);	# We always want a master.
my $logfile;
my $printed_log_message = 0;

# Prototypes
sub user_host_stuff();
sub parse_command_line();
sub find_owner(;$ );
sub find_config_file();
sub find_local_config_file();
sub find_local_dir();
sub install( $ );
sub find_release_dir( $ );
sub safe_mkdir( $$ );
sub condor_init( $ );
sub check_release_dir( $ );
sub set_mail_settings();
sub set_domain_settings();
sub set_central_manager ( $ );
sub set_config_values ( $$$ );
sub set_java_jvm_path();
#sub make_personal_condor();
sub get_config_value( $;$ );
sub debug( $ );
sub set_config_comments();
#sub read_config_file_comments();
#sub is_dynamic( $ );
sub which( $ );
sub credd();
sub log_message( $ );
sub usage( $ );
sub help( );

parse_command_line();

my $timestamp=time();

if ($opt_install_log) {
	open(LOGFILE, ">>$opt_install_log")
		or die "Couldn't open $opt_install_log: $!\n";
	$logfile = *LOGFILE;
} else {
	$logfile = *STDOUT;
}

# Hashes to store values that will go into config files
my %append_config=();
my %global_config=();

# Detrmine UID, domain, etc
user_host_stuff();

# Owner of spool, exec dirs
if ($opt_owner) {
    if ($<) {
		# real user id != 0
		die "Option --owner is only valid when condor_configure is run as root!\n";
    }

    $owner=find_owner($opt_owner);
} else {
    $owner=find_owner();
}

if (defined ($opt_release_dir) || $opt_owner) {
    my $gid=(getpwuid ($owner))[3]; #Get group id
    $append_config{CONDOR_IDS}="$owner.$gid";
}

my @pwuid=getpwuid ($owner);
debug ("Condor will be run as user: " . $pwuid[0]);

# Install if necessary
if ($opt_bosco && !defined($opt_prefix_dir)) {
	my $home;
	if ( $ENV{HOME} ne "" ) {
		$home = $ENV{HOME};
	} else {
		my @pwuid = getpwuid( $< );
		$home = $pwuid[7];
	}
	if ( $home eq "" ) {
		die "Option --bosco can't find user's home directory!\n";
	}
	$opt_prefix_dir = $home . "/bosco";
	$opt_local_dir = $opt_prefix_dir . "/local.bosco";
}
if (defined($opt_release_dir)) {
    # Install
    if ($opt_prefix_dir) {
		$release_dir=install( $opt_prefix_dir );
    } else {
		$release_dir=install( $release_dir=getcwd() );
    }
	set_mail_settings();
	set_domain_settings();
	set_java_jvm_path();
}
else {
    # Verify Install diretory
    if ($opt_prefix_dir) {
		if ( !check_release_dir($opt_prefix_dir) ) {
			warn <<END_BAD_PREFIX_DIR;
No condor installation found in $opt_prefix_dir
  You probably need to install condor into $opt_prefix_dir by specifying
  the '--install=<dir>' option
  or perhaps run 'condor_install' instead of 'condor_configure'
  Run 'condor_install --help' for help.
END_BAD_PREFIX_DIR
			exit( 1 );
		}
		$release_dir=$opt_prefix_dir;
		chomp ($release_dir=`pushd $release_dir >> /dev/null && pwd && popd >> /dev/null`);
    } else {
		$release_dir=find_release_dir( getcwd() );
    }

    $config_file = find_config_file() or exit(1);

    # User requested to change local dir, so copy old
    # local directory into new one
    if ($opt_local_dir) {
		my $old_local_dir=find_local_dir();
		$local_dir=$opt_local_dir; 
		
		(system ("mv $old_local_dir/spool $local_dir") ||
		 system ("mv $old_local_dir/log $local_dir") ||
		 system ("mv $old_local_dir/execute $local_dir")) &&
		 die "\nUnable to move log, spool, execute directories to new local directory: \"$local_dir\"\n\n";
		condor_init ($local_dir);
		#$append_config{LOCAL_DIR}=$local_dir;
		$global_config{LOCAL_DIR}=$local_dir;
    }
}
debug ("Install directory: $release_dir");
if ( ! defined ($opt_env_scripts_dir ) ) {
	$opt_env_scripts_dir = $release_dir;
}

# Config file location
if (!$config_file) {
    $config_file = find_config_file() or exit(1);
}
debug ("Main config file: $config_file");

if (!$local_dir) {
    $local_dir=find_local_dir();
}
debug ("Local directory: $local_dir");

if (!$local_config_file) {
    $local_config_file=find_local_config_file();
}
debug ("Local config file: $local_config_file");

# Which machine is CM?
if ($opt_central_manager) {
    $cm=set_central_manager($opt_central_manager);
    
    unless ($opt_type) {
		if ($cm eq "localhost" || $cm eq $host || $cm eq $fullhost) {
			debug ("\n--type is not specified. Assuming <manager>.");
			$opt_type="manager";
		} else {
			debug ("\n--type is not specified. Assuming <submit,execute>.");
			$opt_type="submit,execute";
		}
    }
}

#tj - removing because this is the default value
## Path to ganglia.d for condor_gangliad configuration
#if ( -d "${release_dir}/etc/condor/ganglia.d" ) {
#	$append_config{GANGLIAD_METRICS_CONFIG_DIR}='${release_dir}/etc/condor/ganglia.d';
#}


# Determine daemons needed to run and other settings based on
# the values of the following options:
#  --type
#  --install
#  --make-personal_condor

if ($opt_bosco) {
    $append_config{START}="";
    $append_config{PREEMPT}="";
    $append_config{SUSPEND}="";
    $append_config{KILL}="";
    
    $append_config{COLLECTOR_NAME}="";

    $append_config{IS_BOSCO}="True";
    $append_config{CREATE_CORE_FILES }="False";
    $append_config{CONDOR_ADMIN}=" ";
    $append_config{PREEN_ARGS}="-r";
    $append_config{NETWORK_INTERFACE}="127.0.0.1";

    $daemon_list{SCHEDD} = 1;
    $daemon_list{COLLECTOR} = 1;
    $daemon_list{NEGOTIATOR} = 1;
    $daemon_list{STARTD} = 1;

    $cm=set_central_manager($fullhost);
    $append_config{COLLECTOR_NAME}="Personal Condor at $fullhost";

    # Campus Factory configuration
    my $config_dir=$local_dir . "/config";
    system("mkdir -p $config_dir && cp $opt_prefix_dir/etc/examples/condor_config.factory $config_dir ");


}
elsif ($opt_make_personal_condor ||
    (defined($opt_release_dir) && !$opt_type)) {

    # we will use the personal role, so we don't want to set DAEMON_LIST
    %daemon_list = ();

    push (@metaknobs,"use ROLE : Personal");
    $comment_hash{"use ROLE : Personal"}="\n##  Configure a personal HTCondor pool.";
    $append_config{COLLECTOR_NAME}='Personal Condor at $(CONDOR_HOST)';

    # as of 9.0 the config *must* set the ALLOW_* knobs or all communication with daemons will fail
    push (@metaknobs,"use SECURITY : USER_BASED");
    $comment_hash{"use SECURITY : USER_BASED"}="\n##  Configure a user-based security for a personal condor.";
    $append_config{ALLOW_ADMINISTRATOR}='$(ALLOW_ADMINISTRATOR) $(USERNAME)@$(UID_DOMAIN)';

    # disable attempts to use the global IDTOKEN directories
    $append_config{SEC_PASSWORD_DIRECTORY}='$(LOCAL_DIR)/signing_keys';
    $append_config{SEC_TOKEN_DIRECTORY}='$(LOCAL_DIR)/tokens';

	#

    if ($opt_make_personal_condor || $fullhost =~ /^localhost/) {
	# dont want to configure CONDOR_HOST=localhost because the personal role
	# already does something more clever than that, so don't call set_central_manager()
	$cm='localhost';
	$append_config{NETWORK_INTERFACE}='$(CONDOR_HOST)';
    } else {
	$cm=set_central_manager($fullhost);
    }
}
elsif ($opt_type) {

    my @types=split(/\,/, $opt_type);

    $append_config{START}="";
    $append_config{PREEMPT}="";
    $append_config{SUSPEND}="";
    $append_config{KILL}="";
    
    $append_config{COLLECTOR_NAME}="";

    foreach $type (@types) {
		if ($type eq "execute") {
			$daemon_list{STARTD} = 1;
		} elsif ($type eq "submit") {
			$daemon_list{SCHEDD} = 1;
		} elsif ($type eq "manager") {
			$daemon_list{COLLECTOR} = 1;
			$daemon_list{NEGOTIATOR} = 1;
			if( !$cm ) {
				$cm=set_central_manager($fullhost);
			}
		} else {
			die "Illegal -type argument: $opt_type!\n";
		}
    }
}

if ($opt_credd)  {
	credd();
}

# Change ownership if necessary
if ($opt_owner) {
    condor_init ($local_dir);
}

#tj- removing because we no longer modify the local config file
# Backup old local config file
#unless (defined($opt_release_dir)) {
#    chomp (my $backup_local_config_file=$local_config_file . ".backup." . $timestamp);
#    debug ("\nBacking up local config file to: $backup_local_config_file");
#    system ("cp $local_config_file $backup_local_config_file");
#}

# Write out values to global config file
unless ($no_config_modify) {
    #read_config_file_comments();
    set_config_comments();

    $append_config{DAEMON_LIST}=join(' ', sort keys %daemon_list );
    set_config_values (\%global_config, $config_file, 0);
    set_config_values (\%append_config, $config_file, 1);
}


if (defined($opt_release_dir)) {
	print "\nCondor has been installed into:\n";
    print "    $release_dir\n";
}

unless ($no_config_modify) {
	print
		"\nConfigured condor using these configuration files:\n".
		"  global: $config_file\n".
		"  local:  $local_config_file\n";
}

unless (defined($ENV{CONDOR_CONFIG}) && ($ENV{CONDOR_CONFIG} eq $config_file) ) {
    log_message( "\nIn order for Condor to work properly you must set your ".
				 "CONDOR_CONFIG environment variable to point to your ".
				 "Condor configuration file: ".
				 "$config_file ".
				 "before running Condor commands/daemons."
				 );

}

unless ( $opt_disable_env_scripts ) {
	my $env_sh = $opt_env_scripts_dir ."/condor.sh";
	open( SH, ">$env_sh" ) or die "Can't write to $env_sh";
	print SH "# The script should be sourced by /bin/sh or similar\n";
	print SH "CONDOR_CONFIG=\"$config_file\"\n";
	print SH "export CONDOR_CONFIG\n";
	print SH "PATH=\"$release_dir/bin:$release_dir/sbin:\$PATH\"\n";
	print SH "export PATH\n";
	print SH "if [ \"X\" != \"X\${PYTHONPATH-}\" ]; then\n";
	print SH "  PYTHONPATH=\"$release_dir/lib/python3:\$PYTHONPATH\"\n";
	print SH "else\n";
	print SH "  PYTHONPATH=\"$release_dir/lib/python3\"\n";
	print SH "fi\n";
	print SH "export PYTHONPATH\n";
	close( SH );

	my $env_csh = $opt_env_scripts_dir ."/condor.csh";
	open( CSH, ">$env_csh" ) or die "Can't write to $env_csh";
	print CSH "# The script should be sourced by /bin/csh or similar\n";
	print CSH "setenv CONDOR_CONFIG \"$config_file\"\n";
	print CSH "setenv PATH \"$release_dir/bin:$release_dir/sbin:\$PATH\"\n";
	print CSH "if (\$?PYTHONPATH) then\n";
	print CSH "  setenv PYTHONPATH \"$release_dir/lib/python3:\$PYTHONPATH\"\n";
	print CSH "else\n";
	print CSH "  setenv PYTHONPATH \"$release_dir/lib/python3\"\n";
	print CSH "endif\n";
	close( CSH );

	my $env_fish = $opt_env_scripts_dir ."/condor.fish";
	open( FISH, ">$env_fish" ) or die "Can't write to $env_fish";
	print FISH "# The script should be sourced by the fish shell\n";
	print FISH "set -x CONDOR_CONFIG \"$config_file\"\n";
	print FISH "set -x -p PATH \"$release_dir/bin\" \"$release_dir/sbin\"\n";
	print FISH "set -x -p PYTHONPATH \"$release_dir/lib/python3\n";
	close( FISH );

	if ( $opt_bosco ) {
		$env_sh = $opt_env_scripts_dir ."/bosco.sh";
		$env_csh = $opt_env_scripts_dir ."/bosco.csh";
		$env_fish = $opt_env_scripts_dir ."/bosco.fish";
		system( "cp $opt_env_scripts_dir/condor.sh $env_sh" );
		system( "cp $opt_env_scripts_dir/condor.csh $env_csh" );
		system( "cp $opt_env_scripts_dir/condor.fish $env_fish" );

		open( SETENV, ">$opt_env_scripts_dir/bosco_setenv" );
		print SETENV "# Shell-independent setup\n";
		print SETENV "source $release_dir/bosco.`$release_dir/libexec/shellselector -q`\n";
		close( SETENV );
	}

	if ( $opt_bosco ) {
		print "Created a script you can source to setup your Condor environment\n";
		print "variables. This command must be run each time you log in or may\n";
		print "be placed in your login scripts:\n";
		print "   source $opt_env_scripts_dir/bosco_setenv\n";
	} else {
		print "Created scripts which can be sourced by users to setup their\n";
		print "Condor environment variables.  These are:\n";
		print "   sh: $env_sh\n";
		print "  csh: $env_csh\n";
		print " fish: $env_fish\n";
	}
}

print "\n";

exit 0;


##################################################################

sub user_host_stuff() {
###  Figure out who and where we are:
    my @pwdent = getpwuid($<);

    $who=$pwdent[0];

    if ($ENV{HOSTNAME}) {
		$host=$ENV{HOSTNAME};
    } else {
		$host=`hostname`;
		if ($? ne 0) {
			die "\nUnable to determine the host name. Please set the \
environment variable \$HOSTNAME to the full name of this machine \
e.g. mymachine.mydomain.com \n";
		}
		chomp ($host);
    }
    
    # Make sure $host is just hostname, with no domain.  Grab everything
    # upto the first ".".
    
    if ($host =~ /^([^.]+)\.(\S+)$/) {

		# $host = mymachine.mydomain.com

		$host=$1;
		$domain=$2;
		$fullhost=$host.'.'.$domain;
    }
    elsif ($host =~ /\w+/) {

		# $host = mymachine

		# Lookup the full hostname.
		if (!gethostbyname($host)) {
			##
			## We use to die right here when we couldn't get the hostname.
			## But the FreeBSD testers run Condor in a jail without a real hostname, so 
			## we need to be able to still install when gethostbyname() fails
			## This is why we just set the fullhost to the host, and blank out the domain
			## Andy Pavlo - 06/27/2007
			##
			$fullhost = $host;
			$domain = "";
			my $msg = "WARNING: Unable to determine full hostname for host '$host'. ".
				"Condor may not work properly\n".
				"Please set the environment variable \$HOSTNAME to the full name ".
				"of this machine (e.g., mymachine.mydomain.com)\n";
			warn($msg);
			return;
		}

		$fullhost=(gethostbyname($host))[0];
		if( ! ($fullhost =~ /.*\..*/) ) {
			# There's no "." in the hostname.  DNS/hosts/YP is probably
			# misconfigured... try the other entry, that might be it.
			$fullhost=(gethostbyname($host))[1];
		}

		if( ! ($fullhost =~ /.*\..*/) ) {
			# There's still no "." in the hostname.  DNS/hosts/YP is totally 
			# misconfigured...
			chomp($fullhost=`host $fullhost | grep \"has address\" | awk \'\{print \$1\}\'`);
		}

		if( ! ($fullhost =~ /.*\..*/) ) { 
			$fullhost=$host;
			$domain="";
			my $msg = "WARNING: Unable to determine full hostname for host '$host'. ".
				"Condor may not work properly\n".
				"Please set the environment variable \$HOSTNAME to the full name ".
				"of this machine (e.g., mymachine.mydomain.com)\n";
			warn($msg);
		} else {
			# Grab just the domain, so we have it.
			$fullhost =~ /\w*\.(.*)/;
			$domain = $1;
		}
    }
}


#    ###  Find condor's home directory, if it exists.
#    
#}

sub parse_command_line() {

	if ( $0 =~ /bosco_install$/ ) {
		unshift( @ARGV, "--bosco" );
	}

	if ( $#ARGV < 0 ) {
		usage( 1 );
	}

	# For condor_install, default behavior is --install=.
	if ( $0 =~ /^\w+_install/ ) {
		unshift( @ARGV, "--install=." );
	}
	elsif ( $0 =~ /^(.*)\/\w+_install/ ) {
		unshift( @ARGV, "--install=$1" );
	}

	&GetOptions (
				 "install:s"				=>	\$opt_release_dir,
				 "prefix=s"					=>	\$opt_prefix_dir,
				 "install-dir=s"			=>	\$opt_prefix_dir,
				 "local-dir=s"				=>	\$opt_local_dir,
				 "make-personal-condor!"	=>	\$opt_make_personal_condor,
				 "bosco!"					=>	\$opt_bosco,
				 "type=s"					=>	\$opt_type,
				 "central-manager=s"		=>	\$opt_central_manager,
				 "credd!"					=>	\$opt_credd,
				 "owner=s"					=>	\$opt_owner,
				 "maybe-daemon-owner!"		=>	\$opt_maybe_daemon_owner,
				 "install-log=s"	        =>	\$opt_install_log,
				 "verbose!"					=>	\$opt_verbose,
				 "help"						=>	sub{ help(); },
				 "usage"					=>	sub{ usage(0); },
				 "overwrite"				=>	\$opt_overwrite,
				 "ignore-missing-libs"		=>	\$opt_ignore_missing_libs,
				 "test-missing-libs=s"		=>	\$opt_test_missing_libs,
				 "env-scripts-dir=s"		=>	\$opt_env_scripts_dir,
				 "no-env-scripts"			=>	\$opt_disable_env_scripts,
				 "force"					=>	\$opt_force,
				 "backup"					=>	\$opt_backup,
				 ) or usage( 1 );

    if ( $opt_local_dir and ( $opt_local_dir !~ /^\// ) ) {
		die "--local-dir must specify absolute path\n";
    }

	if ( $opt_force ) {
		$opt_overwrite = 1;
		$opt_ignore_missing_libs = 1;
	}
}


sub find_owner(;$) {
    my $owner = shift(@_);

    my $uid;
    my $uname;

    my @pwdent_condor = getpwnam( "condor" );
    my $condor_uid=$pwdent_condor[2];

    if ( $< ) {
        # Non-root
        $uid=$<;
    } 
    elsif ($owner) {
        # We're root, see who should own the Condor files/directories
        if ($owner =~ m/^\d+$/) {
            # owner as uid
            # fall through
            $uid=$owner;
        } else {
            #owner as uname
            $uname=$owner;
            $uid=(getpwnam ($uname))[2];
			if ( !defined($uid) ) {
				# Couldn't find $uname in /etc/passwd or other name resolution
				die "\nUser '$uname' does not appear to exist! Please fix or " .
					"select a different user with --owner.\n";
			}
            if( $uid == 0 ) {
				# root can't be used for this purpose, it must be some non-root
				# account.
				die "\nUser 'root' (or equivalent) may not be used as an " .
					"owner of the Condor installation's directories and " .
					"files. Please select a different user with --owner!\n";
            }
        }
    }
    elsif ($condor_uid) {
        $uid = $condor_uid;
    }
    elsif ($opt_maybe_daemon_owner) {
        my @pwdent = getpwnam("daemon");
        if ($pwdent[2]) {
            $uid=$pwdent[2];
            log_message("Condor is being configured to use the daemon user, which "
                        . "will work, but usually isn't "
                        . "what you want. Usually it's the condor user, which doesn't "
                        . "exist on this system. If you like, you can rerun "
                        . "$Program with the --owner option when you decide which user "
                        . "should be used by the Condor daemons.\n");
        } else {
            die wrap("", "", "Unable to determine which user to run Condor as. "
                     . "Please re-run the configure script with the "
                     . "--owner=<uname> option.\n");
        }
    }
    else {
        die wrap("", "", "\nUnable to find the user to run Condor daemons as. "
				 . "Please specify it using the --owner option\n");
    }

    if( ! $uid ) {
        die "\nfind_owner(): can't find a user to run as!\n";
    }
    if( !getpwuid($uid) ) {
        die "\nInvalid user: getpwuid($uid) failed!\n";
    }

    return $uid;
}

sub find_config_file() {
	my @list = (
				$ENV{CONDOR_CONFIG},
				"/etc/condor/condor_config",
				"/usr/local/etc/condor_config",
				$opt_prefix_dir ? "$opt_prefix_dir/etc/condor_config" : undef,
				"$release_dir/etc/condor_config",
				);
	foreach my $config ( @list ) {
		if ( defined $config and -f $config ) {
			return $config;
		}
	}

    print STDERR "Unable to find Condor configuration file (condor_config)!\n";
	print STDERR "$Program searched in these locations:\n";
	foreach my $config ( @list ) {
		if ( defined $config ) {
			print "   $config\n";
		}
	}
	return undef;
}

sub find_local_config_file() {
    my $from_config=get_config_value ("LOCAL_CONFIG_FILE");

    my @files=split(/,/, $from_config);

    $from_config=$files[$#files];
    if ($#files > 0) {
		
		warn "\nWARNING: There are several local config files used: \
@files \
The script will modify the following file (it will be backed up):
$from_config\n";
    }


    $from_config =~ s/\s//g; # Remove spaces

    if ($from_config) { return $from_config; }

    die "Unable to find local configuration file!\n";
}

sub find_local_dir() {
    my $from_config=get_config_value("LOCAL_DIR") ||
		die "Unable to find local directory!\n";

    return $from_config;
}

sub find_os( $$$ )
{
	my $Table = shift;
	my $field = shift;
	my $text = shift;
	foreach my $os ( @{$Table} ) {
		next if ( ! exists( $os->{$field} ) );
		my $pat = $os->{$field};
		if ( $text =~ /$pat/ ) {
			return $os;
		}
	}
	return undef;
}

sub install( $ )
{
    my $release_dir=shift(@_);

    my @release_dirs = qw( etc examples include lib lib64 libexec bin sbin man usr );

	# Get the absolute path to the release directory
	my $release_src_dir;
    if ($opt_release_dir) {
		my $old = getcwd();
		chdir( $opt_release_dir ) or die "Can't chdir to $opt_release_dir";
		$release_src_dir = getcwd();	# Get the complete absolute path
		chdir( $old ) or die "Can't chdir back to $old";
    }
	else {
		$release_src_dir = getcwd();	# Get the complete absolute path
	}

	my @missing;
	foreach my $d ( @release_dirs ) {
		my $dir = "$release_src_dir/$d";
		if ( ! -d $dir ) {
			push( @missing, $d ) if ( ! ($d eq 'man' || $d eq 'lib64' || $d eq 'usr'));
		}
	}

	# Let's look at a sampling of programs, verify that they're there too
	my %bin_dirs = (
					bin  => [ "config_val",
							  "q",
							  "status",
							  "submit",
							  "version",
							  ],
					sbin => [ "collector",
							  "master",
							  "schedd",
							  "startd",
							  ],
					);
	my @programs;
	foreach my $d ( keys( %bin_dirs ) )
	{
		foreach my $p ( @{$bin_dirs{$d}} )
		{
			my $fp = "$release_src_dir/$d/condor_$p";
			if ( ! -x $fp )
			{
				push( @missing, $fp );
			}
			else
			{
				push( @programs, $fp );
			}
		}
	}

	# Now, let's display a list of missing items, and puke if we found any
	if ( scalar @missing ) {
		print STDERR
			"Missing release directories (looking in $release_src_dir):\n".
			"  " . join( "\n  ", @missing ) . "\n";
		die "Unable to find some release directories.\n".
			"  Please specify the correct location of these with \n".
			"--install=<path to release directories> or make sure it's \n".
			"in the current directory\n";
	}

	# Now, let's try to run ldd on the above programs, see what we find
	my %missing_libs;
	my $num_missing_libs = 0;

	determine_missing_libs(\@programs, \%missing_libs, \$num_missing_libs);

	if ( $opt_test_missing_libs ) {
		$missing_libs{$opt_test_missing_libs} = "not found";
		$num_missing_libs++;
	}

	# Try to do something intelligent about missing libraries
	if ( $num_missing_libs )
	{
		my %InstallerTable =
			(
			 linux => {
				 name => "unknown package installer",
			 },
			 apt => {
				 name => "APT",
				 run => "apt-get install %s",
			 },
			 yum => {
				 name => "YUM",
				 run => "yum install %s",
			 },
			 zypper => {
				 name => "zypper",
				 run => "zypper install %s",
			 },
			 UNIX => {
				 name => "unknown UNIX installer",
			 },
			 );
		my @OsTable =
			(
			 {
				 name => "Red Hat",
				 installer => "yum",

				 issue => "CentOS|Red Hat Enterprise|Fedora",
				 libs => {
					 "libstdc++.so.5" => "compat-libstdc++",
				 },
			 },
			 {
				 name => "openSUSE",
				 installer => "zypper",

				 issue => "openSUSE",
				 libs => {
					 "libstdc++.so.5" => "compat-libstdc++",
				 }
			 },
			 {
				 name => "Debian",
				 installer => "apt",

				 issue => "(?i)debian",
				 text => "debian",
				 libs => {
					 "libstdc++.so.5" => "libstdc++5",
				 }
			 },
			 {
				 name => "Linux",
				 installer => "linux",

				 issue => "(?i)linux",
				 uname => "(?i)linux",
				 libs => {
					 "libstdc++.so.5" => "compat-libstdc++",
				 },
			 },
			 {
				 name => "UNIX",
				 installer => "UNIX",

				 true => ".*",
			 },
			 );

		my @OsLookupTable =
			(
			 {
				 run	=> "cat '/etc/issue'",
				 field	=> "issue",
			 },
			 {
				 file	=> "/etc/debian_version",
				 text	=> "debian",
				 field	=> "text",
			 },
			 {
				 run	=> "uname",
				 field	=> "uname",
			 },
			 {
				 run	=> "true",
				 field	=> "true",
			 },
			 );
			 

		my $os = undef;
		my $installer = undef;
		foreach my $lookup ( @OsLookupTable ) {
			my $text = "";
			if ( exists $lookup->{file}  and  -f $lookup->{file} ) {
				$text = $lookup->{text};
			}
			elsif ( exists $lookup->{run} ) {
				$text = `$lookup->{run}`;
				chomp $text;
			}
			else {
				next;
			}
			$os = find_os( \@OsTable, $lookup->{field}, $text );
			if ( $os ) {
				if (  exists $os->{installer}  and 
					  exists $InstallerTable{$os->{installer}}  ) {
					$installer = $InstallerTable{$os->{installer}};
				}
				last;
			}
		}
		die "Unknown O/S" if ( ! $os );
		die "Unknown O/S installer" if ( ! $installer );
		print "Detected O/S '".$os->{name}."'".
			", installer '".$installer->{name}."'\n";
		foreach my $lib ( keys %missing_libs )
		{
			print "Condor requires '$lib':\n";
			if ( exists($os->{libs}{$lib})  and  exists($installer->{run}) )
			{
				my $cmd = sprintf( $installer->{run}, $os->{libs}{$lib} );
				print
					"  This is probably provided by the '".
					($os->{libs}{$lib}) . "' package.\n".
					"  You need to install this package with " .
					$installer->{name}.
					" by running the following as root:\n".
					"    $cmd\n";
			}
			elsif ( exists($os->{libs}{$lib}) )
			{
				print
					"  This is probably provided by package '".
					($os->{libs}{$lib}) . "' or similar.\n".
					"  You need to find and install this package with your\n" .
					"  O/S package installer (as root)\n";
			}
			elsif ( exists($installer->{run}) )
			{
				my $cmd = sprintf( $installer->{run}, $lib );
				print
					"  I don't know what package will provide this library\n".
					"  You need to find and install this package with your\n" .
					"  O/S package installer (".$installer->{name}.")\n".
					"  Try something like '".$cmd."' (as root)\n";
			}
			else
			{
				print
					"  I don't know what package will provide this library\n".
					"  You need to find and install this package with your\n" .
					"  O/S package installer (as root)\n";
			}
		}
		exit( 1 ) if ( ! $opt_ignore_missing_libs );
	}

    if ( !$release_dir ) {
		die "Undefined \$release_dir!\n";
    }
    
    if ( ! -d $release_dir ) {
		(system ("mkdir -p $release_dir") == 0) || 
			die "Unable to create $release_dir!\n" ;
		chmod 0777, $release_dir;
    } elsif ( ! -w $release_dir ) {
		die "Unable to write to $release_dir!\n";
    }

    chdir "$release_dir";

    $release_dir = getcwd();	# Get the complete absolute path

	my $install_in_place = 0;
	if ( $release_dir eq $release_src_dir ) {
		$install_in_place = 1;
	}

    # Move the sbin directories instead of overwriting them,
    # so that the running daemons don't blow up 
	my @installed_programs;
	my $sbin = "$release_dir/sbin";
	foreach my $p ( @{$bin_dirs{sbin}} )
	{
		my $fp = "$sbin/condor_$p";
		push( @installed_programs, $fp ) if ( -x $fp );
	}

	if ( !$install_in_place && -d $sbin && scalar @installed_programs ) {
		if ( $opt_overwrite ) {
			# Do nothing...  overwrite sbin below
		}
		elsif ( $opt_backup ) {
			rename ("$release_dir/sbin", "$release_dir/sbin.old.$timestamp") or
				die "Unable to move $release_dir/sbin!\n";
		}
		else {
			my $n = scalar @installed_programs;
			print STDERR
				"$Program found $n daemons in '$sbin' and can't proceed.\n".
				"  You need to specify '--backup' or '--overwrite' to\n".
				"  tell $Program what to.\n".
				"  --overwrite will cause $Program to overwrite Condor\n".
				"    executables in the above sbin directory\n".
				"  --backup will cause $Program to move the above sbin\n".
				"    directory out of the way and create a new sbin\n".
				"    directory in it's place\n";
			exit( 1 );
		}
    }

	if( $install_in_place ) {
		print "Setting up Condor in $release_dir\n";
	}
	else {
		# Create a process to tar-ify the release directories
		print "Installing Condor from $release_src_dir to $release_dir\n";
		my $cmd = "cd $release_src_dir; tar cf - " . join( " ", @release_dirs );
		open( TARCF, "$cmd|" ) or die "Can't run $cmd (used to copy release)";

		$cmd = "tar xf -";
		open( TARXF, "|$cmd" ) or die "Can't run $cmd (used to copy release)";

		# Read from the "tar cf -", pipe output into the "tar xf -"
		while( 1 ) {
			my $buffer;
			my $size = 1024 * 1024;
			my $read_size = sysread( TARCF, $buffer, $size );
			last if ( $read_size <= 0 );
			my $write_size = syswrite( TARXF, $buffer, $read_size );
			if ( $write_size != $read_size ) {
				die "Failed copying to $release_dir: $!";
			}
		}
		close( TARCF );
		close( TARXF );
	}

    $global_config{RELEASE_DIR}="$release_dir";

    # Create config file, unless one exists

    $config_file="$release_dir/etc/condor_config";

    # If the config file already exists, we're done
    if ( -f $config_file ) {
		debug ("\nThis is an upgrade installation. Will not modify config files.\n");
		$no_config_modify=1;
		return $release_dir;
    }


    # Create config file
    system("cp $release_dir/etc/examples/condor_config.generic $config_file") &&
		die "Unable to create condor_config file: $config_file!\n";

    if ($opt_local_dir) {
		$local_dir=condor_init ($opt_local_dir);
		#$append_config{LOCAL_DIR}="$opt_local_dir";
		$global_config{LOCAL_DIR}="$opt_local_dir";
    } else { 
		# Set up local directory
		$local_dir=condor_init ("$release_dir/local.$host");
		#$append_config{LOCAL_DIR}="$release_dir/local.\$(HOSTNAME)";
		$global_config{LOCAL_DIR}="$release_dir/local.\$(HOSTNAME)";
    }

    # Create local config file
    $local_config_file="$local_dir/condor_config.local";
    (system ("touch $local_config_file") == 0) ||
		die "Unable to create local config file: $local_config_file!\n";
    $global_config{LOCAL_CONFIG_FILE}="$local_config_file";

    # make_personal_condor();
    # Don't assume the CONDOR_HOST will be defined (e.g. Condor-G)
    #$append_config{CONDOR_HOST}=$host;

    $append_config{UID_DOMAIN}="\$(FULL_HOSTNAME)";
    $append_config{FILESYSTEM_DOMAIN}="\$(FULL_HOSTNAME)";
    $append_config{LOCK}="/tmp/condor-lock.".rand();

    # This is necessary so that if no collector host is specified, 
    # Condor doesn't start using "central-manager-hostname.your.domain"
    $global_config{CONDOR_HOST}="";

    return $release_dir;

}	# sub install()

sub determine_missing_libs
{
	my ($progref, $libref, $num_ref) = @_;
	my ($p, $ldd, $lib, $loc);
	my $status = "able_to_check";
	my $line;

	# In macOS Big Sur (Darwin version 20.x), all of the system shared
	# libraries are bundled into a single cache file with no public way
	# to query their presence. Don't try looking for them.
	my $os_ver = `uname -v`;
	if ($os_ver =~ /Darwin Kernel Version 2/) {
		return;
	}

	# When checking the library dependencies, I turn off the warning that
	# open gives me due to use warnings when it can't exec the ldd command
	# (because it might not be there on the machine in question). It is
	# easier for me to just have the command fail then try various methods
	# of discovery to see which one I'm able to run. Just let the control
	# flow fall through the failures until something works, or everything
	# fails and we do one warning later about it.

	PROGRAM: foreach $p ( @{$progref} ) {

		# First, we'll try 'ldd' and see if that works... If not, silently
		# fail. ldd automatically checked to see if the libraries are
		# physically on the machine.
		$ldd = "ldd $p";
		{ # scoping for turning off the exec warning for the open
			no warnings qw(exec);
			if ( open( LDD, "$ldd|" ) ) {
				while( <LDD> ) {
					# Skip it if it is a statically linked binary
					next if (/not a dynamic executable/);

					if (/^\s+(\S+)\s*=>\s*(.*)/ ) {
						$lib = $1;
						$loc = $2;
						if ( $loc =~ /not found/ ) {
							$libref->{$lib} = $loc;
							$$num_ref++;
						}
					}
				}
				close( LDD );

				# It worked, so do the next program
				next PROGRAM;
			}
		}

		# Next, we'll try 'otool -L' and see if that works, if not, silently
		# fail. Unfortunately, otool -L only prints out the libraries the
		# executable depends upon, but doesn't actually check to see if they
		# are present on the machine, so we must perform that functionality
		# here.
		$ldd = "otool -L $p";
		{ # scoping for turning off the exec warning for the open
			no warnings qw(exec);
			if ( open( LDD, "$ldd|" ) ) {
				while( <LDD> ) {
					if (/No such file or directory/) {
						# Hrm, I can't find the programs that I should have
						# been shipped with?
						die "Internal Error: Can't find program '$p' when it " .
							"should have been there. Maybe your " .
							"downloaded package is corrupt?";
					}

					# Grab out the library and check its existence.
					# ignore other lines...
					if (/^\s+(.*)\s+\(.*$/ ) {
						$lib = $1;

						# convert @executable_path in the library path
						# to the path to the executable
						my $executable_path = $p;
						$executable_path =~ s|(.*)/[^/]*|$1|;
						$lib =~ s|\@executable_path|$executable_path|;

						if ( ! -f $lib ) {
							$libref->{$lib} = $lib;
							$$num_ref++;
						}
					}
				}
				close( LDD );

				# It worked, so do the next program
				next PROGRAM;
			}
		}

		# If the control logic reaches here, it means none of the system
		# installed library dependency checking programs we tried here were
		# available.  We keep track of this fact and print out a nice warning
		# message later.

		$status = "not_able_to_check";
	}

	if ($status eq "not_able_to_check") {
		warn "WARNING: " .
			"Unable to determine if the shared library requirements of our " .
			"executables can be satisfied with the shared libraries present " .
			"on this machine. Hopefully, your Condor binaries will execute " .
			"properly.\n";
	}
}

sub find_release_dir( $ ) {
    my $path=shift(@_);

    if ($path && check_release_dir ($path)) {
		return $path;
    }

    chomp($_ = `which condor_config_val 2>/dev/null`);
    if( /^\/.*$/ && !$?) {
		chomp($path = `condor_config_val RELEASE_DIR 2>/dev/null`);
		if( $? == 0 && check_release_dir($path) ) {
			return $path;
		}
    }

    if( check_release_dir("/usr/local/condor") ) {
		return "/usr/local/condor";
    } 

    die "Unable to find directory where Condor is installed! \
Please specify it with --install-dir=<dir>\n";
}

sub safe_mkdir($$) {
    my ($name,$mode) = @_;
    return if -d $name;
    my $prev_umask = umask(0);
    mkdir($name, $mode)
        or die "\nCan't create \"$name\"\n\n";
    umask($prev_umask);
}

sub condor_init( $ ) {
    my $local_dir = shift(@_);

    # Make required local directories
    safe_mkdir( "$local_dir",               0755);
    safe_mkdir( "$local_dir/log",           0755);
    safe_mkdir( "$local_dir/spool",         0755);
    safe_mkdir( "$local_dir/execute",       01777); #world writeable local dir!
    safe_mkdir( "$local_dir/signing_keys",  0700);
    safe_mkdir( "$local_dir/tokens",        0700);

    system ("chown -R $owner $local_dir");  # wish Perl could do this natively
    return $local_dir;
}

sub check_release_dir( $ ) {
    my $dir = shift;

    foreach my $sub ("bin", "sbin", "etc") {
		my $full = "$dir/$sub";
		if ( ! -d $full ) {
			print STDERR "Directory $full does not exist\n";
			return 0;
		}
	}
	return 1;
}

sub set_mail_settings() {
    $append_config{CONDOR_ADMIN}="$who\@$fullhost";
    debug ("Setting CONDOR_ADMIN to \"$append_config{CONDOR_ADMIN}\" If this is not your preferred email address, please modify CONDOR_ADMIN in the configuration file");
    
    my $mail_path;
    
    chomp($_ = `uname`);
  SWITCH: {
      if(/^Linux/) { $mail_path="/usr/bin/mail";   last SWITCH; }
      if(/^Darwin/) { $mail_path="/usr/bin/mail";  last SWITCH; }
      $mail_path="/bin/mail";
  }   
    
    if (-f $mail_path && -x $mail_path) {
		$append_config{MAIL}=$mail_path;
    }
    else {
		foreach $mail_path ( "/bin/mailx", "/usr/sbin/mailx",
							 "/usr/ucb/mailx", "/usr/bin/mail",
							 "/usr/ucb/mail", "/bin/mail" ) {
			if (-f $mail_path && -x $mail_path) {
				$append_config{MAIL}=$mail_path;
				last;
			}
		}
    }

    if ( $append_config{MAIL} ) {
		debug ("Setting mail path to: $append_config{MAIL}");
    } else {
		warn "\n\n WARNING: Unable to find mail program! Condor will not be \n
able to send status notifications until MAIL parameter is configured.\n";
    }

}


# Figure out what to use for UID and FileSystem domain.
sub set_domain_settings() {
    debug ("Setting FILESYSTEM_DOMAIN and UID_DOMAIN to $domain");

    $append_config{FILESYSTEM_DOMAIN}=$domain;
    $append_config{UID_DOMAIN}=$domain;
}

sub set_central_manager ( $ ) {
    my $cm=shift(@_);

    if (!(gethostbyname($cm))[0]) {
		warn "\nWARNING: Unable to contact central manager: $cm!\n";
    }

    $append_config{CONDOR_HOST}=$cm;
    return $cm;
}

sub set_config_values ($$$) {
    my ($hashref, $file, $is_local) = @_;

    my @keylist=keys (%$hashref);

    return if ($#keylist == -1);

    &debug ("\nWriting settings to file: $file");

    open (TEMP, ">/tmp/set_config_values.temp.$$") || die "Unable to open /tmp/set_config_values.temp.$$ $!\n";

    open (SOURCE, "<$file") || die "Unable to open file $file\n";

    while (<SOURCE>) {
      SWITCH:{
		  chomp(my $line=$_);
		  
		  
		  foreach my $key (@keylist) {
			my $matches = 0;
			if ($line =~ m/^\s*$key\s*=.*/) {
			    $matches = 1; # matches
			}  elsif ($line =~ m/^\#\s*$key\s*=.*/) {
			    $matches = 2; # matches a commented out line
			}
			if ($matches) {
			    # if it matches a commented out line, preserve the commented out line (comments show default values)
			    if ($matches == 2) { print TEMP "$line\n"; }
			    if (exists $hashref->{$key}) {
				my $value=$hashref->{$key};
				&debug ("$key=$value");
				if ($value) {
				    print TEMP "$key = $value\n";
				}
				delete $hashref->{$key};
			    }
			    last SWITCH;
			}
		  }
		  
		  print TEMP "$line\n";
      } # SWITCH
    }

    # Print metaknobs at the top of the 'append here' section
    $knobcount = @metaknobs;
    if (($knobcount > 0) && $is_local) {
	foreach my $knob (@metaknobs) {
		my $comment = $comment_hash{$knob};
		if ($comment) { print TEMP "$comment\n"; }
		print TEMP "$knob\n";
	}
	print TEMP "\n";
    }

    # Print out the keys that are in @allparams
    # so that we can group them together
    foreach my $key (@allparams) {
		my $value = $hashref->{$key};
		if ($value) {
			&debug ("$key=$value");
			if ($is_local) {
				my $comment = $comment_hash{$key};
				if ($comment) {
					print TEMP "$comment\n";
				}
			}
			print TEMP "$key = $value\n";
			delete $hashref->{$key};
		}
    }
    print TEMP "\n";

    # Print out all the remaining values
    while (my ($key, $value) = each %$hashref) {
		if ($value) {
			&debug ("$key=$value");
			if ($is_local) {
				my $comment = $comment_hash{$key};
				if ($comment) {
					print TEMP "\n$comment\n";
				}
			}
			print TEMP "$key = $value\n";
		}
    }
    close TEMP;
    close SOURCE;
    system("mv /tmp/set_config_values.temp.$$ $file") &&
		die "Unable to move /tmp/set_config_values.temp.$$ to $file!\n";
}

# Search for default locations for java, and then test to see if it is a
# Sun JVM for the maxheap size argument Java needs in the config files.
# Do a bunch of stuff to make it interactive friendly too.
sub set_java_jvm_path()
{
    my $jvm = "";

    my @default_jvm_locations = ("/bin/java", 
								 "/usr/bin/java", 
								 "/usr/local/bin/java", 
								 "/s/std/bin/java");
    
    unless (system ("which java >> /dev/null 2>&1")) {
		chomp (my $which_java = `which java`);
		@default_jvm_locations = ($which_java, @default_jvm_locations) unless ($?);
    }

    my $java_libdir = "$release_dir/lib";
    my $exec_result;
    my $default_jvm_location;

    # check some default locations for java and pick first valid one
    foreach $default_jvm_location (@default_jvm_locations) {
		if ( -f $default_jvm_location && -x $default_jvm_location) {
			$jvm = $default_jvm_location;
			last;
		}
    }

    # if nothing is found, explain that, otherwise see if they just want to
    # accept what I found. 

    if ($jvm eq "") {
		log_message( "Unable to find a valid Java installation \
Java Universe will not work properly until the JAVA \
(and JAVA_MAXHEAP_ARGUMENT) parameters are set in the configuration file!" );
return;
}


debug ("Setting JAVA=$jvm");

	# Now that we have an executable JVM, see if it is a Sun jvm because that
	# JVM it supports the -Xmx argument then, which is used to specify the
	# maximum size to which the heap can grow.

	# execute a program in the condor lib directory that just got installed.
	# We are going to pass an -Xmx flag to it and see if we have a Sun JVM,
	# if so, mark that fact for the config file.
 
my $tmp = $ENV{"CLASSPATH"} || undef;	# save CLASSPATH environment
my $java_jvm_maxmem_arg = "";


	$ENV{"CLASSPATH"} = $java_libdir;
	$exec_result = 0xffff &
	    system("$jvm -Xmx1024m CondorJavaInfo new 0 > /dev/null 2>&1");
	if ($tmp) {
		$ENV{"CLASSPATH"} = $tmp;
	}

	if ($exec_result == 0) {
	    $java_jvm_maxmem_arg = "-Xmx1024m"; # Sun JVM max heapsize flag
	} else {
	    $java_jvm_maxmem_arg = "";
	}

        $append_config{JAVA}=$jvm;
        $append_config{JAVA_MAXHEAP_ARGUMENT}=$java_jvm_maxmem_arg;

}

#tj-8.2 this is obsolete
#sub make_personal_condor() {
#	$daemon_list{COLLECTOR} = 1;
#	$daemon_list{NEGOTIATOR} = 1;
#	$daemon_list{STARTD} = 1;
#	$daemon_list{SCHEDD} = 1;
#    $append_config{START}="TRUE";
#    $cm=set_central_manager($fullhost);
#}

sub get_config_value($;$) {
    my ($key,$cnf_file)=@_;

    if (!$cnf_file) { $cnf_file=$config_file };
    
    local $ENV{CONDOR_CONFIG}=$cnf_file;
    chomp (my $result = `$release_dir/bin/condor_config_val $key`);
    
    return $result unless $?;

    return "";
}

sub debug( $ ) {
    my $str=shift;
    
    if ($opt_verbose) {
		print "$str\n";
    }
}

# control the output order of generated config statements and set comments. 
# a \n will be automatically appended when the comment is printed.
#
sub set_config_comments() {
    push (@allparams, 'DAEMON_LIST');
    push (@allparams, 'CONDOR_HOST');
    push (@allparams, 'NETWORK_INTERFACE');
    push (@allparams, 'COLLECTOR_HOST');
    push (@allparams, 'COLLECTOR_NAME');

    $comment_hash{UID_DOMAIN}="\n##  What is considered local for UIDs and for files";
    push (@allparams, 'UID_DOMAIN');
    push (@allparams, 'FILESYSTEM_DOMAIN');

    $comment_hash{LOCK}="\n##  unique lock file on the local filesystem";
    push (@allparams, 'LOCK');

    $comment_hash{CONDOR_IDS}="\n##  The user/group ID <uid>.<gid> of the \"Condor\" user";
    push (@allparams, 'CONDOR_IDS');

    $comment_hash{CONDOR_ADMIN}="\n## When something goes wrong with condor at your site, who should get the email?";
    push (@allparams, 'CONDOR_ADMIN');
    push (@allparams, 'MAIL');

    $comment_hash{JAVA}="\n##  java";
    push (@allparams, 'JAVA');
    push (@allparams, 'JAVA_MAXHEAP_ARGUMENT');
}

#tj - as of 8.1.5 the base config has virtually no comments to scrape, so this function does nothing useful
#
sub read_config_file_comments() {
	my $current_comment = "";
	my $key;
	my $found_param = 0;

    open (CONFIG, "<$config_file");

    while (<CONFIG>) {
		if (/^## /) {
			$current_comment .= $_;
		} elsif (/^#?(\w+)\W*=/) {
				 $key=$1;
				 $comment_hash{$key}=$current_comment;
				 $found_param = 1;
				 push (@allparams, $key);
			 } elsif (/^$/) {
				 if ($found_param) {
					 $current_comment="";
					 $found_param = 0;
				 }
			 } elsif (/^####/) {
					  # skip header delimiters
					  $current_comment="";
				  }

		
    }

    close (CONFIG);
}

# find first occurrence of file in PATH, or undef.
sub which( $ ) {
	my $file = shift;
	foreach my $path ( split /:/, $ENV{PATH} ) {
		my $fullpath = join( '/' , $path, $file);
		if ( -x $fullpath ) {
			return $fullpath;
		}
	}
	return undef;
}

# Configure CredD credential management daemon.
sub credd() {
	$daemon_list{CREDD} = 1;

	# Create/publish credential store directory.
	my $cred_dir = "$local_dir/cred_dir";
	unless (-d $cred_dir) {
		mkdir ($cred_dir, 0700) or die "Create $cred_dir: $!";
    }
	my $cred_dir_mode = 0700;
	chmod $cred_dir_mode, $cred_dir or die "chmod $cred_dir: $!";
	$append_config{CRED_STORE_DIR} = '$(LOCAL_DIR)/cred_dir';
}

sub log_message( $ )
{
    my $message = shift;
	
    if (defined($opt_install_log) && $opt_install_log ne "") {
        if ($printed_log_message == 0) {
            print wrap("", "", "You should look inside the installation log ",
                       "for some details about how Condor was installed.\n");
            $printed_log_message = 1;
            
            print $logfile "----------------------------------------------------------------------\n\n";
            print $logfile "Condor Installation Notes\n\n";
        }
    }
    print $logfile (wrap("", "", $message));
    print $logfile "\n";
    return;
}

sub usage($) {
	my $exit = shift;
	print "usage: $Program [options]\n";
	foreach my $opt ( @Options ) {
		print "    " . $opt->{short} . "\n";
	}
	if ( defined $exit ) {
		exit( $exit );
	}
}

sub help() {
	usage( undef );
	print "\n";
	foreach my $opt ( @Options ) {
		print $opt->{short} . "\n";
		print $opt->{long} . "\n";
	}
	exit( 0 );
}

### Local Variables: ***
### mode:perl ***
### tab-width: 4  ***
### End: ***
