USE_SYSTEMD=0
_use_systemd=$(command -v systemctl 2>&1 >/dev/null && systemctl is-system-running)
case "$_use_systemd" in
  offline|unknown)
    USE_SYSTEMD=0
    ;;
  "")
    USE_SYSTEMD=0
    ;;
  *)
    USE_SYSTEMD=1
    ;;
esac

use_systemd()
{
  test $USE_SYSTEMD = 1
}

#!/bin/sh

PREFIX=/var/cfengine

package_type()
{
  echo depot
}

os_type()
{
  echo hpux
}

rc_d_path()
{
  echo "/sbin"
}

rc_start_level()
{
  echo S970
}

rc_kill_level()
{
  echo K050
}

platform_service()
{
  /sbin/init.d/"$1" "$2"
}

native_is_upgrade()
{
  test -f "$PREFIX/bin/cf-agent"
}
PKG_TYPE=depot
SCRIPT_TYPE=preinstall
PROJECT_TYPE=cfengine-nova
BUILT_ON_OS=hpux
BUILT_ON_OS_VERSION=
# postgresql docs, https://www.postgresql.org/docs/current/locale.html, recommend using C locale unless otherwise needed
export LC_ALL=C # overrides all other env vars: https://www.gnu.org/software/libc/manual/html_node/Locale-Categories.html
# Upgrade detection is a mess. It is often difficult to tell, especially from
# the postinstall script, so we use the package-upgrade.txt file to remember.
case "$PKG_TYPE" in
  depot|deb|bff)
    case "$SCRIPT_TYPE" in
      preinstall|preremove)
        if native_is_upgrade; then
          mkdir -p "$PREFIX"
          echo "File used by CFEngine during package upgrade. Can be safely deleted." > "$PREFIX/package-upgrade.txt"
        else
          rm -f "$PREFIX/package-upgrade.txt"
        fi
        alias is_upgrade='native_is_upgrade'
        ;;
      postremove|postinstall)
        if [ -f "$PREFIX/package-upgrade.txt" ]; then
          if [ "$SCRIPT_TYPE" = "postinstall" ]; then
            rm -f "$PREFIX/package-upgrade.txt"
          fi
          alias is_upgrade='true'
        else
          alias is_upgrade='false'
        fi
        ;;
    esac
    ;;
esac

get_cfengine_state() {
    if use_systemd; then
        systemctl list-units -l | sed -r -e '/^\s*(cf-[-a-z]+|cfengine3)\.service/!d' -e 's/\s*(cf-[-a-z]+|cfengine3)\.service.*/\1/'
    else
        platform_service cfengine3 status | awk '/is running/ { print $1 }'
    fi
}

restore_cfengine_state() {
    # $1 -- file where the state to restore is saved (see get_cfengine_state())

    if use_systemd; then
        for service in `cat "$1"`; do
            definition=`systemctl cat "$service"` || continue
            # only try to start service that are defined/exist (some may be gone
            # in the new version)
            if [ -n "$definition" ]; then
                systemctl start "$service" || echo "Failed to start service $service"
            fi
        done
    else
        CALLED_FROM_STATE_RESTORE=1
        if [ -f ${PREFIX}/bin/cfengine3-nova-hub-init-d.sh ]; then
            . ${PREFIX}/bin/cfengine3-nova-hub-init-d.sh
            if grep postgres "$1" >/dev/null; then
                start_postgres >/dev/null || echo "Failed to start PostgreSQL"
            fi
            if grep httpd "$1" >/dev/null; then
                start_httpd >/dev/null || echo "Failed to start Apache"
            fi
        fi

        for d in `grep 'cf-' "$1"`; do
            if [ -f ${PREFIX}/bin/${d} ]; then
                ${PREFIX}/bin/${d} || echo "Failed to start $d"
            fi
        done
    fi
}

wait_for_cf_postgres() {
    # wait for CFEngine Postgresql service to be available, up to 60 sec.
    # Returns 0 is psql command succeeds,
    # Returns non-0 otherwise (1 if exited by timeout)
    for i in $(seq 1 60); do
        true "checking if Postgresql is available..."
        if cd /tmp && su cfpostgres -c "$PREFIX/bin/psql -l" >/dev/null 2>&1; then
            true "Postgresql is available, moving on"
            return 0
        fi
        true "waiting 1 sec for Postgresql to become available..."
        sleep 1
    done
    # Note: it is important that this is the last command of this function.
    # Return code of `psql` is the return code of whole function.
    cd /tmp && su cfpostgres -c "$PREFIX/bin/psql -l" >/dev/null 2>&1
}

