#!/usr/bin/env bash

# Copyright (c) 2009-2011 VMware, Inc.  All rights reserved.
# 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.
#

#
# vaos init.d script
# - execute on each boot
# - drive network setting, hostname setting, ssh keys creation,
#   EULA acceptance, ISV boot scripts execution, VAMI initialization
#
# chkconfig: 35 11 89
# description: Guest OS Initiatization Script
#
### BEGIN INIT INFO
# Provides:     vaos
# Required-Start:       network haveged
# Required-Stop:
# Default-Start:        3 5
# Default-Stop:
### END INIT INFO

export TEXTDOMAINDIR=/opt/vmware/lib/locale
export TEXTDOMAIN=vaos_init

VMBIN=/opt/vmware/share/vami
EULADIR=/opt/vmware/etc/isv/EULA
FIRSTBOOT_SCRIPT=/opt/vmware/etc/isv/firstboot
SUBSEQUENTBOOT_SCRIPT=/opt/vmware/etc/isv/subsequentboot
VAMI_FIRSTBOOT_SCRIPT=/opt/vmware/share/vami/firstboot
VAMI_SUBSEQUENTBOOT_SCRIPT=/opt/vmware/share/vami/subsequentboot
VAMI_OVF_SCRIPT=/opt/vmware/share/vami/vami_ovf_process
RESTORE_SCRIPT=/usr/sbin/restore-script

FLAG_FIRSTBOOT=/opt/vmware/etc/vami/flags/vami_firstboot
FLAG_SET_HOSTNAME=/opt/vmware/etc/vami/flags/vami_sethostname
FLAG_SET_NETWORK=/opt/vmware/etc/vami/flags/vami_setnetwork
FLAG_CREATE_SSH_KEYS=/opt/vmware/etc/vami/flags/vami_createsshkeys
FLAG_SHOW_EULA=/opt/vmware/etc/vami/flags/vami_showeula
FLAG_BOOT_SCRIPT=/opt/vmware/etc/vami/flags/vami_runbootscripts
FLAG_MANAGEMENT_SRV=/opt/vmware/etc/vami/flags/vami_mgmtsrv

COUNTRY_MAPPER=/opt/vmware/etc/init.d/country.sh
LANG_MAPPER=/opt/vmware/etc/init.d/lang.sh

export PATH=$PATH:/opt/vmware/bin

pgm=`basename $0`
stderr()
{
    /bin/echo -e "$*" 1>&2
}

# Shut down any boot program which may interfere with this script.

# plymouth used by Fedora (and possibly others)
if type plymouth > /dev/null 2>&1
then
   plymouth --quit
fi

# usplash used by Ubuntu
pidof /sbin/usplash 2> /dev/null
if [ $? -eq 0 -a -f /etc/init.d/usplash ]; then
   DO_NOT_SWITCH_VT=yes /etc/init.d/usplash start
fi

# Setting tty to sane mode.
SAVEDSTTY=`stty -g`
stty sane


network_is_up()
{
    if [ ! -f $VMBIN/vami_ip_addr ]
    then
        stderr $pgm: `gettext vami_ip_addr not found`
        return 1
    fi

    if [ ! -f $VMBIN/vami_ip6_addr ]
    then
        stderr $pgm: `gettext vami_ip6_addr not found`
        return 1
    fi

    if [ ! -f $VMBIN/vami_default_interface ]
    then
        stderr $pgm: `gettext vami_default_interface not found`
        return 1
    fi

    device=`$VMBIN/vami_default_interface`
    if [ x$device = x ]
    then
        stderr $pgm: `gettext vami_default_interface returns invalid interface`
        return 1
    fi

    if [ "`$VMBIN/vami_ip_addr $device`" = "" -a "`$VMBIN/vami_ip6_addr $device`" = "" ]
    then
        return 1
    else
        return 0
    fi
}

set_hostname()
{
    if [ -x $VMBIN/vami_set_hostname ]
    then
        $VMBIN/vami_set_hostname
    fi
}

wait_for_network()
{
    for i in 1 2 3 4 5 6 7 8 9 10
    do
        echo `gettext "Waiting for network to come up"` \(`gettext "attempt"` $i `gettext "of"` 10\)...
        network_is_up
        ret=$?
        if [ $ret ]
        then
            return 0
        else
            sleep 3
        fi
    done
    return 1
}

