#!/usr/bin/env bash
#
# Author: Dmitry Razumov <asmeron@ublinux.com>
# Copyright (c) 2021-2025 UBLinux <support@ublinux.com>
#

ENABLED=yes
[[ ${ENABLED} == "yes" ]] || exit 0
DEBUGMODE=no

unset ROOTFS; [[ -d /usr/lib/ublinux ]] || ROOTFS=.
SOURCE=${ROOTFS}/usr/lib/ublinux/functions; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
SOURCE=${ROOTFS}/usr/lib/ublinux/default; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null || exit 0
debug_mode "$0" "$@"

SYSCONF="${ROOTFS}${SYSCONF}"
SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
SOURCE=${SYSCONF}/boot; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null

get_path_grub2(){
    NAME_GRUB_CFG="grub.cfg"
    PATH_GRUB=$(find /memory/data/from/*/boot/grub/ -maxdepth 1 -type f -name "${NAME_GRUB_CFG}" | head -1)
    [[ -n ${PATH_GRUB} ]] || PATH_GRUB="$(find /memory/data/from/*/ -maxdepth 3 -type f -name "${NAME_GRUB_CFG}" | head -1)"
    [[ -n ${PATH_GRUB} ]] || return 1
    [[ -w ${PATH_GRUB} ]] && PATH_GRUB="${PATH_GRUB%/*}" || return 1
}
control_grub_var_cfg(){
    if [[ -n ${STR_SET_VALUE} ]]; then
	grep -q "${STR_EXPORT}" ${FILE_GRUB_VAR_USER}  2>/dev/null || echo -e "${STR_EXPORT}" >> ${FILE_GRUB_VAR_USER}
	if ! grep -q "^\s*${STR_SET}${STR_SET_VALUE}\s*$" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	    local QUOTA
	    [[ ${STR_SET_VALUE} =~ " " ]] && QUOTA="\""
	    if grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
		sed -E "s/^\s*(${STR_SET}).*/\1${QUOTA}${STR_SET_VALUE}${QUOTA}/" -i ${FILE_GRUB_VAR_USER}
	    else
		sed "/${STR_EXPORT}/i${STR_SET}${QUOTA}${STR_SET_VALUE}${QUOTA}" -i ${FILE_GRUB_VAR_USER}
	    fi
	fi
    elif grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	sed "/^\s*${STR_SET}.*/d; /^\s*${STR_EXPORT}\s*$/d" -i ${FILE_GRUB_VAR_USER}
    fi
}
exec_grub_timeout(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_TIMEOUT}"
    STR_SET="set timeout="
    STR_EXPORT="export timeout"
    control_grub_var_cfg
}
exec_grub_default(){
    [[ -n $@ ]] && GRUB_DEFAULT="$@"
    if [[ -n ${GRUB_DEFAULT} ]]; then
	FILE_GRUBENV="${PATH_GRUB}/grubenv"
	DATA_GRUBENV=$(cat <<EOF
# GRUB Environment Block
saved_entry=${GRUB_DEFAULT}
EOF
)
	LC_ALL=C
#	echo -e "${DATA_GRUBENV}$(yes "" | head -n $((1024-"${#DATA_GRUBENV}")) | tr \\n '#')" > "${PATH_GRUB}/grubenv"
	echo -ne "${DATA_GRUBENV}\n$(printf -- '#'%.s $(seq -s ' ' $((1023-"${#DATA_GRUBENV}"))))" > "${PATH_GRUB}/grubenv"
    fi
}
exec_grub_superusers(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_SUPERUSERS}"
    STR_SET="set superusers="
    STR_EXPORT="export superusers"
    control_grub_var_cfg
}
exec_grub_password(){
    [[ -n $@ ]] && GRUB_PASSWORD="$@"
    if [[ -n ${GRUB_PASSWORD[0]} ]]; then 
	[[ -n ${GRUB_SUPERUSERS} ]] || return 1
	FIRST_SUPERUSER=${GRUB_SUPERUSERS//\"/}; FIRST_SUPERUSER=${FIRST_SUPERUSER%%,*}; FIRST_SUPERUSER=${FIRST_SUPERUSER%% *}
	local -A GRUB_PASSWORD=( [${FIRST_SUPERUSER}]="${GRUB_PASSWORD}" )
    fi
    if [[ -n ${GRUB_PASSWORD[@]} ]]; then
 	for NAME_USER in "${!GRUB_PASSWORD[@]}"; do
	    STR_SET="password_pbkdf2 ${NAME_USER} "
	    STR_SET_VALUE=${GRUB_PASSWORD[${NAME_USER}]}
	    if [[ ! ${STR_SET_VALUE} =~ ^grub.pbkdf2 ]]; then 
		STR_SET_VALUE=$(echo -e "${STR_SET_VALUE}\n${STR_SET_VALUE}" | grub-mkpasswd-pbkdf2 | awk '/grub.pbkdf/{print$NF}')
		ubconfig --noexecute set boot GRUB_PASSWORD[${NAME_USER}]=${STR_SET_VALUE}
	    fi
	    if ! grep -q "^\s*${STR_SET}${STR_SET_VALUE}$" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
		if grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
		    sed -E "s/^\s*(${STR_SET}).*/\1${STR_SET_VALUE}/" -i ${FILE_GRUB_VAR_USER}
		else
		    echo "${STR_SET}${STR_SET_VALUE}" >> ${FILE_GRUB_VAR_USER}
		fi
	    fi
	done
	# Проверка по файлу ${FILE_GRUB_VAR_USER}, если пароль на пользователя присутствует, но его нет в конфигурации, то удалить из ${FILE_GRUB_VAR_USER}
	while read -r NAME_USER; do
	    [[ -n ${GRUB_PASSWORD[${NAME_USER}]} ]] || sed "/^\s*password_pbkdf2 ${NAME_USER}.*/d" -i ${FILE_GRUB_VAR_USER}
	done < <(sed -En "s/^\s*password_pbkdf2 (.*) .*/\1/p" ${FILE_GRUB_VAR_USER})
    elif grep -q "^\s*password_pbkdf2" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	sed "/^\s*password_pbkdf2.*/d" -i ${FILE_GRUB_VAR_USER}
    fi
}
exec_grub_boot_silent(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_BOOT_SILENT}"
    STR_SET="set BOOT_SILENT="
    STR_EXPORT="export BOOT_SILENT"
    control_grub_var_cfg
}
exec_grub_terminal_input(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_TERMINAL_INPUT}"
    STR_SET="terminal_input "
    if [[ -n ${STR_SET_VALUE} ]]; then
	if ! grep -q "^\s*${STR_SET}${STR_SET_VALUE}\s*$" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	    if grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
		sed -E "s/^\s*(${STR_SET}).*/\1${STR_SET_VALUE}/" -i ${FILE_GRUB_VAR_USER}
	    else
		echo "${STR_SET}${STR_SET_VALUE}" >> ${FILE_GRUB_VAR_USER}
	    fi
	    if [[ ${STR_SET_VALUE} =~ "serial" ]]; then
		grep -q "^\s*serial\s*$" ${FILE_GRUB_VAR_USER} 2>/dev/null || sed "/${STR_SET}/iserial" -i ${FILE_GRUB_VAR_USER}
	    else
		grep -q "^\s*serial\s*$" ${FILE_GRUB_VAR_USER} 2>/dev/null && sed "/^serial$/d" -i ${FILE_GRUB_VAR_USER}
	    fi
	fi
    elif grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	sed "/^\s*${STR_SET}.*/d; /^\s*serial\s*$/d" -i ${FILE_GRUB_VAR_USER}
    fi
}
exec_grub_terminal_output(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_TERMINAL_OUTPUT}"
    STR_SET="terminal_output "
    if [[ -n ${STR_SET_VALUE} ]]; then
	if ! grep -q "^\s*${STR_SET}${STR_SET_VALUE}\s*$" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	    if grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
		sed -E "s/^\s*(${STR_SET}).*/\1${STR_SET_VALUE}/" -i ${FILE_GRUB_VAR_USER}
	    else
		echo "${STR_SET}${STR_SET_VALUE}" >> ${FILE_GRUB_VAR_USER}
	    fi
	fi
    elif grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	sed "/^\s*${STR_SET}.*/d" -i ${FILE_GRUB_VAR_USER}
    fi
}
exec_grub_play(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_PLAY}"
    STR_SET="play "
    if [[ -n ${STR_SET_VALUE} ]]; then
	if ! grep -q "^\s*${STR_SET}${STR_SET_VALUE}\s*$" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	    if grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
		sed -E "s/^\s*(${STR_SET}).*/\1${STR_SET_VALUE}/" -i ${FILE_GRUB_VAR_USER}
	    else
		echo "${STR_SET}${STR_SET_VALUE}" >> ${FILE_GRUB_VAR_USER}
	    fi
	fi
    elif grep -q "${STR_SET}" ${FILE_GRUB_VAR_USER} 2>/dev/null; then
	sed "/^\s*${STR_SET}.*/d" -i ${FILE_GRUB_VAR_USER}
    fi
}
exec_grub_cmdline_linux(){
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_CMDLINE_LINUX}"
    STR_SET="set CMDLINE_LINUX="
    STR_EXPORT="export CMDLINE_LINUX"
    control_grub_var_cfg
}
exec_grub_vmlinuz_file(){
    [[ -z ${KERNEL_BOOT} ]] || return 0
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_VMLINUZ_FILE}"
    STR_SET="set VMLINUZ_FILE="
    STR_EXPORT="export VMLINUZ_FILE"
    control_grub_var_cfg
}
exec_grub_ublinux_file(){
    [[ -z ${KERNEL_BOOT} ]] || return 0
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_UBLINUX_FILE}"
    STR_SET="set UBLINUX_FILE="
    STR_EXPORT="export UBLINUX_FILE"
    control_grub_var_cfg
}
exec_grub_addon_file(){
    [[ -z ${KERNEL_BOOT} ]] || return 0
    [[ -n $@ ]] && STR_SET_VALUE="$@" || STR_SET_VALUE="${GRUB_ADDON_FILE}"
    STR_SET="set ADDON_FILE="
    STR_EXPORT="export ADDON_FILE"
    control_grub_var_cfg
}
exec_grub_kernel_boot(){
# По указанному имени пакета в параметре KERNEL_BOOT= находим каталог с ядром и устаналиваем переменные в GRUB
    [[ -n $@ ]] && PKG_KERNEL_NAME="$@" || PKG_KERNEL_NAME="${KERNEL_BOOT}"
    PATH_KERNEL="/usr/lib/modules"
    PKG_KERNEL_PATH=$(grep -Rlx ${PATH_KERNEL}/*/pkgbase -e "${PKG_KERNEL_NAME}")
    if [[ -n ${PKG_KERNEL_PATH} ]]; then
        PKG_KERNEL_PATH=${PKG_KERNEL_PATH%/*}
        STR_SET_VALUE_VMLINUZ=$(find ${PKG_KERNEL_PATH} -maxdepth 1 -name "vmlinuz-*.*.*-*" -printf "%f\n")
        STR_SET_VALUE_UBLINUX=$(find ${PKG_KERNEL_PATH} -maxdepth 1 -name "ublinux-*.*.*-*" -printf "%f\n")
        STR_SET_VALUE_ADDOD=$(find ${PKG_KERNEL_PATH} -maxdepth 1 -name "addon-*.*.*-*" -printf "%f\n")
    else
        STR_SET_VALUE_VMLINUZ=""
        STR_SET_VALUE_UBLINUX=""
        STR_SET_VALUE_ADDOD=""
    fi
    STR_SET_VALUE="${STR_SET_VALUE_VMLINUZ}"; STR_SET="set VMLINUZ_FILE="; STR_EXPORT="export VMLINUZ_FILE"; control_grub_var_cfg
    STR_SET_VALUE="${STR_SET_VALUE_UBLINUX}"; STR_SET="set UBLINUX_FILE="; STR_EXPORT="export UBLINUX_FILE"; control_grub_var_cfg
    STR_SET_VALUE="${STR_SET_VALUE_ADDOD}"; STR_SET="set ADDON_FILE="; STR_EXPORT="export ADDON_FILE"; control_grub_var_cfg
}

################
##### MAIN #####
################
# Возможность подключить как source из любого скрипта и вызов встроенных функций

    get_path_grub2 || exit 1
    FILE_GRUB_VAR_USER="${PATH_GRUB}/ublinux/grub_var_user.cfg"
    [[ -f ${FILE_GRUB_VAR_USER} ]] || touch ${FILE_GRUB_VAR_USER}

    # Если файл подключен как ресурс с функциями, то выйти
    return 0 2>/dev/null && return 0
    if [[ -z $@ ]]; then
        while read -r FUNCTION; do
            $"${FUNCTION##* }"
        done < <(declare -F | grep "declare -f exec_")
    else
	FUNCTION=
	while [[ $# -gt 0 ]]; do
	    [[ -z ${1} ]] || { declare -f "${1}" &>/dev/null && FUNCTION+="; ${1}" || FUNCTION+=" '${1//\'/}'"; }
	    shift
	done
	eval ${FUNCTION#*; }
    fi

