diff options
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/sbang | 110 |
1 files changed, 15 insertions, 95 deletions
@@ -1,7 +1,7 @@ #!/bin/sh # # Copyright 2013-2020 Lawrence Livermore National Security, LLC and other -# Spack Project Developers. See the top-level COPYRIGHT file for details. +# sbang project developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) @@ -12,85 +12,16 @@ # arguments in shebang lines, making it hard to use interpreters that are # deep in the directory hierarchy or require special arguments. # -# `sbang` can run such scripts, either as a shebang interpreter, or -# directly on the command line. +# To use, put the long shebang on the second line of your script, and +# make sbang the interpreter, like this: # -# Usage -# ----- -# Suppose you have a script, long-shebang.sh, like this: +# #!/bin/sh /path/to/sbang +# #!/long/path/to/real/interpreter with arguments # -# 1 #!/very/long/path/to/some/interp -# 2 -# 3 echo "success!" +# `sbang` will run the real interpreter with the script as its argument. # -# Invoking this script will result in an error on some OS's. On -# Linux, you get this: +# See https://github.com/spack/sbang for more details. # -# $ ./longshebang.sh -# -bash: ./longshebang.sh: /very/long/path/to/some/interp: bad interpreter: -# No such file or directory -# -# On macOS, the system simply assumes the interpreter is the shell and -# tries to run with it, which is not likely 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/sh /path/to/sbang` on line 1, and move the original -# shebang to line 2 of the script: -# -# 1 #!/bin/sh /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 an argument to `/bin/sh`. Obviously, for -# this to work, `sbang` needs to have a short enough path that *it* will -# run without hitting OS limits. -# -# 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.: -# -# 1 #!/bin/sh /path/to/sbang -# 2 --!/long/path/to/lua with arguments -# 3 print "success!" -# -# 1 #!/bin/sh /path/to/sbang -# 2 //!/long/path/to/node with arguments -# 3 print "success!" -# -# 1 #!/bin/sh /path/to/sbang -# 2 <?php #/long/path/to/php with arguments ?> -# 3 <?php echo "success!\n"; ?> -# -# How it works -# ------------ -# `sbang` is a very simple posix shell 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. -# - -# We disable two shellcheck errors below: -# SC2124: when saving arguments, we intentionally assign as an array -# SC2086: when splitting $shebang_line and exec args, we want to expand args # Generic error handling die() { @@ -130,27 +61,16 @@ while read -r line && [ $lines -ne 2 ]; do lines=$((lines+1)) done < "$script" -# shellcheck disable=SC2124 -# this saves arguments for later and intentionally assigns as an array -args="$@" - -# handle scripts with sbang parameters, e.g.: -# -# #!/<spack-long-path>/perl -w -# -# put the shebang line with all the parameters in the $@ array and get -# the first element. -# shellcheck disable=SC2086 -set $shebang_line -set -- "$@" -interpreter="$1" -arg1="$2" - # error if we did not find any interpreter -if [ -z "$interpreter" ]; then +if [ -z "$shebang_line" ]; then die "error: sbang found no interpreter in $script" fi +# parse out the interpreter and first argument +IFS=' ' read -r interpreter arg1 rest <<EOF +$shebang_line +EOF + # Determine if the interpreter is a particular program, accounting for the # '#!/usr/bin/env PROGRAM' convention. So: # @@ -176,8 +96,8 @@ fi # if interpreter_is perl || interpreter_is ruby; then # shellcheck disable=SC2086 - $exec $shebang_line -x "$args" + $exec $shebang_line -x "$@" else # shellcheck disable=SC2086 - $exec $shebang_line "$args" + $exec $shebang_line "$@" fi |