# vim: set filetype=sh :
#   copyright: Bernd Schumacher <bernd.schumacher@hpe.com> (2007-2020)
#     license: GNU General Public License, version 3
# mylib - customized usage of shellia
# can be called as
#   #/bin/sh
#   LOG_DIR=/<path_to_dir>/
#   . /usr/share/doc/shellia/examples/mylib

# we want an easy to remember function to be uses in case of an error
# we also use exit code 1
# each error Message should start equal
err()
{
  ia_exiterr 1 "ERROR: $*"
}

# we want an easy to remember function to give information to the user on stderr
# this info should always be logged
# this information should not be given to stderr if our script has to be silent
info()
{
  [ "$ia_use_silent" ] && ia_log "$@" || ia_logerr "$@"
}

log()
{
  ia_log "$@"
}

# my_ssh - use ssh to call <script> on remote <host>
#
# Usage:
#   my_ssh can call a <script> that is (A,B) or is not (C,D) controlled by
#   shellia. my_ssh can be used as a macro (A,C) that adds ia_add and
#   ia_nocheck if needed, or it can be called by ia_add manually (B,D).
#
#   (A) my_ssh [-x <more-ssh-opts>] <host> "<script> <-i> [[--] <script-args>]"
#   (B) ia_nocheck && ia_add "my_ssh [-x <more-ssh-opts>] --ia <host> \"<script> [<-i>] [[--] <script-args>]\""
#   (C) my_ssh [-x <more-ssh-opts>] <host> "<script> [<script-args>]"
#   (D) ia_add "my_ssh [-x <more-ssh-opts>] --no-ia <host> \"<script> [<script-args>]\""
#
#   <more-ssh-opts>
#             my_ssh already adds some ssh options. Additional options
#             <more-ssh-opts> can be added to ssh.
#   <host>    remote server where the <script> is called
#   <script>  the path of the script to be called on the remote <host>
#   <script-args>
#             optional <script> specific arguments
#   --ia      my_ssh assumes that the remote command uses shellia
#   --no-ia   my_ssh assumes that the remote command does not use shellia
#   <-i>      this option allowes the user to toggle interactive and
#             non-interactive mode
#
# Example:
#   my-ia-script is a script that is controlled by shellia and my-no-ia-script
#   is a script that is not controlled by shellia. Both can print their version
#   with option --version. Both scripts are on host myhost.
#   (A) my_ssh myhost "my-ia-script <-i> -- --version"
#   (B) ia_nocheck && ia_add "my_ssh --ia myhost \"my-ia-script <-i> -- --version\""
#   (C) my_ssh myhost "my-no-ia-script --version"
#   (D) ia_add "my_ssh --no-ia myhost \"my-no-ia-script --version\""
#
my_ssh()
{
  #global ssh
  #global ssh_opts
  local ia # set this if command executed on target server uses shellia
  local ssh_host
  local ret
  local tf
  local script
  #ia_dev_dbg "my_ssh: #=<$#> 1=<$1> 2=<$2> 3=<$3> 4=<$4> 5=<$5> 6=<$6> 7=<$7>"

  ia=""
  ssh_more_opts=""
  while :; do
    if [ "$1" = "--ia" -o "$1" = "--no-ia" ]; then
      ia="$1"
      shift
    elif [ "$1" = "-x" ]; then
      [ "$ssh_more_opts" ] && ssh_more_opts="$ssh_more_opts $2" || ssh_more_opts="$2"
      shift 2
    else
      break
    fi
  done

  ssh_host="$1"
  shift

  script="$(/bin/echo "$*" | ia_easy_backslash)"

  if [ ! "$ia" ]; then # without -ia and --no-ia => (A) or (C)
    if [ "$(ia_is_nocheck)" ]; then # (A)
      # ia_nocheck was called before this script => script is controlled by shellia
      ia="--ia"
    elif [ "$(echo "$*" | grep "<-i>")" ]; then # (A)
      # script contains shellia option, => script is controlled by shellia, but forgot to call ia_nocheck
      ia_nocheck
      ia="--ia"
    else # (C)
      # script is not controlled by shellia
      ia="--no-ia"
    fi
    [ ! "$ssh_more_opts" ] || ssh_more_opts=" -x \"$ssh_more_opts\""
    ia_add "my_ssh $ia$ssh_more_opts $ssh_host \"$script\""
    return $?
  fi

  [ "$ssh" ] || ssh="ssh"
  [ "$ssh_opts" ] || ssh_opts="-q -o \"ConnectionAttempts 1\" -o \
    \"FallBackToRsh no\" -o \"GlobalKnownHostsFile /dev/null\" -o \
    \"KeepAlive yes\" -o \"StrictHostKeyChecking no\" -o \
    \"UserKnownHostsFile /dev/null\" -o \"NoHostAuthenticationForLocalhost yes\" -o \
    \"NumberOfPasswordPrompts 1\""

  if [ "$ia" = "--ia"  ]; then # with --ia => (B)
    tf="$(eval "ssh -n $ssh_opts \"$ssh_host\" mktemp")" # option -n is needed to allow to pipe | my_ssh
    log "|ssh-$ssh_host: temp logfile $tf"
    ( eval "$ssh $ssh_more_opts $ssh_opts \"$ssh_host\" \"export ia_red=\\\"$ia_red\\\"; \
      export ia_green=\\\"$ia_green\\\"; export ia_orange=\\\"$ia_orange\\\"; \
      export ia_no_color=\\\"$ia_no_color\\\"; export ia_use_silent=\\\"$ia_use_silent\\\"; \
      export ia_logfile=\\\"$tf\\\"; export ia_prefix_head=\\\"$ia_head/ssh-$ssh_host\\\"; \
      export dbg_run_level=\\\"$dbg_run_level\\\"; export dbg_run_names=\\\"$dbg_run_names\\\"; \
      $script\"" 2>&$ia_direct_stderr_fd )
    ret=$?
    eval "ssh $ssh_opts \"$ssh_host\" \"cat $tf; rm -f $tf\"" >> $ia_logfile
  else # with --no-ia => (D)
    log "|ssh-$ssh_host:"
    ( eval "$ssh $ssh_more_opts $ssh_opts \"$ssh_host\" \"export ia_use_silent=1; $script\"" )
    ret=$?
  fi

  if [ $ret -eq 255 ]; then
    info "ssh to \"$ssh_host\" does not work (ssh \"$ssh_host\" $*)"
  fi

  return $ret
}

