#!/bin/sh


TIMEOUT=-1 # default timeout is unlimited
KILLPID=-1
KILLED="no"
RSYSTEM2="" # define empty value 
IGNORESTDIN="no"
FALLBACK_PARAM=""

#########################################################################
# Definition of functions 

printUsage() {
  echo "sshr is commandline wrapper to execute command on remote system"
  echo "where remote system is associated Assistant or SOCO2 Platform"
  echo ""
  echo "USAGE: sshr"
  echo "sshr [-t timeout] [-h] [-x] [-c system] [-u user]| <command>"
  echo " -h          -print usage"
  echo " -t          -set the connection timeout in seconds"
  echo " -c <system> -define system to connect with"
  echo " -x          -ignore standart input"
  echo " -u <user>   -specify user to communicate with"
  echo 

  echo "Locking by sshr:"
  echo "sshr -c host_intl createLock -i <instance> -o <operation> -c <callback>"
  echo "                             -s <callback_argument> [-t <type>] [-a <ancestor_lockfile_target>]"
  echo "rc 0: Lock was created. Contents of lock is printed to STDOUT"
  echo "rc 1: Lock was not created."
  echo 
  echo "sshr -c host_intl deleteLock -i <instance> [-o <operation>] [-s <callback_argument> [-f]"
  echo 
  echo "sshr -c host_intl checkLock"
  echo "rc 0: Valid lock exists. Contents of lock is printed to STDOUT"
  echo "rc 1: Lock does not exist or it is invalid. Invalid lock is automatically deleted"
  echo 

  echo "Error code:" 
  echo " 200 -no command specified"
  echo " 202 -remote system is not accessible due to network problem"
  echo " 203 -remote system is not accessible due to problem with key pair"
  echo " 204 -command timeout"
  echo " 205 -internal error"
  echo " 206 -command is not available on remote system"
  echo " 209 -unable to detect remote system, use -c parameter"
  echo " 211 -unable to lock sshr"
  echo " 212 -unable to get IP of system (via nslookup)"
  echo " 213 -unable to get IP of system (from /etc/hosts)"
  echo " 214 -paramtable doesn't exist"
  echo " 215 -unable to read IP address from interface"
  echo " 216 -unable to find HA configuration file"
}

endOfProgram() {
  #set +x
  tracef "== End of execution (sshr) [$(/bin/date)] (err=$1) == "
  tracef ""
  tracef ""

  #Close fd9
  exec 9<&-
  exit $1

}

#################################################################
#
# MAIN function
#
#################################################################
# import common variable and functions
. /opt/rcon/bin/sshr-base

cutLog
tracef "== Start of execution (sshr) [$(/bin/date)] =="
PARAM="$@"
tracef "parameters and command=\"$PARAM\""

# evaluate options
while getopts "t:u:hc:x" OPTION; do
    case $OPTION in
        t) TIMEOUT=$OPTARG;FALLBACK_PARAM="$FALLBACK_PARAM -t $TIMEOUT";;
        h) printUsage;endOfProgram 0;;
	c) RSYSTEM2=$OPTARG;;
	u) RUSER2=$OPTARG;;
	x) IGNORESTDIN="yes";FALLBACK_PARAM="$FALLBACK_PARAM -x";;
    esac
done
shift $(($OPTIND - 1))

PARAM="$@"

if [ "$IGNORESTDIN" == "yes" ];then
  tracef "stdin is ignored"
  exec 9</dev/null
else
  #tracef "stdin is read"
  #Link file descriptor #9 with stdin.
  exec 9<&0
fi

#ls -l /proc/self/fd


#if not paramater is specified, print usage
if [ "$1" = "" ];then
  printUsage
  endOfProgram 200 
fi

#Step1: Detect current system type
SYSTEMTYPE=$(detectSystem)
tracef "current system=\"$SYSTEMTYPE\""

#Step2: Detect remote system type
RSYSTEM=$(getRSystem $SYSTEMTYPE "$RSYSTEM2")
RC=$?
if [ $RC -ne 0 ];then
  tracef "ERROR:unable to detect remote system, exit (res=$RC)"
  endOfProgram $RC
fi
tracef "param:remote system=\"$RSYSTEM\""


#Special behaviour when local and remote systems are same
if [ $SYSTEMTYPE = $RSYSTEM ]; then
  tracef "sshr is running on local system"
  tracef "execute locally: \"$RCON_DIR/sshr-check $PARAM\""

  #unset of SSH_ORIGINAL_COMMAND is needed to avoid wring execution
  unset SSH_ORIGINAL_COMMAND
  $RCON_DIR/sshr-check $PARAM
  RC=$?

  tracef "local execution finished (ret=$RC)"
  endOfProgram $RC
fi


