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