#!/bin/bash
#
# /etc/rc.sysinit
#

. /etc/rc.conf
. /etc/rc.d/functions

echo " "
printhl "Arch Linux\n"
printhl "${C_H2}http://www.archlinux.org"
printsep

# mount /proc, /sys, /run, /dev, /run/lock, /dev/pts, /dev/shm (the api filesystems)
mountpoint -q /proc    || mount -t proc proc /proc -o nosuid,noexec,nodev
mountpoint -q /sys     || mount -t sysfs sys /sys -o nosuid,noexec,nodev
mountpoint -q /run     || mount -t tmpfs run /run -o mode=0755,nosuid,nodev
mountpoint -q /dev     || mount -t devtmpfs dev /dev -o mode=0755,nosuid
mkdir -p -m 1777 /run/lock
mkdir -p /dev/{pts,shm}
mountpoint -q /dev/pts || mount /dev/pts &>/dev/null ||
	mount -n -t devpts devpts /dev/pts -o mode=0620,gid=5,nosuid,noexec
mountpoint -q /dev/shm || mount /dev/shm &>/dev/null ||
	mount -n -t tmpfs shm /dev/shm -o mode=1777,nosuid,nodev

if [[ ! -e /run/initramfs/fsck-root ]]; then
	# remount root ro to allow for fsck later on, we remount now to
	# make sure nothing can open files rw on root which would block a remount
	findmnt / --options ro &>/dev/null ||
		status "Mounting Root Read-Only" mount -o remount,ro /
fi

run_hook sysinit_start

# log all console messages
bootlogd -p /run/bootlogd.pid

if [[ ! -a /usr/lib ]] ; then
	printf "${C_FAIL}/usr is not mounted. This is not supported.${C_OTHER}\n"
fi

if ! grep -q devtmpfs /proc/filesystems; then
	printf "${C_FAIL}Your kernel does not have devtmpfs support. This is not supported.${C_OTHER}\n"
fi

HWCLOCK_PARAMS="--systz"
case $HARDWARECLOCK in
	"") ;;
	UTC) HWCLOCK_PARAMS+=" --utc --noadjfile";;
	localtime) HWCLOCK_PARAMS+=" --localtime --noadjfile";;
	*) HWCLOCK_PARAMS="";;
esac

if [[ $HWCLOCK_PARAMS ]]; then
	stat_busy "Adjusting system time and setting kernel timezone"
		# enable rtc access
		modprobe -q -a rtc-cmos rtc genrtc

		# Adjust the system time for timezone offset if rtc is not in UTC
		# 1. Make creation time on device nodes sane (FS#8665)
		# 2. Filesystem checks can depend on system time
		# 3. This also sets the kernel time zone, used by e.g. vfat
		# If TIMEZONE is not set in rc.conf, the timezone stored in /etc/localtime
		# is used. If HARDWARECLOCK is not set in rc.conf, the value in
		# /var/lib/hwclock/adjfile is used (in this case /var can not be a separate
		# partition).
	TZ=$TIMEZONE hwclock $HWCLOCK_PARAMS && stat_done || stat_fail
fi

# Start/trigger UDev, load MODULES and settle UDev
udevd_modprobe sysinit

# bring up the loopback interface
[[ -d /sys/class/net/lo ]] &&
	status "Bringing up loopback interface" ip link set up dev lo

# FakeRAID devices detection
[[ $USEDMRAID = [Yy][Ee][Ss] && -x $(type -P dmraid) ]] &&
	status "Activating FakeRAID arrays" dmraid -i -ay

# BTRFS devices detection
[[ $USEBTRFS = [Yy][Ee][Ss] && -x $(type -P btrfs) ]] &&
	status "Activating BTRFS volumes" btrfs device scan

# Activate LVM2 groups if any
activate_vgs

