#!/bin/sh

### BEGIN INIT INFO
# Provides:         opsi
# Required-Start:   $syslog
# Required-Stop:    $syslog
# Default-Start:    2 3 4 5
# Default-Stop:     0 1 6
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
LOG_FILE=/tmp/log
BOOTIMAGE_VERSION="$(cat /version)"
OPSI_HOST_KEY=""

. /lib/lsb/init-functions

set +e


logMessage(){
	message="$1"
	if [ "${OPSI_HOST_KEY}" != "" ]; then
		message=$(echo "$message" | sed s"/${OPSI_HOST_KEY}/*** confidential ***/g")
	fi
	if [ "${easypass}" != "" ]; then
		message=$(echo "$message" | sed s"/${easypass}/***confidential***/g")
	fi
	date +"%b %d %H:%M:%S" | tr -d '\n' >> $LOG_FILE
	echo " [opsiinit] $message" >> $LOG_FILE 
}

checkGetty(){
	if [[ -f /dev/ttyS0 ]]; then
		logMessage "starting getty@ttyS0"
		systemctl start serial-getty@ttyS0
	fi
}

getOpsiHostKey(){
	CMDLINE="$(cat /proc/cmdline)"
	OPSI_HOST_KEY="${CMDLINE##*pckey=}"
	OPSI_HOST_KEY="${OPSI_HOST_KEY%%[     ]*}"
}

getBootParam(){
	CMDLINE="$(cat /proc/cmdline)"
	logMessage "getBootParam($1): cmdline: $CMDLINE"
	case $CMDLINE in
		*$1=*)
			result="${CMDLINE##*$1=}"
			result="${result%%[     ]*}"
			echo "$result"
			return 0
		;;
		*\ $1\ *|*\ $1)
			return 0
		;;
	esac
	return 1
}

setEasyPassword() {
	easypassword=$1
        echo -e $easypassword"\n"$easypassword | passwd >/dev/null 2>/dev/null
        logMessage "set root-password to value received by append-Parameter easypass"
}

setPasswordHash() {
	pwh=$1
	sep_found="0"
	echo $pwh | grep ":" >/dev/null 2>/dev/null && sep_found="1"
	if [ "sep_found" = "1" ]; then
		sed -i "s|root:.*|root:$pwh|" /etc/shadow
	else
		opt=$(cat /etc/shadow | grep root | cut -d ':' -f3-)
		sed -i "s|root:.*|root:$pwh:$opt|" /etc/shadow
	fi
}

getNetworkDevices() {
	force_link=$1
	[ "$force_link" != "" ] &&  logMessage "getNetworkDevices(): link forced"
	devices_link=""
	devices=""
	for device in $(awk -F: '/ens|enp|eno|enx|eth/ {print $1}' /proc/net/dev | sed s'/ //g' 2>/dev/null); do
		ip link set dev $device up
		link=$(ethtool $device | grep -i "link detected" | cut -d ":" -f2 | sed 's/ //g')
		devices="$devices $device"
		[ "$link" = "yes" ] && devices_link="$devices_link $device"
	done
	logMessage "getNetworkDevices(): device(s) found: $devices, device(s) with link: $devices_link"
	if [ "$devices_link" != "" ]; then
		# link-up devices found, returning link-up devices
		logMessage "getNetworkDevices(): device(s) with link found, returning $devices_link"
		echo $devices_link
		return 0
	else
		if [ "$force_link" != "" ]; then
			# no link-up devices found, returning error
			logMessage "getNetworkDevices(): no devices with link found and link forced, returning error"
			return 1
		fi
		# no link-up devices found, returning all devices found
		logMessage "getNetworkDevices(): no devices with link found, returning $devices"
		echo $devices
		return 0
	fi
}

