| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 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 appened 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. | 
|  | 27 | program_name="${0##*/}" | 
|  | 28 | program_uppercase_name=${program_name^^} | 
|  | 29 |  | 
|  | 30 |  | 
|  | 31 | function 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 |  | 
| Michael Walsh | 2bcd654 | 2019-06-24 14:41:10 -0500 | [diff] [blame] | 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 |  | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 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 | 
| Michael Walsh | a607607 | 2019-06-14 13:19:54 -0500 | [diff] [blame] | 117 | # Use exec in order to replace this process with the target process. | 
|  | 118 | exec ${target_program_path} "${@}" | 
| Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 119 | fi | 
|  | 120 |  |