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