diff --git a/makeself-header.sh b/makeself-header.sh index 53e3577..b991a5a 100755 --- a/makeself-header.sh +++ b/makeself-header.sh @@ -24,6 +24,14 @@ scriptargs="$SCRIPTARGS" cleanup_script="${CLEANUP_SCRIPT}" licensetxt="$LICENSE" helpheader="${HELPHEADER}" +preextract=' +EOF +if test -n "${PREEXTRACT_FILE}"; then + sed -e "s/['\\]/\\\\&/g" "${PREEXTRACT_FILE}" >> "$archname" +fi +cat << EOF >> "$archname" +' +preextract="\${preextract#?}"; preextract="\${preextract%?}" # trim redundant newlines targetdir="$archdirname" filesizes="$filesizes" totalsize="$totalsize" @@ -164,7 +172,8 @@ Makeself version $MS_VERSION \$0 --lsm Print embedded lsm entry (or no LSM) \$0 --list Print the list of files in the archive \$0 --check Checks integrity of the archive - \$0 --verify-sig key Verify signature agains a provided key id + \$0 --verify-sig key Verify signature against a provided key id + \$0 --show-preextract Print pre-extraction script 2) Running \$0 : \$0 [options] [--] [additional arguments to embedded script] @@ -305,6 +314,31 @@ MS_Check() fi } +MS_Preextract() +{ + if test -z "\$preextract"; then + return + elif test x"\$verbose" = xy; then + MS_Printf "About to run pre-extraction script ... Proceed ? [Y/n] " + read yn + if test x"\$yn" = xn; then + eval \$finish; exit 1 + fi + fi + + prescript=\`mktemp -t XXXXX -p "\$tmpdir"\` + echo "\$preextract" > "\$prescript" + chmod a+x "\$prescript" + + (cd "\$tmpdir"; eval "\"\$prescript\" \$scriptargs \"\\\$@\""); res=\$? + + rm -f "\$prescript" + if test \$res -ne 0; then + echo "Pre-extraction script returned an error code (\$res)" >&2 + eval \$finish; exit 1 + fi +} + MS_Decompress() { if test x"\$decrypt_cmd" != x""; then @@ -456,6 +490,14 @@ EOLSM shift 2 || { MS_Help; exit 1; } MS_Verify_Sig "\$0" ;; + --show-preextract) + if test -z "\$preextract"; then + echo "Pre-extraction script is not provided." >&2 + exit 1 + fi + echo "\$preextract" + exit 0 + ;; --confirm) verbose=y shift @@ -463,6 +505,7 @@ EOLSM --noexec) script="" cleanup_script="" + preextract="" shift ;; --noexec-cleanup) @@ -623,6 +666,8 @@ if test x"\$SETUP_NOCHECK" != x1; then fi offset=\`head -n "\$skip" "\$0" | wc -c | sed "s/ //g"\` +MS_Preextract "\$@" + if test x"\$verbose" = xy; then MS_Printf "About to extract $USIZE KB in \$tmpdir ... Proceed ? [Y/n] " read yn diff --git a/makeself.1 b/makeself.1 index be84973..3d1557d 100644 --- a/makeself.1 +++ b/makeself.1 @@ -105,6 +105,9 @@ Specify location of the header script. .B --help-header file Add a header to the archive's help output. .TP +.B --preextract file +Specify a pre-extraction script. +.TP .B --cleanup file Specify a cleanup script that executes on interrupt and when finished successfully. .TP diff --git a/makeself.sh b/makeself.sh index 0efcef8..f3d87d8 100755 --- a/makeself.sh +++ b/makeself.sh @@ -93,6 +93,7 @@ MS_Usage() echo " --nocrc : Don't calculate a CRC for archive" echo " --sha256 : Compute a SHA256 checksum for the archive" echo " --header file : Specify location of the header script" + echo " --preextract file : Specify a pre-extraction script" echo " --cleanup file : Specify a cleanup script that executes on interrupt and when finished successfully." echo " --follow : Follow the symlinks in the archive" echo " --noprogress : Do not show the progress during the decompression" @@ -311,6 +312,11 @@ do HEADER="$2" shift 2 || { MS_Usage; exit 1; } ;; + --preextract) + PREEXTRACT_FILE="$2" + shift 2 || { MS_Usage; exit 1; } + test -r "$PREEXTRACT_FILE" || { echo "Unable to open pre-extraction script: $PREEXTRACT_FILE" >&2; exit 1; } + ;; --cleanup) CLEANUP_SCRIPT="$2" shift 2 || { MS_Usage; exit 1; } diff --git a/test/preextracttest b/test/preextracttest new file mode 100755 index 0000000..b8453b5 --- /dev/null +++ b/test/preextracttest @@ -0,0 +1,98 @@ +#!/bin/bash +set -eu +THIS="$(readlink -f "$0")" +THISDIR="$(dirname "${THIS}")" +SUT="$(dirname "${THISDIR}")/makeself.sh" + +setUp() { + temp=$(mktemp -d -t XXXXX) + pushd "${temp}" + mkdir src + echo "echo This is a test" > src/startup.sh + chmod a+x src/startup.sh +} + +tearDown() { + popd + rm -rf "${temp}" +} + +testPreextractOpts() { + echo 'echo A complex pre-extraction script. + sleep 99 & + cat a.txt 2>/dev/null || cat b.txt && cat c.txt + echo "$$ Some\toutput\n\a\b\0777 $var1 ${var2} `cat var3.txt` $(env)" > text.txt + ' > preextract.sh + + ${SUT} --nox11 --preextract preextract.sh src src.sh alabel ./startup.sh + assertEquals 0 $? + + ./src.sh --show-preextract > show-preextract.out + assertEquals 0 $? + + diff preextract.sh show-preextract.out + assertEquals 0 $? +} + +testWithNoPreextractOpts() { + ${SUT} src src.sh alabel ./startup.sh + assertEquals 0 $? + + ./src.sh --show-preextract + assertEquals 1 $? +} + +testPreextractRun() { + echo 'echo Validating provided options...' > preextract.sh + ${SUT} --nox11 --preextract preextract.sh src src.sh alabel ./startup.sh + assertEquals 0 $? + + ./src.sh + assertEquals 0 $? + + ./src.sh | grep -qF 'Validating provided options...' + assertEquals 0 $? +} + +testPreextractNoexec() { + echo 'exit 2' > preextract.sh + ${SUT} --preextract preextract.sh src src.sh alabel ./startup.sh + assertEquals 0 $? + + ./src.sh + assertEquals 1 $? + + ./src.sh --noexec + assertEquals 0 $? +} + +testPreextractArgs() { + echo 'echo $*' > preextract.sh + ${SUT} --nox11 --preextract preextract.sh src src.sh alabel ./startup.sh --logdir /var/log + assertEquals 0 $? + + test_cmd='./src.sh -- --env dev' + + eval "${test_cmd}" + assertEquals 0 $? + + eval "${test_cmd}" | grep -qF -- '--logdir /var/log --env dev' + assertEquals 0 $? +} + +testPreextractEnvPassing() { + # imitate user input + echo 'echo "export INSTALLATION_DIR=/usr/bin" > preextract.env' > preextract.sh + echo '. ./preextract.env; echo $INSTALLATION_DIR' > src/startup.sh + ${SUT} --nox11 --preextract preextract.sh src src.sh alabel ./startup.sh + assertEquals 0 $? + + ./src.sh + assertEquals 0 $? + + ./src.sh | grep -qF '/usr/bin' + assertEquals 0 $? +} + +# Load and run shUnit2. +source "./shunit2/shunit2"