#Step3: Detect remote system IP
SERVERIP=$(/opt/rcon/bin/getremintIP -c $RSYSTEM)
RC=$?
if [ $RC -ne 0 ];then
  tracef "ERROR:unable to detect IP of remote system, exit (res=$RC)"
  endOfProgram $RC
fi
tracef "param:remote IP=\"$SERVERIP\""

#Step5: Get name of user which will be used
if [ -n "$RUSER2" ];then
  RUSER="$RUSER2"
else
  RUSER=$(getValue $RSYSTEM user)
fi
tracef "param:remote user=\"$RUSER\""


#set -x

#####################################################################
#Step6: Test of remote connection, execute simple command (pwd)
TESTRES=$(connectivityTest $SERVERIP $RUSER $RSYSTEM)
RES=$?
if [ $RES -ne 0 ];then
   tracef "ERROR:test of connectivity failed, exit (res=$RES)"
   endOfProgram $RES
fi

if false ; then
#old SLES11 code
#Step7: Execution of remote command
tracef "execute command \"$PARAM\" remotely [$(/bin/date)]" 
( ssh -q -l $RUSER $SERVERIP -i $PRIVATE_KEYP -F $SSH_CONFIGF $PARAM <&9 ) &
SSHPID=$!
tracef "command started with pid: $SSHPID"

if [ $TIMEOUT -gt 0 ];then
  tracef "timeout set to \"$TIMEOUT\" seconds"
  ( sleep $TIMEOUT; kill $SSHPID >/dev/null 2>/dev/null ) &
  KILLPID=$!
fi

# wait to finish ssh execution
wait $SSHPID >/dev/null 2>&1
RES=$?

# kill timeout mechanism
if [ $TIMEOUT -gt 0 ];then
  usleep 100
  kill $KILLPID 1>/dev/null 2>&1
  KILLRES=$?
  if [ ! $KILLRES -eq 0 ]; then
    tracef "ERROR:command timeouted"
    RES=204
  fi
fi
else
#SLES15 - new code based on fsshr
if [ $TIMEOUT -gt 1200 ] ; then
    tracef "ERROR timeout set too high to \"$TIMEOUT\" seconds"
    endOfProgram 1
fi

#prepare timeout as command line param for fsshr
if [ $TIMEOUT -gt 0 ] ; then
    TIMEOUT="-t $TIMEOUT"
else
    TIMEOUT=""
fi

#prepare IGNORESTDIN as param
if [ "x$IGNORESTDIN" = "xyes" ] ; then
    IGNORESTDIN="-x"
else
    IGNORESTDIN=""
fi

#prepare RSYSTEM as param for fsshr
if [ "x$RSYSTEM" = "xhost_intl" ] ; then
    #by default fsshr goes to PLT, but in case of CSTA then make it explicitly
    RSYSTEM=""
    [ "x$SYSTEMTYPE" = "xcap_intl" ] && RSYSTEM="-c host"
else
    if [ "x$RSYSTEM" = "xcap_intl" ] ; then
        RSYSTEM="-c cap"
    else
        if [ "x$RSYSTEM" = "xassistant_intl" ] ; then
            RSYSTEM="-c assistant"
        else
            tracef "ERROR unknown remote target system \"$RSYSTEM\""
            endOfProgram 1
        fi
    fi
fi

#finally make the fsshr call
/opt/rcon/bin/fsshr $RSYSTEM $TIMEOUT $IGNORESTDIN /opt/rcon/bin/sshr-check $PARAM
RES=$?
fi

case "$RES" in
  127 )
    # command is not available on remote system
    tracef "ERROR:command is not available on remote system"
    RES=206 
    ;;
  204 )
    # command timeouted 
    tracef "ERROR:command timeouted after \"$TIMEOUT\" seconds."
    ;;

  255 )
    #Error sshr during connection
    #Verify if remote system is reachable, is yes, verify if local key pair is OK,
        #if yes, inform remote system to download public key
        #if no, generate new key pair
    tracef "ERROR:error during ssh connection ($RES)"
    ping -c 1 $SERVERIP >/dev/null 2>&1
    PINGRES=$?
    if [ ! $PINGRES -eq 0 ]; then
      #Ping was not successful
      tracef "ERROR:remote system not accessible (ping)"
      endOfProgram 202
    fi

    if [ "$RUSER" != "root" ]; then 
      tracef "sles15skip WARNING:fallback:unable to connect with user \"$RUSER\", use \"root\" account"
      #/bin/sshr -c $RSYSTEM -u root $FALLBACK_PARAM $PARAM
      #RES=$?
      #tracef "end of fallback scenario (ret=$RES)"
    fi

    ;;
  * )
    # command was succesfully executed, response value is in $RES
    tracef "command result=$RES"
    ;;
esac

endOfProgram $RES



