#!/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: 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;