| #!/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 <program |
| # name>_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 <program name>_VERSION is blank or not set, then the program version will be whatever the system |
| # default program version is. If <program name>_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 <program |
| # name>_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 |
| |