#!/usr/bin/perl

# $Id: multicmd,v 1.1 2003/10/27 22:55:28 tgkolda Exp $
# $Source: /space/CVS-Acro/acro/packages/appspack/appspack/maintenance/multicmd,v $

# ASYNCHRONOUS PARALLEL PATTERN SEARCH (APPS)
# COPYRIGHT (2000) Sandia Corporation.
# Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
# license for use of this work by or on behalf of the U.S. Government.
# LICENSE & WARRANTY INFORMATION in README.txt and LICENSE.txt.
# CONTACT Tamara G. Kolda (tgkolda@sandia.gov).

$hostfile = "hostfile";
$rsh = "rsh";
$rcp = "rcp";

@options = ();
@list = ();
while (@ARGV) {
    $_ = shift @ARGV;
    if (/^-h/) {
	print "\n";
	print "Usage: multicmd [OPTIONS] [COMMAND]\n";
	print "   or: multicmd -c [OPTIONS] SOURCE DEST\n";
	print "   or: multicmd -c [OPTIONS] SOURCE... DIRECTORY\n";
	print "\n";
	print "Execute COMMAND on all hosts, \n";
	print "or remote copy (local) SOURCE to DEST on all hosts, \n";
	print "or remote copy (local) SOURCE(s) to DIRECTORY on all hosts.\n";
	print "The hosts are specified in the PVM-like hostfile.\n";
	print "\n";
	print "Options: -h              Generate this help message.\n";
	print "         -f hostfile     Specify hostfile.\n";
        print "         -rsh command    Specify alternate rsh.\n";
        print "         -rcp command    Specify alternate rcp.\n";
	print "         -i              Print header for each machine.\n";
	print "         -a              Include all machines, even reserved (&) ones.\n";
	print "         -d              Debug mode.\n";
	die "\n";
    }
    elsif (/^-f/) {
	$hostfile = shift @ARGV;
	push(@options, $_);
	push(@options, $hostfile);
    }
    elsif (/^-rsh/) {
	$rsh = shift @ARGV;
	push(@options, $_);
	push(@options, $rsh);
    }	
    elsif (/^-rcp/) {
	$rcp = shift @ARGV;
	push(@options, $_);
	push(@options, $rcp);
    }	
    elsif (/^-/) {
	push(@options, $_);
    }
    else {
	push(@list, $_);
    }
}

$options = join(' ', @options);
print "Options: $options\n";

if ($options =~ /-c/) {
    $last = $#list - 1;
    @files = @list[0 .. $last];
    $files = join(' ', @files);
    $dest = $list[$#list];
    $list = $files;
    print "Files: $list\n";
    print "Destination: $dest\n";
}
else {
    $list = join(' ', @list);
    print "Command: $list\n";
}

open(HOSTFILE, $hostfile)
    || die "Can't open $hostfile: $!\n";

@hosts = ();
while (<HOSTFILE>) {
    @terms = split(/\s+/);
    if ($terms[0] =~ /^\w/) {	# first character is alphanumeric
	push(@hosts, $terms[0]);
    }
    if ($options =~ /-a/) {	# use inactive hosts too
	if ($terms[0] =~ /^&/) { # first character is '&'
	    $terms[0] =~ s/^&//; # remove '&'
	    push(@hosts, $terms[0]);
	}
    }
}

if ($list =~ /\S/) {		# non-empty list
    foreach $host (@hosts) {

	if ($options =~ /-c/) {
	    $command = "$rcp $list \@$host\:$dest\n";
	}
	else {
	    $command = "$rsh $host \"$list\"";
	}

	if ($options =~ /-i/) {	
	    print "*** Results on host $host *** \n";
	}

	if ($options =~ /-d/) {
	    print "Debug mode: $command\n";
	}
	else {
	    @info = `$command`;
	    if ($info[0] =~ /\S/) {
		if ($options =~ /-i/) {	
		    print @info;
		}
		else {
		    foreach (@info) {
			print "$host: $_";
		    }
		}
	    }
	}
    }
}
else {				# just list hosts
    foreach $host (@hosts) {
	print "$host\n";
    }    
}

