#!/bin/bash # This script is a wrapper for programs that may have alternate versions # (e.g. python2, python3). This wrapper allows the user to influence the # selection of the program version by setting the _VERSION (e.g. # PYTHON_VERSION, ROBOT_VERSION, etc.) environment variable. # Users would be expected to create a link with the base name of the program # that points to this file. # Example: # cd openbmc-test-automation/bin # ln -s select_version python # The PATH variable should contain the expanded path to # openbmc-test-automation/bin. # If _VERSION is blank or not set, then the program version # will be whatever the system default program version is. If _VERSION is set to a value, then that value will be appended to the name # of the program (e.g. if PYTHON_VERSION = "3", then python3 will be used.). # If _VERSION is set to some value that does not correspond to a # valid program version for the given system, this program will fail. # Make sure program_name is set. program_name="${0##*/}" program_uppercase_name=${program_name^^} function get_target_program_path { local target_program_path_var="${1:-target_program_path}" ; shift # Get the full path to the "real" program and assign it to the variable # named in target_program_path_var. # Description of argument(s): # target_program_path_var The name of the variable to receive the # result. # Example result: # /usr/bin/python3 local version_var_name local alternate_program_name local base_program_path local base_program_name local candidate local candidates local base_file_path # The typical use of this program would be to create a link to it like this: # ln -s select_version python # That being the case, get the name of this actual program (rather than the # name of the link to it). base_program_path=$(readlink -f "${0}") base_program_name=${base_program_path##*/} if [ "${program_name}" == "${base_program_name}" ] ; then { echo -n "**ERROR** ${base_program_name} should never be called directly." echo " Only links to ${base_program_name} should be called." } >&2 exit 1 fi # Compose the version_var_name value (e.g. PYTHON_VERSION). version_var_name=${program_uppercase_name}_VERSION # Compose the alternate_program_name (e.g. python3). alternate_program_name=${program_name}${!version_var_name} # Now use the "type" built-in to search the PATH variable for a list of # target program candidates. candidates=$(type -ap ${alternate_program_name}) # Example candidates: # /home/robot/openbmc-test-automation/bin/python # /usr/bin/python # In this example, the first candidate is actually a link to # /home/robot/openbmc-test-automation/bin/select_version. As such it will # be rejected. for candidate in ${candidates} do if [ -L "${candidate}" ] ; then # The candidate is a link so we need to see if it's a link to this # program file. base_file_path=$(readlink "${candidate}") [ "${base_file_path}" == "${base_program_name}" ] && continue fi # The candidate is NOT a link so it qualifies as the desired target # program path. eval ${target_program_path_var}=\"\${candidate}\" return done } # Main get_target_program_path target_program_path # Compose program path var name (e.g. PYTHON_PGM_PATH). pgm_path_var_name=${program_uppercase_name}_PGM_PATH # Set and export pgm_path_var_name (e.g. PYTHON_PGM_PATH=/usr/bin/python3). # This value can be used by child programs for debug. eval export ${pgm_path_var_name}=${target_program_path} if [ "${1}" == "--print_only" ] ; then echo "${target_program_path}" else # Use exec in order to replace this process with the target process. exec ${target_program_path} "${@}" fi