#!/bin/bash
# Copyright (c) 2015 SUSE LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

set -e

TEXTDOMAIN='jeos-firstboot'

. /etc/os-release
. "$0-functions"

EULA_FILE=/etc/YaST2/licenses/base/license.txt

stty_size() {
    set -- `stty size`; LINES=$1; COLUMNS=$2
    # stty size can return zero when not ready or
    # its a serial console
    if [ "$COLUMNS" = "0" -o "$LINES" = "0" ]; then
        LINES=24
        COLUMNS=80
    fi
}; stty_size

# for testing we may run as non root
if [ -w /run ]; then
    export TMPDIR=/run
    # debugging
    if [ -n "$FIRSTBOOT_DEBUG" ]; then
	set -x
	exec 2>/var/log/firstboot-debug
    fi
else
    dry=1
fi

if [ -n "$dry" ]; then
    run() {
	echo "$@"
    }
else
    run() {
	"$@"
    }
fi

dialog_out=`mktemp -qt 'firstboot-XXXXXX'`
cleanup() {
	echo .oOo.oOo.oOo. > $dialog_out
	rm -f "$dialog_out"
	kill -s SIGRTMAX-10 1
	run setterm -msglevel 4
}
trap cleanup EXIT

# avoid kernel messages spamming our console
run setterm -msg off
# Avoid systemd messages spamming our console
kill -s SIGRTMAX-9 1

systemd_firstboot_args=('--setup-machine-id')

result=
list=
keytable=''
locale=''
password=''

# Console fonts mapping to locales
# this need to be reworked, check bsc#1094346
declare -A consolefonts
consolefonts["el_GR.UTF-8"]="iso07u-16.psfu"
consolefonts["ru_RU.UTF-8"]="UniCyr_8x16.psf"
consolefonts["sr_RS.UTF-8"]="UniCyr_8x16.psf"
consolefonts["uk_UA.UTF-8"]="UniCyr_8x16.psf"
consolefonts["tg_TJ.UTF-8"]="UniCyr_8x16.psf"
consolefonts["bg_BG.UTF-8"]="UniCyr_8x16.psf"

let dh_menu=LINES-15
let dh_text=LINES-5

d(){
    if dialog --backtitle "$PRETTY_NAME" "$@" 2>"$dialog_out"; then
	# need || true as dialog doesn't write newlines
	read result < $dialog_out || true
    else
	return $?
    fi
}

menulist()
{
    list=()
    local line
    while read line; do
	    list+=("$line" '')
    done < <("$@"||true)
    [ -n "$list" ]
}

# for some reason localectl doesn't work here
#menulist localectl --no-pager list-keymaps
findkeymaps()
{
    list=('us' '')
    local line
    while read line; do
	    list+=("${line%.map.gz}" '')
    done < <(find /usr/share/kbd/keymaps -name '*.map.gz' -printf "%f\n" | sort -u)
    [ -n "$list" ]
}