askuser()
{
    srcdir=$1

    for EULAFILE in `ls -d $srcdir/* 2> /dev/null`; do

        if [ -f "$EULAFILE" ] && [ -s "$EULAFILE" ]
        then
            AGREE=no
            until [ "$AGREE" = "yes" ]
            do
                echo
                echo
                echo
                more $EULAFILE
                echo
                echo
                /bin/echo -e `gettext 'Do you agree with the terms of the End User License Agreement?'`
                /bin/echo -e 'yes/no [no]: \c'
                read AGREE
            done
        fi
    done
}

#
# and set $userlang as output
#   do NOT use array or bash feature; this is init.d script and dash does not support array
#
getuserlang()
{
    local lang
    local userinput
    local langopts

    langopts=`find "$EULADIR/" -mindepth 1 -type d -exec basename '{}' \; 2>/dev/null`
    set -- $langopts

    if [ $# -eq 0 ]
    then
        userlang=
        return 0
    elif [ $# -eq 1 ]
    then
        userlang=$1
        return 0
    fi

    while [ 1 ]
    do

        echo
        echo `gettext "Available languages for EULA are: "`
        for lang in $langopts
        do
            langname=
            countryname=
            if [ -x "$LANG_MAPPER" ]
            then
                langcode=`echo $lang | sed -n "s/^\([a-z][a-z][a-z]*\).*/\1/p"`
                langname=`$LANG_MAPPER  $langcode`
            fi
            if [ -x "$COUNTRY_MAPPER" ]
            then
                countrycode=`echo $lang | sed -n "s/.*-\([a-z][a-z]\)$/\1/p"`

                if [ ! -z "$countrycode" ]
                then
                    countryname=`$COUNTRY_MAPPER  $countrycode`
                fi
            fi

            promptstr="\t$lang"
            if [ ! -z "$langname" ]
            then
                promptstr="$promptstr : $langname"
            fi
            if [ ! -z "$countryname" ]
            then
                promptstr="$promptstr , $countryname"
            fi
            /bin/echo -e "$promptstr"
        done
        echo

        echo -n `gettext "Please choose a language to display EULA"` "[$1]:"
        read userinput
        userinput=`echo "$userinput" | tr "[A-Z]" "[a-z]"`
        if [ -z "$userinput" ]
        then
            userlang=$1
            return 0
        else
            for lang in $@
            do
                if [ "$userinput" = "$lang" ]
                then
                    userlang=$lang
                    return 0
                fi
            done
        fi
        echo `gettext "The language you have chosen"` "($userinput)" `gettext "is not available"`
    done

    return 1
}


case "$1" in
  stop)
    exit 0
    ;;
  status)
    # noop
    exit 0
    ;;
  start)
    true
    ;;
  *)
    echo "Unsupported argument $1"
    exit 1
    ;;
esac

# Per request via bug# 1211660
# If on a distro that does not have innserv such as current Studio release then check mannually
if [[ -f /etc/init.d/haveged ]]; then
    echo `gettext "Checking haveged"`
    /etc/init.d/haveged status
    if (( $? != 0 )); then
        echo `gettext "haveged not running attempting to start..."`
        /etc/init.d/haveged start
        if (( $? != 0 )); then
            echo `gettext "ERROR: failed to start haveged"`
            exit 1
        else
            echo `gettext "haveged started"`
        fi
    else
        echo `gettext "haveged already running"`
    fi
elif [[ -f /usr/lib/systemd/system/haveged.service ]]; then
    echo `gettext "Checking haveged on systemd"`
    systemctl status haveged
    if (( $? != 0 )); then
        echo `gettext "haveged not running attempting to start..."`
        systemctl start haveged
        if (( $? != 0 )); then
            echo `gettext "ERROR: failed to start haveged"`
            exit 1
        else
            echo `gettext "haveged started"`
        fi
    else
        echo `gettext "haveged already running"`
    fi
else
    echo `gettext "WARNING: haveged is not installed"`
fi

# Warn if no network is present
wait_for_network
ret=$?
if [ $ret ]
then
    :;
else
    echo
    echo `gettext WARNING: AUTOMATIC CONFIGURATION OF THE NETWORK HAS FAILED.`
    echo
fi

if [ -f $FLAG_FIRSTBOOT ]
then

    #
    # Operations during the first boot of the appliance (by the end user)
    #

    # Set hostname from dns; hostname can be changed once the vm is up
    # and running.
    network_is_up
    ret=$?
    if [ $ret -a -f $FLAG_SET_HOSTNAME ]
    then
        set_hostname
    fi

    if [ -f $FLAG_SET_NETWORK -a -x $VAMI_OVF_SCRIPT ]
    then
        # Set network from OVF properties if present.
        # This needs to execute before generating ssh keys.
        $VAMI_OVF_SCRIPT --setnetwork
    fi

    tput bel
    trap "" 2 3

    RET=1
    if [ -f $FLAG_SHOW_EULA -a -x $VAMI_OVF_SCRIPT ]
    then
        # Check if EULA had already been accepted through OVF deployment.
        $VAMI_OVF_SCRIPT --ignoreeula
        RET=$?
    else
        RET=0
    fi

    # Check if there is EULA to be displayed for acceptance.
    if [ $RET -ne 0 ]; then

        #
        # find available language versions of EULAs
        #

        # getuserlang will set $userlang
        getuserlang

        #
        # no-language-preference EULAs
        #
        askuser "$EULADIR"

        # language specific EULAs
        if [ ! -z "$userlang" ] && [ -d "$EULADIR/$userlang" ]
        then
            askuser "$EULADIR/$userlang"
        fi
    fi

    echo

    trap 2 3

    if [ -f $FLAG_CREATE_SSH_KEYS -a -x /usr/bin/ssh-keygen ]
    then
        echo `gettext "Regenerating ssh host keys..."`
        rm -f /etc/ssh/ssh_host_*

        if [ -x /usr/bin/debconf-set-selections ]
        then
            #
            # Assuming a Debian-type release, like Ubuntu
            #
            dpkg-reconfigure openssh-server 2>/dev/null

        elif [ -f /usr/lib/systemd/system/sshd.service ]
        then
            #
            # For systemd
            #
            systemctl status sshd 2>/dev/null
            RET=$?
            if [ $RET -ne 0 ]; then
                systemctl start sshd 2>/dev/null
            fi

        elif [ -x /etc/init.d/sshd ]
        then
            #
            # Assuming a Red Hat-like release
            #
            /etc/init.d/sshd status 2>/dev/null
            RET=$?
            if [ $RET -ne 0 ]; then
                /etc/init.d/sshd start 2>/dev/null
            fi
        fi

        #
        # Generate root's keys
        #
        echo `gettext "Regenerating keys for the root user..."`
        rm -f ~root/.ssh/id_rsa*
        /usr/bin/ssh-keygen -t rsa -f ~root/.ssh/id_rsa -P ''
        /bin/cat ~root/.ssh/id_rsa.pub >> ~root/.ssh/authorized_keys

    fi

else

    #
    # Operations during each subsequent boot of the appliance (by the end user)
    #

    if [ -f $FLAG_SET_NETWORK -a -x $VAMI_OVF_SCRIPT ]
    then
        # Set network from OVF properties if present.
        echo "Updating network config through vaos.service."
        $VAMI_OVF_SCRIPT --setnetwork
    fi

    if [ -x $RESTORE_SCRIPT ]
    then
        # Run the restore-script
        $RESTORE_SCRIPT
    fi
fi


if [ -f $FLAG_FIRSTBOOT ]
then
    [ -f $FLAG_MANAGEMENT_SRV -a -x $VAMI_FIRSTBOOT_SCRIPT ] && $VAMI_FIRSTBOOT_SCRIPT
    [ -f $FLAG_BOOT_SCRIPT -a -f $FIRSTBOOT_SCRIPT ] && sh $FIRSTBOOT_SCRIPT
    rm $FLAG_FIRSTBOOT
else
    [ -f $FLAG_MANAGEMENT_SRV -a -x $VAMI_SUBSEQUENTBOOT_SCRIPT ] && $VAMI_SUBSEQUENTBOOT_SCRIPT
    [ -f $FLAG_BOOT_SCRIPT -a -f $SUBSEQUENTBOOT_SCRIPT ] && sh $SUBSEQUENTBOOT_SCRIPT
fi

stty $SAVEDSTTY

exit 0
