#
# Set up extra packages and diskless workstation.  Partly based on
# ltsp-make-client originally created by Finn-Arne Johansen.
#
info() {
    echo "info: $@"
}

warning() {
    echo "warning: $@"
}

error() {
    echo "error: $@"
}

in_target() {
    chroot $ROOT "$@"
}

# Clean up changes done to the tasksel behaviour earlier and go back
# to the default behavior.
diverts_remove() {
    for test in desktop new-install ; do
        if [ -f $ROOT/usr/lib/tasksel/tests/$test.edu ] ; then
            rm $ROOT/usr/lib/tasksel/tests/$test
            in_target dpkg-divert --package debian-edu-install --rename --quiet \
                --remove /usr/lib/tasksel/tests/$test
            rm $ROOT/usr/lib/tasksel/tests/$test.edu
        fi
    done
}

# Modify tasksel desktop test so the normal Debian desktop profiles
# are not installed. Use dpkg-divert to to switch to our version while
# tasksel runs.
diverts_insert() {
    file=/usr/lib/tasksel/tests/desktop
    sed -e 's/if desktop_hardware/# Do not install a desktop - added by debian-edu-install\nunmark\n\n&/' \
        <$ROOT$file >$ROOT$file.edu
    in_target dpkg-divert --package debian-edu-install --rename --quiet --add $file
    ln -s ./desktop.edu $ROOT$file

# And for the standard system task too
    file=/usr/lib/tasksel/tests/new-install
    sed -e 's/^case/# Do not install standard system task - added by debian-edu-install\nexit 3\n\n&/' \
        <$ROOT$file >$ROOT$file.edu
    in_target dpkg-divert --package debian-edu-install --rename --quiet --add $file
    ln -s ./new-install.edu $ROOT$file
}

only_run_on_rclevel() {
    runlevel=$1 # Use level N to disable on all levels
    shift
    for service in $@ ; do
	info "Making sure init.d/$service only run in runlevel $runlevel"
	for link in $(cd $ROOT/etc; ls rc[S2345].d/[SK]*$service || true); do
            # link now look like 'rcS.d/S99foo'
            set `echo $link|sed "s%rc\(.\).d\/\([SK]\)\(..\)$service%\1 \2 \3%"`
            lvl=$1
            action=$2
            seq=$3
            if [ "K" = "$action" ] && [ "$runlevel" = "$lvl" ]; then
		mv $ROOT/etc/$link $ROOT/etc/rc$lvl.d/S$seq$service
            fi
            if [ "S" = "$action" ] && [ "$runlevel" != "$lvl" ]; then
		mv $ROOT/etc/$link $ROOT/etc/rc$lvl.d/K$seq$service
            fi
	done
    done
}

enable_on_rclevel() {
    service=$1
    shift
    if [ ! -f $ROOT/etc/init.d/$service ] ; then
        error "Unable to enable service $service, do not exist"
        return
    fi
    info "Making sure init.d/$service run in runlevel $@"
    for runlevel in $@ ; do
        rcd=$ROOT/etc/rc$runlevel.d
        if [ ! -f $rcd/S??$service ] ; then
            seq=""
            for link in $(cd $ROOT/etc; ls rc$runlevel.d/K??$service 2>/dev/null || true); do
                set `echo $link|sed "s%rc\(.\).d\/\([SK]\)\(..\)$service%\1 \2 \3%"`
                seq=$3
                mv $rcd/K??$service $rcd/S$seq$service
            done
            if [ -z "$seq" ] ; then # No stop link found, create start link
                # Assume insserv will pick a better sequence number
                ln -s ../init.d/$service $rcd/S01$service
            fi
        fi
    done
}

disable_cronjob() {
    for jobname in $@ ; do
        for crondir in /etc/cron.d /etc/cron.daily /etc/cron.hourly \
            /etc/cron.monthly /etc/cron.weekly ; do
            job="$ROOT$crondir/$jobname"
            if [ -f "$job" ] ; then
                mv "$job" "${job}~disabled"
            fi
        done
    done
}

