2016-03-05 12:18:48 +00:00
|
|
|
#!/bin/bash
|
2016-05-12 04:22:25 +00:00
|
|
|
#
|
2019-12-31 06:36:56 +00:00
|
|
|
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
|
2018-10-07 20:52:23 +00:00
|
|
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
2016-05-12 04:22:25 +00:00
|
|
|
#
|
2018-10-07 20:52:23 +00:00
|
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
|
2016-03-05 12:18:48 +00:00
|
|
|
#
|
|
|
|
# `sbang`: Run scripts with long shebang lines.
|
|
|
|
#
|
|
|
|
# Many operating systems limit the length of shebang lines, making it
|
|
|
|
# hard to use interpreters that are deep in the directory hierarchy.
|
|
|
|
# `sbang` can run such scripts, either as a shebang interpreter, or
|
|
|
|
# directly on the command line.
|
|
|
|
#
|
|
|
|
# Usage
|
|
|
|
# -----------------------------
|
|
|
|
# Suppose you have a script, long-shebang.sh, like this:
|
|
|
|
#
|
|
|
|
# 1 #!/very/long/path/to/some/interpreter
|
|
|
|
# 2
|
|
|
|
# 3 echo "success!"
|
|
|
|
#
|
|
|
|
# Invoking this script will result in an error on some OS's. On
|
|
|
|
# Linux, you get this:
|
|
|
|
#
|
|
|
|
# $ ./long-shebang.sh
|
|
|
|
# -bash: ./long: /very/long/path/to/some/interp: bad interpreter:
|
|
|
|
# No such file or directory
|
|
|
|
#
|
|
|
|
# On Mac OS X, the system simply assumes the interpreter is the shell
|
|
|
|
# and tries to run with it, which is likely not what you want.
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# `sbang` on the command line
|
|
|
|
# -----------------------------
|
|
|
|
# You can use `sbang` in two ways. The first is to use it directly,
|
|
|
|
# from the command line, like this:
|
|
|
|
#
|
|
|
|
# $ sbang ./long-shebang.sh
|
|
|
|
# success!
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# `sbang` as the interpreter
|
|
|
|
# -----------------------------
|
|
|
|
# You can also use `sbang` *as* the interpreter for your script. Put
|
|
|
|
# `#!/bin/bash /path/to/sbang` on line 1, and move the original
|
|
|
|
# shebang to line 2 of the script:
|
|
|
|
#
|
|
|
|
# 1 #!/bin/bash /path/to/sbang
|
|
|
|
# 2 #!/long/path/to/real/interpreter with arguments
|
|
|
|
# 3
|
|
|
|
# 4 echo "success!"
|
|
|
|
#
|
|
|
|
# $ ./long-shebang.sh
|
|
|
|
# success!
|
|
|
|
#
|
|
|
|
# On Linux, you could shorten line 1 to `#!/path/to/sbang`, but other
|
|
|
|
# operating systems like Mac OS X require the interpreter to be a
|
|
|
|
# binary, so it's best to use `sbang` as a `bash` argument.
|
|
|
|
# Obviously, for this to work, `sbang` needs to have a short enough
|
|
|
|
# path that *it* will run without hitting OS limits.
|
|
|
|
#
|
2020-10-27 05:11:43 +00:00
|
|
|
# For Lua, node, and php scripts, the second line can't start with #!, as
|
|
|
|
# # is not the comment character in these languages (though they all
|
|
|
|
# ignore #! on the *first* line of a script). So, instrument such scripts
|
|
|
|
# like this, using --, //, or <?php ... ?> instead of # on the second
|
|
|
|
# line, e.g.:
|
2016-06-23 07:03:23 +00:00
|
|
|
#
|
|
|
|
# 1 #!/bin/bash /path/to/sbang
|
|
|
|
# 2 --!/long/path/to/lua with arguments
|
2020-10-27 05:11:43 +00:00
|
|
|
# 3 print "success!"
|
|
|
|
#
|
|
|
|
# 1 #!/bin/bash /path/to/sbang
|
|
|
|
# 2 //!/long/path/to/node with arguments
|
|
|
|
# 3 print "success!"
|
|
|
|
#
|
|
|
|
# 1 #!/bin/bash /path/to/sbang
|
|
|
|
# 2 <?php #/long/path/to/php with arguments ?>
|
|
|
|
# 3 <?php echo "success!\n"; ?>
|
2016-03-05 12:18:48 +00:00
|
|
|
#
|
|
|
|
# How it works
|
|
|
|
# -----------------------------
|
|
|
|
# `sbang` is a very simple bash script. It looks at the first two
|
|
|
|
# lines of a script argument and runs the last line starting with
|
|
|
|
# `#!`, with the script as an argument. It also forwards arguments.
|
|
|
|
#
|
|
|
|
|
|
|
|
# First argument is the script we want to actually run.
|
|
|
|
script="$1"
|
|
|
|
|
|
|
|
# Search the first two lines of script for interpreters.
|
|
|
|
lines=0
|
|
|
|
while read line && ((lines < 2)) ; do
|
|
|
|
if [[ "$line" = '#!'* ]]; then
|
|
|
|
interpreter="${line#\#!}"
|
2017-08-18 18:57:52 +00:00
|
|
|
elif [[ "$line" = '//!'*node* ]]; then
|
|
|
|
interpreter="${line#//!}"
|
2016-06-23 07:03:23 +00:00
|
|
|
elif [[ "$line" = '--!'*lua* ]]; then
|
|
|
|
interpreter="${line#--!}"
|
2020-10-27 05:11:43 +00:00
|
|
|
elif [[ "$line" = '<?php #!'*php* ]]; then
|
|
|
|
interpreter="${line#<?php\ \#!}"
|
|
|
|
interpreter="${interpreter%\ ?>}"
|
2016-03-05 12:18:48 +00:00
|
|
|
fi
|
|
|
|
lines=$((lines+1))
|
|
|
|
done < "$script"
|
2017-06-14 18:24:01 +00:00
|
|
|
# this is ineeded for scripts with sbang parameter
|
|
|
|
# like ones in intltool
|
|
|
|
# #!/<spack-long-path>/perl -w
|
|
|
|
# this is the interpreter line with all the parameters as a vector
|
|
|
|
interpreter_v=(${interpreter})
|
2020-10-27 05:11:43 +00:00
|
|
|
# this is the single interpreter path
|
2017-06-14 18:24:01 +00:00
|
|
|
interpreter_f="${interpreter_v[0]}"
|
2016-03-05 12:18:48 +00:00
|
|
|
|
|
|
|
# Invoke any interpreter found, or raise an error if none was found.
|
2017-06-14 18:24:01 +00:00
|
|
|
if [[ -n "$interpreter_f" ]]; then
|
2020-01-16 09:34:02 +00:00
|
|
|
if [[ "${interpreter_f##*/}" = "perl"* ]]; then
|
|
|
|
exec $interpreter -x "$@"
|
2016-09-22 07:43:47 +00:00
|
|
|
else
|
2020-01-16 09:34:02 +00:00
|
|
|
exec $interpreter "$@"
|
2016-09-22 07:43:47 +00:00
|
|
|
fi
|
2016-03-05 12:18:48 +00:00
|
|
|
else
|
|
|
|
echo "error: sbang found no interpreter in $script"
|
|
|
|
exit 1
|
|
|
|
fi
|