#!/usr/bin/bash

# system-setup has been split into scripts under /etc/scripts/system-setup.d
# the purpose is to have different skel areas contribute different scripts
# into the system-setup stage

# Set null globbing, we need this for our scripts (cf. usr/sbin/rear).
# With nullglob set when e.g. for foo*bar no file matches are found, then foo*bar is removed
# (e.g. "ls foo*bar" becomes plain "ls" without "foo*bar: No such file or directory" error).
shopt -s nullglob

source /etc/scripts/system-setup-functions.sh

# The hardcoded 'sleep 1' is used as workaround to avoid whatever inexplicable actual reason
# that at least on SLES12 some initial output lines of this script would get lost
# (perhaps somewhere in systemd's nowhere land) and even in unattended_recovery mode
# all output should always appear regardless if someone is actually watching.
# In particular in Relax-and-Recover debug mode missing initial output lines results
# that the user sits in front of an empty screen wondering why nothing happens
# because in particular the read prompt "Press ENTER ..." was lost,
# cf. the 'if rear_debug' part below:
sleep 1

# Set variables like SHARE_DIR, CONFIG_DIR, we will need them soon
# (also in source_all_config).
set_rear_paths

# Because "rear recover" won't work without default.conf
# we abort when there is no default.conf (or when it is empty),
# cf. https://github.com/rear/rear/pull/3070#discussion_r1389361339
if ! test -s $SHARE_DIR/conf/default.conf ; then
    echo -e "\nERROR: ReaR recovery cannot work without $SHARE_DIR/conf/default.conf\n"
    # Wait hardcoded 10 seconds in any case so that the user can notice the
    # 'ERROR: ReaR recovery cannot work without /usr/share/rear/conf/default.conf'
    # on his screen before the screen gets cleared and replaced by the login screen
    # also in unattended mode regardless if someone is actually watching:
    sleep 10
    # Replace the usual /etc/motd message
    # 'Welcome to Relax-and-Recover. Run "rear recover" to restore your system !'
    # because it does not make sense to run "rear recover" without default.conf:
    echo -e "\nRelax-and-Recover cannot work without $SHARE_DIR/conf/default.conf\n" >/etc/motd
    # exiting this script proceeds directly to the login screen:
    # also execution of unattended/automated recovery is prevented by automatic-rear.service requiring
    # this one, i.e. depending on its successful execution.
    exit 1
fi

# Source ReaR config files, we need some ReaR variables in this script, even though it is run
# outside the 'rear' executable itself.
source_all_config

# Default USER_INPUT_INTERRUPT_TIMEOUT is 30 seconds and default USER_INPUT_UNATTENDED_TIMEOUT is 3 seconds:
unattended_recovery && timeout=$USER_INPUT_UNATTENDED_TIMEOUT || timeout=$USER_INPUT_INTERRUPT_TIMEOUT
if rear_debug ; then
    # Messages should not be longer than 80 characters
    # because this is the usual maximum usable width here:
    echo -e "\nIn Relax-and-Recover debug mode a shell will be started by default on tty9"
    read -n 1 -t $timeout -p "Press ENTER or type a tty digit '2...9' or '0' to skip (timeout $timeout) "
    case "$REPLY" in
        (0)
            echo -e "\nNo debug mode shell started"
            ;;
        ([2-9])
            /bin/bash </dev/tty$REPLY >/dev/tty$REPLY 2>&1 &
            echo -e "\nStarted debug mode shell on tty$REPLY"
            ;;
        (*)
            /bin/bash </dev/tty9 >/dev/tty9 2>&1 &
            echo -e "\nStarted debug mode shell by default on tty9"
            ;;
    esac
fi

