#!/usr/bin/env 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

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 => "--make-personal-stork",
	 long => <<END_OPT_MAKE_PERSONAL_STORK,
Creates a personal Stork, using the credential manager daemon.
END_OPT_MAKE_PERSONAL_STORK
 },
 {
	 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 => "--stork",
	 long => <<END_OPT_STORK,
Configures Stork data placement server.  It is recommended to also use
the --credd option with the --stork option.
END_OPT_STORK
 },
 {
	 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).
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 => "--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 => "--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_make_personal_stork,
		$opt_type,
		$opt_central_manager,
		$opt_stork,
		$opt_credd,
		$opt_owner,
		$opt_maybe_daemon_owner,
		$opt_install_log,
		$opt_verbose,
		$opt_overwrite,
		$opt_backup,
		);


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 %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 make_personal_stork();
sub get_config_value( $;$ );
sub debug( $ );
sub read_config_file_comments();
#sub is_dynamic( $ );
sub which( $ );
sub myproxy();
sub credd();
sub stork();
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 %local_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
    $local_config{CONDOR_IDS}="$owner.$gid";
}

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

# Install if necessary
if (defined($opt_release_dir)) {
    # Install
    if ($opt_prefix_dir) {
		$release_dir=install($opt_prefix_dir);
    } else {
		chomp($release_dir=`pwd`);
		$release_dir=install($release_dir);
    }
}
else {
    # Verify Install diretory
    if ($opt_prefix_dir) {
		check_release_dir($opt_prefix_dir) or
			die "Invalid install directory: $opt_prefix_dir!\n";
		$release_dir=$opt_prefix_dir;
		chomp ($release_dir=`pushd $release_dir >> /dev/null && pwd && popd >> /dev/null`);
    } else {
		chomp (my $pwd=`pwd`);
		$release_dir=find_release_dir($pwd);
    }

    $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);
		$local_config{LOCAL_DIR}=$local_dir;
    }
}
debug ("Install directory: $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";
		}
    }
}



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

if ($opt_make_personal_condor ||
    (defined($opt_release_dir) && !$opt_type)) {

	$daemon_list{COLLECTOR} = 1;
	$daemon_list{NEGOTIATOR} = 1;
	$daemon_list{STARTD} = 1;
	$daemon_list{SCHEDD} = 1;
    $local_config{START}="TRUE";
    $local_config{PREEMPT}="FALSE";
    $local_config{SUSPEND}="FALSE";
    $local_config{KILL}="FALSE";

    $cm=set_central_manager($fullhost);
    $local_config{COLLECTOR_NAME}="Personal Condor at $fullhost";
}
elsif ($opt_type) {

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

    $local_config{START}="";
    $local_config{PREEMPT}="";
    $local_config{SUSPEND}="";
    $local_config{KILL}="";
    
    $local_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;
		} else {
			die "Illegal -type argument: $opt_type!\n";
		}
    }
}

if ($opt_make_personal_stork) {
	make_personal_stork();
}

# Condor-G and CredD can use MyProxy.
myproxy();

if ($opt_credd)  {
	credd();
}

if ($opt_stork)  {
	stork();
}

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

# 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 local and global config files
unless ($no_config_modify) {
    read_config_file_comments();

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


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."
				 );

}

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 ( $#ARGV < 0 ) {
		usage( 1 );
	}

	# For condor_install, default behavior is --install=.
	if ( $0 =~ /_install/ ) {
		unshift( @ARGV, "--install=." );
	}

	&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,
				 "make-personal-stork!"		=>	\$opt_make_personal_stork,
				 "type=s"					=>	\$opt_type,
				 "central-manager=s"		=>	\$opt_central_manager,
				 "stork!"					=>	\$opt_stork,
				 "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(); exit 0; },
				 "overwrite"				=>	\$opt_overwrite,
				 "backup"					=>	\$opt_backup,
				 ) or usage( 1 );

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


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( ! $uid ) {
                die "\nInvalid user: getpwnam(\"$uname\") failed!\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 the condor_configure "
                        . "$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 install( $ ) {
    my $release_dir=shift(@_);

    my @release_dirs = qw( etc include src lib libexec bin sbin sql man );

	chomp(my $curdir=`pwd`);
    my $release_src_dir="$curdir";
    if ($opt_release_dir) {
		$release_src_dir=$opt_release_dir;
    }

	my $old = $ENV{PWD};
    chdir "$release_src_dir" or die "Can't chdir to $release_src_dir";
    chomp ($release_src_dir=`pwd`); # Get the complete absolute path
	chdir( $old ) or die "Can't chdir back to $old";

	my @missing;
	foreach my $d ( @release_dirs ) {
		my $dir = "$release_src_dir/$d";
		if ( ! -d $dir ) {
			push( @missing, $d );
		}
	}
	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";
	}

    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";

    chomp ($release_dir=`pwd`); # 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 $sbin = "$release_dir/sbin";
	if ( !$install_in_place && -d $sbin && -x "$sbin/condor_master" ) {
		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 {
			print STDERR
				"$Program found '$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 );
	}

    $local_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);
		$local_config{LOCAL_DIR}="$opt_local_dir";
    } else { 
		# Set up local directory
		$local_dir=condor_init ("$release_dir/local.$host");
		$local_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)
    #$local_config{CONDOR_HOST}=$host;

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

    # if GT3 gahp is installed, fix a few wsdl files
    my $gt3_install=$release_dir."/lib/gt3";
    if ( -d $gt3_install ) {
		
		system ("cat $gt3_install/server-config.wsdd.in | sed -e \'s|\@GT3_INSTALL\@|$gt3_install|\' > $gt3_install/server-config.wsdd");
		system ("cat $gt3_install/local-server-config.wsdd.in | sed -e \'s|\@GT3_INSTALL\@|$gt3_install|\' > $gt3_install/local-server-config.wsdd");
    }

    # 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}="";

    if (-x "/sbin/ifconfig") {
        my @network_interfaces=`/sbin/ifconfig | grep \"inet addr:\" | grep -v 127.0.0.1`;
        if ($? == 0 && $#network_interfaces > 0) {
            log_message("WARNING: Multiple network interfaces detected. "
                        . "Condor might not work properly until you "
                        . "set NETWORK_INTERFACE = <interface IP>\n");
        }
    }

    chomp (my $network_interface=`host $host | grep \"has address\" | awk \'\{print \$4\}\'`);
    
    if ($? == 0 && 
		($network_interface =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ )) {
		#$local_config{NETWORK_INTERFACE}=$network_interface;
    } else {
		log_message( "\nWARNING: Unable to determine local IP address. Condor "
					 ." might not work propertly until you set "
					 ." NETWORK_INTERFACE=<machine IP address>\n");
    }  

    set_mail_settings();
    
    set_domain_settings();

    &set_java_jvm_path();
    
    return $release_dir;
}


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/log/GridLogs,   01777); #world writeable local dir!
    safe_mkdir( "$local_dir/spool",         0755);
    safe_mkdir( "$local_dir/execute",       01777); #world writeable local dir!
    #safe_mkdir( "$local_dir/ViewHist",      0755);

    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 exit\n";
			return 0;
		}
	}
	return 1;
}

