#!/bin/bash
# Copyright (c) 2018-2020 VMware, Inc. All rights reserved.
#
# Configure and register the PSC agent.
#

shopt -s extglob
umask 077

TYPE_AMAZON="amazon"
TYPE_CENTOS="centos"
TYPE_ORACLE="ol"
TYPE_REDHAT="rhel"
TYPE_SUSE="suse"
TYPE_UBUNTU="ubuntu"
TYPE_DEBIAN="debian"

AMAZON_VARIANTS=( "amz" )
CENTOS_VARIANTS=( "centos" "cent" )
ORACLE_VARIANTS=( "os" )
REDHAT_VARIANTS=( "rhel" "redhat" "red hat" )
SUSE_VARIANTS=( "suse" "opensuse" "sles" "sled" )

TYPE_UNKNOWN="unknown"
VERSION_UNKNOWN="unknown"

ERROR_FILE="/var/opt/carbonblack/tmp/cberror"
CIPHER_FILE="/var/opt/carbonblack/tmp/cbcipher"
CUSTOM_CFG_FILE="/var/opt/carbonblack/tmp/cbcustomcfg"
LRDISABLE_FILE="/var/opt/carbonblack/tmp/cblrdisable"
SKIPSTART_FILE="/var/opt/carbonblack/tmp/cbskipstart"
CLEANUP_FILE="/var/opt/carbonblack/tmp/cbcleanup"
PROP_FILE="/var/opt/carbonblack/tmp/cbpropfile"
TH_PROP_FILE="/var/opt/carbonblack/tmp/cbthpropfile"

# Blades Base DIR
TH_BLADE_BASE_DIR="/opt/carbonblack/psc/blades/E51C4A7E-2D41-4F57-99BC-6AA907CA3B40"
LQ_BLADE_BASE_DIR="/opt/carbonblack/psc/blades/40E797FD-4322-4D33-8E8C-EF697F4C2323"

DISTRO_IS_RPM=false
DISTRO_IS_DEB=false

echo_log() {
  echo "$@" 1>&2
}

#=============================================================================
# Parses a string in an effort to determine the type of Linux distribution
# Parameters:
#   - distro_name_str: a string containing information about the distro (from
#       /etc/os-release, lsb_release, etc.)
# Result:
#   Success: (0) returns the distribution TYPE
#   Failure: (1) returns TYPE_UNKNOWN
#=============================================================================
parse_distro_type() {
  local distro_name_str="$1"

  distro_name_str="$(echo $distro_name_str | tr '[:upper:]' '[:lower:]')"

  # check variants of amazon
  for variant in "${AMAZON_VARIANTS[@]}"; do
    case "$distro_name_str" in
        *"$variant"* )
         echo "$TYPE_AMAZON"
         exit 0
         ;;
    esac
  done

  # check variants of redhat
  for variant in "${REDHAT_VARIANTS[@]}"; do
    case "$distro_name_str" in
        *"$variant"* )
         echo "$TYPE_REDHAT"
         exit 0
         ;;
    esac
  done

  # check variants of centos
  for variant in "${CENTOS_VARIANTS[@]}"; do
    case "$distro_name_str" in
        *"$variant"* )
         echo "$TYPE_CENTOS"
         exit 0
         ;;
    esac
  done

   # check variants of suse
   for variant in "${SUSE_VARIANTS[@]}"; do
     case "$distro_name_str" in
        *"$variant"* )
         echo "$TYPE_SUSE"
         exit 0
         ;;
     esac
   done

    #check ubuntu
    if [ "$distro_name_str" = "$TYPE_UBUNTU" ]; then
        echo "$TYPE_UBUNTU"
        return 0
    fi

    #check debian
    if [ "$distro_name_str" = "$TYPE_DEBIAN" ]; then
        echo "$TYPE_DEBIAN"
        return 0
    fi
    
    #check oracle
    if [ "$distro_name_str" = "$TYPE_ORACLE" ]; then
        echo "$TYPE_ORACLE"
        return 0
    fi

  # No variants found!
  echo "$TYPE_UNKNOWN"
  return 1
}

