1#!/bin/bash 2 3# This script is a wrapper for programs that may have alternate versions (e.g. python2, python3). This 4# wrapper allows the user to influence the selection of the program version by setting the <program 5# name>_VERSION (e.g. PYTHON_VERSION, ROBOT_VERSION, etc.) environment variable. 6 7# Users would be expected to create a link with the base name of the program that points to this file. 8 9# Example: 10# cd openbmc-test-automation/bin 11# ln -s select_version python 12 13# The PATH variable should contain the expanded path to openbmc-test-automation/bin. 14 15# If <program name>_VERSION is blank or not set, then the program version will be whatever the system 16# default program version is. If <program name>_VERSION is set to a value, then that value will be appended 17# to the name of the program (e.g. if PYTHON_VERSION = "3", then python3 will be used.). If <program 18# name>_VERSION is set to some value that does not correspond to a valid program version for the given 19# system, this program will fail. 20 21 22# Make sure program_name is set. 23program_name="${0##*/}" 24program_uppercase_name=${program_name^^} 25 26 27function get_target_program_path() { 28 local target_program_path_var="${1:-target_program_path}" ; shift 29 30 # Get the full path to the "real" program and assign it to the variable named in target_program_path_var. 31 32 # Description of argument(s): 33 # target_program_path_var The name of the variable to receive the result. 34 35 # Example result: 36 37 # /usr/bin/python3 38 39 local version_var_name 40 local alternate_program_name 41 local base_program_path 42 local base_program_name 43 local candidate 44 local candidates 45 local base_file_path 46 47 # The typical use of this program would be to create a link to it like this: 48 # ln -s select_version python 49 # That being the case, get the name of this actual program (rather than the name of the link to it). 50 base_program_path=$(readlink -f "${0}") 51 base_program_name=${base_program_path##*/} 52 53 if [ "${program_name}" == "${base_program_name}" ] ; then 54 { 55 echo -n "**ERROR** ${base_program_name} should never be called directly." 56 echo " Only links to ${base_program_name} should be called." 57 } >&2 58 exit 1 59 fi 60 61 # Compose the version_var_name value (e.g. PYTHON_VERSION). 62 version_var_name=${program_uppercase_name}_VERSION 63 # Compose the alternate_program_name (e.g. python3). 64 alternate_program_name=${program_name}${!version_var_name} 65 66 # Now use the "type" built-in to search the PATH variable for a list of target program candidates. 67 candidates=$(type -ap ${alternate_program_name}) 68 69 # Example candidates: 70 # /home/robot/openbmc-test-automation/bin/python 71 # /usr/bin/python 72 73 # In this example, the first candidate is actually a link to 74 # /home/robot/openbmc-test-automation/bin/select_version. As such it will be rejected. 75 76 for candidate in ${candidates} 77 do 78 if [ -L "${candidate}" ] ; then 79 # The candidate is a link so we need to see if it's a link to this program file. 80 base_file_path=$(readlink "${candidate}") 81 [ "${base_file_path}" == "${base_program_name}" ] && continue 82 fi 83 84 # The candidate is NOT a link so it qualifies as the desired target program path. 85 eval ${target_program_path_var}=\"\${candidate}\" 86 return 87 88 done 89 90} 91 92 93# Main 94 95get_target_program_path target_program_path 96 97# Compose program path var name (e.g. PYTHON_PGM_PATH). 98pgm_path_var_name=${program_uppercase_name}_PGM_PATH 99# Set and export pgm_path_var_name (e.g. PYTHON_PGM_PATH=/usr/bin/python3). This value can be used by 100# child programs for debug. 101eval export ${pgm_path_var_name}=${target_program_path} 102 103if [ "${1}" == "--print_only" ] ; then 104 echo "${target_program_path}" 105else 106 # Use exec in order to replace this process with the target process. 107 exec ${target_program_path} "${@}" 108fi 109 110