sub set_mail_settings() {
    $local_config{CONDOR_ADMIN}="$who\@$fullhost";
    debug ("Setting CONDOR_ADMIN to \"$local_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(/^SunOS/) { $mail_path="/usr/ucb/mail";   last SWITCH; }
      if(/^HP-UX/) { $mail_path="/bin/mailx";      last SWITCH; }
      if(/^IRIX.*/) { $mail_path="/usr/sbin/mailx";  last SWITCH; }
      if(/^OSF1/)  { $mail_path="/usr/ucb/mailx";  last SWITCH; }
      if(/^AIX/)  { $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) {
		$local_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) {
				$local_config{MAIL}=$mail_path;
				last;
			}
		}
    }

    if ( $local_config{MAIL} ) {
		debug ("Setting mail path to: $local_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");

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

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

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

    $local_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 file in /tmp directory!\n";

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

    while (<SOURCE>) {
      SWITCH:{
		  chomp(my $line=$_);
		  
		  
		  foreach my $key (@keylist) {
			  if ($line =~ m/^\s*$key\s*=.*/) {
				  #print TEMP "#$ line\n";  # Comment the old line

				  if (exists $hashref->{$key}) {
					  my $value=$hashref->{$key};
					  &debug ("$key=$value");
					  if ($value) {
						  print TEMP "$key = $value\n";
					  }
					  delete $hashref->{$key};
				  }
				  last SWITCH; 
			  } elsif ($line =~ m/^\#\s*$key\s*=.*/) {
				  last SWITCH;
			  }
		  }
		  
		  print TEMP "$line\n";
      } # SWITCH
    }

    # 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 "\n$comment\n";
				}
			}
			print TEMP "$key = $value\n\n";
			delete $hashref->{$key};
		}
    }

    # 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\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 = "-Xmx"; # Sun JVM max heapsize flag
	} else {
	    $java_jvm_maxmem_arg = "";
	}

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

}

sub make_personal_condor() {
	$daemon_list{COLLECTOR} = 1;
	$daemon_list{NEGOTIATOR} = 1;
	$daemon_list{STARTD} = 1;
	$daemon_list{SCHEDD} = 1;
    $local_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";
    }
}

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 myproxy.  Condor-G and CredD can use this service to
# auto-refresh GSI credentials.  Look for myproxy in the PATH, and add
# to configuration, if found.  If the binary is dyanamically linked,
# also add the LD_LIBRARY_PATH to config.
sub myproxy() {
	my $myproxy_get_delegation = which "myproxy-get-delegation";
	if ($myproxy_get_delegation) {
		$local_config{MYPROXY_GET_DELEGATION} = $myproxy_get_delegation;
	}
}

# Create a personal Stork/CredD
sub make_personal_stork()
{
	$daemon_list{COLLECTOR} = 1;
	$opt_credd = 1;
	$opt_stork = 1;
}

# 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: $!";
	$local_config{CRED_STORE_DIR} = '$(LOCAL_DIR)/cred_dir';

	unless ( $local_config{MYPROXY_GET_DELEGATION} ) {
		warn<<EOF;
myproxy-get-delegation not found in PATH.  To enable GSI proxy auto-refresh,
edit MYPROXY_GET_DELEGATION configuration macro.
EOF
	}
}

# Configure Stork server.
sub stork() {
	$daemon_list{STORK} = 1;

}

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";
	}
}

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