#!/bin/sh

VERSION="2.1"
# this is used to enter containerised environment
PROGCHROOT="${PROGCHROOT:-sudo chroot}"
# this is used inside container to switch to plain user.
# needed with plain chroot
PROGSU="${PROGSU:-/usr/bin/sudo}"

print_help()
{
    printf "%s\n" "
Usage:
anch COMMAND PROFID [options]
anch COMMAND PROFID OBJECTS [options]
anch COMMAND PROFID OBJECTS METHODS [options]

This executable enters the chroot in current working directory
and launches the any(1) with all given parameters.
See \"man any-do\", \"man any\" or \"any --help\" for descriptions
of actual build work.
"
}


case "$1" in
    --help)
            print_help
            exit 0
        ;;
    --version)
            printf "%s\n" "${VERSION}"
            exit 0
        ;;
esac

work_dir="$(rootrdd)"

if test -z "${work_dir}" ; then
    printf "%s\n" "
    Root of working directory has not been set.
    Executable \"rootrdd\" is unavailable,
    or there are troubles with current directory (does it exist?)"
    exit 1
fi

if ! test -x "${work_dir}/rrr/bin/any" ; then
    printf "%s\n" "
    Working directory hasn't executable file \"${work_dir}/rrr/bin/any\".
    That file is actually performing anch task.
    Check correctness of working directory and any-engine installation into it."
    exit 2
fi

# -----------------------------
# find the executable command.
# it can be installed into limited locations: ./any or ./rrr

# we could avoid the search and just call 'any' inside chroot - that's straightforward.
# But we need to load shell environment now to get info about directories for binding.
# to load shell we need to get right arguments from cmd, and that requires search for command already here

command=
for local_commands in "${work_dir}/any/libexec" "${work_dir}/rrr/bin" "${work_dir}/rrr/libexec" ; do
    # note name 'any' instead of '$0', as $0 contains 'anch'
    command="$( subcom -p "${local_commands}" "any" "$@" 2> /dev/null )"
    if test -n "${command}" ; then
        args_command="$(subcom -p "${local_commands}" -s "any" "$@")"
        break
    fi
done
if test -z "${command}" ; then
    printf "%s\n" "No proper command for anch was found."
    print_help
    exit 1
fi

# after that cmd ${@} will contain arguments without command, and we can use *rdd tools
for arg in ${args_command} ; do
    shift
done

#path to found command inside chroot
command_chrooted="${command#${work_dir}}"

# -----------------------------
# prepare the chroot environment for work

if test -x "${work_dir}/any/bin/dobefore" ; then
    WORKDIR="${work_dir}" "${work_dir}/any/bin/dobefore" "${command}" "${@}"
fi

if test -x "${work_dir}/any/bin/enter" ; then
    ${PROGCHROOT} \
        "${work_dir}" \
        /any/bin/enter \
        "${command_chrooted}" \
        "${@}"
fi

# -----------------------------
# bind outer directories into sandbox, if needed

eval "$(dumprdd "${@}" rdd_prf_id="output" )"
if test -z "${ANYAPI}" ; then
    printf "%s\n" "
Failed to init shell environment, needed for command execution.
The command must be launched within working directory.
Check your cmd arguments and correctness of data.
Check your dumprdd executable as well.
"
    exit 2
fi

if test -d "${any_pkg}" ; then
    pack_dir="$(cd ${any_pkg} ; pwd -P)"
    bind=
    if test "${bool_SANDBOX}" = 1 ; then
        # for some reason we are inside sandbox already.
        # no binding and path is unchanged
        bind=
    elif test "${pack_dir}" != "${pack_dir#${BASEDIR}}" ; then
        # pack_dir is subdirectory of BASEDIR, no need to bind
        bind=
        # we should edit the path, so it would match inside sandbox
        pack_dir="${pack_dir#${BASEDIR}}"
        pack_dir="/${pack_dir}"
    elif test "${any_mountbind}" = 1 ; then
        # we need to bind and the support for that is declared by option any_mountbind
        bind=1
        # create new directory, visible inside sandbox
        tmpmnt="$(od -An -N16 -tx1 /dev/urandom | tr -d ' ')"
        mkdir -p "${BASEDIR}var/mnt-${tmpmnt}"
        sudo umount -l "${BASEDIR}var/mnt-${tmpmnt}" 2> /dev/null || true
        sudo mount -o ro,bind "${pack_dir}" "${BASEDIR}var/mnt-${tmpmnt}"
        # we are out of sandbox
        # path for pkg_deploy must be from inside sandbox
        # so not adding ${BASEDIR}
        pack_dir="/var/mnt-${tmpmnt}"
    else
        printf "%s\n" "
Path in any_pkg points out of working directory, so it will not be available inside a sandbox.
No support of binding in mount command is declared (any_mountbind is not set to 1).
Change the path in any_pkg or set up any_mountbind=1, if your 'mount' command supports
'-o bind' option.
"
        exit 3
    fi
fi
if test -z "${pack_dir}" ; then
    # use original value, if new value is absent
    pack_dir="${any_pkg}"
fi

# ------------------------------

stay_group="$(id -g)"
stay_user="$(id -u)"

sustring=
if test -x "${work_dir}${PROGSU}" ; then
    sustring="${PROGSU} -u $(id -un)"
fi
${PROGCHROOT} \
    "${work_dir}" \
     ${sustring} \
    /rrr/bin/chrootenv \
    "${command_chrooted}" \
    "${@}" \
    any_pkg="${pack_dir}" \
    any_out_basedir="${work_dir}" \
    any_admin_groupid="${stay_group}" \
    any_admin_userid="${stay_user}"

if test "${bind}" = 1 ; then
    sudo umount -l "${BASEDIR}var/mnt-${tmpmnt}" 2> /dev/null || true
    rmdir "${BASEDIR}var/mnt-${tmpmnt}"
fi

if test -x "${work_dir}/any/bin/doafter" ; then
    WORKDIR="${work_dir}" "${work_dir}/any/bin/doafter" "${command}" "${@}"
fi