#=============================================================================
# Sets the package type for known distros
#=============================================================================
parse_package_type() {

  if [ "$DISTRIBUTION_TYPE" = "$TYPE_UBUNTU" ]; then
        DISTRO_IS_DEB=true
  elif [ "$DISTRIBUTION_TYPE" = "$TYPE_DEBIAN" ]; then
        DISTRO_IS_DEB=true
  elif [ "$DISTRIBUTION_TYPE" = "$TYPE_AMAZON" ]; then
        DISTRO_IS_RPM=true
  elif [ "$DISTRIBUTION_TYPE" = "$TYPE_CENTOS" ]; then
        DISTRO_IS_RPM=true
  elif [ "$DISTRIBUTION_TYPE" = "$TYPE_ORACLE" ]; then
        DISTRO_IS_RPM=true
  elif [ "$DISTRIBUTION_TYPE" = "$TYPE_REDHAT" ]; then
        DISTRO_IS_RPM=true
  elif [ "$DISTRIBUTION_TYPE" = "$TYPE_SUSE" ]; then
        DISTRO_IS_RPM=true
  fi
}


#=============================================================================
# Parses a string to determine the major version of the Linux distribution
# Parameters:
#  - major_version_str: a string containing version information; expected to
#      begin with a numeric character
# Result:
#   Success: (0) return the identified version
#   Failure: (1) return VERSION_UNKNOWN
#=============================================================================
parse_distro_major_version() {
  local major_version_str="$1"
  major_version_str="$(echo $major_version_str | sed -rn 's/\s*([0-9]+).*/\1/p')"
  if [ -n "$major_version_str" ]; then
    echo "$major_version_str"
    return 0
  else
    echo "$VERSION_UNKNOWN"
    return 1
  fi
}

#=============================================================================
# Attempts to retrieve Linux distribution information from the OS
# Parameters:
#   None
# Result:
#   Success: (0) sets DISTRIBUTION_[BITS, TYPE, VERSION] to valid values
#   Failure: (1) sets 1 or more DISTRIBUTION_[BITS, TYPE, VERSION] to UNKNOWN
#=============================================================================
collect_distro_info() {
  local distro_type=""
  local distro_version=""

  # Get distribution type and major version
  if [ -f /etc/os-release ]; then
    source /etc/os-release
    distro_type="$ID"
    distro_version="$VERSION_ID"
  elif type lsb_release >/dev/null 2>&1; then
    distro_type="$(lsb_release -si)"
    distro_version="$(lsb_release -sr)"
  elif [ -f /etc/redhat-release ]; then
    distro_type="$(cat /etc/redhat-release)"
    # sed does not support non-greedy matching, must extract the version number
    distro_version="$(sed -rn 's/.*release ([0-9\.]+).*/\1/p' /etc/redhat-release)"
  elif [ -f /etc/system-release]; then
    distro_type="$(cat /etc/system-release)"
    distro_version="$(sed -rn '/.*release ([0-9\.]+).*/\1/p' /etc/system-release)"
  else
    distro_type="$TYPE_UNKNOWN"
    distro_version="$VERSION_UNKNOWN"
  fi

  DISTRIBUTION_TYPE=$(parse_distro_type "$distro_type")
  DISTRIBUTION_VERSION=$(parse_distro_major_version "$distro_version")
  DISTRIBUTION_BITS="$(getconf LONG_BIT)"
  parse_package_type

  if [ "$DISTRIBUTION_TYPE" = "$TYPE_UNKNOWN" ] ; then
    if rpm --version >/dev/null 2>&1; then
      export DISTRO_IS_RPM=true
    fi

    if dpkg-query --version >/dev/null 2>&1; then
      export DISTRO_IS_DEB=true
    fi
    
    if [ "$DISTRO_IS_RPM" = "$DISTRO_IS_DEB" ]; then
      echo_log "Failed: Unable to determine package type for unknown distribution."
      return 1 
    fi
  fi

  return 0
}

