#!/bin/sh -efu
### This file is covered by the GNU General Public License
### version 2 or later.
###
### Copyright (C) 2018  ALT Linux Team
### Author: Leonid Krivoshein <klark@altlinux.org>

# Parse arguments
autorun_parse_args() {
	local keys="method label uuid server directory mpoint run"
	local method="auto" label="alt-autorun" mpoint="/mnt/autorun"
	local short="${0##*/}" netok=0 override_cmdline=0
	local config="/etc/$short.conf" run="autorun"
	local uuid= server= directory= propagator= args= v= x=

	# override defaults by config
	if [ -r "$config" ]; then
		for x in $keys; do
			if grep -qsE "^$x=" "$config"; then
				v="$(cat "$config" | grep -E "^$x=" | tail -n1)"
				eval "$x=\"${v#*=}\""
			fi
		done
	fi

	# parse kernel command-line
	for x in $(cat /proc/cmdline) _; do
		case "$x" in
		automatic=*)
			propagator="${x##automatic=}"
			;;
		autorun|autorun=1|autorun=on|autorun=auto)
			args="method:auto"
			override_cmdline=1
			;;
		autorun=*)
			args="${x##autorun=}"
			;;
		esac
	done

	# override settings by propagator arguments
	if [ -n "$propagator" ]; then
		for x in $(echo "$propagator" | tr ',' ' '); do
			test -n "$x" || continue
			v="${x%%:*}"
			if echo "label uuid server" | grep -wqs "$v"; then
				eval "$v=\"${x#*:}\""
			fi
		done
	fi

	# override settings by rescue-launcher arguments
	if [ -n "$args" ]; then
		for x in $(echo "$args" | tr ',' ' '); do
			test -n "$x" || continue
			v="${x%%:*}"
			if echo "$keys" | grep -wqs "$v"; then
				eval "$v=\"${x#*:}\""
			fi
		done
	fi

	# return back config version of the method key
	if [ "$override_cmdline" = "1" -a -r "$config" ]; then
		if grep -qsE "^method=" "$config"; then
			method="$(cat "$config" | grep -E "^method=" | tail -n1 | cut f2- -d=)"
		fi
	fi

	# replace all '%20' to spaces in the label
	label="$(echo "$label" | sed -E 's,%20, ,g')"

	# export all settings
	keys="$keys netok keys"
	for x in $keys; do
		v="$(echo "$x" | tr '[[:lower:]]' '[[:upper:]]')"
		eval "export AUTORUN_$v=\"\$$x\""
	done

	# debugging
	autorun_debug "AUTORUN arguments is:"
	env | grep -E '^AUTORUN_' >&2
}

# Shell cleanup
autorun_unset_all() {
	local k= x=

	for x in $AUTORUN_KEYS; do
		k="$(echo "$x" | tr '[[:lower:]]' '[[:upper:]]')"
		eval "export AUTORUN_$k=; unset AUTORUN_$k"
	done
	autorun_debug "Shell cleanup finished"
}

# Debugging
autorun_debug() {
	echo "[$(date +%T)] $*" >&2
}

# Log and exec
autorun_spawn() {
	echo "[$(date +%T)] Executing: '$*'..." >&2
	"$@" >&2 || return $?
	return 0
}

# General mount
autorun_mount() {
	if autorun_spawn mount "$@" "$AUTORUN_MPOINT"; then
		if [ -x "$AUTORUN_MPOINT/$AUTORUN_RUN" ]; then
			autorun_debug "$AUTORUN_RUN executable found in the '$AUTORUN_MPOINT/'"
			return 0
		fi
		autorun_debug "$AUTORUN_RUN executable not found"
		autorun_spawn umount "$AUTORUN_MPOINT" ||
			autorun_spawn umount -l "$AUTORUN_MPOINT"
	fi

	return 1
}

# Main logic
autorun_main() {
	local name="${0##*/}"

	autorun_parse_args
	test -d "$AUTORUN_MPOINT" || autorun_spawn mkdir -pm755 "$AUTORUN_MPOINT"
	test -d "$TMPDIR" || autorun_spawn mkdir -pm700 "$TMPDIR"
	export AUTORUN_METHOD="${AUTORUN_METHOD:-auto}"

	if [ -r "/etc/$name/network.list" ]; then
		if grep -wqs "$AUTORUN_METHOD" "/etc/$name/network.list"; then
			. "/usr/libexec/$name/net-functions"
			autorun_networking || {
				echo; echo "AUTORUN: network unreachable!"
				autorun_unset_all
				exit 3
			}
		fi
	fi

	if [ -r "/usr/libexec/$name/methods/$AUTORUN_METHOD" ]; then
		. "/usr/libexec/$name/methods/$AUTORUN_METHOD"
	else
		autorun_debug "Helper script for '$AUTORUN_METHOD' method not found"
		echo; echo "AUTORUN: unknown method: '$AUTORUN_METHOD'!"
		autorun_unset_all
		exit 4
	fi

	if autorun_probe_${AUTORUN_METHOD}_method; then
		name="$AUTORUN_MPOINT/$AUTORUN_RUN"
		autorun_spawn cd "$AUTORUN_MPOINT/"
		autorun_unset_all
		exec "$name" 2>&1
		exit $?
	fi

	autorun_spawn rmdir "$AUTORUN_MPOINT" ||:
	autorun_unset_all
}

# Entry point
test "$(id -u 2>/dev/null ||:)" = "0" || exit 1
(	flock -n 900 || exit 2

	test -d /var/log || mkdir -pm755 /var/log
	exec 2>"/var/log/${0##*/}.log"

	export PATH="/sbin:/usr/sbin:/bin:/usr/bin"
	export TERM="${TERM:-linux}"
	export TMPDIR="/root/tmp"

	autorun_main
) 900>"/run/${0##*/}.lock"
rm -f "/run/${0##*/}.lock"

# Return to rescue shell on any error