wait_for_cf_postgres_down() {
    # wait for CFEngine Postgresql service to be shutdown, up to 60 sec.
    # Returns 0 if postgresql service is not running
    # Returns non-0 otherwise (1 if exited by timeout)
    for i in $(seq 1 60); do
        true "checking if Postgresql is shutdown..."
        if cd /tmp && ! su cfpostgres -c "$PREFIX/bin/psql -l" >/dev/null 2>&1; then
            true "Postgresql is shutdown, moving on"
            return 0
        fi
        true "waiting 1 sec for Postgresql to shutdown..."
        sleep 1
    done
    # Note: it is important that this is the last command of this function.
    # Return code of `psql` is the return code of whole function.
    cd /tmp && ! su cfpostgres -c "$PREFIX/bin/psql -l" >/dev/null 2>&1
}

safe_cp() {
    # "safe" alternative to `cp`. Tries `cp -al` first, and if it fails - `cp -a`.
    # Deletes partially-copied files if copy operation fails.
    # Args:
    #   * dir you're copying stuff from
    #   * name of stuff you're copying (one arg!)
    #   * dir you're copying stuff to
    # Example: instead of
    #   cp "$PREFIX/state/pg/data" "$BACKUP_DIR"
    # use
    #   safe_cp "$PREFIX/state/pg" data "$BACKUP_DIR"
    test "$#" -eq 3 || return 2
    from="$1"
    name="$2"
    to="$3"
    # First, try copying files creating hardlinks
    # Do not print errors - we'll do it another way
    if cp -al "$from/$name" "$to" 2>/dev/null; then
        # Copy succeeded
        return 0
    fi
    echo "Copy creating hardlinks failed, removing partially-copied data and trying simple copy"
    rm -rf "$to/$name"
    if cp -a "$from/$name" "$to"; then
        # Copy succeeded
        return 0
    fi
    echo "Copy failed, so removing partially-copied data and aborting"
    rm -rf "$to/$name"
    return 1
}

safe_mv() {
    # "safe" alternative to `mv`. Executes `safe_cp` and deletes source dir if
    # that succeeds.
    # Args are same as in safe_cp
    # Exampe: instead of
    #   mv "$PREFIX/state/pg/data" "$BACKUP_DIR"
    # use
    #   safe_mv "$PREFIX/state/pg" data "$BACKUP_DIR"
    test "$#" -eq 3 || return 2
    from="$1"
    name="$2"
    to="$3"
    if safe_cp "$from" "$name" "$to"; then
        # Copy succeeded - so we can delete old dir
        rm -rf "$from/$name"
        return 0
    else
        # Copy failed (partially-copied data is removed by safe_cp)
        return 1
    fi
}

on_files() {
    # perform operation $1 on each file in $2 with optional extra argument $3
    # Examples:
    # to copy only files:
    #   on_files cp "$PREFIX/lib" "$BACKUP_DIR/lib"
    # to move only files:
    #   on_files mv "$PREFIX/lib" "$PREFIX/lib.new"
    # to remove only files:
    #   on_files rm "$PREFIX/lib"
    test "$#" -ge 2 || return 2
    # Split on newlines, not on spaces.
    IFS='
'
    for file in $(ls -a1 "$2"); do
        if [ -f "$2/$file" ]; then
            $1 "$2/$file" $3
        fi
    done
    # Restore normal splitting semantics.
    unset IFS
}

case "`uname -s`" in
	Linux)
		if [ -f /etc/os-release ]; then
			OS_VERSION="$(sed '/VERSION_ID/!d;s/[^0-9]*\([0-9]\+\).*/\1/' /etc/os-release)"
			OS_NAME="$(sed '/^ID=/!d;s/.*=//;s/^"//;s/"$//' /etc/os-release)"
		elif [ -f /etc/redhat-release ]; then
			if cat /etc/redhat-release | grep -iq centos; then
				OS_NAME=centos
			else
				OS_NAME=rhel
			fi
			OS_VERSION="$(sed 's/[^0-9]*\([0-9]\+\).*/\1/' /etc/redhat-release)"
		fi
		;;
	SunOS)
		OS_NAME=solaris
		OS_VERSION=`uname -r | sed -e 's/^5\.//'`
		;;
	AIX)
		OS_NAME=aix
		OS_VERSION=`uname -v`
		;;
