#! /bin/bash
#   BAREOS® - Backup Archiving REcovery Open Sourced
#
#   Copyright (C) 2013-2025 Bareos GmbH & Co. KG
#
#   This program is Free Software; you can redistribute it and/or
#   modify it under the terms of version three of the GNU Affero General Public
#   License as published by the Free Software Foundation and included
#   in the file LICENSE.
#
#   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
#   Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
#   02110-1301, USA.
# A function to find the pid of a program.
pidofproc()
{
  pid=""
  # Test syntax.
  if [ $# = 0 ]; then
    echo "Usage: pidofproc {program} {port}"
    return 1
  fi

  # Get base program name
  base=$(basename $1)

  # First try "pidof"
  if [ ! -z "${PIDOF}" -a -x "${PIDOF}" ]; then
    pid=$(${PIDOF} $1)
    if [ "$pid" != "" ]; then
      echo $pid
      return 0
    fi
  fi

  # Next try "pgrep"
  if [ ! -z "${PGREP}" -a -x "${PGREP}" ]; then
    pid=$(${PGREP} -f $base)
    if [ "$pid" != "" ]; then
      echo $pid | cut -d' ' -f 1
      return 0
    fi
  fi

  # Finally try to extract it from ps
  pid=$(ps | grep ${base} | awk '{print $1}' | head -n1)
  echo $pid
  return 0
}

checkPid()
{
  pid="$1"
  wait="${2:-0}"
  waittext="${3:-}"
  output=""

  if [ -z "$pid" ]; then
    return 1
  fi

  start=$(date +%s)
  end=$(expr $start + $wait)

  while [ "$(date +%s)" -lt "$end" ] && ${PS} -p "$pid" >/dev/null 2>&1; do
    if [ "${waittext}" ]; then
      printf "%s" "$waittext"
      output="yes"
    fi
    # not all systems offer floating point numbers as sleep parameter, therefore try both.
    sleep 0.1 || sleep 1
  done
  if [ "${output}" ]; then printf " "; fi
  ${PS} -p "$pid" >/dev/null 2>&1
  return $?
}

# A function to stop a program.
killproc()
{
  RC=0
  # Test syntax.
  if [ $# = 0 ]; then
    echo "Usage: killproc {program} {port} [signal]"
    return 1
  fi

  notset=0
  # check for third arg to be kill level
  if [ "$3" != "" ]; then
    killlevel=$3
  else
    notset=1
    killlevel="-9"
  fi

  # Get base program name
  base=$(basename $1)

  # Find pid.
  pid=$(pidofproc $base $2)

  # Kill it.
  if checkPid "$pid"; then
    if [ "$notset" = "1" ]; then
      # TERM first, then KILL if not dead
      kill -TERM $pid 2>/dev/null
      if checkPid "$pid" 3 "."; then
        kill -KILL $pid 2>/dev/null
      fi
      if checkPid "$pid" 3 "_"; then
        failure
      else
        success
      fi
    else
      if kill $killlevel $pid 2>/dev/null; then
        success "sent signal $killlevel"
      else
        failure
      fi
    fi
  else
    success "already stopped"
  fi
  return $RC
}

# Checks if the Database can be connected to
check_database()
{
  echo "Checking Database connection for $1"
  log_file="${tmp}/bareos-$1-config-test.out"
  "$2" -f -t "${@:3}" &>"$log_file"

  if grep -q "Could not open Catalog" "$log_file"; then
    echo "Fail: Could not connect to the Catalog when running $2 -t ${*:3}, see below." >&2
    cat "$log_file"
    return 2
  fi
  return 0
}
# Checks if the configuration outputs warnings
check_config()
{
  echo "Checking Configuration for $1"
  log_file="${tmp}/bareos-$1-config-test.out"
  "$2" -t "${@:3}" &>"${log_file}"

  if ! ${IGNORE_CONFIG_WARNINGS}; then
    if grep -q "There are configuration warnings" "${log_file}"; then
      echo "Fail: There are configuration warnings when running $2 -t ${*:3}, see below." >&2
      cat "${log_file}"
      return 7
    fi
  else
    cat "${log_file}"
  fi
  return 0
}

status()
{
  # Test syntax.
  if [ $# = 0 ]; then
    echo "Usage: status {program} {port}"
    return 1
  fi

  # Get base program name
  base=$(basename $1)

  # Find pid.
  pid=$(pidofproc $base $2)

  if checkPid "$pid"; then
    echo "$base (pid $pid) is running..."
    return 0
  fi

  echo "$base is stopped"
  return 3
}

success()
{
  MESSAGE="OK"
  if [ "$1" ]; then
    MESSAGE="OK ($1)"
  fi
  echo $MESSAGE
  return 0
}

failure()
{
  rc=$?
  echo "failed (rc=$rc)"
  return $rc
}
