#! /bin/sh
# 'teston' is used for testing software build properly on remote
# machines. 
# Copyright (C) Dr. David Kirkby, drkirkby@ntlworld.com

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any
# later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

# In other words, you are welcome to use, share and improve this program.
# You are forbidden to forbid anyone else to use, share and improve
# #what you give them.   Help stamp out software-hoarding!  */

# The following script allows a distribution of any program which ends
# .tar.gz to be configured/built on a remote platform. By doing this,
# possible to spot bugs that are not apparent on a local machine. The
# script uses ssh/scp to copy the commands and should not require the
# entry of passwords. A script is created on the local machine, which
# is copied by scp/scp2 to a remote machine and executed there. Trying
# to execute the individual staments in the script via ssh takes too
# long, as the authentication needs to be repeated each time. 
########################################################################
########################################################################
# The following parameters should be set, to save specifying them on the
# command line each time you run. However ALL can be set on the command
# line, but it make sense to set the defaults how you will most often use
########################################################################
########################################################################

# This shell might look a bit alful, but is writen in a portable way.
: ${USERNAME='davek'}            # The user name on the remote system
: ${COMPILER='gcc'}              # can be set to cc or whatever
: ${MAKE='make'}                   # you might user 'gmake as default 
COMPILER=_FLAGS=${COMPILER_FLAGS="-Wall -O2"}  # can be set on command line
LINKER_FLAGS=${LINKER_FLAGS="-L/usr/local/lib"}  
MAKE_OPTIONS=${MAKE_OPTIONS=""}       # can be changed on the commmand line
SCP=${SCP="scp"}                      # can be changed on commmand line.
SSH=${SSH="ssh"}                      # could be changed to rsh 
EXTENSION=${EXTENSION=".tar.gz"}       #                         
CONFIGURE_OUTPUT=${CONFIGURE_OUTPUT=''}  # Change to /dev/null if you want
MAKE_OUTPUT=${MAKE_OUTPUT=''}            # Chnage to /null if you want. 

########################################################################
########################################################################
# NOTHING BELOW HERE SHOULD NEED ALTERING !! Don't touch
# NOTHING BELOW HERE SHOULD NEED ALTERING !! Don't touch
########################################################################
########################################################################

#: ${DELETE_FILES_AFTER_USE='no'}  # Don't change
TMP_NAME=${TMP_NAME=""}

EX1a="eg #1 teston dove atlc-5.0.0"
EX1b="copies atlc-5.0.0.tar.gz to dove and builds it on dove\n"

EX2a="eg #2 teston -b -c '--with-x --without-y' -m check woodpecker atlc-4.2.12"
EX2b="Builds and checks atlc-4.2.2.tar.bz2 on woodpecker, configured with x, but not y\n"

EX3a="eg #3 teston -m '-j2' -z bluetit atlc-4.0.0"
EX3b="copies atlc-4.0.0.zip to bluetit and does a parallel build\n"

EX4a="eg #4 teston -c --enable-hardware-info -M gmake  crow atlc-4.0.0"
EX4b="copies atlc-4.0.0.tar.gz to crow, configures with --enable-hardware-info and uses gmake to build\n"

EX5a="eg #5 teston -u root duke@medphys.ucl.ac.uk gcc-3.2.2"
EX5b="builds+tests gcc-3.2.2.tar.gz on duke@medphys.ucl.ac.uk using username root"

TMP_DIR=  # Don't be fooled. Don't touch it. It is not what you think!

while getopts c:m:M:u:tbRrNnTzZ supplied_options
do 
  case $supplied_options in
  u)
  USERNAME=$OPTARG;;
  R)
  SCP="rsh cp"
  SSH=rsh;;
  b)
  EXTENSION=".tar.bz2" ;;
  t)
  EXTENSION=".tgz" ;;
  z)
  EXTENSION=".zip" ;;
  Z)
  EXTENSION='.ZIP'  ;;

  c)
  CONFIG_OPTIONS=$OPTARG;;

  m)
  MAKE_OPTIONS=$OPTARG;;

  M)
  MAKE=$OPTARG;;

  N)
  CONFIGURE_OUTPUT=\>/dev/null;;

  N)
  MAKE_OUTPUT=\>/dev/null;;
  T)
