#
# Copyright (c) 2010-2011 Novell Inc, John Shi
#           All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like.  Any license provided herein, whether implied or
# otherwise, applies only to this software file.  Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.


quit()
{
  local ret
  ret="$1"

  while [ $__OCFT__atexit_num -gt 0 ]; do
    atexit$__OCFT__atexit_num
    let __OCFT__atexit_num--
  done

  rm -rf $__OCFT__fakebin

  exit $ret
}

agent_install()
{
  local pkg

  if [ $# -eq 0 ]; then
    return 0
  fi

  for pkg in "$@"; do
    if [ -e /etc/SuSE-release ]; then
      if ! zypper -q install -y "$pkg" >/dev/null 2>&1; then
        echo
        echo "${__OCFT__showhost}ERROR: Install '$pkg' failed."
        quit 2
      fi
    elif [ -e /etc/debian_version ]; then
      if ! apt-get -y install "$pkg" >/dev/null 2>&1; then
        echo
        echo "${__OCFT__showhost}ERROR: Install '$pkg' failed."
        quit 2
      fi
    elif [ -e /etc/redhat-release ]; then
      if ! yum -y install "$pkg" >/dev/null 2>&1; then
        echo
        echo "${__OCFT__showhost}ERROR: Install '$pkg' failed."
        quit 2
      fi
    else
      echo "${__OCFT__showhost}ERROR: Cannot detect your OS type."
      quit 2
    fi
  done
}

set_ocf_env()
{
  export OCF_RA_VERSION_MAJOR=1
  export OCF_RA_VERSION_MINOR=0
  export OCF_RESOURCE_TYPE=$1
  export OCF_RESOURCE_INSTANCE=${OCF_RESOURCE_INSTANCE:-"ocft"}
}

agent_run()
{
  local agent cmd timeout pid i ret aroot
  agent="$1"
  cmd="$2"
  timeout="$3"

  set_ocf_env $agent

  export OCF_RESKEY_CRM_meta_timeout
  : ${OCF_RESKEY_CRM_meta_timeout:=$((timeout*1000))}

  aroot=${__OCFT__MYROOT:-$__OCFT__AGENT_ROOT}

  setsid $aroot/$agent $cmd >${HA_RSCTMP}/.ocft_runlog 2>&1 &
  pid=$!

  i=0
  while [ $i -lt $timeout ]; do
    if [ ! -e /proc/$pid ]; then
      break
    fi
    sleep 1
    let i++
  done

  if [ $i -ge $timeout ]; then
    kill -SIGTERM -$pid >/dev/null 2>&1
    sleep 3
    kill -SIGKILL -$pid >/dev/null 2>&1
    echo -n "${__OCFT__showhost}ERROR: The agent was hanging, killed it, "
    echo "maybe you damaged the agent or system's environment, see details below:"
    cat ${HA_RSCTMP}/.ocft_runlog
    echo
    quit 1
  fi

  wait $pid
}

check_success()
{
  local ret msg
  ret="$1"
  msg="$2"

  if [ $ret -ne 0 ]; then
    echo "${__OCFT__showhost}ERROR: '${msg}' failed, the return code is ${ret}."
    quit 1
  fi
}

__maxfd()
{
  (echo 0; ls -1 /proc/$$/fd) | sort -rn | head -1
}

__getfd()
{
  local host rw fd file
  host="$1"
  rw="$2"

  for fd in /proc/$$/fd/*; do
    file=$(basename "$(readlink $fd)")
    if [ "$file" = "${host}_$rw" ]; then
      basename $fd
      break
    fi
  done
}

backbash_start()
{
  local host fd rfd wfd
  host="$1"

  if [ ! -d "$__OCFT__CASES_DIR" ]; then
    echo "${__OCFT__showhost}ERROR: Could not found Directory: ${__OCFT__CASES_DIR}."
    quit 1
  fi

  if lsof $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then
    echo "${__OCFT__showhost}ERROR: Connection exist with $host."
    quit 1
  fi
  if [ ! -p "$__OCFT__CASES_DIR/${host}_r" ] || [ ! -p "$__OCFT__CASES_DIR/${host}_w" ]; then
    rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w
    if ! mkfifo $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w >/dev/null 2>&1; then
      echo "${__OCFT__showhost}ERROR: Could not create pipe file: $__OCFT__CASES_DIR/${host}_*."
      quit 1
    fi
  fi

  ssh root@$host '/bin/bash 2>&1
                  sed "s/00/001/g" ${HA_RSCTMP}/.backbash-log
                  echo 000
                  echo 1' >$__OCFT__CASES_DIR/${host}_r <$__OCFT__CASES_DIR/${host}_w &

  fd=$(__maxfd)
  rfd=$(expr $fd + 1)
  wfd=$(expr $fd + 2)
  eval "exec ${rfd}<$__OCFT__CASES_DIR/${host}_r ${wfd}>$__OCFT__CASES_DIR/${host}_w"
}

backbash()
{
  local host rfd wfd ret
  host="$1"

  rfd=$(__getfd $host r)
  wfd=$(__getfd $host w)

  if [ -z "$rfd" -o -z "$wfd" ]; then
    echo "${__OCFT__showhost}ERROR: Could not found connection with $host."
  fi

  cat >&$wfd <<EOF
{
true
EOF
  cat >&$wfd
  cat >&$wfd <<EOF

} >&${HA_RSCTMP}/.backbash-log
sed 's/00/001/g' ${HA_RSCTMP}/.backbash-log
echo 000
echo 0
EOF
  if [ $? -ne 0 ]; then
    echo "${__OCFT__showhost}ERROR: Broken connection with $host."
    quit 1
  fi

  awk -vlive=2 '{
    if (sub(/000$/, "")) {
      if ($0 != "") {
        gsub("001", "00");
        printf("%s", $0);
      }
      getline live;
      exit;
    }
    gsub("001", "00");
    print;
  } END {
    exit(live);
  }' <&$rfd
  case $? in
      1)
        quit 1
        ;;
      2)
        echo "${__OCFT__showhost}ERROR: Broken connection with $host."
        quit 1
        ;;
  esac
}

backbash_stop()
{
  local host rfd wfd
  host="$1"

  wfd=$(__getfd $host w)
  if [ -n "$wfd" ]; then
    cat >&$wfd <<<'quit 0'
  fi
  rm -f $__OCFT__CASES_DIR/${host}_r $__OCFT__CASES_DIR/${host}_w
}


export OCF_ROOT=/usr/lib/ocf
export OCF_LIB=/usr/lib/ocf/lib/heartbeat
__OCFT__AGENT_ROOT=/usr/lib/ocf/resource.d/heartbeat
__OCFT__CASES_DIR=/var/lib/resource-agents/ocft/cases
OCFT_DIR=/usr/share/resource-agents/ocft

. $OCFT_DIR/helpers.sh

__OCFT__atexit_num=0

if [ $EUID -ne 0 ]; then
  echo "${__OCFT__showhost}ERROR: '$0' needs to be run by root."
  quit 3
fi

__OCFT__fakebin=./fakebin

mkdir -p $__OCFT__fakebin >/dev/null 2>&1 &&
ln -sf /bin/true $__OCFT__fakebin/crm_master >/dev/null 2>&1 &&
ln -sf /bin/true $__OCFT__fakebin/crm_mon >/dev/null 2>&1
if [ $? -ne 0 ]; then
  echo "${__OCFT__showhost}ERROR: initialize 'fakebin' failed."
  quit 3
fi
export HA_SBIN_DIR=$__OCFT__fakebin

. $OCF_LIB/ocf-returncodes || {
  echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-returncodes not found."
  quit 3
}

. $OCF_LIB/ocf-directories || {
  echo "${__OCFT__showhost}ERROR: $OCF_LIB/ocf-directories not found."
  quit 3
}

while read __OCFT__line; do
  if [ -n "$__OCFT__line" ]; then
    __OCFT__retn=${__OCFT__line%%=*}
    __OCFT__reti=$(eval echo \$$__OCFT__retn)
    __OCFT__retval[__OCFT__reti]=$__OCFT__retn
  fi
done <<<"$(sed 's/#.*//' $OCF_LIB/ocf-returncodes)"


# vim:ts=2:sw=2:et:
