aboutsummaryrefslogtreecommitdiff
path: root/shar.sh
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2017-03-31 08:28:10 +0200
committerMarc André Tanner <mat@brain-dump.org>2017-03-31 09:32:42 +0200
commitda4e2efb9249cb8cd1e382a7653da0140bb1c95d (patch)
treee1a3af0838317dca1de73d2d069d8d6e4bbac5fe /shar.sh
parent12f50c8b515642d2510364115778ef90a26ebcb7 (diff)
downloadvis-da4e2efb9249cb8cd1e382a7653da0140bb1c95d.tar.gz
vis-da4e2efb9249cb8cd1e382a7653da0140bb1c95d.tar.xz
Use a minimal POSIX shar implementation for self extracting executable
This only requires POSIX shell utilies for extraction. The resulting archive is bigger (it is not gzip compressed) and startup will be slower due to many spawned processes.
Diffstat (limited to 'shar.sh')
-rwxr-xr-xshar.sh120
1 files changed, 120 insertions, 0 deletions
diff --git a/shar.sh b/shar.sh
new file mode 100755
index 0000000..c7a532c
--- /dev/null
+++ b/shar.sh
@@ -0,0 +1,120 @@
+#!/bin/sh
+# Modified version of https://shiz.me/junk/code/fun/shar.sh
+# The generated shell archive is automatically extracted to a
+# temporary directory and the first archive member is executed.
+set -e
+
+if test $# -lt 2 ; then
+ echo "usage: $0 <output> <files>"
+ exit 1
+fi
+
+save() {
+ for i ; do
+ printf "%s\n" "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
+ done
+ echo " "
+}
+
+octal_mode() {
+ local mode
+
+ mode="$(ls -ld "$1" | awk '{ print $1 }' | tr '[A-Z]' '-' | cut -c2-)"
+ for i in 1 2 3 ; do
+ i=0
+ case "$mode" in r??*) i=$((i + 4)) ;; esac
+ case "$mode" in ?w?*) i=$((i + 2)) ;; esac
+ case "$mode" in ??-*) ;; ???*) i=$((i + 1)) ;; esac
+ printf "%d" "$i"
+ mode=$(echo "$mode" | cut -c4-)
+ done
+}
+
+out=$1
+tmpout=$1.tmp
+exe=$2
+shift
+
+rm -f "$tmpout"
+for f ; do
+ if test -f "$f" ; then
+ cat "$f" >> "$tmpout"
+ fi
+done
+trap 'rm "$tmpout"' EXIT
+
+clear=
+
+for f ; do
+ if test -z "$clear" ; then
+ set --
+ clear=1
+ fi
+
+ mode=$(octal_mode "$f")
+ if test -f "$f" ; then
+ size=$(wc -c "$f" | awk '{ print $1 }')
+ echo "adding: $f (mode $mode, $size bytes)"
+ set -- "$@" "f+$mode+$size:$f"
+ elif test -d "$f" ; then
+ echo "adding directory: $f (mode $mode)"
+ set -- "$@" "d+$mode:$f"
+ else
+ echo "can't add unknown file type $f" >&2
+ fi
+done
+
+cat >"$out"<<HEADER
+#!/bin/sh
+set -e
+
+outdir="\$(mktemp -d -p "\${TMPDIR:-/tmp}" .unshar-XXXXXX)"
+if test \$? -ne 0 -o ! -d "\$outdir" ; then
+ echo "failed to create temporary directory"
+ exit 1
+fi
+trap 'rm -rf "\$outdir"' EXIT INT QUIT TERM HUP
+argc=\$#
+
+self="\$0"
+set -- $(save "$@") "\$@"
+
+exec 3<"\$self"
+while read -r l ; do
+ test "\$l" = "exit 0;" && break
+done <&3
+
+while test \$# -gt \$argc ; do
+ file="\$1"
+ shift
+ meta="\${file%%:*}"
+ fn="\${file#*:}"
+ type="\${meta%%+*}"
+ meta="\${meta#*+}"
+ mode="\${meta%%+*}"
+ size="\${meta#*+}"
+ base="\${fn%/*}"
+
+ case "\$type" in
+ f)
+ echo "unpacking: \$fn (mode \$mode, \$size bytes)"
+ test "\$base" != "\$fn" && mkdir -p "\$outdir/\$base"
+ dd of="\$outdir/\$fn" bs="\$size" count=1 >/dev/null <&3
+ ;;
+ d)
+ echo "creating: \$fn (mode \$mode)"
+ mkdir -p "\$outdir/\$fn"
+ ;;
+ esac
+ chmod "\$mode" "\$outdir/\$fn" || :
+done >/dev/null 2>&1
+
+PATH="\$outdir:\$PATH" "\$outdir/$exe" "\$@"
+exit \$?
+
+exit 0;
+HEADER
+
+cat "$tmpout" >> "$out"
+chmod +x "$out"
+