#!/bin/bash -efu

. altboot-sh-functions
. altboot-net-functions

check_parameter ALTBOOT_CIFS

b_a()
{
	get_bootarg CIFS "$1"
}

b_a server
b_a directory
b_a domain
b_a user
b_a pass
b_a timeout
b_a options

# You can change defaults in /etc/sysconfig/bootchain
OEM_CIFS_NETINST="${OEM_CIFS_NETINST:-/netinst}"

entered=


samba_input_form()
{
	enter "samba_input_form"

	local title="[ SAMBA-server connection data ]"

	local text="Please enter the name or IP address of the"
	text="$text SAMBA-server, and the directory (or ISO image"
	text="$text file)${STAGENAME:+ containing the squash $STAGENAME}"
	text="$text, and the Domain/Login/Password if necessary"
	text="$text (leave Login blank for guest logon)."

	while :; do
		IM_form "$title" "$text" 4		\
			server     64 "SAMBA-server"	\
			directory 128 "Directory"	\
			options    64 "Mount options"	\
			domain     32 "Domain"		\
			user       32 "Login"		\
			pass       32 "Password"	\
			||
			altboot_restart
		if [ -z "$server" ]; then
			IM_errmsg "Valid SAMBA-server required!"
		elif [ -z "$directory" ]; then
			IM_errmsg "Valid Directory required!"
		elif [ -n "${server//[^[:space:]]/}" ]; then
			IM_errmsg "Invalid SAMBA-server: '$server'!"
		elif [ -n "${directory//[^[:space:]]/}" ] ||
			[ -n "$directory" ] && [ "${directory:0:1}" != "/" ]
		then
			IM_errmsg "Invalid Directory: '$directory'!"
		elif [ -n "${domain//[^[:space:]]/}" ]; then
			IM_errmsg "Invalid Domain: '$domain'!"
		else
			[ -z "$pass" ] && user="" ||
				pass="${pass//\"/\\\"}"
			[ -z "$user" ] && pass="" ||
				user="${user//\"/\\\"}"
			break
		fi
	done

	server="${server//\"/\\\"}"
	directory="${directory//\"/\\\"}"
	options="${options//\"/\\\"}"
	domain="${domain//\"/\\\"}"
	entered=1

	leave "samba_input_form"
}

is_server_online()
{
	enter "is_server_online"

	if [ -z "$server" ] || [ -z "$directory" ]; then
		leave "is_server_online"
		return 1
	fi

	local ip dirty=1 opts="${options-}"
	local share rc=0 service="${directory:1}"
	local dirpart mp="$datadir" image="$destdir"

	if [ -n "$ALTBOOT_OLDROOT" ]; then
		[ -z "$OEM_CDROOT" ] ||
			image="$OEM_CDROOT"
		mp="$BC_ROOT"
	fi

	[ -n "$opts" ] ||
		opts="${CIFSOPTS-}"
	run mkdir -p -- "$mp" "$image"

	share="${service%%/*}"
	service="//$server/$share"
	dirpart="${directory#/"$share"}"
	ip="$(run resolve -s -t5 -- "$server" ||:)"
	[ -z "$ip" ] || [ "$ip" = "$server" ] ||
		opts="${opts:+$opts,}ip=$ip"
	[ -z "$domain" ] ||
		opts="${opts:+$opts,}domain=$domain"
	[[ -z "$user" || -z "$pass" ]] && opts="${opts:+$opts,}guest" ||
		opts="${opts:+$opts,}username=$user,password=$pass"
	if ! run mount.cifs "$service" "$mp" -o "ro${opts:+,$opts}"; then
		leave "is_server_online"
		return 1
	fi

	message "$service has been mounted successfully"

	if [ -z "$dirpart" ]; then
		run mount --move -- "$mp" "$image" || rc=1
		dirty=0
	elif [ -d "${mp}${dirpart}" ]; then
		run mount --bind -- "${mp}${dirpart}" "$image" || rc=1
	elif [ ! -s "${mp}${dirpart}" ]; then
		message "however specified ISO-image or directory not found: '$dirpart'"
		rc=1
	else
		message "assuming ISO-image, CIFS-path: '$dirpart'"
		lomount "" "${mp}${dirpart}" "$image" || rc=1
	fi

	if [ "$rc" != 0 ]; then
		message "$service will be unmounted"
		run umount -fl -- "$mp"
		leave "is_server_online"
		return 1
	fi

	if [ -n "$ALTBOOT_OLDROOT" ]; then
		stage2_setenv METHOD "cifs"
		stage2_setenv HOST "$server"
		stage2_setenv PREFIX "$directory"
		stage2_setenv SMBOPTS "$opts"
		[ -z "$domain" ] ||
			stage2_setenv SMBDOMAIN "$domain"
		if [ -n "$user" ]; then
			stage2_setenv LOGIN "$user"
			stage2_setenv PASSWORD "$pass"
		fi
		[ "$dirty" = 0 ] ||
			stage2_setenv PIGGYBACK 1
		bypass_results "$image"
	fi

	IM_update_bootsplash "found_media"
	leave "is_server_online"
}

start_connection()
{
	IM_ponder_start "[ Connecting... ]"
}

connection_loop()
{
	enter "connection_loop"
	IM_start_output form errmsg ponder

	if [ -z "$server" ] || [ -z "$directory" ]; then
		[ -z "$NOASKUSER" ] ||
			fatal "server/directory not specified, dialogs are disabled"
		samba_input_form
	fi

	start_connection

	local i=0

	while ! is_server_online; do
		if [ "$i" -ge "$timeout" ] || [ -z "$entered" ]; then
			IM_ponder_stop

			if [ -z "$NOASKUSER" ]; then
				[ "$i" -lt "$timeout" ] ||
					IM_errmsg "Connection timeout, try again!"
				samba_input_form
			else
				[ "$i" -lt "$timeout" ] ||
					message "connection timeout, dialogs are disabled"
				fatal "specified SAMBA-server does not responds"
			fi

			i=0
			debug "connection timeout, go to the next ring"
			start_connection
			continue
		fi
		i=$((1 + $i))
		sleep 1
	done

	IM_ponder_stop
	leave "connection_loop"
}


# Entry point
debug "$PROG started ($(get_parameter ALTBOOT_CIFS))"

if [ -f "$altboot_auto" ]; then
	directory=
	server=
	options=
	domain=
	user=
	pass=
fi

[ -n "$server" ] ||
	server="$(get_dhcp_wins)"
[ -n "$server" ] ||
	server="$(get_first_dns)"
[ -n "$server" ] ||
	server="$(get_dhcp_next_server)"
[ -n "$server" ] ||
	server="$OEM_SRV_NETINST"
[ -n "$directory" ] ||
	directory="$OEM_CIFS_NETINST/current"
timeout="${timeout:-$BC_DEVICE_TIMEOUT}"

is_server_online || connection_loop

debug "$PROG finished"