#  TIME=`date | awk '{print $4}'`
#  TMP_DIR=$TIME.$$/
#  TMP_NAME=$TIME.$$.;;
 TMP_DIR=$$/
 TMP_NAME=$$.;;
  r)
  DELETE_FILES_AFTER_USE="yes" ;;
  \?)
  echo "Usage: teston [options] host package\n"
  echo  "Options are:"
  echo  "Options are:"
  echo  "            -u username             # username on host (default = $USERNAME)"
  echo  "            -R                      # rsh and 'rsh cp' rather than $SSH and $SCP"
  echo  "            -b                      # assume .tar.bz2 rather than $EXTENSION"
  echo  "            -t                      # assume .tgz extention rather than $EXTENSION"
  echo  "            -z                      # assume .zip extention rather than $EXTENSION"
  echo  "            -Z                      # assume .ZIP extention rather than $EXTENSION"
  echo  "            -c option_to_configure  # e.g --with-foo"
  echo  "            -M name_of_make         # e.g. gmake (default = $MAKE)"
  echo  "            -m option_to_make       # e.g. install (default $MAKE_OPTIONS)"
  echo  "            -B                      # run make in background. "
  echo  "            -N                      # Redirect output of make to /dev/null"
  echo  "            -T                      # Use a unique tmp directory on remote host"
  echo  "            -r                      # Removes files afterwards"
  echo  "            -n                      # Redirect output of configure to /dev/null"
  echo $EX1a  
  echo $EX1b 
  echo $EX2a  
  echo $EX2b 
  echo $EX3a 
  echo $EX3b  
  echo $EX4a  
  echo $EX4b 
  echo $EX5a  
  echo $EX5b 
  esac
  done
shift `expr $OPTIND - 1`

