#!/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"
	run setterm -msglevel 4
}
trap cleanup EXIT

# avoid kernel messages spamming our console
run setterm -msg off

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

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

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=('en_US' '')
    local l
    for l in /usr/lib/locale/*_??; do
	list+=("${l#/usr/lib/locale/}" '')
    done
    [ -n "$list" ]
}

if findlocales && d --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
	fi
else
	d --msgbox $"Error setting locale" 0 0
fi

if [ -e "$EULA_FILE" -a ! -e "${EULA_FILE%/*}/no-acceptance-needed" ]; then
    if [ -n "$locale" ]; then
	for i in "${EULA_FILE%.txt}.$locale.txt" "${EULA_FILE%.txt}.${locale%%_*}.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 /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

#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/3 ]; then
    run create_snapshot 3 "Initial Status" "yes" || true
fi
/usr/lib/snapper/plugins/grub --refresh

# vim: sw=4
