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