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

ENABLED=yes
[[ ${ENABLED} == yes ]] || exit 0

DEFAULT_CONF=$(< /usr/lib/ublinux/default)
[[ ${DEFAULT_CONF} =~ (^|$'\n')[[:blank:]]*SYSCONF=([^$|$'\n']+)[[:blank:]]*($|$'\n') ]] && SYSCONF=${BASH_REMATCH[2]} || SYSCONF="/etc/sysconf"

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

# Extended pattern matching: https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html#Pattern-Matching
shopt -s extglob

##  Назначение модулей:
##  account   подтвердить личность, проверив учетные данные, такие как пароль, ключ, токен и другие
##  auth      проверить авторизацию для таких действий, как разрешения, ограничения и т. д.
##  password  обновить учетные данные
##  session   распределять ресурсы во время входа в систему, такие как личные данные, лимиты и другие.
##
##  Выполнение из /etc/pam.d/system-login
##  Тип модуля: session
##  Глобальные переменные:
##    PAM_RHOST    Удалённый хост
##    PAM_RUSER    Удалённый пользователь
##    PAM_SERVICE  Сервис выполняющий вход /etc/pam.d/service_name
##    PAM_TTY      Консоль, может быть как "/dev/tty2" так и ":0"
##    PAM_USER     Текущий пользователь
##    PAM_TYPE     Тип сессии, возможные значения: account, auth, password, open_session, close_session
##
## PAM_RHOST=        PAM_RUSER= PAM_SERVICE=login             PAM_TTY=/dev/tty2 PAM_USER=superadmin PAM_TYPE=open_session
## PAM_RHOST=        PAM_RUSER= PAM_SERVICE=login             PAM_TTY=/dev/tty2 PAM_USER=superadmin PAM_TYPE=close_session
## PAM_RHOST=        PAM_RUSER= PAM_SERVICE=lightdm-autologin PAM_TTY=:0        PAM_USER=superadmin PAM_TYPE=open_session
## PAM_RHOST=        PAM_RUSER= PAM_SERVICE=systemd-user      PAM_TTY=          PAM_USER=lightdm    PAM_TYPE=open_session
## PAM_RHOST=        PAM_RUSER= PAM_SERVICE=systemd-user      PAM_TTY=          PAM_USER=user-2     PAM_TYPE=open_session
## PAM_RHOST=        PAM_RUSER= PAM_SERVICE=lightdm           PAM_TTY=:0        PAM_USER=user-2     PAM_TYPE=open_session
## PAM_RHOST=1.2.3.4 PAM_RUSER= PAM_SERVICE=sshd              PAM_TTY=ssh       PAM_USER=user-2     PAM_TYPE=open_session

if [[ ${PAM_TYPE} == "open_session" && -n ${PAM_USER} ]]; then
# Выполнение функции вызвано используя PAM, получаем имя пользователя вызвавшего PAM, будем пременять только для пользователя
    SELECT_USERNAME="${PAM_USER}"
fi

declare -A USERADD

# По сокращённому имени, вернуть полное имя, пример 'get_fullname_lang en' : en_US.UTF-8
get_fullname_lang(){
    local NEWLANG=$1
    local SUPPORTED=$(< ${ROOTFS}/usr/share/i18n/SUPPORTED)
    # Из за того, что нет en_EN, а через груб прилетает просто en, то выбираем en_US.UTF-8
    [[ ${NEWLANG} == "en" ]] && NEWLANG="en_US.UTF-8"
    if [[ ${SUPPORTED} =~ ($'\n'|^)"${NEWLANG} ".*($'\n'|$) ]]; then
	echo "${NEWLANG}"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${NEWLANG,,}_${NEWLANG^^}.UTF-8 ".*($'\n'|$) ]]; then
	echo "${NEWLANG,,}_${NEWLANG^^}.UTF-8"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${NEWLANG,,}_${NEWLANG^^} ".*($'\n'|$) ]]; then
	echo "${NEWLANG,,}_${NEWLANG^^}"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)"${NEWLANG}.UTF-8 ".*($'\n'|$) ]]; then
	echo "${NEWLANG}.UTF-8"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)("${NEWLANG,,}_"[:A-Z:]+".UTF-8")" ".*($'\n'|$) ]]; then
	echo "${BASH_REMATCH[2]}"
    elif [[ ${SUPPORTED} =~ ($'\n'|^)("${NEWLANG,,}_"[:A-Z:]+)" ".*($'\n'|$) ]]; then
	echo "${BASH_REMATCH[2]}"
    else		
	echo "en_US.UTF-8"
    fi
}