# my_file - call <script> on same host
#
# Usage:
#   my_file can call a <script> that is (A,B) or is not (C,D) controlled by
#   shellia. my_file can be used as a macro (A,C) that adds ia_add and
#   ia_nocheck if needed, or it can be called by ia_add manually (B,D).
#
#   (A) my_file "<script> <-i> [[--] <script-args>]"
#   (B) ia_nocheck && ia_add "my_file --ia \"<script> [<-i>] [[--] <script-args>]\""
#   (C) my_file "<script> [<script-args>]"
#   (D) ia_add "my_file --no-ia \"<script> [<script-args>]\""
#
#   <script>  the path of the script to be called
#   <script-args>
#             optional <script> specific arguments
#   --ia      my_file assumes that the remote command uses shellia
#   --no-ia   my_file assumes that the remote command does not use shellia
#   <-i>      this option allowes the user to toggle interactive and
#             non-interactive mode
#
# Example:
#   my-ia-script is a script that is controlled by shellia and my-no-ia-script
#   is a script that is not controlled by shellia. Both can print their version
#   with option --version.
#   (A) my_file "my-ia-script <-i> -- --version"
#   (B) ia_nocheck && ia_add "my_file --ia \"my-ia-script <-i> -- --version\""
#   (C) my_file "my-no-ia-script --version"
#   (D) ia_add "my_file --no-ia \"my-no-ia-script --version\""
#
my_file()
{
  local ia script

  ia=""
  while :; do
    if [ "$1" = "--ia" -o "$1" = "--no-ia" ]; then
      ia="$1"
      shift
    else
      break
    fi
  done

  if [ ! "$ia" ]; then # without -ia and --no-ia => (A) or (C)
    # we are actually adding commands with ia_add
    if [ "$ia_is_nocheck" ]; then # (A)
      # ia_nocheck was called before this script. => script is controlled by shellia
      ia="--ia"
    elif [ "$(echo "$*" | grep "<-i>")" ]; then # (A)
      # script contains shellia option, => script is controlled by shellia, but forgot to call ia_nocheck
      ia_nocheck
      ia="--ia"
    else # (C)
      # script is not controlled by shellia
      ia="--no-ia"
    fi

    script="$(/bin/echo "$*" | ia_easy_backslash)"

    ia_add "my_file $ia \"$script\""
    return $?
  fi

  # we are actually executing script with ia command
  log "|start-file $*"
  if [ "$ia" = "--ia"  ]; then # with --ia => (B)
    # the other shellia file called by this script should use the same logfile and silent value
    ( export ia_logfile; export ia_use_silent; export ia_red; export ia_green; \
      export ia_orange; export ia_no_color; \
      export ia_prefix_head="$ia_head/new-file"; eval "$*" 2>&$ia_direct_stderr_fd )
  else # with --no-ia => (D)
    # called file is not shellia controlled
    eval "$*"
  fi
}

# we want to log to directory /var/log/mylib/ (if LOG_DIR is not otherwise set)
# we want to have a logfile with the name of our script
# we want 3 rotating copies
if ! [ "$ia_logfile" ]; then
  ia_logfile="${LOG_DIR:-/var/log/mylib}/$(basename $0)"
  [ -f $ia_logfile.2 ] && mv $ia_logfile.2 $ia_logfile.3
  [ -f $ia_logfile.1 ] && mv $ia_logfile.1 $ia_logfile.2
  [ -f $ia_logfile ] && mv $ia_logfile $ia_logfile.1
fi

# we want our script only to import this file (which automatically includes shellia libs)
# we prefer a local copy of ia, if it exists
[ -f ia ] && . ./ia || . /usr/share/shellia/ia
