: # *-*-perl-*-*
    eval 'exec perl -S $0 "$@"'
    if $running_under_some_shell;  
#
#  CreateBroker - Generates a new Broker based on user input.
#  
#  Usage: CreateBroker [skeleton-tree [destination]]
#
#  	For example, CreateBroker /usr/local/harvest/brokers/skeleton
#
#  Darren Hardy, hardy@cs.colorado.edu, October 1994
#
#  $Id: CreateBroker,v 1.44 1995/09/22 20:44:01 duane Exp $
#
#######################################################################
#
#  Copyright (c) 1994, 1995.  All rights reserved.
#  
#    The Harvest software was developed by the Internet Research Task
#    Force Research Group on Resource Discovery (IRTF-RD):
#  
#          Mic Bowman of Transarc Corporation.
#          Peter Danzig of the University of Southern California.
#          Darren R. Hardy of the University of Colorado at Boulder.
#          Udi Manber of the University of Arizona.
#          Michael F. Schwartz of the University of Colorado at Boulder.
#          Duane Wessels of the University of Colorado at Boulder.
#  
#    This copyright notice applies to software in the Harvest
#    ``src/'' directory only.  Users should consult the individual
#    copyright notices in the ``components/'' subdirectories for
#    copyright information about other software bundled with the
#    Harvest source code distribution.
#  
#  TERMS OF USE
#    
#    The Harvest software may be used and re-distributed without
#    charge, provided that the software origin and research team are
#    cited in any use of the system.  Most commonly this is
#    accomplished by including a link to the Harvest Home Page
#    (http://harvest.cs.colorado.edu/) from the query page of any
#    Broker you deploy, as well as in the query result pages.  These
#    links are generated automatically by the standard Broker
#    software distribution.
#    
#    The Harvest software is provided ``as is'', without express or
#    implied warranty, and with no support nor obligation to assist
#    in its use, correction, modification or enhancement.  We assume
#    no liability with respect to the infringement of copyrights,
#    trade secrets, or any patents, and are not responsible for
#    consequential damages.  Proper use of the Harvest software is
#    entirely the responsibility of the user.
#  
#  DERIVATIVE WORKS
#  
#    Users may make derivative works from the Harvest software, subject 
#    to the following constraints:
#  
#      - You must include the above copyright notice and these 
#        accompanying paragraphs in all forms of derivative works, 
#        and any documentation and other materials related to such 
#        distribution and use acknowledge that the software was 
#        developed at the above institutions.
#  
#      - You must notify IRTF-RD regarding your distribution of 
#        the derivative work.
#  
#      - You must clearly notify users that your are distributing 
#        a modified version and not the original Harvest software.
#  
#      - Any derivative product is also subject to these copyright 
#        and use restrictions.
#  
#    Note that the Harvest software is NOT in the public domain.  We
#    retain copyright, as specified above.
#  
#  HISTORY OF FREE SOFTWARE STATUS
#  
#    Originally we required sites to license the software in cases
#    where they were going to build commercial products/services
#    around Harvest.  In June 1995 we changed this policy.  We now
#    allow people to use the core Harvest software (the code found in
#    the Harvest ``src/'' directory) for free.  We made this change
#    in the interest of encouraging the widest possible deployment of
#    the technology.  The Harvest software is really a reference
#    implementation of a set of protocols and formats, some of which
#    we intend to standardize.  We encourage commercial
#    re-implementations of code complying to this set of standards.  
#  
#
$ENV{'HARVEST_HOME'} = "/usr/local/harvest" if (!defined($ENV{'HARVEST_HOME'}));
$ENV{'PATH'} = $ENV{'PATH'} . ":" . "$ENV{'HARVEST_HOME'}/bin" .
			      ":" . "$ENV{'HARVEST_HOME'}/lib/broker". 
			      ":" . "$ENV{'HARVEST_HOME'}/lib";
$whoami_cmd = "whoami";
$whoami_cmd = "/bin/whoami" if (-x "/bin/whoami");
$whoami_cmd = "/usr/bin/whoami" if (-x "/usr/bin/whoami");
$whoami_cmd = "/usr/ucb/whoami" if (-x "/usr/ucb/whoami");
chop($this_person = &grab_cmd_output("$whoami_cmd"));
$hostname_cmd = "hostname";
$hostname_cmd = "/usr/bin/hostname" if (-x "/usr/bin/hostname");
$hostname_cmd = "/usr/ucb/hostname" if (-x "/usr/ucb/hostname");
$hostname_cmd = "/bin/hostname" if (-x "/bin/hostname");
chop($this_host = &grab_cmd_output("$hostname_cmd"));
($this_host_full, @x) = gethostbyname($this_host);
undef @x;

print <<EOM;

  ----------------------------------------------------------------------
                           Welcome to Harvest!

   This program will create and configure a Harvest Broker.  First, you 
   will be asked a few questions about how you want this new Broker to 
   look.  Second, this program will create the Broker and configure it.  
   Finally, this program will generate a script that can be used to run 
   the new Broker.  If you have any questions or problems, please refer 
   to http://harvest.cs.colorado.edu/support.html.
  ----------------------------------------------------------------------

EOM

while (1) {
	&init_vars();
	&get_user_input();
	&print_info();

	$vals{"YorN"} = "yes";
	&get_ans("Is this information correct?", "YorN");
	last if ($vals{"YorN"} =~ /^y/io);
}

&build_broker();
print <<EOM;

  Harvest Brokers can collect indexing information from Gatherers or 
  other Brokers.  The list of collection points for your Broker is in 
  $vals{'Destination-Directory'}/admin/Collection.conf.

EOM
$vals{"YorN"} = "yes";
while (1) {
	print "\n";
	&get_ans("Would you like to add a collection point to the Broker now?", "YorN");
	last if ($vals{"YorN"} =~ /^n/io);
	&add_collection_point("$vals{'Destination-Directory'}/admin/Collection.conf");
	$vals{"YorN"} = "no";
}
print <<EOM;

  ----------------------------------------------------------------------
  The new Broker was successfully built.  To start the new Broker, run

        $vals{'Destination-Directory'}/RunBroker 

  The new Broker's home page is:

        http://$vals{'HTTP-Host'}/Harvest/brokers/$vals{'Broker-Short-Name'}/query.html

  The new Broker's administrative interface is:

        http://$vals{'HTTP-Host'}/Harvest/brokers/$vals{'Broker-Short-Name'}/admin/admin.html

  Please register your Broker with the Harvest Server Registry:

        http://grand.central.org/Harvest/gatherers/HSR/cgi-bin/vdbhome.cgi

  You can query the Harvest Server Registry at:

        http://grand.central.org/Harvest/brokers/HSR/query.html

  ----------------------------------------------------------------------

EOM
exit 0;		# END OF PROGRAM

sub get_ans {
	local($prompt, $tag) = @_;

	$default_value = "";
	$default_value = $vals{$tag} if (defined($vals{$tag}));
	print $prompt, " [$default_value]: ";
	$in = <STDIN>;
	chop($in);
	$vals{$tag} = $in if ($in !~ /^\s*$/io);
}

sub print_info {
	print<<EOM;

  ----------------------------------------------------------------------
EOM
	foreach $key (sort keys %vals) {
		next if ($key eq "YorN");
	   	next if ($key eq "Skeleton-Directory");
		next if ($key =~ /glimpse/io && $INDEXER ne "glimpse");
		next if ($key =~ /wais/io && $INDEXER ne "wais");
		printf "%21s: ", $key;
		if ($vals{$key} eq "No_Default") {
			print "none";
		} else {
			print $vals{$key};
		}
		print "\n";
	}
	print<<EOM;
  ----------------------------------------------------------------------
EOM
	print "\n";
}

