| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 1 | #!/bin/bash | 
 | 2 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 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. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 6 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 7 | # Users would be expected to create a link with the base name of the program that points to this file. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 8 |  | 
 | 9 | # Example: | 
 | 10 | # cd openbmc-test-automation/bin | 
 | 11 | # ln -s select_version python | 
 | 12 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 13 | # The PATH variable should contain the expanded path to openbmc-test-automation/bin. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 14 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 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. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 20 |  | 
 | 21 |  | 
 | 22 | # Make sure program_name is set. | 
 | 23 | program_name="${0##*/}" | 
 | 24 | program_uppercase_name=${program_name^^} | 
 | 25 |  | 
 | 26 |  | 
 | 27 | function get_target_program_path { | 
 | 28 |   local target_program_path_var="${1:-target_program_path}" ; shift | 
 | 29 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 30 |   # Get the full path to the "real" program and assign it to the variable named in target_program_path_var. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 31 |  | 
 | 32 |   # Description of argument(s): | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 33 |   # target_program_path_var         The name of the variable to receive the result. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 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 | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 49 |   # That being the case, get the name of this actual program (rather than the name of the link to it). | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 50 |   base_program_path=$(readlink -f "${0}") | 
 | 51 |   base_program_name=${base_program_path##*/} | 
 | 52 |  | 
| Michael Walsh | 2bcd654 | 2019-06-24 14:41:10 -0500 | [diff] [blame] | 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 |  | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 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 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 66 |   # Now use the "type" built-in to search the PATH variable for a list of target program candidates. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 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 | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 74 |   # /home/robot/openbmc-test-automation/bin/select_version.  As such it will be rejected. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 75 |  | 
 | 76 |   for candidate in ${candidates} | 
 | 77 |   do | 
 | 78 |     if [ -L "${candidate}" ] ; then | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 79 |       # The candidate is a link so we need to see if it's a link to this program file. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 80 |       base_file_path=$(readlink "${candidate}") | 
 | 81 |       [ "${base_file_path}" == "${base_program_name}" ] && continue | 
 | 82 |     fi | 
 | 83 |  | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 84 |     # The candidate is NOT a link so it qualifies as the desired target program path. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 85 |     eval ${target_program_path_var}=\"\${candidate}\" | 
 | 86 |     return | 
 | 87 |  | 
 | 88 |   done | 
 | 89 |  | 
 | 90 | } | 
 | 91 |  | 
 | 92 |  | 
 | 93 | # Main | 
 | 94 |  | 
 | 95 |   get_target_program_path target_program_path | 
 | 96 |  | 
 | 97 |   # Compose program path var name (e.g. PYTHON_PGM_PATH). | 
 | 98 |   pgm_path_var_name=${program_uppercase_name}_PGM_PATH | 
| Michael Walsh | 410b178 | 2019-10-22 15:56:18 -0500 | [diff] [blame] | 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. | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 101 |   eval export ${pgm_path_var_name}=${target_program_path} | 
 | 102 |  | 
 | 103 |   if [ "${1}" == "--print_only" ] ; then | 
 | 104 |     echo "${target_program_path}" | 
 | 105 |   else | 
| Michael Walsh | a607607 | 2019-06-14 13:19:54 -0500 | [diff] [blame] | 106 |     # Use exec in order to replace this process with the target process. | 
 | 107 |     exec ${target_program_path} "${@}" | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 108 |   fi | 
 | 109 |  |