#!/bin/bash
# minimal config version
MIN_VERSION="3.0"

# Run with tee
if echo "$@" |grep -Eqw '\-v|--verbose' && [ "$1" != 'RESTARTED' ]; then
	# set dir or filename for full log of notamock (with key -v) by environment
	VLOGD=$(realpath ${VLOGD:-./})
	VLOG=${VLOG:-${VLOGD}/$(basename $0)-$(date +%H%M%S).log}
	mkdir -p $(dirname $VLOG)
	date > $VLOG
	echo "==> $(basename $0): log: $VLOG"
	chmod 666 "$VLOG"
	$0 RESTARTED "$@" 2>&1 |tee -a $VLOG
	exit ${PIPESTATUS[0]}
fi

[ "$1" == 'RESTARTED' ] && 	shift

PLATFORM=$(rpm --eval %distro_release)
UPD=${UPD:-"yes"}
VARIABLES=''
BUILD_args=''
EXIT=0
MBINDS=""
STDOUT=""
STDERR=""
BIND=""
NEEDUPDATE='yes'

CFG=/etc/notamock.cfg
CFGD=/etc/notamock.d

# special config for project
if [ -f './notamock.cfg' ] ; then
	CFG=$(realpath ./notamock.cfg)
	CFGD=''
fi

HLP(){
echo "$0 - script to create layered chroot, like in notamock"
echo "Usage:
	$0 <variables> <parameters>"
echo "Parameters:
	-c | --config        -  specify config file, default is /etc/notamock.cfg
	-h | --help          -  this help
	-n | --name          -  name for overlayfs upper dir (works same as \"notamock REUSABLE=yes\")
	-r | --release       -  target OS release (ex. 2021.1)
	-u | --update        -  assemble or rebuild new rootfs
	-v | --verbose       -  verbose mode with a full logging
	-S | --showrc        -  show current configuration and exit
	-X | --x11           -  forward x11 applications
	--no-update          -  skip packages update stage
	--stdout             -  chroot command stdout to file
	--stderrr            -  chroot command stderr to file
	--                   -  command to exec in chroot"
echo "Variables:
	all variables specified from config file can be overridden from the cmdline of script in KEY=VALUE format
	also you may set variables from environment, but config file priority is higher
	See /etc/notamock.cfg.
"
exit
}

NOTAMOCKLIB="/usr/share/notamock/libnotamock"
[ -f './libnotamock' ] && NOTAMOCKLIB=./libnotamock
source "$NOTAMOCKLIB"

echo "==> $(basename $0): find parameters"
sep=''
while [ -n "$1" ] ; do
	case "${1}" in
	"-h" | "--help") HLP ;;
	"-v" | "--verbose") DEVNULL=''
						VERBOSE=yes;;
	"-S" | "--showrc" ) SHOWRC=yes
						VERBOSE=yes;;
	"-u" | "--update") RF_BUILD=yes ;;
	"-n" | "--name" ) shift
					  CHROOTNAME="$1"
					  REUSABLE=yes ;;
	"-c" | "--config")  shift
						CFG="$1"
						CFGD='';;
	"-s" | "--shell" ) START='/bin/bash' ;;
	"-r" | "--release") shift ; PLATFORM="$1" ;;
	"--stdout" ) shift ; STDOUT="1> >(tee $1)" ;;
	"--stderr" ) shift ; STDERR="2> >(tee $1)" ;;
	"--no-update" ) NEEDUPDATE='no' ;;
	"-X" | "--x11" ) X11='yes' ;;
	"--" ) shift ; COMMAND="$@"
				   break ;;
	*)  if echo "$1" |grep -q '=' ; then
			VARIABLES="${VARIABLES}${sep}$(echo $1 |sed 's/ /#/g')"
			sep=' '
		else
			echo_exit "Unknown parameter: $1" ${LINENO}
		fi;;
	esac
shift
done

echo "==> $(basename $0): seting up variables from cmdline"

source "$CFG"
VER=${CFG_VERSION:-0.1}
if [ $(echo -e "$VER\n$MIN_VERSION" |sort -V| tail -n1) != "$VER" ] ; then
	echo "Version of config file is less then minimum required for $0.
$VER < $MIN_VERSION
Please update $CFG from /usr/share/notamock/default.notamock.cfg"
	exit
fi

if [ -d "$CFGD" ] ; then
	for a in $(ls -1 ${CFGD}/. |sort ) ; do
		source ${CFGD}/$a
	done
fi

for a in $VARIABLES; do
	echo "==> $(basename $0):  variable: $a"
	a=$(echo $a |sed 's/#/ /g')
	if echo "$a" |grep -q '[[:alnum:]]*+=.*$' ; then
		eval $(echo $a |sed -e 's/=/=("/' -e 's/$/")/')
	elif echo "$a" |grep -q '[[:alnum:]]*=.*$' ; then
		eval $(echo $a |sed -e 's/=/="/' -e 's/$/"/')
	fi