if [ $# -ne 2 ] ; then
  echo "Usage: teston [options] host package\n"
  echo  "Options are:"
  echo  "            -u username             # username on host (default = $USERNAME)"
  echo  "            -R                      # rsh and 'rsh cp' rather than $SSH and $SCP"
  echo  "            -b                      # assume .tar.bz2 rather than $EXTENSION"
  echo  "            -t                      # assume .tgz extention rather than $EXTENSION"
  echo  "            -z                      # assume .zip extention rather than $EXTENSION"
  echo  "            -Z                      # assume .ZIP extention rather than $EXTENSION"
  echo  "            -c option_to_configure  # e.g --with-foo"
  echo  "            -M name_of_make         # e.g. gmake (default = $MAKE)"
  echo  "            -m option_to_make       # e.g. install (default $MAKE_OPTIONS)"
  echo  "            -B                      # run make in background. "
  echo  "            -N                      # Redirect output of make to /dev/null"
  echo  "            -T                      # Use a unique tmp directory on remote host"
  echo  "            -r                      # Removes files afterwards"
  echo  "            -n                      # Redirect output of configure to /dev/null"
  echo $EX1a  
  echo $EX1b 
  echo $EX2a  
  echo $EX2b 
  echo $EX3a 
  echo $EX3b  
  echo $EX4a  
  echo $EX4b 
  echo $EX5a  
  echo $EX5b 
  exit 4
fi   

REMOTE_HOST=`echo $* | awk '{print $1}'`
VER=`echo $* | awk '{print $2}'`

# Check the file needed to be sent does acutally exist. 
if test ! -f $VER$EXTENSION ; then
  echo $VER$EXTENSION can not be opened for reading
  exit 3
fi

DATE=`date`
echo $TIME
LOCAL_HOST=`hostname` > /dev/null

# Find the home directory of the user on the remote host.
REMOTE_HOME=`$SSH $USERNAME@$REMOTE_HOST pwd`

# Create a file 'remote_test.$REMOTE_HOST' on the local machine, which we want
# executed on the remote host, not on the local machine. 
echo "#! /bin/sh" | tee > remote-test.$TMP_NAME$REMOTE_HOST.out > remote-test.$TMP_NAME$REMOTE_HOST
echo "# Script created on $LOCAL_HOST at $DATE using 'teston' " >> remote-test.$TMP_NAME$REMOTE_HOST
echo "# to run on the remote host $REMOTE_HOST " >> remote-test.$TMP_NAME$REMOTE_HOST
echo PATH=\$PATH:/usr/local/bin >> remote-test.$TMP_NAME$REMOTE_HOST
echo "Output from the script created on $LOCAL_HOST at $DATE using 'teston' " >> remote-test.$TMP_NAME$REMOTE_HOST.out
echo cd $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR >> remote-test.$TMP_NAME$REMOTE_HOST

# the exact method of decompressing the file depends on the file extension. 
if [ "x$EXTENSION" = "x.tar.gz" ] ; then
  echo gzip -d $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar.gz >> remote-test.$TMP_NAME$REMOTE_HOST
  echo tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
  echo rm $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
elif [ "x$EXTENSION" = "x.tgz" ] ; then
  echo  gzip -d $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tgz >> remote-test.$TMP_NAME$REMOTE_HOST
  echo  tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
  echo rm $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
elif [ "x$EXTENSION" = "x.tar.bz2" ] ; then
  echo  $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar.bz2 >> remote-test.$TMP_NAME$REMOTE_HOST
  echo  tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
  echo rm $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
elif [ "x$EXTENSION" = "x.tar.Z" ] ; then
  echo gzip -d $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar.Z  >> remote-test.$TMP_NAME$REMOTE_HOST
  echo  tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
  echo rm $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
elif [ "x$EXTENSION" = "x.zip" ]  ; then
  echo unzip $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.zip >> remote-test.$TMP_NAME$REMOTE_HOST
  echo tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
elif [ "x$EXTENSION" = "x.ZIP" ]  ; then
  echo unzip $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.ZIP >> remote-test.$TMP_NAME$REMOTE_HOST
  echo tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
elif [ "x$EXTENSION" = "x.tar" ] ; then
  echo tar xf $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER.tar >> remote-test.$TMP_NAME$REMOTE_HOST
else
  echo "unknown extension $EXTENSION"
  exit 1
fi

REMOTE_HOST=`echo $* | awk '{print $1}'`
VER=`echo $* | awk '{print $2}'`
if test ! -f $VER$EXTENSION ; then
  echo $VER$EXTENSION can not be opened for reading
  exit 3
fi

DATE=`date`
# The rest of the script to go to the remote machine. 
echo mkdir $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER-build >> remote-test.$TMP_NAME$REMOTE_HOST
echo cd $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER-build >> remote-test.$TMP_NAME$REMOTE_HOST
echo $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER/configure $CONFIG_OPTIONS $CONFIGURE_OUTPUT >> remote-test.$TMP_NAME$REMOTE_HOST
echo $MAKE $MAKE_OPTIONS $MAKE_OUTPUT >> remote-test.$TMP_NAME$REMOTE_HOST
if [ "x$DELETE_FILES_AFTER_USE" = "xyes" ] ; then 
  rm -r $REMOTE_HOME/$REMOTE_HOST/$TMP_DIR$VER >> remote-test.$TMP_NAME$REMOTE_HOST
fi 

# The script is now created on the local machine, so make it executable
chmod 755 remote-test.$TMP_NAME$REMOTE_HOST

# Remove any direcotory on the remove machine that might have files
# in so messing up our build. If we want to build more than once on the
# remote machine, the -T option should be given to create a 
# directory on the remote machine that is unique. The method used 
# here does not guarantee uniqness, but it should be okay. 

$SSH $USERNAME@$REMOTE_HOST rm -fR $REMOTE_HOST/$TMP_DIR 2> /dev/null

# Make direcotries on the remote machine. #

$SSH $USERNAME@$REMOTE_HOST mkdir $REMOTE_HOST 2> /dev/null
$SSH $USERNAME@$REMOTE_HOST mkdir $REMOTE_HOST/$TMP_DIR 2> /dev/null

# Copy via scp/scp2 the script file in addition to the package
# (somename.tar.gz or somename.tgz etc) to the remote machine.

$SCP -p $VER$EXTENSION remote-test.$TMP_NAME$REMOTE_HOST $USERNAME@$REMOTE_HOST:$REMOTE_HOST/$TMP_DIR
 
# Put a copy of the remote script locally for debugging. 
cat remote-test.$TMP_NAME$REMOTE_HOST >> remote-test.$TMP_NAME$REMOTE_HOST.out

# Execute the script on the distant machine.
$SSH -f $USERNAME@$REMOTE_HOST $REMOTE_HOST/$TMP_DIR/remote-test.$TMP_NAME$REMOTE_HOST | tee -a remote-test.$TMP_NAME$REMOTE_HOST.out &

# Clean up the local file after ourselves. 
if [ DELETE_FILES_AFTER_USE = "yes" ] ; then 
  rm remote-test.$TMP_NAME$REMOTE_HOST
fi