case "$1" in
	start)
		log_begin_msg "Starting opsi init"

		logMessage "opsi init script started"
		logMessage "opsi linux bootimage version: $BOOTIMAGE_VERSION (4.2)"
		#/usr/sbin/rngd -b -r /dev/urandom -o /dev/random
		#sleep 10
		#/usr/sbin/rngd -b -r /dev/urandom -o /dev/random
		checkGetty
		getOpsiHostKey

		# Boot params
		easypass="$(getBootParam easypass 2>/dev/null || true)"
		logMessage "boot param easypass found"
		[ "$easypass" != "" ] && setEasyPassword $easypass

                pwh="$(getBootParam pwh 2>/dev/null || true)"
		logMessage "boot param pwh=$pwh"
		[ "$pwh" != "" ] && setPasswordHash $pwh

		nodhcp="0"
		getBootParam nodhcp 2>/dev/null
		[ "$?" = "0" ] && nodhcp="1"
		logMessage "boot param nodhcp=$nodhcp"

		hn="$(getBootParam hn 2>/dev/null || true)"
		logMessage "boot param hn=$hn"

		dhclientTimeout="$(getBootParam dhclienttimeout 2>/dev/null || true)"
		if [ -n $dhclientTimeout ]; then
			re='^[0-9]+$'
			if [[ $dhclientTimeout =~ $re ]] ; then
				logMessage "new dhclient timeout is now $dhclientTimeout"
				sed -i -- "s/timeout 30;/timeout ${dhclientTimeout};/g" /etc/dhcp/dhclient.conf
			fi
		fi

		LANGUAGE="$(getBootParam lang 2>/dev/null || true)"
		logMessage "boot param lang=$LANGUAGE"
		[ -n "$LANGUAGE" ] || LANGUAGE="en"

		# resolv.conf fix
		logMessage "unlinking resolv.conf from stub systemd resolver"
		unlink /etc/resolv.conf
		ln -sf /var/run/systemd/resolve/resolv.conf /etc/resolv.conf

		# Localization
		LOCALE="en_US.UTF8"
		KEYMAP="us"

		case "$LANGUAGE" in
			de)
				# German version
				LOCALE="de_DE.UTF8"
				KEYMAP="de-latin1-nodeadkeys"
				;;
			fr)
				# French version
				LOCALE="fr_FR.UTF8"
				KEYMAP="fr"
				;;
			be)
				# Belgian version
				LOCALE="nl_BE.UTF8"
				KEYMAP="be-latin1"
				;;
			da)
				#Danish version
				LOCALE="da_DK.UTF8"
				KEYMAP="dk"
				;;
			it)
				# Italy
				LOCALE="it_IT.UTF8"
				KEYMAP="it"
				;;
		esac

		logMessage "loading keymap $KEYMAP"
		loadkeys -q $KEYMAP

		logMessage "setting language environment (LANG=$LOCALE, LANGUAGE=$LANGUAGE, LC_ALL=$LOCALE)"
		echo "LANG=\"$LOCALE\""		>  /etc/environment
		echo "LANGUAGE=\"$LANGUAGE\""	>> /etc/environment
		echo "LC_ALL=\"$LOCALE\""	>> /etc/environment

		# Networking
		#echo "auto lo" > /etc/network/interfaces
		#echo "iface lo inet loopback" >> /etc/network/interfaces
		#echo "" >> /etc/network/interfaces

		failed="1"
		count="0"
		while [ "$failed" = "1" -a "$count" != "20" ]; do
			count=$(($count+1))
			devices="$(getNetworkDevices force_link 2>/dev/null)"
			failed=$?
			if [ "$failed" = "0" ]; then
				logMessage "device(s) found: $devices"
			else
				logMessage "no devices found, sleeping 3 seconds"
				sleep 3
			fi
		done

		spoofAddress="$(getBootParam macaddress 2>/dev/null || true)"
		if [ "$spoofAddress" != "" ]; then
			logMessage "macaddress Parameter found"
		fi
		devices="$(getNetworkDevices 2>/dev/null || true)"
		for device in $devices; do
			if [[ $device == enx* ]]; then 
				logMessage "docking station/dongle network device found"
				deviceAddress="$(ip link | grep -A1 $device | awk '{print $2}' | tail -n1)"
				if [[ "$deviceAddress" != "$spoofAddress" ]]; then
					logMessage "Mac address of $device is $deviceAddress and differs to $spoofAddress, spoofing mac address"
					ip link set dev $device down
					ip link set dev $device address $spoofAddress
					ip link set dev $device up
				else
					logMesage "Mac addresses are the same"
				fi
			fi
			if [ "$nodhcp" = "0" ]; then
				logMessage "using dhcp, adding entry for device $device to /etc/netplan/01-$device.yaml"
				echo "network:" >> /etc/netplan/01-$device.yaml
				echo "  version: 2" >> /etc/netplan/01-$device.yaml
				echo "  renderer: networkd" >> /etc/netplan/01-$device.yaml
				echo "  ethernets:" >> /etc/netplan/01-$device.yaml
				echo "    $device:" >> /etc/netplan/01-$device.yaml
				echo "      dhcp4: true" >> /etc/netplan/01-$device.yaml
				dhclient $device -lf /var/lib/dhcp/dhclient.leases || true
			else
				logMessage "not using dhcp"
			fi
		done


		# Hostname
		if [ "$hn" != "" ]; then
			logMessage "Setting hostname to $hn as supplied by cmdline"
			hostname $hn
		elif [ "$nodhcp" = "0" ]; then
			for device in $devices; do
				hn=`pump -s -i $device | grep Hostname | cut -d: -f2 2>/dev/null | sed 's/ //g'`
				if [ "$hn" != "" ]; then
					logMessage "Setting hostname to $hn as set by dhcp for device $device"
					hostname $hn
				fi
			done
		fi

		logMessage "opsi init script ended"

		#initctl emit opsi-init &

		;;
	*)
		N=/etc/init.d/$NAME
		echo "Usage: $N {start}" >&2
		exit 1
		;;
esac

exit 0