done

PM_opts="$PM_opts \
$PM_cfg_opt $PM_config \
$PM_addrep_opt $PM_cache"

# parameters conflicts
if [ "$VERBOSE" ] ; then
	vecho "Arrays current values:"
	for a in $(cat $CFG |grep -E '^[[:alnum:]]+.*=' |grep -E -v '\+=|=\(' |sed 's/\+*=.*//'  |sort -u); do
		eval echo -e "\  \  ${a}: \${$a[@]}"
	done
	[ "$SHOWRC" ] && exit ${LINENO}
	if [ ! "$COMMAND" ] ; then
		echo "==> $(basename $0):  conflict parameters"
		echo "==> $(basename $0):  verbose mode can not be interactive"
		exit ${LINENO}
	fi
fi

if [ ! "$COMMAND" ] ; then
	COMMAND="/bin/bash"
fi

# build new rootfs if not exists, or key "-u" enabled
if [ ! -f ${BASE}/${ROOTFSNAME}/bin/bash ] || [ "$RF_BUILD" ] ; then
	build_new_rootfs || echo_exit "Build new rootfs - error!" ${LINENO}
# update rootfs
elif ! cat /proc/mounts |grep -q "${BASE}/$ROOTFSNAME" && [ "$NEEDUPDATE" == 'yes' ] ; then
	# wait direct update of rootfs by another notamock process
	waitfor "${BASE}/${ROOTFSNAME}.lock" "==> $(basename $0): waiting while another notamock process update rootfs"
	update_rootfs || echo_exit "Update rootfs - error!" ${LINENO}
fi

mkdir -p ${TMPD}/$PLATFORM || echo_exit "Cannot create temporary directory" ${LINENO}

if [ "$CHROOTNAME" ] ; then
	BUILD_DIR=${TMPD}/${PLATFORM}/$CHROOTNAME
	mkdir -p $BUILD_DIR
	vecho "Build dir: $BUILD_DIR"
else
	BUILD_DIR=$(mktemp -d -p ${TMPD}/${PLATFORM} --suffix "_rootfs")
fi

mkdir -p $BUILD_DIR
echo "==> $(basename $0): Build dir: $BUILD_DIR"
OVERLAY=${BUILD_DIR}/overlay
WORKDIR=${BUILD_DIR}/work
UPPERDIR=${BUILD_DIR}/upper
mkdir -p $OVERLAY $WORKDIR $UPPERDIR

trap 'clear_overlay' EXIT

LOWERDIR="${BASE}/$ROOTFSNAME"

vrun mount -t overlay overlay -o lowerdir="${LOWERDIR}",upperdir="$UPPERDIR",workdir="$WORKDIR" "$OVERLAY"
[ $? != 0 ] &&  echo_exit "Mounting overlay - error!" ${LINENO}

[ "$NEEDUPDATE" == 'yes' ] && vrun $PM_update $PM_root_opt "$OVERLAY" $PM_opts
touch  ${OVERLAY}/etc/machine-id

# additional environment variables for container
: > "${OVERLAY}/ENV.lst"
for str in $(seq 0 $(( ${#ENV[@]} - 1 )) ) ; do
	echo "==> $(basename $0): set env: ${ENV[$str]}"
	echo "export ${ENV[$str]}" >> "${OVERLAY}/ENV.lst"
done
grep 'source /ENV.lst' ${OVERLAY}/root/.bashrc || echo "source /ENV.lst" >> ${OVERLAY}/root/.bashrc

if [ "$X11" = "yes" ] ; then
	if ! xhost |grep -q "LOCAL:" ; then
		xhost +local:
		need_remove_X_perm='yes'
	fi
	echo "export DISPLAY=$DISPLAY" >> "${OVERLAY}/ENV.lst"
	if [ "$BIND" ] ; then
		BIND="${BIND},/tmp/.X11-unix::/tmp/.X11-unix"
	else
		BIND="/tmp/.X11-unix::/tmp/.X11-unix"
	fi
	CHROOT=$(echo $CHROOT |sed 's#systemd-nspawn#systemd-nspawn  --bind=/tmp/.X11-unix:/tmp/.X11-unix #')
fi

if [ "$BIND" ] ; then
	MBINDS=''
	echo "==> $(basename $0): BIND: $BIND"
	inter_mount
	trap 'clear_overlay ${MBINDS}' EXIT
fi

[ "$CHROOT" == 'INTERNAL' ] && CHROOT="chroot_internal"


eval $CHROOT "$OVERLAY" $COMMAND $STDOUT $STDERR
EXIT=$?
[ "$need_remove_X_perm" ] && xhost -local:
echo "==> $(basename $0): done."
echo $EXIT
exit $EXIT

