#!/bin/sh # Runs a shell command (or interactive shell) using the binaries and # libraries bundled with this app. # Set this variable when using this script inside a package of git-annex, # which arranges for git-annex, git-annex-shell, and git to all be in the # standard PATH. This also makes the system locales be used. GIT_ANNEX_PACKAGE_INSTALL= set -e orig_IFS="${IFS}" unset IFS os="$(uname -o 2>/dev/null || true)" base="$(dirname "$0")" if [ ! -d "$base" ]; then echo "** cannot find base directory (I seem to be $0)" >&2 exit 1 fi if [ ! -e "$base/bin/git-annex" ]; then echo "** base directory $base does not contain bin/git-annex" >&2 exit 1 fi # Get absolute path to base, to avoid breakage when things change directories. orig="$(pwd)" cd "$base" base="$(pwd)" cd "$orig" # --library-path won't work if $base contains : or ; # Detect this problem, and work around it by using a temp directory. if echo "$base" | grep -q '[:;]'; then tbase=$(mktemp -d -p /tmp annexshimXXXXXXXXX 2>/dev/null || true) if [ -z "$tbase" ]; then tbase="/tmp/annexshim.$$" mkdir "$tbase" fi ln -s "$base" "$tbase/link" base="$tbase/link" cleanuptbase () { rm -rf "$tbase" } trap cleanuptbase EXIT else tbase="" fi if [ -z "$GIT_ANNEX_PACKAGE_INSTALL" ]; then # Install shim that's used to run git-annex-shell from ssh authorized # keys. The assistant also does this when run, but the user may not # be using the assistant. if [ ! -e "$HOME/.ssh/git-annex-shell" ]; then mkdir "$HOME/.ssh" >/dev/null 2>&1 || true if [ -e "$HOME/.ssh" ]; then ( echo "#!/bin/sh" echo "set -e" echo "if [ \"x\$SSH_ORIGINAL_COMMAND\" != \"x\" ]; then" echo "exec '$base/runshell' git-annex-shell -c \"\$SSH_ORIGINAL_COMMAND\"" echo "else" echo "exec '$base/runshell' git-annex-shell -c \"\$@\"" echo "fi" ) > "$HOME/.ssh/git-annex-shell.$$" chmod +x "$HOME/.ssh/git-annex-shell.$$" mv -f "$HOME/.ssh/git-annex-shell.$$" "$HOME/.ssh/git-annex-shell" fi fi # And this shim is used by the webapp when adding a remote ssh server. if [ ! -e "$HOME/.ssh/git-annex-wrapper" ]; then mkdir "$HOME/.ssh" >/dev/null 2>&1 || true if [ -e "$HOME/.ssh" ]; then ( echo "#!/bin/sh" echo "set -e" echo "exec '$base/runshell' \"\$@\"" ) > "$HOME/.ssh/git-annex-wrapper.$$" chmod +x "$HOME/.ssh/git-annex-wrapper.$$" mv -f "$HOME/.ssh/git-annex-wrapper.$$" "$HOME/.ssh/git-annex-wrapper" fi fi fi # Used by git-annex assistant to further install itself. GIT_ANNEX_APP_BASE="$base" export GIT_ANNEX_APP_BASE # Put our binaries first, to avoid issues with out of date or incompatible # system binaries. Extra binaries come after system path. ORIG_PATH="$PATH" export ORIG_PATH PATH="$base/bin:$PATH:$base/extra" export PATH # These env vars are used by the shim wrapper around each binary. for lib in $(cat "$base/libdirs"); do GIT_ANNEX_LD_LIBRARY_PATH="$base/$lib:$GIT_ANNEX_LD_LIBRARY_PATH" done export GIT_ANNEX_LD_LIBRARY_PATH GIT_ANNEX_DIR="$base" export GIT_ANNEX_DIR ORIG_GCONV_PATH="$GCONV_PATH" export ORIG_GCONV_PATH GCONV_PATH="$base/$(cat "$base/gconvdir")" export GCONV_PATH ORIG_GIT_EXEC_PATH="$GIT_EXEC_PATH" export ORIG_GIT_EXEC_PATH GIT_EXEC_PATH="$base/git-core" export GIT_EXEC_PATH ORIG_GIT_TEMPLATE_DIR="$GIT_TEMPLATE_DIR" export ORIG_GIT_TEMPLATE_DIR GIT_TEMPLATE_DIR="$base/templates" export GIT_TEMPLATE_DIR ORIG_MANPATH="$MANPATH" export ORIG_MANPATH MANPATH="$base/usr/share/man:$MANPATH" export MANPATH # LD_PRELOAD may interact badly with the bundled libc and other libraries, # which may have a different subarchitecture than the preloaded library. unset LD_PRELOAD # Avoid using system locales, which may interact badly with bundled libc. # (But if LOCPATH is set, don't override it. ORIG_LOCPATH="$LOCPATH" export ORIG_LOCPATH if [ -z "${LOCPATH+set}" ] && [ -z "$GIT_ANNEX_PACKAGE_INSTALL" ]; then LOCPATH="$HOME/.cache/git-annex/locales/$(cat "$base/buildid")_$(echo "$base" | tr / _ )" # try to generate a short version, if md5sum is available locpathmd5=$( (echo "$LOCPATH" | md5sum | cut -d ' ' -f 1 2>/dev/null) || true) if [ -n "$locpathmd5" ]; then LOCPATH="$HOME/.cache/git-annex/locales/$locpathmd5" fi export LOCPATH # Clean up locale caches when their standalone bundle no longer exists. for localecache in $HOME/.cache/git-annex/locales/*; do cachebase=$(cat "$localecache/base" 2>/dev/null || true) if [ ! -d "$cachebase" ] || ! cmp "$localecache/buildid" "$cachebase/buildid" >/dev/null 2>&1 ; then rm -rf "$localecache" >/dev/null 2>&1 || true fi done if [ ! -d "$LOCPATH" ]; then if ! mkdir -p "$LOCPATH"; then echo "Unable to write to $LOCPATH; can't continue!" >&2 exit 1 fi fi if [ ! -e "$LOCPATH/base" ]; then echo "$base" > "$LOCPATH/base.$$" mv -f "$LOCPATH/base.$$" "$LOCPATH/base" fi # Not using cp to avoid using the one bundled with git-annex # before the environment is set up to run it. if [ ! -e "$LOCPATH/buildid" ]; then cat < "$base/buildid" > "$LOCPATH/buildid.$$" mv -f "$LOCPATH/buildid.$$" "$LOCPATH/buildid" fi # Generate locale definition files for the locales in use, # using the localedef and locale files from the bundle. # Currently only utf-8 locales are handled. lastlocaleenv="" for localeenv in "$LANG" "$LANGUAGE" "$LC_CTYPE" "$LC_NUMERIC" "$LC_TIME" \ "$LC_COLLATE" "$LC_MONETARY" "$LC_MESSAGES" "$LC_PAPER" \ "$LC_NAME" "$LC_ADDRESS" "$LC_TELEPHONE" "$LC_MEASUREMENT" \ "$LC_IDENTIFICATION" "$LC_ALL"; do if [ -n "$localeenv" ] && [ "$localeenv" != "$lastlocaleenv" ]; then lastlocaleenv="$localeenv" if [ ! -d "$LOCPATH/$localeenv" ]; then if [ "${localeenv##[!.]*.}" = "utf8" ] || [ "${localeenv##[!.]*.}" = "UTF-8" ]; then ( rm -rf "$LOCPATH/$localeenv.new.$$" && mkdir -p "$LOCPATH/$localeenv.new.$$" && # cd to $base since localedef reads files from pwd cd "$base" && # Run localedef using the bundled i18n files; # use LANG=C to avoid it reading the system locale archive. I18NPATH="$base/i18n" LANG=C localedef -i "${localeenv%%.*}" -c -f UTF-8 "$LOCPATH/$localeenv.new.$$" && mv "$LOCPATH/$localeenv.new.$$" "$LOCPATH/$localeenv" # In a race, LOCPATH may get created by another process, # in which cache the mv above would put it here. rm -rf "$LOCPATH/$localeenv/$localeenv.new.$$" ) >/dev/null 2>/dev/null || true fi fi fi done fi useproot="" case "$os" in # Make this bundle work well on Android. Android) if [ -e "$base/git" ]; then echo "Running on Android.. Tuning for optimal behavior." >&2 # The bundled git does not work well on sdcard, so delete # it and use termux's git which works better. cd "$base" find . | grep git | grep -v git-annex | grep -v git-remote-tor-annex | grep -v git-remote-gcrypt | xargs rm -rf # Use termux's uname, which knows it's on android, # not the bundled one. rm -f bin/uname # Fix shell scripts to work when run inside proot. termux-fix-shebang bin/* runshell git-annex git-annex-shell git-annex-webapp cd "$orig" # Save the poor Android user the typing. if echo "$SHELL" | grep -q '/bash'; then if ! [ -e "$HOME/.profile" ] || ! grep -q "$base" "$HOME/.profile"; then echo "Adding git-annex to PATH for you, in $HOME/.profile" echo 'PATH=$PATH:'"$base" >> $HOME/.profile fi else echo "To use git-annex, you will need to add $base to your shell's PATH." fi fi # Work around Android 8's seccomp filtering of some crucial # system calls, using termux's version of proot. useproot=1 # Store ssh connection caching sockets outside of sdcard. GIT_ANNEX_SSH_SOCKET_DIR="$TMPDIR" export GIT_ANNEX_SSH_SOCKET_DIR GIT_ANNEX_STANDLONE_ENV="PATH GCONV_PATH MANPATH LOCPATH" export GIT_ANNEX_STANDLONE_ENV ;; *) # Indicate which variables were exported above and should be cleaned # when running non-bundled programs. GIT_ANNEX_STANDLONE_ENV="PATH GCONV_PATH GIT_EXEC_PATH GIT_TEMPLATE_DIR MANPATH LOCPATH" export GIT_ANNEX_STANDLONE_ENV ;; esac if [ "$1" ]; then cmd="$1" shift 1 else cmd=sh fi LD_HWCAP_MASK= export LD_HWCAP_MASK if [ -n "${orig_IFS}" ]; then IFS="${orig_IFS}" export IFS fi if [ -z "$tbase" ]; then if [ "$useproot" ]; then exec proot "$cmd" "$@" else exec "$cmd" "$@" fi else # allow EXIT trap to cleanup if [ "$useproot" ]; then proot "$cmd" "$@" else "$cmd" "$@" fi fi