#!/bin/bash
#
# Copyright (C) 2007-2009  Stanislav Ievlev <inger@altlinux.org>
# Copyright (C) 2009  Dmitry V. Levin <ldv@altlinux.org>
# Copyright (C) 2009  Sergey Bolshakov <sbolshakov@altlinux.org>
# Copyright (C) 2011  Andrey Cherepanov <cas@altlinux.org>
# Copyright (C) 2011-2020  Anton V. Boyarshinov <boyarsh@altlinux.org>
# Copyright (C) 2011  Michael Shigorin <mike@altlinux.org>
# Copyright (C) 2011  Mikhail Efremov <sem@altlinux.org>
# Copyright (C) 2021  Paul Wolneykien <manowar@altlinux.org>
# Copyright (C) 2022-2025  Anton Midyukov <antohami@altlinux.org>
# Copyright (C) 2024  Ajrat Makhmutov <rauty@altlinux.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

. shell-config
. shell-var

### global variables
pipedir="/var/run/alterator-pkg/"
errpipe="$pipedir/stderr.fifo"
inpipe="$pipedir/stdin.fifo"

slideshow_conf="/etc/alterator/slideshow.conf"
# Default slideshow timeout, sec
default_slideshow_step=30
default_slideshow_path="/usr/share/install2/slideshow"

alterator_api_version=1

pipe_pid=
templist=

. alterator-sh-functions
. install2-init-functions
. alterator-pkg-functions

### pipe handlers

exit_handler()
{
    local rc=$?
    trap - EXIT
	
    rm -f "$templist"
    stop_pipe
    exit $rc
}

stdin_handler()
{
    while :; do
        [  -e "$inpipe" ] || break
    	    while read n; do
	        if [ "$n" = "q" ]; then
	    	    rm -f "$inpipe"
		    break 2
		fi
		echo "$n"
	    done < "$inpipe"
    done
}

message_quote()
{
    echo "$1"|string_quote
}

stderr_handler()
{
    while read -r n; do
	printf >&2 '%s\n' "$n"
	alterator-mailbox-send "error \"$(message_quote "$n")\""
    done <"$errpipe"
}

stdout_handler()
{
    while read -r n;do
	[ -z "${DURING_INSTALL-}" ] ||
		printf >&2 '%s\n' "$n"
	alterator-mailbox-send "message \"$(message_quote "$n")\""
    done
    write_pipe "q"
}


### main pipe operations

make_manifest()
{
    [ "$#" -gt 0 ] || return

    templist="$(mktemp -t pkg-install.XXXXXX)"

	cd "$lists_dir"
	    paste -d\\n "$@" |
		sed -r \
		    -e '/^[[:space:]]*$/ d' \
		    -e '/-[[:space:]]*$/ d' \
		    -e '/^[[:space:]]*#/ d' \
		    -e '/^[^[:space:]#]+/ s/[[:space:]]+/\n/g' \
		    >"$templist"
	cd - >/dev/null

    echo "$templist"
}

#note first install rpm to have correct package install order (setup and filesystem should be first packages)
make_apt()
{
	local rc=0
	echo "pkg-install:start"
	if [ -r "$pkg_list_file" ]; then
		echo "reading the list of package groups from $pkg_list_file"
		in_lists=$(cat "$pkg_list_file")
	fi

	local base_listname=".base"
	if [ -r "$lists_dir/$edition_id/base" ]; then
		read_use_edition_conf && base_listname="$edition_id/base"
	fi
	local base_tmpfile="$(make_manifest ${base_listname})"
	local rest_tmpfile="$(make_manifest ${in_lists//;/ })"
	echo "base_tmpfile=$base_tmpfile" >&2
	echo "rest_tmpfile=$rest_tmpfile" >&2

	if [ -s "$base_tmpfile" -o -s "$rest_tmpfile" ]; then
	    echo "pkg-install:stage-index"
	    apt-get update

	    echo "pkg-install:stage-rpm"
	    apt-get -y --simple-output install rpm

	    echo "pkg-install:stage-install-base"
	    if [ -s "$base_tmpfile" ]; then
		if test_bool "$in_auto"; then
		    apt-get -y --simple-output install --manifest "$base_tmpfile" || rc=$?
		else
		    stderr_handler &
		    apt-get -y --simple-output install --manifest "$base_tmpfile" 2>"$errpipe" || rc=$?
		fi
		xargs apt-mark manual < "$base_tmpfile" || rc=$?
	    fi

	    echo "pkg-install:stage-install-rest"
	    if [ "$rc" = "0" -a -s "$rest_tmpfile" ]; then
		if test_bool "$in_auto"; then
		    apt-get -y --simple-output install --manifest "$rest_tmpfile" || rc=$?
		else
		    stderr_handler &
		    apt-get -y --simple-output install --manifest "$rest_tmpfile" 2>"$errpipe" || rc=$?
		fi
		xargs apt-mark manual < "$rest_tmpfile" || rc=$?
	    fi
	fi
	rm -f -- "$base_tmpfile" "$rest_tmpfile"
	echo "pkg-install:finish:$rc"
}

make_pipe()
{
    mkdir -p "$pipedir"
    [ -p "$errpipe" ] || (rm -rf "$errpipe"; mkfifo -m600 "$errpipe")
    [ -p "$inpipe" ] || (rm -rf "$inpipe"; mkfifo -m600 "$inpipe")

    stdin_handler|make_apt|stdout_handler
}

write_pipe()
{
    if [ -n "$pipe_pid" ] && kill -0 "$pipe_pid" ;then
	[ ! -p "$inpipe" ] || echo "$in_message" >"$inpipe"
    fi
}

stop_pipe()
{
    write_pipe "q"
    killall -9 apt-get >/dev/null 2>/dev/null ||:
    rm -f "$errpipe" "$inpipe"
}

start_pipe()
{
    stop_pipe
    make_pipe&
    pipe_pid=$!
}

### slideshow configuration
read_slideshow_conf()
{
	local step="$(shell_config_get "$slideshow_conf" step)"
	if [ -z "$step" ] || echo "$step" | grep -Evqs '^[[:digit:]]+$'; then
		step="$default_slideshow_step"
	fi
	write_string_param step "$step"

	local once="$(shell_config_get "$slideshow_conf" once)"
	if [ -n "$once" ] && shell_var_is_yes "$once"; then
		once='true'
	else
		once='false'
	fi
	write_bool_param once "$once"

	local url="$(shell_config_get "$slideshow_conf" url)"
	[ -n "$url" ] || url="$default_slideshow_path"
	write_string_param url "$url"
}

### initial actions

export LANG=C
trap exit_handler EXIT HUP INT QUIT TERM

on_message()
{
	case "$in_action" in
		read)
			case "$in__objects" in
				slideshow-config)
					read_slideshow_conf
				;;
				*)
				;;
			esac
			;;
		write)
			[ ! -f "$destdir"/_NEW_SYSTEM_ ] || export DURING_INSTALL=1
			[ -z "$AUTOINSTALL" ] || in_auto='#t'
			case "$in__objects" in
			    /)
				run-parts /usr/lib/alterator/hooks/pkg-preinstall.d
				if test_bool "$in_auto"; then
					make_apt < /dev/null &> /tmp/pkg-install.log
				else
					start_pipe &> /tmp/pkg-install.log
				fi
				;;
			    notify)
				write_pipe "$in_message"
				;;
			esac
			;;
	esac
}

message_loop
