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 |
Gunnar Mills | acc7c56 | 2019-08-20 13:12:46 -0500 | [diff] [blame] | 20 | # name>_VERSION is set to a value, then that value will be appended to the name |
Michael Walsh | ae96c5e | 2019-05-29 17:19:44 -0500 | [diff] [blame] | 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 | |