## При после авторизации пользователя проверяем праметр в USERADD[*] --land у текужего пользователя, если задан, 
## то под указанную локал создаём файл "${HOME}/.config/locale.conf"
exec_01_user_locale(){
    [[ -n $1 ]] && SELECT_USERNAME="$1"
    if [[ -n ${SELECT_USERNAME} && -n ${USERADD[${SELECT_USERNAME}]} ]]; then
	local SELECT_GECOS SELECT_UID SELECT_GROUP SELECT_EXTRAGROUP SELECT_OPTIONAL SELECT_PASSWORD NULL
	local LANG=
	IFS=: read -r SELECT_GECOS SELECT_UID SELECT_GROUP SELECT_EXTRAGROUPS SELECT_OPTIONAL SELECT_PASSWORD NULL <<< "${USERADD[${SELECT_USERNAME}]}"
	[[ ${SELECT_OPTIONAL} =~ ("--lang ")([^' ']+)(' '|$) ]] && LANG="${BASH_REMATCH[2]}"
	if [[ ${LANG} == "system" ]]; then
	    rm -f ${HOME}/.config/locale.conf
	elif [[ -n ${LANG} ]]; then
	    LANG=$(get_fullname_lang ${LANG})
	    # Проверка выбранного языка в системе, и если не совпадает, то устанавливаем
	    local LOCALE_FILE=$(< /etc/locale.conf)
    	    LOCALEDEF_LIST="$(localedef --list-archive)"
    	    LOW_LOCALEDEF_LIST="${LOCALEDEF_LIST,,}"
    	    LOW_LANG=${LANG,,}
	    if [[ ${LOCALE_FILE} =~ (^|$'\n')[[:blank:]]*LANG=([^$|$'\n']+)[[:blank:]]*($|$'\n') && ! "${BASH_REMATCH[2]}" == "${LANG}" ]] \
	    && [[ ${LOW_LOCALEDEF_LIST//-/} =~ (^|$'\n')"${LOW_LANG//-/}"($|$'\n') ]]; then
		# Устанавливаем локаль
		env LANG="${LANG}" LANGUAGE="${LANG}" LC_CTYPE="${LANG}" LC_NUMERIC="${LANG}" \
		LC_TIME="${LANG}" LC_COLLATE="${LANG}" LC_MONETARY="${LANG}" LC_MESSAGES="${LANG}" LC_PAPER="${LANG}" \
		LC_NAME="${LANG}" LC_ADDRESS="${LANG}" LC_TELEPHONE="${LANG}" LC_MEASUREMENT="${LANG}" \
    		LC_IDENTIFICATION="${LANG}" locale > ${HOME}/.config/locale.conf 2>/dev/null
    		chown ${SELECT_USERNAME}:${SELECT_USERNAME} "${HOME}/.config/locale.conf" 2>/dev/null
	    fi
	fi
    fi    
}

################
##### MAIN #####
################

    # Если файл подключен как ресурс с функциями, то выйти
    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}'"; }
	    # Что-бы передавать пустые параметры как аргументы, нужно для соблюдения очередности и кол-ва, отключил [[ -z ${1} ]] ||
	    declare -f "${1}" &>/dev/null && FUNCTION+="; ${1}" || FUNCTION+=" '${1}'"
	    shift
	done
	eval ${FUNCTION#*; }
    fi
    true