esac

cmp_version()
{
	# compares OS versions: where this script is running vs where the package was built.
	# pass extra third argument if it's *not* supported when these versions match.
	this_version="$1"
	built_on_version="$2"
	same_version_is_bad="$3"
	if [ -z "$this_version" -o -z "$built_on_version" ]; then
		echo "WARNING: error detecting version. Likely $OS_NAME $OS_VERSION is too new for this package."
		echo "This configuration might be unsupported, please consider downloading a proper package."
		echo "Press Ctrl+C within next 15 seconds to abort."
		sleep 15 || return 1
		return 0
	elif [ "$this_version" -gt "$built_on_version" ]; then
		echo "WARNING: this package was built on $BUILT_ON_OS $BUILT_ON_OS_VERSION, and you're installing it on $OS_NAME $OS_VERSION, which seems to be newer."
		echo "This configuration might be unsupported, please consider downloading a proper package."
		echo "Press Ctrl+C within next 15 seconds to abort."
		sleep 15 || return 1
		return 0
	elif [ -z "$same_version_is_bad" -a "$this_version" = "$built_on_version" ]; then
		return 0
	else
		return 1
	fi
}

# debian-to-ubuntu match
# From https://askubuntu.com/a/445496
deb2ubuntu()
{
	case "$1" in
		(6) echo 11;;
		(7) echo 13;;
		(8) echo 15;;
		(9) echo 17;;
		(10) echo 19;;
		(11) echo 21;;
	esac
	# TODO: or can it be simply Debian[N]=Ubuntu[2*N-1]?
}

# rhel-to-fedora match
# From https://docs.fedoraproject.org/en-US/quick-docs/fedora-and-red-hat-enterprise-linux/index.html#_history_of_red_hat_enterprise_linux_and_fedora
rhel2fedora()
{
	case "$1" in
		(6) echo 12;;
		(7) echo 19;;
		(8) echo 28;;
	esac
}

compatible()
{
	if [ "$OS_NAME" = "" -o "$OS_VERSION" = "" ]; then
		# no version checking
		return 0
	fi
	if [ "$OS_NAME" = "$BUILT_ON_OS" ]; then
		cmp_version "$OS_VERSION" "$BUILT_ON_OS_VERSION"
		return $?
	fi
	if [ "$BUILT_ON_OS-$OS_NAME" = "centos-rhel" -o "$BUILT_ON_OS-$OS_NAME" = "rhel-centos" ]; then
		cmp_version "$OS_VERSION" "$BUILT_ON_OS_VERSION"
		return $?
	fi
	if [ "$BUILT_ON_OS-$OS_NAME" = "centos-fedora" -o "$BUILT_ON_OS-$OS_NAME" = "rhel-fedora" ]; then
		build_compat="`rhel2fedora "$BUILT_ON_OS_VERSION"`"
		cmp_version "$OS_VERSION" "$build_compat" same_version_is_bad
		return $?
	fi
	if [ "$BUILT_ON_OS" = "sles" ] && expr "$OS_NAME" : ".*suse" >/dev/null; then
		cmp_version "$OS_VERSION" "$BUILT_ON_OS_VERSION"
		return $?
	fi
	if [ "$BUILT_ON_OS-$OS_NAME" = "debian-ubuntu" ]; then
		build_compat="`deb2ubuntu "$BUILT_ON_OS_VERSION"`"
		cmp_version "$OS_VERSION" "$build_compat" same_version_is_bad
		return $?
	fi
	if [ "$BUILT_ON_OS-$OS_NAME" = "ubuntu-debian" ]; then
		this_compat="`deb2ubuntu "$OS_VERSION"`"
		cmp_version "$this_compat" "$BUILT_ON_OS_VERSION" same_version_is_bad
		return $?
	fi
	# different platforms
	echo "WARNING: this package was built on $BUILT_ON_OS $BUILT_ON_OS_VERSION, and you're installing it on $OS_NAME $OS_VERSION."
	echo "Names differ! This configuration might be unsupported, please consider downloading a proper package."
	echo "Press Ctrl+C within next 15 seconds to abort."
	sleep 15 || return 1
	return 0
}