# Verifying md5sums must happen first of all during recovery system startup
# before files may get changed by the recovery system startup scripts below
# otherwise one may get false positives like
#   ./var/log/lastlog: FAILED
#   ./etc/resolv.conf: FAILED
#   ./etc/udev/rules.d/70-persistent-net.rules: FAILED
#   ./etc/inittab: FAILED
#   ./etc/issue: FAILED
# The /md5sums.txt file would be empty if the md5sums were not successfully created
# during "rear mkrescue/mkbackup" by the build/default/995_md5sums_rootfs.sh script:
if test -s "/md5sums.txt" ; then
    echo -e "\nVerifying md5sums of the files in the Relax-and-Recover rescue system"
    # /etc/motd is excluded because it was changed above when default.conf is missing.
    # /etc/issue is excluded to avoid that verifying its md5sum fails with "./etc/issue: FAILED"
    # when there is no rsa SSH host key /etc/ssh/ssh_host_rsa_key in the recovery system
    # because then /etc/scripts/run-sshd creates one and adds its SSH fingerprint to /etc/issue
    # and /etc/scripts/run-sshd is run by SysVinit or systemd
    # (via /etc/inittab and /etc/init/start-sshd.conf or /usr/lib/systemd/system/sshd.service)
    # so that /etc/issue may get modified before its md5sum is verified here.
    # run-sshd also modifies /etc/ssh/sshd_config, so this is excluded as well.
    # Also /etc/udev/rules.d/70-persistent-net.rules is excluded to avoid false alarm
    # because it seems it can be modified even before this md5sum verification here runs,
    # see https://github.com/rear/rear/issues/1883#issuecomment-409875733
    egrep_pattern="/etc/motd|/etc/issue|/etc/ssh/sshd_config|/etc/udev/rules.d/70-persistent-net.rules"
    test "$EXCLUDE_MD5SUM_VERIFICATION" && egrep_pattern+="|$EXCLUDE_MD5SUM_VERIFICATION"
    # Regardless of '--quiet' md5sum shows "FAILED" messages nevertheless (cf. 'man md5sum'):
    if grep -E -v "$egrep_pattern" md5sums.txt | md5sum --quiet --check ; then
        echo "md5sums are OK"
    else
        # In case of a FAILED md5sum inform the user:
        echo "Possibly corrupted Relax-and-Recover rescue system"
        if rear_debug ; then
            # In debug mode let the user confirm to proceed:
            read -t $timeout -p "Press ENTER to proceed 'bona fide' nevertheless (timeout $timeout) "
        else
            # In non-debug mode wait USER_INPUT_INTERRUPT_TIMEOUT (by default 30 seconds)
            # so that the user can read and understand the md5sum output (could be several lines)
            # unless in unattended_recovery mode where there is normally no user who reads something:
            echo -e "Proceeding 'bona fide' nevertheless...\n"
            unattended_recovery || sleep $USER_INPUT_INTERRUPT_TIMEOUT
        fi
    fi
fi

echo -e "\nConfiguring Relax-and-Recover rescue system\n"
for system_setup_script in /etc/scripts/system-setup.d/*.sh ; do
    if rear_debug ; then
        read -t $timeout -p "Press ENTER to run $( basename $system_setup_script ) (timeout $timeout) "
        echo
        set -x
        source $system_setup_script || echo -e "\n'source $system_setup_script' results exit code $?\n"
        # The only known way how to do 'set +x' after 'set -x' without a '+ set +x' output:
        { set +x ; } 2>/dev/null
        echo
    else
        echo "Running $( basename $system_setup_script )..."
        # In non-debug mode when a system setup script results non-zero exit code
        # do not show an 'exit code' message (like the above) to avoid false alarm
        # cf. https://github.com/rear/rear/pull/3070#discussion_r1393738863
        # but just wait USER_INPUT_UNATTENDED_TIMEOUT (by default 3 seconds)
        # so that the user could at least notice potential error messages from the script
        # unless in unattended_recovery mode where there is normally no watching user:
        if ! source $system_setup_script ; then
            unattended_recovery || sleep $USER_INPUT_UNATTENDED_TIMEOUT
        fi
    fi
done
echo -e "\nRelax-and-Recover rescue system is ready\n"
# Wait USER_INPUT_UNATTENDED_TIMEOUT (by default 3 seconds)
# so that the user can notice the 'Relax-and-Recover rescue system is ready' message
# on his screen before the screen gets cleared and replaced by the login screen
# unless in unattended_recovery mode where there is normally no watching user:
unattended_recovery || sleep $USER_INPUT_UNATTENDED_TIMEOUT