sub init_vars {
	print <<EOM;

  CreateBroker will try to set the default answers as correctly as possible.
  Hold on a moment, trying to guess your configuration...
EOM
	$vals{"Broker-Host"} = $this_host_full;
	$vals{"HTTP-Host"} = $vals{"Broker-Host"};
	$vals{"Broker-Name"} = "No_Default";
	$vals{"Broker-Short-Name"} = "No_Default";
	$vals{"Broker-Port"} = "8501";
	$vals{"Broker-Password"} = "";
	$vals{"Contact-Email"} = "$this_person\@$this_host_full";
	$vals{"Contact-Message"} = "";
	$vals{"glimpse-Command"} = "$ENV{'HARVEST_HOME'}/lib/broker/glimpse";
	$vals{"glimpseindex-Command"} = "$vals{'glimpse-Command'}index";
	$vals{"glimpseserver-Command"} = "$vals{'glimpse-Command'}server";
	$vals{'Broker-WAIS-Host'} = $vals{'Broker-Host'};
	$vals{'Broker-WAIS-Port'} = $vals{'Broker-Port'} + 1;
	$vals{'Broker-Glimpse-Host'} = $vals{'Broker-Host'};
	$vals{'Broker-Description-Tag'} = "description";
	$vals{'Broker-Replicas'} = "";
	$INDEXER = "glimpse";
	srand(time);
	$vals{'Broker-Collect'} = sprintf("%02d:%02d", rand(8) % 9 , rand(59) % 60 );
	
	foreach $key ("waisindex", "waissearch", "waisserver", "waisparse", "waislookup", "waisdelete") {
		$vals{"$key-Command"} = &fake_which("$key");
		$vals{"$key-Command"} = "No_Default" 
			if ($vals{"$key-Command"} !~ /^\//o);
	}
	$vals{"Skeleton-Directory"} = "$ENV{'HARVEST_HOME'}/brokers/skeleton";
}


sub get_user_input {
print "\n\n";
&get_ans("Enter a one-line descriptive name for your Broker",
	   "Broker-Name");
&get_ans("Enter a one-word name for your Broker",
	   "Broker-Short-Name");
if ($vals{"Broker-Short-Name"} ne "No_Default") {
	$vals{"Destination-Directory"} = "$ENV{'HARVEST_HOME'}/brokers/" .  $vals{"Broker-Short-Name"};
}
&get_ans("Enter the hostname on which the broker will run", 
	   "Broker-Host");
&get_ans("Enter the port number on which the broker will run",
	   "Broker-Port");

$line = &check_brokers_cf ($vals{'Broker-Short-Name'}, $vals{'Broker-Host'},
	$vals{'Broker-Port'});

print <<EOM if ($line ne '');

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
WARNING: This broker seems to conflict with another.  The following line
was found in $ENV{'HARVEST_HOME'}/brokers/Brokers.cf:

    $line

Please remedy this conflict by manually editing the Brokers.cf file or
abort this procedure.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

EOM


&get_ans("Enter the password to the broker administrative interface", 
	   "Broker-Password");
&get_ans("Enter the hostname for your HTTP server.  If you want to use\na different port number than 80, append it to the hostname\nwith a colon (e.g., www.cs.colorado.edu:9000)", 
	   "HTTP-Host");
&get_ans("Enter your email address",
	   "Contact-Email");
$vals{"Contact-Message"} = "Please send questions and comments to $vals{'Contact-Email'}" if ($vals{'Contact-Email'} ne "");
&get_ans("Enter the name of the attribute that will be displayed to the\nuser as one-line object description in search results",
	   "Broker-Description-Tag");
$vals{"Indexer"} = "glimpse";
&get_ans("Do you want to use Glimpse or WAIS as an Indexer",
	   "Indexer");
$INDEXER = "glimpse";
if ($vals{"Indexer"} =~ /wais/io) {
	$INDEXER = "wais";
} 

if ($vals{"Indexer"} =~ /glimpse/io) {
	&get_ans("Enter the pathname to the glimpse command", 
	   	"glimpse-Command");
	&get_ans("Enter the pathname to the glimpseindex command", 
	   	"glimpseindex-Command");
	&get_ans("Enter the pathname to the glimpseserver command", 
	   	"glimpseserver-Command");
	&get_ans("Enter the host on which to run glimpseserver", 
	   	"Broker-Glimpse-Host");
} else {
	$vals{'Broker-WAIS-Host'} = $vals{'Broker-Host'};
	$vals{'Broker-WAIS-Port'} = $vals{'Broker-Port'} + 1;
	$vals{'WAIS-Flavor'} = "WAIS";
	$vals{"YorN"} = "no";
	&get_ans("Are you using the commericial version of WAIS?", "YorN");
	if ($vals{"YorN"} =~ /^y/io) {
		&get_ans("Enter the pathname to the waisdelete command", 
	   		"waisdelete-Command");
		&get_ans("Enter the pathname to the waislookup command", 
	   		"waislookup-Command");
		&get_ans("Enter the pathname to the waisparse command", 
	   		"waisparse-Command");
		$vals{'WAIS-Flavor'} = "Commercial-WAIS";
	} else {
		$vals{'waisdelete-Command'} = "none";
		$vals{'waislookup-Command'} = "none";
		$vals{'waisparse-Command'} = "none";
	}
	&get_ans("Enter the host on which to run the WAIS server", 
	   	"Broker-WAIS-Host");
	&get_ans("Enter the port on which to run the WAIS server", 
	   	"Broker-WAIS-Port");
	&get_ans("Enter the pathname to the waisindex command", 
	   	"waisindex-Command");
	&get_ans("Enter the pathname to the waissearch command", 
	   	"waissearch-Command");
	&get_ans("Enter the pathname to the waisserver command", 
	   	"waisserver-Command");
}
	
&get_ans("Enter the destination Broker directory",
   	"Destination-Directory");
if (! -d $vals{"Skeleton-Directory"}) {
	print "Couldn't find the Broker skeleton directory.\n";
	&get_ans("Enter the Broker skeleton directory",
   		"Skeleton-Directory");
}
}	# end of get_user_input

sub build_broker {
	print <<EOM;

  ----------------------------------------------------------------------
  CreateBroker will now perform the following tasks:
      1. Create the directory $vals{'Destination-Directory'}
         in which the new Broker will live.
      2. Build the Broker configuration files from the skeleton Broker 
         tree in $vals{'Skeleton-Directory'}
      3. Create the program $vals{'Destination-Directory'}/RunBroker
  ----------------------------------------------------------------------

EOM
	$vals{"YorN"} = "yes";
	&get_ans("Should I build this Broker now?", "YorN");
	return if ($vals{"YorN"} !~ /^y/io);

	$vals{'Broker-Indexer-Type'} = "Glimpse";
	$vals{'Broker-Indexer-Type'} = "WAIS" if ($INDEXER =~ /wais/io);
	#  Make the broker directory
	mkdir($vals{'Destination-Directory'}, 0755) || die 
		"Cannot make $vals{'Destination-Directory'}: $!\n";
	mkdir("$vals{'Destination-Directory'}/admin", 0755) || die 
		"Cannot make $vals{'Destination-Directory'}/admin: $!\n";

        $vals{'Description-URL'} = "http://$vals{'HTTP-Host'}/Harvest/brokers/$vals{'Broker-Short-Name'}/description.html";
        $vals{'Admin-Process'} = "$vals{'Destination-Directory'}/RunUpdate";
	@files = ("Makefile", "RunBroker", "Query.cgi", "query-$INDEXER.html",
		"RunUpdate", "admin/Collection.conf", "admin/broker.conf",
		"admin/admin.html");

	foreach $file (@files) {
		open(IN, "< $vals{'Skeleton-Directory'}/$file.in") || die
		"Cannot read $vals{'Skeleton-Directory'}/$file.in: $!\n";
		open(OUT, "> $vals{'Destination-Directory'}/$file") || die
		"Cannot create $vals{'Destination-Directory'}/$file: $!\n";
		print "Creating $vals{'Destination-Directory'}/$file\n";
		while (<IN>) {
	s/\@THIS_HARVEST_HOME\@/$ENV{'HARVEST_HOME'}/g;
	s/\@THIS_HTTP_HOST\@/$vals{'HTTP-Host'}/g;
	s/\@CONTACT_EMAIL\@/$vals{'Contact-Email'}/g;
	s/\@CONTACT_MESSAGE\@/$vals{'Contact-Message'}/g;
	s/\@THIS_BROKER_ADMIN_PROCESS\@/$vals{'Admin-Process'}/g;
	s/\@THIS_BROKER_COLLECT\@/$vals{'Broker-Collect'}/g;
	s/\@THIS_BROKER_DIR\@/$vals{'Destination-Directory'}/g;
	s/\@THIS_BROKER_NAME\@/$vals{'Broker-Name'}/g;
	s/\@THIS_BROKER_SHORT_NAME\@/$vals{'Broker-Short-Name'}/g;
	s/\@THIS_BROKER_PORT\@/$vals{'Broker-Port'}/g;
	s/\@THIS_BROKER_PASSWORD\@/$vals{'Broker-Password'}/g;
	s/\@THIS_BROKER_HOST\@/$vals{'Broker-Host'}/g;
	s/\@THIS_BROKER_GLIMPSE\@/$vals{'glimpse-Command'}/g;
	s/\@THIS_BROKER_GLIMPSEINDEX\@/$vals{'glimpseindex-Command'}/g;
	s/\@THIS_BROKER_GLIMPSESERVER\@/$vals{'glimpseserver-Command'}/g;
	s/\@THIS_BROKER_GLIMPSE_HOST\@/$vals{'Broker-Glimpse-Host'}/g;
	s/\@THIS_BROKER_INDEXER_TYPE\@/$vals{'Broker-Indexer-Type'}/g;
	s/\@THIS_BROKER_WAIS_FLAVOR\@/$vals{'WAIS-Flavor'}/g;
	s/\@THIS_BROKER_WAISINDEX\@/$vals{'waisindex-Command'}/g;
	s/\@THIS_BROKER_WAISPARSE\@/$vals{'waisparse-Command'}/g;
	s/\@THIS_BROKER_WAISSEARCH\@/$vals{'waissearch-Command'}/g;
	s/\@THIS_BROKER_WAISSERVER\@/$vals{'waisserver-Command'}/g;
	s/\@THIS_BROKER_WAISDELETE\@/$vals{'waisdelete-Command'}/g;
	s/\@THIS_BROKER_WAISLOOKUP\@/$vals{'waislookup-Command'}/g;
	s/\@THIS_BROKER_WAIS_HOST\@/$vals{'Broker-WAIS-Host'}/g;
	s/\@THIS_BROKER_WAIS_PORT\@/$vals{'Broker-WAIS-Port'}/g;
	s/\@THIS_BROKER_DESCRIPTION\@/$vals{'Broker-Description-Tag'}/g;
	s/\@THIS_BROKER_DESC_URL\@/$vals{'Description-URL'}/g;
	s/\@REPLICAS\@/$vals{'Broker-Replicas'}/g;
	s#\@THIS_BROKER_TOPDIR\@#$ENV{'HARVEST_HOME'}#g;
			print OUT;
		}
		close(IN);
		close(OUT);
	}
	chmod(0755, "$vals{'Destination-Directory'}/RunBroker");
	chmod(0755, "$vals{'Destination-Directory'}/RunUpdate");
	chmod(0755, "$vals{'Destination-Directory'}/Query.cgi");
	chmod(0644, "$vals{'Destination-Directory'}/query-$INDEXER.html");
	system("ln -s query-$INDEXER.html $vals{'Destination-Directory'}/query.html");
	system("ln -s query.html $vals{'Destination-Directory'}/index.html");

	&add_brokers_cf ($vals{'Broker-Short-Name'},
		$vals{'Broker-Host'},
		$vals{'Broker-Port'});

	&add_broker_to_master_desc();

	print "Finished.\n\n";
}

# Check if (name,host,port) are already in use in the Brokers.cf file
#
# If so, return the line from the file, else return an empty string.
#
sub check_brokers_cf {
	local ($name,$host,$port) = @_;
	local ($BROKERSCF) = $ENV{'HARVEST_HOME'} . '/brokers/Brokers.cf';
	return '' unless ( -s $BROKERSCF );
	open (BROKERSCF) || die "$BROKERSCF: $!\n";
	while (<BROKERSCF>) {
		chop;
		s/#.*//;
		next unless (/\s*(\S+)\s+(\S+)\s+(\d+)\s*$/);
		return $_ if ($name eq $1);
		return $_ if ($host eq $2 && $port == $3);
	}
	close (BROKERSCF);
	return '';
}

sub add_brokers_cf {
	local ($name,$host,$port) = @_;
	local ($BROKERSCF) = $ENV{'HARVEST_HOME'} . '/brokers/Brokers.cf';
	open (BROKERSCF, ">>$BROKERSCF") || die "$BROKERSCF: $!\n";
	chmod (0644, $BROKERSCF)
		unless ( -s $BROKERSCF );
	printf BROKERSCF ("%-31s %-31s %s\n", '#NAME','HOST','PORT')
		unless ( -s $BROKERSCF );
	printf BROKERSCF ("%-31s %-31s %d\n", $name,$host,$port);
	close BROKERSCF;
}


sub add_collection_point {
	local($file) = @_;

	$vals{'Collection-Host'} = $this_host_full;
	$vals{'Collection-Port'} = 8500;
	$vals{'Collection-Type'} = 3;
	$vals{'Collection-Query'} = "";

	&get_ans("Enter the host from which to collect",
		   "Collection-Host");
	&get_ans("Enter the port from which to collect",
		   "Collection-Port");
	print <<EOM;
The Broker supports various types of collections:
    0 - From Gatherer: Full collection each time,    without data compression.
    1 - From Gatherer: Incremental collections,      without data compression.
    2 - From Gatherer: Full collection each time,    with    data compression.
    3 - From Gatherer: Incremental collections,      with    data compression.
    4 - From Broker:   Full collection each time,    without data compression.
    5 - From Broker:   Incremental collections,      without data compression.
    6 - From Broker:   Collection based on a query,  without data compression.
    7 - From Broker:   Incremental based on a query, without data compression.
EOM
	&get_ans("Enter the collection type",
		   "Collection-Type");
	if ($vals{"Collection-Type"} == "6") {
		&get_ans("Enter the query filter", "Collection-Query");
	}
	if ($vals{"Collection-Type"} == "7") {
		&get_ans("Enter the query filter", "Collection-Query");
	}

	print <<EOM;

  ----------------------------------------------------------------------
EOM
	foreach $key (	"Collection-Host", 
			"Collection-Type",
			"Collection-Port", 
			"Collection-Query") {
		printf "%21s: ", $key;
		print $vals{$key}, "\n";
	}
	print <<EOM;
  ----------------------------------------------------------------------
EOM
	$vals{"YorN"} = "yes";
	&get_ans("Is this information correct?", "YorN");
	&add_collection_point($file), return if ($vals{"YorN"} =~ /^n/io);

	open(OUT, ">> $file") || die "Cannot append to $file: $!\n";
	print OUT $vals{'Collection-Host'}, " ";
	print OUT $vals{'Collection-Port'}, " ";
	print OUT $vals{'Collection-Type'}, " ";
	print OUT "--";
	print OUT $vals{'Collection-Query'}, "\n";
	close(OUT);
	print "Ok, the collection point was successfully added.\n\n";
}

#
#  This is an ugly hack so that it works with Perl 4.036 on Solaris 2.3.
#  The backticks (`) don't work on Solaris like they should. -Darren.
#
sub grab_cmd_output {
	local($the_cmd) = @_;
	undef $the_var;
	unlink("/tmp/cmdoutput.$$");
	system("$the_cmd > /tmp/cmdoutput.$$");
	open(CMDOUT, "< /tmp/cmdoutput.$$") || return "none";
	$the_var = <CMDOUT>;
	close(CMDOUT);
	unlink("/tmp/cmdoutput.$$");
	return $the_var;
}

#
# fake the which command
#
sub fake_which {
	local($prog) = @_;
	local($x) = '';
	local($foundit) = '';
	local($foo) = $ENV{'PATH'};
	$foo =~ s/^:/.:/;
	$foo =~ s/:$/:./;
	$foo =~ s/::/:.:/g;
    	foreach $x (split(/:/, $foo)) {
		if (-x "$x/$prog") {
            		$foundit = "$x/$prog";
			last;
		}
    	}
	return $foundit;
}

sub add_broker_to_master_desc {
	$desc = "$ENV{'HARVEST_HOME'}/brokers/AdminTools/descriptions/descriptions";
	open(DESC, ">> $desc") || die "Cannot append: $desc: $!\n";
	print DESC "BROKER";
	print DESC "\t";
	print DESC "$vals{'Destination-Directory'}/description.html";
	print DESC "\t";
	print DESC $vals{'Destination-Directory'};
	print DESC "\n";
	close(DESC);
}