findlocales()
{
    list=()
    local l
    for l in /usr/lib/locale/*.utf8; do
	code=${l#/usr/lib/locale/}
	list+=("${code/.utf8/}" '')
    done
    [ -n "$list" ]
}

if findlocales && d --default-item "en_US" --menu  $"Select System Locale" 0 0 $dh_menu "${list[@]}"; then
	if [ -n "$result" ]; then
	    locale="${result}.UTF-8"
	    systemd_firstboot_args+=("--locale=$locale")
	    LANG="$locale"
	    export LANG
        if [ ${consolefonts[$locale]+_} ]; then
            run sed -i -e "s/^FONT=.*/FONT=${consolefonts[$locale]}/" /etc/vconsole.conf
            run sed -i -e "s/^CONSOLE_FONT=.*/CONSOLE_FONT=i\"${consolefonts[$locale]}\"/" /etc/vconsole.conf
            run /usr/lib/systemd/systemd-vconsole-setup || true # true for nspawn
        fi
	fi
else
	d --msgbox $"Error setting locale" 0 0
fi

if [ -e "$EULA_FILE" -a ! -e "${EULA_FILE%/*}/no-acceptance-needed" ]; then
    [ -n "${locale}" ] && language="${locale%%_*}" || language="en"

    # Those languages can't be displayed in the console
    declare -A use_english_license
    use_english_license["ja"]=1
    use_english_license["zh"]=1
    use_english_license["ko"]=1

    if [ -n "$locale" -a -z "${use_english_license[${language}]+_}" ]; then
	for i in "${EULA_FILE%.txt}.$locale.txt" \
	         "${EULA_FILE%.txt}.${locale%%.UTF-8}.txt" \
	         "${EULA_FILE%.txt}.${language}.txt"; do
	    if [ -e "$i" ]; then
		EULA_FILE="$i"
		break
	    fi
	done
    fi
    while ! d --textbox "$EULA_FILE" $dh_text 85 --and-widget --yesno $"Do you agree with the terms of the license?" 0 0; do
	d --msgbox $"Well, we cannot continue then ..." 6 40
    done
fi

if findkeymaps \
    && d --menu  $"Select Keyboard Layout" 0 0 $dh_menu "${list[@]}"; then
	if [ -n "$result" ]; then
	    keytable="$result"
	fi
else
	d --msgbox $"Error setting keyboard" 0 0
fi

# timedatectl doesn't work as dbus is not up yet
# menulist timedatectl --no-pager list-timezones
if menulist awk \
    'BEGIN{print "UTC"; sort="sort"}/^#/{next;}{print $3|sort}END{close(sort)}' \
    /usr/share/zoneinfo/zone.tab \
    && d --menu  $"Select Time Zone" 0 0 $dh_menu "${list[@]}"; then
	if [ -n "$result" ]; then
	    systemd_firstboot_args+=("--timezone=$result")
	fi
else
	d --msgbox $"error setting timezone" 0 0
fi

# we need to adjust the keyboard and locale before the password is typed, in
# case umlauts are used
if [ -n "$keytable" ]; then
    echo "KEYMAP=$keytable" | run tee -a /etc/vconsole.conf
    run sed -i -e "s/^KEYTABLE=.*/KEYTABLE=\"$keytable\"/" /etc/sysconfig/keyboard
fi
# FIXME: systemd sets /etc/locale.conf which is ignored
if [ -n "$locale" ]; then
    run sed -i -e "s/^RC_LANG=.*/RC_LANG=\"$locale\"/" /etc/sysconfig/language
    export LANG="$locale"
fi
run systemd-firstboot "${systemd_firstboot_args[@]}"
run /usr/lib/systemd/systemd-vconsole-setup || true # true for nspawn

# NOTE: must be last as dialog file is used to set the password
while true; do
    password=
    if d --insecure --passwordbox  $"Enter root Password" 0 0; then
	password="$result"
	if d --insecure --passwordbox  $"Confirm root Password" 0 0; then
	    if [ "$password" != "$result" ]; then
		d --msgbox $"Entered passwords don't match" 5 40 || true
		continue
	    fi
	    # don't use that one as we need to switch locale
	    #systemd_firstboot_args+=("--root-password-file=$dialog_out")
	fi
    fi
    if [ -z "$password" ]; then
	d --msgbox $"Warning: No root password set.

You cannot log in that way. A debug shell will be started on tty9 just this time. Use it to e.g. import your ssh key." 0 0 || true
	run systemctl start debug-shell.service
    fi
    break
done

if [ -x /usr/bin/SUSEConnect ]; then
    d --msgbox $"Please register this image using your existing SUSE entitlement.

As \"root\" use the following command:

 SUSEConnect -e company@example.com -r YOUR_CODE

to register the instance with SCC

Without registration this instance does not have access to updates and
security fixes." 0 0 || true
fi

d --infobox $"Applying firstboot settings ..." 3 40 || true
# FIXME: systemd-firstboot doesn't set password if shadow present
if [ -n "$password" ]; then
    echo "root:$password" | run /usr/sbin/chpasswd
fi

EFI_SYSTAB="/sys/firmware/efi/systab"
# Look for EFI dir to see if the machine is booted in UEFI mode
modprobe efivars
if ! [ -f "$EFI_SYSTAB" ]; then
    run sed -i -e "s/LOADER_TYPE=.*/LOADER_TYPE=grub2/g" /etc/sysconfig/bootloader 
fi

# Configure initial network settings
#
shopt -s nullglob

candidates=()
for p in /sys/class/net/* ; do
        test -f "$p" && continue # skip bonding_masters file

        # only devices having ID_NET_NAME.* attrs
        udevadm info -q all -p "$p" | grep -qs ID_NET_NAME || continue
        d=${p##*/}

        unset IPADDR GATEWAYS
        eval `wicked test dhcp4 "$d" 2>/dev/null | grep -E "^IPADDR=|^GATEWAYS="`
        ip link set down "$d" # set link down after probe once done

        test -n "$IPADDR"   && candidates+=("$d")  || continue # ok, track it
        test -n "$GATEWAYS" && candidates=("$d")  || continue # just use it
        break
done

for d in ${candidates[@]} ; do
        rm -f "/etc/sysconfig/network/ifcfg-$d" || exit 1
        printf "STARTMODE=auto\nBOOTPROTO=dhcp\n" \
                > "/etc/sysconfig/network/ifcfg-$d"
        break # one is enough
done

# Run snapper to setup quota for btrfs
/usr/bin/snapper --no-dbus setup-quota

#d --infobox "Creating snapshot ..." 3 40 || true
#run snapper --no-dbus -v create -d "Initial Status" --userdata "important=yes" || d --msgbox "snapper failed" 0 0 || true
if [ ! -e /.snapshots/2 ]; then
    run create_snapshot 2 "Initial Status" "yes" || true
fi
/usr/lib/snapper/plugins/grub --refresh

# vim: sw=4