append_if_missing() {
    file="$1"
    pattern="$2"
    if [ -f "$file" ] && grep -q "$pattern" "$file" ; then
        :
    else
        (
            if [ -f "$file" ] ; then cat "$file" ; fi
            cat -
        ) > "$file.new" && mv "$file.new" "$file"
    fi
}

etcvcs_commit() {
    msg="$1"
    if [ -x $ROOT/usr/bin/etckeeper ] ; then
	in_target etckeeper commit "$msg" || true
    fi
    if [ -x /usr/bin/etckeeper ] ; then
	etckeeper commit "$msg" || true
    fi
}

setup_diskless_workstation() {
    etcvcs_commit "Before diskless workstation is set up"

    # Add Edu config with language and profile.
    mkdir -p $ROOT/etc/debian-edu
    sed 's/^PROFILE=\".*/PROFILE=\"Workstation\"/' \
        < /etc/debian-edu/config > $ROOT/etc/debian-edu/config

    # Install the installation package to load preseeding values based
    # on the /etc/debian-edu/config PROFILE
    in_target apt-get install -y -q debian-edu-install

    # Add preseeding values, without the popularity-contest settings
    # to avoid several hosts reporting with the same popcon ID.
    (
        debconf-get-selections | egrep "^locales"
    ) | in_target debconf-set-selections

    # Set same default-wordlist and default-ispell as on the server side
    (
        debconf-get-selections | egrep "^dictionaries-common" | grep default-wordlist
    ) | in_target debconf-set-selections

    (
        debconf-get-selections | egrep "^dictionaries-common" | grep default-ispell
    ) | in_target debconf-set-selections

    if [ -f /etc/locale.gen -a ! -f $ROOT/locale.gen ] ; then
        cp /etc/locale.gen $ROOT/etc/locale.gen
    fi

    if [ -f /etc/environment -a ! -f $ROOT/etc/environment ] ; then
        cp /etc/environment $ROOT/etc/environment
    fi

    # set the timezone
    cp -d /etc/localtime $ROOT/etc
    cp -d /etc/timezone $ROOT/etc

    # Pass on the current desktop setting and the profile we
    # want to install
    (
        debconf-get-selections | grep tasksel/desktop
        echo debian-edu-install debian-edu-install/profile multiselect Workstation
    ) | in_target debconf-set-selections

    # Do not dynamically detect on Main-Server, because in this
    # setting it is not possible for a workstation to get its settings
    # from the Main-Server.
    if grep '^PROFILE=\".*Main-Server.*\"' /etc/debian-edu/config ; then
        ldapserver=$(debian-edu-ldapserver -f)
        ldapbase=$(debian-edu-ldapserver -f -s $ldapserver -b)
        # Tell nslcd to use FQDN for LDAP server to get SSL cert check working
        echo nslcd nslcd/ldap-uris string "ldap://$ldapserver" | \
            in_target debconf-set-selections || \
            error "Failed to load preseed 'nslcd/ldap-uris'"

    else
        # Preseed Kerberos and LDAP stuff before installing packages.
        in_target /usr/share/debian-edu-config/tools/preseed-ldap-kerberos
        # Preseed Sitesummary too
        in_target /usr/share/debian-edu-config/tools/preseed-sitesummary
    fi

    # Fetch current default locale to make tasksel pick the correct
    # language specific tasks.
    if [ -e /etc/default/locale ] ; then
	. /etc/default/locale
    fi

    # Workaround for sudo refusing to be replaced by sudo-ldap when no
    # root password is set (#586887).
    SUDO_FORCE_REMOVE=yes
    export SUDO_FORCE_REMOVE

    info "installing packages the same way tasksel do it"

    # Query tasksel for its apt-get command, and use it directly to
    # get output from the process.
    diverts_insert
    cmd="$(LANG=$LANG in_target tasksel -t --new-install | sed 's/debconf-apt-progress -- //')"
    info "cmd: $cmd"
    if in_target $cmd ; then
        diverts_remove
    else
        diverts_remove
        return 1
    fi

    # Get rid of lvm2, as it causes the shutdown to hang.
    in_target apt-get -y purge lvm2

    # Get rid of some network services we do not want on diskless
    # workstations
    in_target apt-get -y purge munin-node xfs

    # LTSP take care of updating resolv.conf, no need to have
    # resolvconf try to do the same.
    in_target apt-get -y purge resolvconf

    # No dynamic network configuration on diskless clients.
    in_target apt-get -y purge network-manager wpasupplicant \
	network-manager-openvpn network-manager-pptp network-manager-vpnc

    # Do not fail if openvpn isn't installed.  This is the case in Jessie
    in_target apt-get -y purge openvpn || true

    # No VPN nor serial network either
    in_target apt-get -y purge ppp

    # No modem either
    in_target apt-get -y purge modemmanager

    # consolekit is deprecated: replacement is systemd-logind.
    in_target apt-get -y purge consolekit

    # cups isn't needed for LTSP clients to be able to print.
    in_target apt-get -y purge cups

    # Missing unique ID on the clients, so no use keeping it around
    in_target apt-get -y purge popularity-contest

    # Probably not very useful without a disk
    in_target apt-get -y purge readahead readahead-fedora hdparm hddtemp

    # Remove dependencies pulled in by removed packages
    in_target apt-get -y --purge autoremove

    # Needed to get the loopback interface
    only_run_on_rclevel S ifupdown networking

    # Needed to get utmp (and w/who working)
    only_run_on_rclevel S bootmisc.sh

    # a lot of services should only be started in runlevel 3, eg, when
    # running in workstation mode.  Portmap should not start in rcS.d,
    # to avoid it on thin clients.
    #enable_on_rclevel portmap 3
    #enable_on_rclevel nfs-common 3
    #enable_on_rclevel dbus 3
    #enable_on_rclevel hal 3
    #only_run_on_rclevel 3 gdm kdm xdm nscd cupsys autofs pulseaudio \
    #    rpcbind nfs-common nslcd rwhod saned cups timidity jackd cron \
    #    speech-dispatcher binfmt-support avahi-daemon bluetooth

    # a lot of services should only be started in runlevel 4, eg. when running
    # in thin client mode
    #only_run_on_rclevel 4 ltsp-client samba ltsp-client-core

    # Some services should not be started on the terminals
    only_run_on_rclevel N enable-nat \
        cfengine2 xdebian-edu-firstboot \
        early-readahead later-readahead readahead readahead-desktop \
        stop-readahead stop-readahead-fedora \
        exim4 openvpn \
        resize_lvm hdparm rsync hddtemp fam resolvconf fetch-ldap-cert \
        firefox-ldapconf

    # check which network the install is on, and start either as
    # diskless workstation or thin client.  Make sure to insert these
    # after using only_run_on_rclevel, as the latter do not invoke
    # update-rc.d to reorder scripts based on dependencies.
    #if [ ! -h $ROOT/etc/init.d/ltsp_set_runlevel ] ; then
    #    ln -s /usr/share/debian-edu-config/ltsp_set_runlevel \
    #        $ROOT/etc/init.d/ltsp_set_runlevel
    #    in_target update-rc.d ltsp_set_runlevel start 99 S .
    #fi

    # make cdrom and other static local devices work for diskless
    # workstation.
    #if [ ! -h $ROOT/etc/init.d/ltsp_local_mount ] ; then
    #    ln -sf /usr/share/debian-edu-config/ltsp_local_mount \
    #        $ROOT/etc/init.d/ltsp_local_mount
    #    in_target update-rc.d ltsp_local_mount start 01 3 .
    #fi


    # Disable the cron jobs that should not be running on a diskless
    # workstation.  Keep rwhod, shutdown-at-night and
    # sitesummary-client.
    disable_cronjob \
        apt \
        apt-xapian-index \
        aptitude \
        bsdmainutils \
        cvs \
        debian-edu-config \
        desktop-profiles \
        dpkg \
        etcinsvk \
        etckeeper \
        exim4-base \
        htdig \
        killer \
        logrotate \
        man-db \
        mlocate \
        ntp \
        popularity-contest \
        readahead \
        readahead-monthly \
        scrollkeeper \
        standard

    # Make sure ifupdown knows about loopback
    cat <<'EOF' | append_if_missing $ROOT/etc/network/interfaces \
    "iface lo inet loopback"
# The loopback network interface
auto lo
iface lo inet loopback
    dns-search intern
EOF

    # Create /skole, since the chroot will be read-only
    mkdir -p $ROOT/skole

    etcvcs_commit "Before cfengine is executed"

    # Make sure Debian::Edu find the correct LDAP server when
    # autodetection do not work.
    if grep '^PROFILE=\".*Main-Server.*\"' /etc/debian-edu/config ; then
        cat >> $ROOT/etc/ldap/ldap.conf <<EOF
HOST $ldapserver
BASE $ldapbase
EOF
    fi

    # Make the ldap users availible in the chroot
    in_target cfengine-debian-edu -Dinstallation

    etcvcs_commit "After cfengine is executed"

    # it is nice to have a running ssh for the admin
    rm -f $ROOT/etc/ssh/sshd_not_to_be_run

    etcvcs_commit "After diskless workstation is set up"
}