get_distribution_rpm() {
  if [ "$DISTRIBUTION_VERSION" = "6" ] || [ "$DISTRIBUTION_VERSION" = "7" ] || [ "$DISTRIBUTION_VERSION" = "8" ]; then

    rpm_file=$(ls -1 "$this_dir"/cb-psc-sensor-+([[:digit:]-.]).el"$DISTRIBUTION_VERSION".x86_64.rpm | tail -1)
  else
    rpm_file=$(ls -1 "$this_dir"/cb-psc-sensor-+([[:digit:]-.]).x86_64.rpm | tail -1)
  fi

  echo "$rpm_file"
}

get_distribution_deb() {
  deb_file=$(ls -1 "$this_dir"/cb-psc-sensor-+([[:digit:]-.]).x86_64.deb | tail -1)

  echo "$deb_file"
}

#=============================================================================
# Execution to cleanup the blades BASE DIR
#=============================================================================
cleanup_blades_dirs() {
   # Cleanup the LQ blade base dir
   if [ -d "$LQ_BLADE_BASE_DIR" ]; then
       rm -rf "$LQ_BLADE_BASE_DIR"
   fi

   # Cleanup the TH blade base dir
   if [ -d "$TH_BLADE_BASE_DIR" ]; then
       rm -rf "$TH_BLADE_BASE_DIR"
   fi
}

#=============================================================================
# Installs the agent on the system
# Parameters:
#   - cipher_code: string representing v3 registration code
# Result:
#   Success: (0)
#   Failure: (1)
#=============================================================================
install_agent() {
  local cipher_code="$1"
  local force_pkg="$2"
  local dirname="$(dirname $0)"
  local this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && /bin/pwd )"
  local rpm_file=""
  local deb_file=""
  local already_installed=0

  echo_log "Starting install of cbagentd at $(date)."

  if bootctl status 2>/dev/null | grep "Secure Boot: enabled" >/dev/null 2>&1; then
      echo_log "Secure boot enabled system."
  fi

  # Cleanup any errors from a previous run
  rm -f "$ERROR_FILE"

  # Write the cipher file if needed
  if [ -n "$cipher_code" ]; then
    echo "$cipher_code" > "$CIPHER_FILE"
    chmod 400 "$CIPHER_FILE"
  fi

  # Write the policy file if needed
  if [ -n "$POLICY_NAME" ]; then
    echo "GroupName=$POLICY_NAME" >> "$PROP_FILE"
    chmod 400 "$PROP_FILE"
  fi

  # Write the proxy file if needed
  if [ -n "$PROXY_NAME" ]; then
    echo "ProxyServer=$PROXY_NAME" >> "$PROP_FILE"
    chmod 400 "$PROP_FILE"
  fi

  # Write the disable live response file if needed
  if [ -n "$LR_DISABLE" ]; then
    touch "$LRDISABLE_FILE"
    chmod 400 "$LRDISABLE_FILE"
  fi

  # Write the register endpoint only file if needed
  if [ -n "$START_DISABLE" ]; then
    touch "$SKIPSTART_FILE"
    chmod 400 "$SKIPSTART_FILE"
  fi

  # Write the bypass file if needed
  if [ -n "$BYPASS_ENABLE" ]; then
    echo "Bypass=true" >> "$TH_PROP_FILE" 
    chmod 400 "$TH_PROP_FILE"
  fi

  # Write the Sensor properties if any specified
  if [ -n "$PROP_NAME" ]; then
    echo -e "$PROP_NAME" >> "$PROP_FILE"
    chmod 400 "$PROP_FILE"
  fi

  # Write the TH properties if any specified
  if [ -n "$TH_PROP_NAME" ]; then
    echo -e "$TH_PROP_NAME" >> "$TH_PROP_FILE"
    chmod 400 "$TH_PROP_FILE"
  fi

  # Write the custom cfg if any specified
  if [ -f "$CUSTOM_CFG" ]; then
    echo "$CUSTOM_CFG" > "$CUSTOM_CFG_FILE"
    chmod 400 "$CUSTOM_CFG_FILE"
  fi

  # Ignore distribution and use forced package
  if [ "$force_pkg" ]; then
    extension=${force_pkg: -3}
    if [ ${extension^^} = "RPM" ]; then
      DISTRO_IS_RPM=true
      rpm_file="$this_dir/$force_pkg"
      if [ ! -f "$rpm_file" ]; then
        echo_log "$rpm_file not found"
        return 1
      fi
    elif [ ${extension^^} = "DEB" ]; then
      DISTRO_IS_DEB=true
      deb_file="$this_dir/$force_pkg"
      if [ ! -f "$deb_file" ]; then
        echo_log "$deb_file not found"
        return 1
      fi
    else
        echo_log "$force_pkg is not a valid package type";
        return 1
    fi
  else
    # Reject non-64 bit distributions
    if [ "$DISTRIBUTION_BITS" != "64" ]; then
      echo_log "Failed: Only 64-bit operating systems are supported (detected: ${DISTRIBUTION_BITS}-bit)"
      return 1
    fi

    # Choose RPM for distribution
    if [ "$DISTRO_IS_RPM" = true ];
    then
      rpm_file="$(get_distribution_rpm)"
      if [ "$rpm_file" = "" ]; then
        echo_log "Failed RPM install: this installer does not support this distribution ($DISTRIBUTION_TYPE-$DISTRIBUTION_VERSION)"
        return 1
      fi

      if rpm --quiet -q cb-psc-sensor;then
        already_installed=1
      fi

    # Choose DEB for distribution
    elif [ "$DISTRO_IS_DEB" = true ];
    then
      deb_file="$(get_distribution_deb)"
      if [ "$deb_file" = "" ]; then
        echo_log "Failed DEB install: this installer does not support this distribution ($DISTRIBUTION_TYPE-$DISTRIBUTION_VERSION)"
        return 1
      fi

      if dpkg-query -f='${Status}' -W cb-psc-sensor | grep -qG "^install ok installed"; then
        already_installed=1
      fi
    fi
  fi

  if [ $already_installed = 1 ]; then
    echo_log "Failed: Agent is already installed. If attempting to manually upgrade, use dpkg -i against the deb file or rpm -U against the rpm file, depending on your distribution."
    return 1
  fi

  dpkg --purge cb-psc-sensor 2> /dev/null
  if [ -d "$this_dir/blades" ]; then
    # Touch the cleanup file since after this cleanup is required
    touch "$CLEANUP_FILE"

    # Since these directories are created before agent install, we need to set the permissions correctly.
    mkdir -pm 755 "/opt/carbonblack/"
    mkdir -pm 700 "/opt/carbonblack/psc"

    /bin/bash "$this_dir/blades/bladesUnpack.sh"
    bladeRet=$?

    if [ $bladeRet -ne 0 ]; then
      return 1
    fi
  fi

  # Install the agent package
  if [ "$DISTRO_IS_RPM" = true ]; then
    echo_log "Installing agent from $rpm_file"
    rpm_flags=""
    # FIPS Bypass check: Check if we are running on Rhel 8+ systems that has fips enabled. 
    # If so, use rpm install options to bypass fips install constraints
    #
    if egrep -q "fips" /proc/cmdline; then 
        echo_log "FIPS enabled on system"
        if egrep -q "release 8" /etc/redhat-release; then 
            rpm_flags="--nodigest --nofiledigest"
        fi
    fi

    if ! rpm -i $rpm_flags "$rpm_file"; then
      echo_log "Failed: an error occurred while installing $rpm_file"
      return 1
    fi

    # Check for registration errors
    if [ -f "$ERROR_FILE" ]; then
      echo_log "An error occurred during registration ($(cat $ERROR_FILE))."
      echo_log "The agent ($(rpm -qa cb-psc-sensor)) will be uninstalled..."
      rpm -e cb-psc-sensor
      echo_log "The agent was uninstalled."
      return 1
    fi

  elif [ "$DISTRO_IS_DEB" = true ]; then
    echo_log "Installing agent from $deb_file"

    # deb bubbles up scriptlet error codes to dpkg -i command (whereas rpm does not)
    if ! dpkg -i --force-confold "$deb_file"; then
      echo_log "Failed: an error occurred while installing $deb_file. The package will be uninstalled."
      dpkg --remove cb-psc-sensor
      return 1
    fi

    # Check for registration errors
    if [ -f "$ERROR_FILE" ]; then
      echo_log "An error occurred during registration ($(cat $ERROR_FILE))."
      echo_log "The agent will be uninstalled..."
      dpkg --remove cb-psc-sensor
      echo_log "The agent was uninstalled."
      return 1
    fi
  else
    echo_log "Failed: Agent was unable to install."
    return 1
  fi

  # Remove the Cleanup File
  rm -f "$CLEANUP_FILE"

  return 0
}

FreeSpaceMB() {
    FREE_SPACE_KB=$(df -Pk $1 | tail -1 | sed 's/  */ /g' | cut -f 4 -d ' ')
    echo $((FREE_SPACE_KB / 1024))
}

CheckDiskSpace() {
    local DIR_PATH="$1"
    local NEED_SIZE_MB="$2"

    while ! [ -d "$DIR_PATH" ]
    do
        DIR_PATH=$(dirname "$DIR_PATH")
    done

    local AVAIL_SPACE=$(FreeSpaceMB $DIR_PATH)

    if [ "$AVAIL_SPACE" -lt "$NEED_SIZE_MB" ]; then
        echo_log "Warning: '$DIR_PATH' has only ${AVAIL_SPACE}MB free space; at least ${NEED_SIZE_MB}MB recommended"
        echo_log "Warning: See sensor installation guide for resource requirements"
    fi
}

#=============================================================================
# Cleanup the temporary files created while parsing the options.
#=============================================================================
cleanup_temp_files_and_dirs() {
    # Remove the disable live response file
    if [ -f "$LRDISABLE_FILE" ]; then
        rm -f "$LRDISABLE_FILE"
    fi

    # Remove the skipstart file
    if [ -f "$SKIPSTART_FILE" ]; then
        rm -f "$SKIPSTART_FILE"
    fi

    # Remove the PROP and TH PROP files
    if [ -f "$PROP_FILE" ]; then
       rm -f "$PROP_FILE"
    fi

    if [ -f "$TH_PROP_FILE" ]; then
       rm -rf "$TH_PROP_FILE"
    fi

    # Remove the CIPHER file
    if [ -f "$CIPHER_FILE" ]; then
        rm -f "$CIPHER_FILE"
    fi

    # Remove the CUSTOM CFG file
    if [ -f "$CUSTOM_CFG_FILE" ]; then
        rm -f "$CUSTOM_CFG_FILE"
    fi

    # Remove the tmp directories in TMP DIRS
    for dirs in /var/opt/carbonblack/tmp/tmp*; do
        rm -rf "$dirs"
    done
}

