#!/bin/bash
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
#------------------------------------------------------------------------------
set -u

#------------------------------------------------------------------------------
# This broker_wrapper script is called by the Helix p4broker server when users
# use the 'p4' command line client targeting the HMS broker and runs 'p4 hms'
# commands.
#
# It's purposes are:
# * Enable HMS commands to be called via the Perforce Broker, e.g. as
# 'p4 hms status all'.
#
# * Provide a bridge between broker filter scripts command-line parsing of
# stdin, translating that into traditional command line calls.
#
# * Captures stdin, stderr and the exit code of called scripts so they can
# be returned to the user.  This script must always exit with a 1, so the
# exit code of the user is repoted to the user as EXIT_CODE: <N> as the
# last line of output.
# 
# This simplifies development broker-enabled scripts, enabling them to
# be written without being concerned too much about the vagaries of
# broker filter scripts.  There are, however, some restrictions on
# the 'hms' script called by this script:
#
# 1. The output must be devoid of any '"' (double quote) characters.
# 2. The script cannot be interactive in any way.
# 3. The script cannot give real-time progress info to the user.
#    All output is captured, and only when the script exits, the
#    entirety of the output is sent back to the user at once.
# 4. The exit code will be translated to text for the user to see,
#    but cannot be interpreted in anyway.
#
# This scripts job is to build the command line for the 'hms' script,
# call it, and return the output to the user.
#
# The HMS_CALLED_BY_WRAPPER environment variable is set to 1 in this
# script, so that it can be checked by the HMS script.  This allows the
# know when it is being called via the broker (and thus subject to the
# above restrictions) or not.  For example, the hms script may want to
# offer an interactive mode, which cannot be supported when called by
# the broker.
#
# The broker config file should contain the following snippet (uncommented):
#------------------------------------------------------------------------------
# # Implement Helix Management System (hms) commands.
#
# command: ^hms$
# {
#    action  = filter;
#    checkauth = true;
#    execute = /p4/common/hms/scripts/broker_wrapper;
# }
#------------------------------------------------------------------------------

function log () {
   declare message="$*"
   [[ -n "$Log" ]] || return 1
   echo -e "$(date +'%Y/%m/%d %H:%M:%S %Z: ') $message" >> $Log 2>&1
}

declare InputFile=$(mktemp)
declare OutputFile=$(mktemp)
declare Log=${LOGS:-/tmp}/${0##*/}.log
declare User
declare UserHost
declare HMSCmdLine
declare -i LoggedInSuperUser=0
declare -i ExitCode
declare -i ArgCount
declare -i i=0
export HMS_CALLED_BY_WRAPPER=1

# Sample broker input:
#
# message: brokerListenPort: 4737
# brokerTargetPort: 4738
# command: hms
# clientProg: p4
# clientVersion: 2015.2/LINUX26X86_64/1387115
# clientProtocol: 79
# apiProtocol: 99999
# workspace: SDP.waukperforce03
# user: ttyler
# maxPerm: super
# clientIp: 127.0.0.1
# clientHost:
# cwd: /p4/common/bin
# clientPort: 4737
# argCount: 2
# Arg0: status
# Arg1: 1:master

# Load HMS environment.
source /p4/common/bin/p4_vars hms

export HMS_HOME=${HMS_HOME:-/p4/common/hms}

declare Version=1.0.10

# Read from STDIN the input stream provided by the broker.
log "Started parsing broker input."
while read line; do
   echo $line >> $InputFile
   [[ $line == "user: "* ]] && User=${line#user: }

   [[ $line == "maxPerm: super" ]] && LoggedInSuperUser=1

   if [[ $line == "argCount: "* ]]; then
      ArgCount=${line#argCount: }

      if [[ $ArgCount -eq 0 ]]; then
         HMSCmdLine="$P4CBIN/hms -h"
         log "HMSCmdLine=$P4CBIN/hms -h"
      else
         i=0
         HMSCmdLine="$P4CBIN/hms"
         while [[ $i -lt $ArgCount ]]; do
            read line
            log "ARG $i is ${line#Arg*: }"
            HMSCmdLine="$HMSCmdLine ${line#Arg*: }"
            i=$((i+1))
         done
         log "HMSCmdLine=$P4CBIN/hms -h"
      fi
   fi
done

HMSCmdLine=$(echo $HMSCmdLine)

echo "action: REJECT"

if [[ LoggedInSuperUser -eq 1 ]]; then
   $HMSCmdLine > $OutputFile 2>&1
   ExitCode=$?
   echo -e "message: \"$(cat $OutputFile)\nEXIT_CODE: $ExitCode\n\""
else
   echo -e "message: \"\nError: You must be logged in as a super user to run 'hms' commands.\n\""
   ExitCode=1
fi

rm -f $InputFile $OutputFile

# Always exit 1, so the broker won't try to pass commands on to p4d.
exit 1;