if [ -z "$IGNORE_VERSION_CHECK" ]; then
	if ! compatible; then
		echo "ERROR: this package was built on $BUILT_ON_OS $BUILT_ON_OS_VERSION, and this seems to be $OS_NAME $OS_VERSION."
		echo "This combination is not compatible. To override this check, export non-empty IGNORE_VERSION_CHECK variable."
		exit 1
	fi
fi
if [ -f "$PREFIX/CFENGINE_TEST_PACKAGE_SCRIPT.txt" ]; then
  # Special mode during testing. Dump some info for verification.
  (
    echo "new_script----"
    echo "script_type=$SCRIPT_TYPE"
    if is_upgrade; then
      echo "is_upgrade=1"
    else
      echo "is_upgrade=0"
    fi
  ) >> "$PREFIX/CFENGINE_TEST_PACKAGE_SCRIPT.log"
fi

is_community()
{
  test "$PROJECT_TYPE" = "cfengine-community"
}

is_nova()
{
  test "$PROJECT_TYPE" = "cfengine-nova" || test "$PROJECT_TYPE" = "cfengine-nova-hub"
}

case "`os_type`" in
    aix)
        INSTLOGGROUP="system"
        ;;
    *)
        INSTLOGGROUP="root"
        ;;
esac

INSTLOG="/var/log/CFEngine-Install-$(date '+%Y-%m-%d_%H:%M:%S_%Z').log"
mkdir -p "$(dirname "$INSTLOG")"
touch "$INSTLOG"
rm -f /var/log/CFEngineHub-Install.log
rm -f /var/log/CFEngine-Install.log
ln -s "$INSTLOG" /var/log/CFEngine-Install.log
chown root:$INSTLOGGROUP "$INSTLOG"
chmod 600 "$INSTLOG"
CONSOLE=7
# Redirect most output to log file, but keep console around for custom output.
case "$SCRIPT_TYPE" in
  pre*)
    eval "exec $CONSOLE>&1 > $INSTLOG 2>&1"
    ;;
  *)
    eval "exec $CONSOLE>&1 >> $INSTLOG 2>&1"
    ;;
esac
echo "$SCRIPT_TYPE:"

# Output directly to console, bypassing log.
cf_console()
{
  # Use subshell to prevent "set +x" from leaking out into the rest of the
  # execution.
  (
    set +x
    "$@" 1>&$CONSOLE 2>&$CONSOLE
  )
}

set -x
if is_upgrade; then
  # This is nice to know to provide fixes for bugs in already released
  # package scripts.
  "$PREFIX/bin/cf-agent" -V | grep '^CFEngine Core' | sed -e 's/^CFEngine Core \([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/' > "$PREFIX/UPGRADED_FROM.txt"

  # Save the pre-upgrade state so that it can be restored
  get_cfengine_state > "${PREFIX}/UPGRADED_FROM_STATE.txt"

  # Stop the services on upgrade.
  cf_console platform_service cfengine3 stop
fi

case `os_type` in
  redhat)
    #
    # Work around bug in CFEngine <= 3.6.1: The %preun script stops the
    # services, but it shouldn't when we upgrade. Later versions are fixed, but
    # it's the *old* %preun script that gets called when we upgrade, so we have
    # to work around it by using the %posttrans script, which is the only script
    # from the new package that is called after %preun. Unfortunately it doesn't
    # tell you whether or not you're upgrading, so we need to remember it by
    # using the file below.
    #
    # This section can be removed completely when we no longer support upgrading
    # from the 3.6 series, as well as the posttrans script.
    #
    if is_upgrade; then
      if %{prefix}/bin/cf-agent -V | egrep '^CFEngine Core 3\.([0-5]\.|6\.[01])' > /dev/null; then
        ( echo "Upgraded from:"; %{prefix}/bin/cf-agent -V ) > %{prefix}/BROKEN_UPGRADE_NEED_TO_RESTART_DAEMONS.txt
      fi
    fi
    ;;
esac

case `os_type` in
  debian)
    if [ -x /etc/init.d/cfengine3 ]; then
      /usr/sbin/update-rc.d -f cfengine3 remove
    fi
    ;;
esac

exit 0