#=============================================================================
# Validate the user input provided to the script.
# Check if proper proxy server and policy name has been provided.
#=============================================================================
validate_user_input() {
    if [ -n "$PROXY_NAME" ]; then
        num=$(echo "${PROXY_NAME}" | awk -F: '{print NF-1}')
        if [[ "$PROXY_NAME" =~ "http" ]]; then
             num_of_occu=2
        else
             num_of_occu=1
        fi
        if [ $num -ne $num_of_occu ]; then
            echo_log "Failed: Proxy server input is not in correct format"
            echo_log "It should be in format IP:port or http://ip:port or https://ip:port"
            return 1
        fi
    fi
    if [ -n "$POLICY_NAME" ] ; then
	if [ ${#POLICY_NAME} -ge 256 ]; then
            echo_log "Failed: Policy Name provided is greater than 256 characters"
            return 1
        fi
    fi

    return 0
}

#=============================================================================
# Main execution to install the agent.
# Parameters:
#   - cipher_code: string representing v3 registration code
#   - (optional) force_pkg: when set distribution detection is skipped and the
#     specified package file is installed
# Result:
#   Success: (0)
#   Failure: (1)
#=============================================================================
main() {
  local cipher_code="$1"
  local force_pkg="$2"
  local var_opt_cb_dir="/var/opt/carbonblack"
  local log_dir="/var/opt/carbonblack/psc/log"
  local tmp_dir="/var/opt/carbonblack/tmp"

  if [ -z "$force_pkg" ]; then
    # Collect distro information
    if ! collect_distro_info; then
      echo_log "Failed: Unable to gather enough info about this distribution to begin install."
      echo_log "(type: $DISTRIBUTION_TYPE; version: $DISTRIBUTION_VERSION; bits: $DISTRIBUTION_BITS)"
      return 1
    fi
  fi

  # Validate user is root
  if [ "$EUID" -ne 0 ]; then
    echo_log "Failed: Must be root to run this script."
    return 1
  fi

  # Warn if insufficient space is available
  CheckDiskSpace "/opt/carbonblack/psc"       "200"
  CheckDiskSpace "/var/opt/carbonblack/psc" "2000"

  # Validate the user input provided
  if (! validate_user_input); then
      echo_log "Failed: The arguments provided for installation are not in correct format, failing the installation. "
      return 1
  fi

  # Perform the agent installation
  mkdir -p -m 700 "$var_opt_cb_dir"
  mkdir -p -m 700 "$log_dir" "$tmp_dir"

  if (! install_agent "$cipher_code" "$force_pkg" 2>&1 | cat -n | tee -a "${log_dir}/cbagentd-install.log"); then
    #
    # Cleanup the blade base dir
    #
    if [ -f "$CLEANUP_FILE" ]; then
       rm -f "$CLEANUP_FILE"
       cleanup_blades_dirs
    fi

    #
    # Cleanup the temporary files/directories if any left behind
    #
    cleanup_temp_files_and_dirs
    echo_log "Failed: agent installation failed."
    return 1
  fi

  echo_log "Success: agent was successfully installed."

  return 0
}

usage() {
    echo -n "usage: $0 [--force-pkg PKGFILE] [-h|--help] [-d|--disable-lr] "
    echo -n "[-g|--groupname 'POLICY_NAME'] [-r|--register 'COMPANY_CODE'] "
    echo -n "[-b|--bypass] [-p|--proxy 'PROXY_HOST:PROXY_PORT'] "
    echo "[COMPANY_CODE]"
    exit 1
}

usage_prop() {
    echo "Usage:"
    echo "  $0 --prop <Sensor property> --thprop <Threat Hunter Property> -c|--custom-cfg <custom_cfg_file>"
    echo ""
    echo "Options:"
    echo " --prop <Sensor Property> : set a single cfg.ini property, repeat it multiple times"
    echo " --thprop <Threat Hunter Property>: set a single th.ini property, repeat it multiple times"
    echo " --custom-cfg <custom_cfg_file absolute path>: Custom cfg file will be used as cfg.ini"
    echo ""
  exit 1
}

validate_custom_cfg() {
    # custom-cfg should be regular file, non-executable and with absolute path
    if [ ! -f "$CUSTOM_CFG" ] || [[ "$CUSTOM_CFG" != /* ]] || [ -x "$CUSTOM_CFG" ]; then
        return 1
    fi

    # Checking for custom-cfg filename ending with .ini
    filename=`basename $CUSTOM_CFG`
    if [[ $filename != *.ini ]]; then
        return 1
    fi

    # Checking first line format of custom-cfg
    template_first_line=$(head -n 1 $CUSTOM_CFG)
    if [ "$template_first_line" != "[customer]" ]; then
        return 1
    fi

    return 0
}

# -e: Fail script if a command exits with non-zero
# -u: Fail script if undeclared variable is used
# -o pipefail: Piped command returns last non-zero exit

set -euo pipefail

CIPHER_CODE=""
POLICY_NAME=""
PROXY_NAME=""
BYPASS_ENABLE=
LR_DISABLE=
START_DISABLE=
PROP_NAME=""
TH_PROP_NAME=""
PROP_ARG=""
TH_PROP_ARG=""
CUSTOM_CFG=""

while [ "${1:-}" != "" ]; do
  case "${1:-}" in
    -h | --help)
      usage
      ;;
    -f | --force-pkg)
      FORCE_PKG="${2:-}"
      if [ -z "$FORCE_PKG" ]; then
        usage
      fi
      shift 2
      ;;
    -b | --bypass)
      BYPASS_ENABLE=1
      shift 1
      ;;
    -c | --custom-cfg)
      CUSTOM_CFG="${2:-}"
      if (! validate_custom_cfg); then
        echo_log "Validation of custom-cfg failed."
        usage_prop
      fi
      shift 2
      ;;
    -d | --disable-lr)
      LR_DISABLE=1
      shift 1
      ;;
    -r | --register)
      START_DISABLE=1
      shift 1
      ;;
    -g | --groupname)
      POLICY_NAME="${2:-}"
      if [ -z "$POLICY_NAME" ]; then
        usage
      fi
      shift 2
      ;;
    -p | --proxy)
      PROXY_NAME="${2:-}"
      if [ -z "$PROXY_NAME" ]; then
        usage
      fi
      shift 2
      ;;
    --prop)
      PROP_ARG="${2:-}"
      if [ -z "$PROP_ARG" ]; then
        usage_prop
      fi
      if [ -z "$PROP_NAME" ]; then
        PROP_NAME="$PROP_ARG"
      else
        PROP_NAME="$PROP_NAME\n$PROP_ARG"
      fi
      shift 2
      ;;
    --thprop)
      TH_PROP_ARG="${2:-}"
      if [ -z "$TH_PROP_ARG" ]; then
        usage_prop
      fi
      if [ -z "$TH_PROP_NAME" ]; then
        TH_PROP_NAME="$TH_PROP_ARG"
      else
        TH_PROP_NAME="$TH_PROP_NAME\n$TH_PROP_ARG"
      fi
      shift 2
      ;;
    *)
      if [ -z "$CIPHER_CODE" ]; then
        CIPHER_CODE="${1:-}"
      else
        usage
      fi
      shift 1
      ;;
    esac
done

# Extracting Encoded company code from custom-cfg
if test -f "$CUSTOM_CFG" && grep -q "EncodedCompanyCode" "$CUSTOM_CFG"; then
    if [ -n "$CIPHER_CODE" ]; then
        echo_log ""
        echo_log "EncodedCompanyCode and custom-cfg options cannot be used together."
        echo_log ""
        usage_prop
    fi
    CIPHER_CODE=$(grep "EncodedCompanyCode" "$CUSTOM_CFG" | awk -F'=' '{ print $2}' | tr -d ' ')
fi

#
# Bail out of the installer if Register is not used with company code
#
if [ -n "$START_DISABLE" -a -z "$CIPHER_CODE" ]; then
    echo_log "Failed to install the agent. -r|--register used but no Company Code found"
    usage
fi

main "$CIPHER_CODE" "${FORCE_PKG:-}"
