#! /bin/sh -f
#
# $Id$

if [ X$program = X ]; then
    echo gfarm-ptool cannot be executed directly
    exit 1
fi

PRUN_DEFAULT_RSH="ssh"
PRUN_DEFAULT_RCP="scp -pr"
PRUN_DEFAULT_HOSTFILE=$HOME/.nodelist
hostname -I > /dev/null 2>&1 && HS=`hostname -I`
PRUN_DEFAULT_HOSTNAME="`hostname` $HS"
PRUN_DEFAULT_MAX_JOBS=16

[ "X$PRUN_RCP" = X ]      && PRUN_RCP=$PRUN_DEFAULT_RCP
[ "X$PRUN_RSH" = X ]      && PRUN_RSH=$PRUN_DEFAULT_RSH
[ "X$PRUN_HOSTFILE" = X ] && PRUN_HOSTFILE=$PRUN_DEFAULT_HOSTFILE
[ "X$PRUN_HOSTNAME" = X ] && PRUN_HOSTNAME=$PRUN_DEFAULT_HOSTNAME
[ "X$PRUN_MAX_JOBS" = X ] && PRUN_MAX_JOBS=$PRUN_DEFAULT_MAX_JOBS
[ "X$PRUN_PARALLEL" = X ] && PRUN_PARALLEL=no
[ "X$PRUN_ALL_INCLUDE_MYSELF" = X ] && PRUN_ALL_INCLUDE_MYSELF=no
[ "X$PRUN_VERBOSE" = X ]  && PRUN_VERBOSE=no
PRUN_STDIN=

while [ $# -gt 0 ]; do
	case $1 in
	    -h) shift; PRUN_HOSTFILE=$1 ;;
	    -rsh) shift; PRUN_RSH=$1 ;;
	    -rcp) shift; PRUN_RCP=$1 ;;
	    -stdin) shift; PRUN_STDIN="$PRUN_STDIN $1" ;;
	    -p) PRUN_PARALLEL=yes ;;
	    -a) PRUN_ALL_INCLUDE_MYSELF=yes ;;
	    -v) PRUN_VERBOSE=yes ;;
	    -m) shift; PRUN_MAX_JOBS=$1 ;;
	    -n) ECHO=echo ;;
	    -*) echo "unknown option: $1"
		usage ;;
	    *) break ;;
	esac
	shift
done

if [ $# -lt 0$MIN_ARGS ]; then
	usage
fi

hostfile=$PRUN_HOSTFILE
if [ "X$hostfile" = X ]; then
	echo Hostfile should be specified.
	usage
fi
if [ X$hostfile = X- ]; then
    hostfile=/tmp/$program-host-$$
    cat > $hostfile
    REMOVE_HOSTFILE=1
fi
if [ ! -f $hostfile ]; then
	echo $hostfile: no such hostfile
	exit 1
fi

if [ "X$PRUN_STDIN" != X ]; then
    for f in $PRUN_STDIN; do
	if [ X$f = X- ]; then
	    if [ X$REMOVE_HOSTFILE != X -o X$REMOVE_STDIN_FILE != X ]; then
		echo \'-\' should not be specified more than once
		exit 1
	    fi
	    f=/tmp/$program-stdin-$$
	    cat > $f
	    REMOVE_STDIN_FILE=$f
	fi
	if [ ! -f $f ]; then
	    echo $f: no such stdin file
	    exit 1
	fi
	prun_stdin="$prun_stdin $f"
    done
fi
PRUN_STDIN=$prun_stdin

rcp_by_rsh() {
    host="$1"
    shift
    files=
    while [ $# -gt 1 ]; do
	files="$files $1"
	shift
    done
    dst=$1
    for f in $files; do
	b=`basename $f`
	case $PRUN_PARALLEL in
	    no) cat $f | $PRUN_RSH $host "cat > $dst/$b" ;;
	    yes) cat $f | $PRUN_RSH $host "cat > $dst/$b" & ;;
	esac
    done
}

case $program in
    gfarm-prun)
	CMD="$ECHO $PRUN_RSH"
	[ "X$PRUN_STDIN" = X ] && CMD="$CMD -n"
	ARG="$*" ;;
    gfarm-pcp)
	if [ X"$PRUN_RCP" = Xno ]; then
	    CMD="$ECHO rcp_by_rsh"
	    ARG="$*"
	else
	    rcpargs=
	    while [ $# -gt 1 ]; do
		rcpargs="$rcpargs $1"
		shift
	    done
	    CMD="$ECHO $PRUN_RCP $rcpargs"
	    HOSTSUF=:$1
	fi ;;
    *)
	echo unknown program: $program
	exit 1 ;;
esac

MESSAGE=true
if [ "X$PRUN_PARALLEL" != Xyes -a "X$PRUN_VERBOSE" = Xyes ]; then
    MESSAGE=echo
fi

p=0
for host in `sed -e 's/#.*//' -e '/^[ 	]*$/d' $hostfile | awk '{ print $1 }'`; do
    [ "X$PRUN_ALL_INCLUDE_MYSELF" != Xyes ] &&
	echo $PRUN_HOSTNAME | grep $host > /dev/null && continue
    $MESSAGE $host
    case $PRUN_PARALLEL$PRUN_STDIN in
	no) $CMD $host$HOSTSUF $ARG ;;
	no*) cat $PRUN_STDIN | $CMD $host$HOSTSUF $ARG ;;
	yes) $CMD $host$HOSTSUF $ARG & ;;
	yes*) cat $PRUN_STDIN | $CMD $host$HOSTSUF $ARG & ;;
    esac
    p=$((p + 1))
    if [ $p -ge $PRUN_MAX_JOBS ]; then
	p=0
	wait
    fi
done
wait

[ X$REMOVE_HOSTFILE != X ] && rm -f $hostfile
[ X$REMOVE_STDIN_FILE != X ] && rm -f $REMOVE_STDIN_FILE

exit 0
