diff options
author | Tobias Bergkvist <tobias@bergkv.ist> | 2021-06-01 01:02:08 +0200 |
---|---|---|
committer | Tobias Bergkvist <tobias@bergkv.ist> | 2021-06-01 01:02:08 +0200 |
commit | 8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973 (patch) | |
tree | e93ccd3604f6836730d783b220aebd1feafc9d83 /pkgs/build-support/setup-hooks/make-binary-wrapper.sh | |
parent | e8cedf381914d28e162810f567216f8c00f87edc (diff) | |
download | nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.tar nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.tar.gz nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.tar.bz2 nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.tar.lz nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.tar.xz nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.tar.zst nixpkgs-8d2964a8e6ee63c31f54aa408a2ca3a0c4e1b973.zip |
Rename make-c-wrapper.sh to make-binary-wrapper.sh. Refactor to match style of other setup-hooks. Add compilation step with gcc. Embed the entire generated source code into the binary for troubleshooting.
Diffstat (limited to 'pkgs/build-support/setup-hooks/make-binary-wrapper.sh')
-rwxr-xr-x | pkgs/build-support/setup-hooks/make-binary-wrapper.sh | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/pkgs/build-support/setup-hooks/make-binary-wrapper.sh b/pkgs/build-support/setup-hooks/make-binary-wrapper.sh new file mode 100755 index 00000000000..b77aca60a01 --- /dev/null +++ b/pkgs/build-support/setup-hooks/make-binary-wrapper.sh @@ -0,0 +1,108 @@ +# Generate a binary executable wrapper for wrapping an executable. +# The binary is compiled from generated C-code using gcc. +# makeBinaryWrapper EXECUTABLE OUT_PATH ARGS + +# ARGS: +# --argv0 NAME : set name of executed process to NAME +# (defaults to EXECUTABLE) +# --set VAR VAL : add VAR with value VAL to the executable’s +# environment +# --set-default VAR VAL : like --set, but only adds VAR if not already set in +# the environment +# --unset VAR : remove VAR from the environment +# +# To troubleshoot a binary wrapper after you compiled it, +# use the `strings` command or open the binary file in a text editor. +makeBinaryWrapper() { + makeDocumentedCWrapper "$1" "${@:3}" | gcc -x c -o "$2" - +} + +# Generate source code for the wrapper in such a way that the wrapper source code +# will still be readable even after compilation +# makeDocumentedCWrapper EXECUTABLE ARGS +# ARGS: same as makeBinaryWrapper +makeDocumentedCWrapper() { + local src=$(makeCWrapper "$@") + local docs=$(documentationString "$src") + printf "%s\n" "$src" + printf "\n%s\n" "$docs" +} + +# makeCWrapper EXECUTABLE ARGS +# ARGS: same as makeBinaryWrapper +makeCWrapper() { + local argv0 n params cmd + local executable=$(escapeStringLiteral "$1") + local params=("$@") + + printf "%s\n" "#include <unistd.h>" + printf "%s\n" "#include <stdlib.h>" + printf "\n%s\n" "int main(int argc, char **argv) {" + + for ((n = 1; n < ${#params[*]}; n += 1)); do + p="${params[$n]}" + if [[ "$p" == "--set" ]]; then + cmd=$(setEnv "${params[$((n + 1))]}" "${params[$((n + 2))]}") + n=$((n + 2)) + printf "%s\n" " $cmd" + elif [[ "$p" == "--set-default" ]]; then + cmd=$(setDefaultEnv "${params[$((n + 1))]}" "${params[$((n + 2))]}") + n=$((n + 2)) + printf "%s\n" " $cmd" + elif [[ "$p" == "--unset" ]]; then + cmd=$(unsetEnv "${params[$((n + 1))]}") + printf "%s\n" " $cmd" + n=$((n + 1)) + elif [[ "$p" == "--argv0" ]]; then + argv0=$(escapeStringLiteral "${params[$((n + 1))]}") + n=$((n + 1)) + else + # Using an error macro, we will make sure the compiler gives an understandable error message + printf "%s\n" " #error makeCWrapper did not understand argument ${p}" + fi + done + + printf "%s\n" " argv[0] = \"${argv0:-${executable}}\";" + printf "%s\n" " return execv(\"${executable}\", argv);" + printf "%s\n" "}" +} + +# setEnv KEY VALUE +setEnv() { + local key=$(escapeStringLiteral "$1") + local value=$(escapeStringLiteral "$2") + printf "%s" "putenv(\"${key}=${value}\");" +} + +# setDefaultEnv KEY VALUE +setDefaultEnv() { + local key=$(escapeStringLiteral "$1") + local value=$(escapeStringLiteral "$2") + printf "%s" "setenv(\"$key\", \"$value\", 0);" +} + +# unsetEnv KEY +unsetEnv() { + local key=$(escapeStringLiteral "$1") + printf "%s" "unsetenv(\"$key\");" +} + +# Put the entire source code into const char* SOURCE_CODE to make it readable after compilation. +# documentationString SOURCE_CODE +documentationString() { + local docs=$(escapeStringLiteral $'\n----------\n// This binary wrapper was compiled from the following generated C-code:\n'"$1"$'\n----------\n') + printf "%s" "const char * SOURCE_CODE = \"$docs\";" +} + +# Makes it safe to insert STRING within quotes in a C String Literal. +# escapeStringLiteral STRING +escapeStringLiteral() { + local result + result=${1//$'\\'/$'\\\\'} + result=${result//\"/'\"'} + result=${result//$'\n'/"\n"} + result=${result//$'\r'/"\r"} + printf "%s" "$result" +} + +makeBinaryWrapper "$@" |