# Set up non-root encrypted partition mappings
if [[ -f /etc/crypttab && $CS ]] && grep -q ^[^#] /etc/crypttab; then
	stat_busy "Unlocking encrypted volumes:"
		modprobe -q dm-crypt 2>/dev/null
		do_unlock() {
			# $1 = requested name
			# $2 = source device
			# $3 = password
			# $4 = options
			stat_append "${1}.."
			local open=create a=$1 b=$2 failed=0
			# Ordering of options is different if you are using LUKS vs. not.
			# Use ugly swizzling to deal with it.
			# isLuks only gives an exit code but no output to stdout or stderr.
			if $CS isLuks "$2" 2>/dev/null; then
				open=luksOpen
				a=$2
				b=$1
			fi
			case $3 in
				SWAP)
					local _overwriteokay=0
					if [[ -b $2 && -r $2 ]]; then
						# This is DANGEROUS! If there is any known file system,
						# partition table, RAID or LVM volume on the device
						# we don't overwrite it.
						#
						# 'blkid' returns 2 if no valid signature has been found.
						# Only in this case we should allow overwriting the device.
						#
						# This sanity check _should_ be sufficient, but it might not.
						# This may cause dataloss if it is not used carefully.
						blkid -p "$2" &>/dev/null
						(( $? == 2 )) && _overwriteokay=1
					fi
					if (( _overwriteokay == 0 )); then
						false
					elif $CS -d /dev/urandom $4 $open "$a" "$b" >/dev/null; then
						stat_append "creating swapspace.."
						mkswap -f -L $1 /dev/mapper/$1 >/dev/null
					fi;;
				ASK)
					printf "\nOpening '$1' volume:\n"
					$CS $4 $open "$a" "$b" < /dev/console;;
				/dev*)
					local ckdev=${3%%:*}
					local cka=${3#*:}
					local ckb=${cka#*:}
					local cka=${cka%:*}
					local ckfile=/dev/ckfile
					local ckdir=/dev/ckdir
					case ${cka} in
						*[!0-9]*)
							# Use a file on the device
							# cka is not numeric: cka=filesystem, ckb=path
							mkdir ${ckdir}
							mount -r -t ${cka} ${ckdev} ${ckdir}
							dd if=${ckdir}/${ckb} of=${ckfile} >/dev/null 2>&1
							umount ${ckdir}
							rmdir ${ckdir};;
						*)
							# Read raw data from the block device
							# cka is numeric: cka=offset, ckb=length
							dd if=${ckdev} of=${ckfile} bs=1 skip=${cka} count=${ckb} >/dev/null 2>&1;;
					esac
					$CS -d ${ckfile} $4 $open "$a" "$b" >/dev/null
					dd if=/dev/urandom of=${ckfile} bs=1 count=$(stat -c %s ${ckfile}) conv=notrunc >/dev/null 2>&1
					rm ${ckfile};;
				/*)
					$CS -d "$3" $4 $open "$a" "$b" >/dev/null;;
				*)
					echo "$3" | $CS $4 $open "$a" "$b" >/dev/null;;
			esac
			if (( $? )); then
				failed=1
				stat_append "failed "
			else
				stat_append "ok "
			fi
			return $failed
		}
	crypto_unlocked=0
	read_crypttab do_unlock && stat_done || stat_fail
	# Maybe someone has LVM on an encrypted block device
	(( crypto_unlocked )) && activate_vgs
fi

#Felix's crypto hook mod
echo "Felix's crypto hook mod: decrypting other filesystems"
	#change /dev/sdaX to your partitions, and change the last word
	#on the line to what you've called your encrypted volume.
	#then make sure you don't have anything in /etc/crypttab,
	#and put entries in /etc/fstab for these, e.g. var would be
	#/dev/mapper/var /var ...
	cryptsetup luksOpen /dev/sda5 --key-file=/run/tmptoken var
	cryptsetup luksOpen /dev/mmcblk0p1 --key-file=/run/tmptoken data
	shred /run/tmptoken
	rm -f /run/tmptoken
echo "Done & temp keyfile cleared."

# Check filesystems
[[ -f /forcefsck ]] || in_array forcefsck $(< /proc/cmdline) && FORCEFSCK="-- -f"
declare -r FORCEFSCK

if [[ -n $FORCEFSCK ]] || { [[ ! -f /fastboot ]] && ! in_array fastboot $(< /proc/cmdline); }; then
	run_hook sysinit_prefsck
	if [[ -x $(type -P fsck) ]]; then
		stat_busy "Checking Filesystems"
			fsck_all >|"${FSCK_OUT:-/dev/stdout}" 2>|"${FSCK_ERR:-/dev/stdout}"
		declare -r fsckret=$?
		(( fsckret <= 1 )) && stat_done || stat_fail
	else
		declare -r fsckret=0
	fi
	run_hook sysinit_postfsck

	# Single-user login and/or automatic reboot if needed
	fsck_reboot $fsckret
fi

status "Remounting Root" \
	mount -o remount /

# now mount all the local filesystems
run_hook sysinit_premount
status "Mounting Local Filesystems" \
	mount_all
run_hook sysinit_postmount

# enable monitoring of lvm2 groups, now that the filesystems are mounted rw
[[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] &&
	status "Activating monitoring of LVM2 groups" \
		vgchange --monitor y >/dev/null

status "Activating Swap" swapon -a

[[ $TIMEZONE ]] && status "Configuring Time Zone" set_timezone "$TIMEZONE"

RANDOM_SEED=/var/lib/misc/random-seed
[[ -f $RANDOM_SEED ]] &&
	status "Initializing Random Seed" \
		cp $RANDOM_SEED /dev/urandom

# Remove leftover files
remove_leftover

if [[ -s /etc/hostname ]]; then
	HOSTNAME=$(< /etc/hostname)
fi
if [[ $HOSTNAME ]]; then
	stat_busy "Setting Hostname: $HOSTNAME"
	echo "$HOSTNAME" >| /proc/sys/kernel/hostname && stat_done || stat_fail
fi

if [[ -s /etc/locale.conf ]]; then
	parse_envfile /etc/locale.conf "LANG"
	[[ $LANG ]] && LOCALE=$LANG
fi
if [[ ${LOCALE,,} =~ utf ]]; then
	stat_busy "Setting Consoles to UTF-8 mode"
		# UTF-8 consoles are default since 2.6.24 kernel
		# this code is needed not only for older kernels,
		# but also when user has set vt.default_utf8=0 but LOCALE is *.UTF-8.
		for i in /dev/tty[0-9]*; do
			kbd_mode -u < ${i}
			printf "\e%%G" > ${i}
		done
		echo 1 >| /sys/module/vt/parameters/default_utf8
	stat_done
else
	stat_busy "Setting Consoles to legacy mode"
		# make non-UTF-8 consoles work on 2.6.24 and newer kernels
		for i in /dev/tty[0-9]*; do
			kbd_mode -a < ${i}
			printf "\e%%@" > ${i}
		done
		echo 0 >| /sys/module/vt/parameters/default_utf8
	stat_done
fi

if [[ -s /etc/vconsole.conf ]]; then
	parse_envfile /etc/vconsole.conf "${vconsolevars[@]}"
	[[ $FONT ]] && CONSOLEFONT=$FONT
	[[ $FONT_MAP ]] && CONSOLEMAP=$FONT_MAP
fi
[[ $KEYMAP ]] &&
	status "Loading Keyboard Map: $KEYMAP" loadkeys -q $KEYMAP

# Set console font if required
set_consolefont

stat_busy "Saving dmesg Log"
	if [[ -e /proc/sys/kernel/dmesg_restrict ]] &&
		(( $(< /proc/sys/kernel/dmesg_restrict) == 1 )); then
		install -Tm 0600 <( dmesg ) /var/log/dmesg.log
	else
		install -Tm 0644 <( dmesg ) /var/log/dmesg.log
	fi
(( $? == 0 )) && stat_done || stat_fail

run_hook sysinit_end

# End of file
# vim: set ts=2 sw=2 noet:
