|
|
#!/usr/bin/bash
|
|
|
#
|
|
|
# Author: Dmitry Razumov <asmeron@ublinux.com>
|
|
|
# Copyright (c) 2021-2025 UBLinux <support@ublinux.com>
|
|
|
#
|
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
#
|
|
|
|
|
|
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
|