case "$MODE" in
    commandline)
        add_option "no-diskless-edu-workstation" "$(eval_gettext "do not install debian-edu diskless workstation environment")" "advanced" "false"
        option_diskless_edu_workstation_value=true
        ;;
    configure)
        if [ -n "$option_no_diskless_edu_workstation_value" ]; then
            option_diskless_edu_workstation_value=""
        fi
        # education-thin-client should contain all dependencies needed
        DEBCONF_SEEDS="$DEBCONF_SEEDS /usr/lib/debian-edu-install/defaults.ltsp-chroot"
        LATE_PACKAGES="$LATE_PACKAGES education-thin-client openbsd-inetd"
        if [ -n "$option_diskless_edu_workstation_value" ]; then
            # Be backwards compatible with ltsp-make-client, and allow
            # the diskless workstation setup to be disabled during
            # installation.
            if grep -wq edu-skip-ltsp-make-client /proc/cmdline ; then
                info "Found edu-skip-ltsp-make-client in /proc/cmdline"
                info "Not generating diskless workstation."
                option_diskless_edu_workstation_value=""
            else
                # Try to get the sudo package we want without having
                # to first install sudo and then try to switch to
                # sudo-ldap (which fail due to #586887).
                EARLY_PACKAGES="$EARLY_PACKAGES sudo-ldap"

                LATE_PACKAGES="$LATE_PACKAGES debian-edu-archive-keyring education-tasks"
            fi
        fi
        ;;
    install)
        if [ -n "$option_diskless_edu_workstation_value" ]; then
            if [ "true" = "$LTSP_CDROM_INSTALL" ]; then
                # Our CDs and DVDs are unsigned, so we can not check
                # authentication when using them.  These options
                # should work with apt and aptitude.  Need to do this
                # as well as the --allow-unauthenticated option above,
                # to make sure aptitude work for installing diskless
                # workstation packages.
                (
                    echo 'APT::Get::AllowUnauthenticated "true";'
                    echo 'APT::Authentication::TrustCDROM "true";'
                    echo 'APT::Cmdline::ignore-trust-violations "true";'
                ) >> $ROOT/etc/apt/apt.conf.d/90ltsp-build-client
            fi

            # Bind-mount /var/cache/apt/archives/ on
            # $target/var/cache/apt/archives/, to avoid having to
            # download packages twice.
            chroot_mount /var/cache/apt/archives /var/cache/apt/archives --bind
        fi

        # Try to speed up installation by dropping some fsync() calls
        # in dpkg.  This is the same d-i is doing on first time
        # installations.
        cat > $ROOT/etc/dpkg/dpkg.cfg.d/force-unsafe-io <<EOF
force-unsafe-io
EOF
        ;;
    finalization)
        # Run this in finalization and not in after-install to make
        # sure boot system modifications are done after the ones done
        # in LTSP by default.
        if [ -n "$option_diskless_edu_workstation_value" ]; then
            setup_diskless_workstation
            if [ "true" = "$LTSP_CDROM_INSTALL" ]; then
                rm -f $ROOT/etc/apt/apt.conf.d/90ltsp-build-client
            fi
        fi

        # Remove dpkg optimization after setup_diskless_workstation,
        # to ensure it have effect while most packages are installed.
        rm $ROOT/etc/dpkg/dpkg.cfg.d/force-unsafe-io
        ;;
esac
