#!/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
#

ere_quote_grep() {
    # Что экранировать
    sed 's/[][\.|$(){}?+*^]/\\&/g' <<< "$*"
    # Что не экранировать
    #sed 's/[^a-zA-Z0-9=",;/_@#%&<> -]/\\&/g' <<< "$*"
}

ere_quote_sed() {
    # Что экранировать
    sed 's/[][\.|$(){}!?+*^;/]/\\&/g' <<< "$*"
    # Что не экранировать
    #sed 's/[^a-zA-Z0-9=",_@#%&<> -]/\\&/g' <<< "$*"
}

    # https://en.wikipedia.org/wiki/Crypt_(C)
    # https://man.archlinux.org/man/core/libxcrypt/crypt.5.en    # /etc/shadow file format
    # user:$6$.n.:17736:0:99999:7:::
    # [--] [----] [---] - [---] ----
    # |      |      |   |   |   |||+-----------> 9. Неиспользованный
    # |      |      |   |   |   ||+------------> 8. Срок годности
    # |      |      |   |   |   |+-------------> 7. Период бездействия
    # |      |      |   |   |   +--------------> 6. Период предупреждения
    # |      |      |   |   +------------------> 5. Максимальный возраст пароля
    # |      |      |   +----------------------> 4. Минимальный возраст пароля
    # |      |      +--------------------------> 3. Последнее изменение пароля
    # |      +---------------------------------> 2. Зашифрованный пароль
    # +----------------------------------------> 1. Имя пользователя
    # Если поле пароля содержит первый символ звездочку (*), то пользователь не сможет войти по паролю, но сможет другим способом (например по ключу через ssh)
    # Если поле пароля содержит первый символ восклицательный знак (!), то пользователь вообще не сможет войти, даже по ключу
    # Алгоритмы хеширования пароля:
    # (empty)	# DES
    # $_$	# BSDi
    # $1$	# MD5
    # $2$	# bcrypt based on Blowfish
    # $2a$	# Blowfish
    # $2b$	# OpenBSD blowfish
    # $2x$	# blowfish
    # $2y$	# Eksblowfish
    # $3$	# NTHASH
    # $5$	# SHA-256
    # $6$	# SHA-512
    # $7$	# scrypt
    # $md5$	# Solaris MD5
    # $sha1$	# PBKDF1 with SHA1
    # $gy$	# gost-yescrypt
    # $y$	# yescrypt
    # $argon2d$ # Argon2d
    # $argon2i$ # Argon2i
    # $argon2ds$ # Argon2ds
    # $argon2id$ # Argon2id
# Получить хеш пароля, тип хеша
# $1		# Режим получения хеша, значения: hash, phash
#   hash	# Вернуть хеш, если первые символы %%, то удалить их и вернуть хеш
#   phash	# Если первые символы %%, то убрать %% и вернуть не шифрованный пароль, в остальных случаях вернуть хеш
# $2		# Тип хеша, поддерживаются yescrypt|gost-yescrypt|scrypt|bcrypt|bcrypt-a|sha512crypt|sha256crypt|sunmd5|md5crypt|bsdicrypt|descrypt|nt
#		# В разработке argon2d|argon2i|argon2ds|argon2id
# $3 		# Пароль пользователя шифрованный или не шифрованный. Если шифрованный, то вернётся как есть.
# Применяется в ubconfig, 10-accounts
return_hash_password(){
    SOURCE=${SYSCONF}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    local DEFAULT_HASHPASSWD="yescrypt"
    local ARG_HASH=
    [[ $1 == @(hash|phash) ]] && ARG_MODE=$1 && shift
    [[ -n ${ARG_MODE} ]] || ARG_MODE='hash'
    [[ $1 == @(yescrypt|gost-yescrypt|scrypt|bcrypt|bcrypt-a|sha512crypt|sha256crypt|sunmd5|md5crypt|bsdicrypt|descrypt|nt|argon2d|argon2i|argon2ds|argon2id) ]] && ARG_HASH=$1 && shift
    [[ -n ${ARG_HASH} ]] || ARG_HASH=${HASHPASSWD}
    [[ -n ${ARG_HASH} ]] || ARG_HASH=$(${ROOTFS}/usr/bin/ubconfig --raw --default get users HASHPASSWD)
    [[ -n ${ARG_HASH} && ${ARG_HASH} != "(null)" ]] || ARG_HASH="${DEFAULT_HASHPASSWD}"
    local ARG_PASSWORD="$1"
    local HASH_PASSWORD=${ARG_PASSWORD}
    local BLOCK_PASSWORD=
    [[ -n ${ARG_PASSWORD} ]] || return 0
    if [[ ! ${ARG_PASSWORD} =~ ^('!*'|'!'|'!!'|'*')*'$'(_|1|2|2a|2b|2x|2y|3|4|5|6|7|md5|sha1|gy|y|argon2d|argon2i|argon2ds|argon2id)'$' ]]; then
	[[ ${ARG_PASSWORD} =~ ^'%%'(.*) ]] && ARG_PASSWORD=${BASH_REMATCH[1]} && HASH_PASSWORD=${ARG_PASSWORD} || ARG_MODE='hash'
	[[ ${ARG_PASSWORD} =~ ^'!*'(.*) ]] && ARG_PASSWORD=${BASH_REMATCH[1]} && HASH_PASSWORD=${ARG_PASSWORD} && BLOCK_PASSWORD="!*"
	[[ ${ARG_PASSWORD} =~ ^[!]+(.*) ]] && ARG_PASSWORD=${BASH_REMATCH[1]} && HASH_PASSWORD=${ARG_PASSWORD} && BLOCK_PASSWORD="!"
	[[ ${ARG_PASSWORD} =~ ^[*]+(.*) ]] && ARG_PASSWORD=${BASH_REMATCH[1]} && HASH_PASSWORD=${ARG_PASSWORD} && BLOCK_PASSWORD="*"
	if [[ ${ARG_PASSWORD} != @("*"|"") && ${ARG_MODE} == 'hash' ]]; then
	    if [[ ${ARG_HASH} =~ (yescrypt|gost-yescrypt|scrypt|bcrypt|bcrypt-a|sha512crypt|sha256crypt|md5crypt|descrypt) ]]; then
		HASH_PASSWORD=$(echo "${ARG_PASSWORD}" | ${ROOTFS}/usr/bin/mkpasswd2 -sm ${ARG_HASH})
    	    elif [[ ${ARG_HASH} =~ (sunmd5|bsdicrypt|nt) ]]; then
		# Алгоритм отключен, использует алгоритм по умолчанию ${DEFAULT_HASHPASSWD}
		HASH_PASSWORD=$(echo "${ARG_PASSWORD}" | ${ROOTFS}/usr/bin/mkpasswd2 -sm ${DEFAULT_HASHPASSWD})
    	    elif [[ ${ARG_HASH} =~ (argon2d|argon2i|argon2ds|argon2id) ]]; then
		# Алгоритм отключен, использует алгоритм по умолчанию ${DEFAULT_HASHPASSWD}
		HASH_PASSWORD=$(echo "${ARG_PASSWORD}" | ${ROOTFS}/usr/bin/mkpasswd2 -sm ${DEFAULT_HASHPASSWD})
	    else
		HASH_PASSWORD=$(echo "${ARG_PASSWORD}" | ${ROOTFS}/usr/bin/mkpasswd2 -sm ${DEFAULT_HASHPASSWD})
	    fi
	fi
    fi
    echo "${BLOCK_PASSWORD}${HASH_PASSWORD}"
}

# Получить хеш пароля base64
# $1		# Режим получения хеша, значения: hash, phash
#   hash	# Вернуть хеш, если первые символы %%, то удалить их и вернуть хеш
#   phash	# Если первые символы %%, то убрать %% и вернуть не шифрованный пароль, в остальных случаях вернуть хеш
#   decode	# Если хеш, то декодировать в пароль
# $2 		# Пароль пользователя шифрованный или не шифрованный. Если шифрованный, то вернётся как есть.
# Применяется в ubconfig, 41-x11vnc
return_base64_password(){
    local ARG_HASH=
    [[ $1 == @(hash|phash|decode) ]] && ARG_MODE=$1 && shift
    [[ -n ${ARG_MODE} ]] || ARG_MODE='hash'
    local ARG_PASSWORD="$1"
    local HASH_PASSWORD=${ARG_PASSWORD}
    [[ -n ${ARG_PASSWORD} ]] || return 0
    if [[ ${ARG_MODE} == 'decode' ]]; then
	if [[ ${ARG_PASSWORD} =~ ^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=|[A-Za-z0-9+/][AQgw]==)?$ ]]; then
	    HASH_PASSWORD=$(${ROOTFS}/usr/bin/base64 -d <<< "${ARG_PASSWORD}" 2>/dev/null)
	    [[ ${HASH_PASSWORD} = *[^[:print:]]* ]] && HASH_PASSWORD=${ARG_PASSWORD}
	else
	    [[ ${ARG_PASSWORD} =~ ^'%%'(.*) ]] && ARG_PASSWORD=${BASH_REMATCH[1]} && HASH_PASSWORD=${ARG_PASSWORD}
	fi
    else
	if [[ ! ${ARG_PASSWORD} =~ ^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=|[A-Za-z0-9+/][AQgw]==)?$ ]]; then
	    [[ ${ARG_PASSWORD} =~ ^'%%'(.*) ]] && ARG_PASSWORD=${BASH_REMATCH[1]} && HASH_PASSWORD=${ARG_PASSWORD} || ARG_MODE='hash'
	    [[ ${ARG_MODE} == 'hash' ]] && HASH_PASSWORD=$(${ROOTFS}/usr/bin/base64 <<< "${ARG_PASSWORD}" 2>/dev/null)
	else
	    HASH_PASSWORD_TEST=$(return_base64_password decode "${ARG_PASSWORD}")
	    [[ ${ARG_PASSWORD} == ${HASH_PASSWORD_TEST} ]] && HASH_PASSWORD=$(${ROOTFS}/usr/bin/base64 <<< "${ARG_PASSWORD}" 2>/dev/null)
	fi
    fi
    echo "${HASH_PASSWORD}"
}

# External: ubl-settings-usergroups
#
# Если параметр $1 известный хеш, то вернуть true, иначе false
# Применяется ubl-settings-usergroup
is_hash_password(){
    local HASH_PASSWORD="$1"
    [[ -n ${HASH_PASSWORD} ]] || return 0
    [[ ${HASH_PASSWORD} =~ ^('!*'|'!'|'!!'|'*')*'$'(_|1|2|2a|2b|2x|2y|3|4|5|6|7|md5|sha1|gy|y|argon2d|argon2i|argon2ds|argon2id)'$' ]] || return 1
}

# External: ubl-settings-usergroups
#
# Remove user home directories. Used ubl-settings-usergroup
# $1	# Users name a comma separated list
# TODO: Запросить хомяк по умолчанию из /etc/default/useradd HOME=
remove_userhome(){
    local LIST_USERNAME="$@"
    [[ ${LIST_USERNAME} != "" ]] || return 1
    while IFS= read -r SELECT_USERNAME; do
	rm -rf ${ROOTFS}/home/"${SELECT_USERNAME}"
    done < <(tr ',;' '\n' <<< ${LIST_USERNAME})
}

# External: ubl-settings-usergroups
#
# Convert plain passwords to a hash in the global configuration
# Конвертировать не шифрованные пароли в шифрованные для глобальных переменных USERADD GROUPADD DEFAULTPASSWD DEFAULTROOTPASSWD
# $1	# Параметр конфигурации, где содержится пароль который нужно конвертировать, если первые символы %%, то пароль останется не шифрованным
# Если запущенно без параметра, то все пароли зашифровать в переменных USERADD GROUPADD DEFAULTPASSWD DEFAULTROOTPASSWD
globalconf_convert_pass_plain_to_hash(){
    [[ -z ${ROOTFS} ]] || return 0
    local PARAM="$@"
    local -A USERADD
    local -A GROUPADD
    local DEFAULTPASSWD
    local DEFAULTROOTPASSWD
    [[ -n ${HASHPASSWD} ]] || HASHPASSWD=$(/usr/bin/ubconfig --raw --default get users HASHPASSWD)
    [[ -n ${HASHPASSWD} && ${HASHPASSWD} != "(null)" ]] || HASHPASSWD='yescrypt'
    if [[ -n ${PARAM} ]]; then
        [[ ${PARAM} =~ ^[[:alnum:]_]+("="|"[".*"]=") ]] && eval "${PARAM%%=*}=\${PARAM#*=}"
    else
	SOURCE=${SYSCONF}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
	SOURCE=${SYSCONF}/.users_credential; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    fi
    # Проверим DEFAULTPASSWD, если не указан в $1, то подгрузить из глобальной конфигурации
    [[ -n ${PARAM} ]] || DEFAULTPASSWD=$(ubconfig --raw --source global get [users] DEFAULTPASSWD)
    if [[ -n ${DEFAULTPASSWD} && ${DEFAULTPASSWD} != "(null)" ]]; then
	if [[ -n ${PARAM} && $(is_hash_password ${DEFAULTPASSWD}) ]]; then
	    ubconfig set [users] DEFAULTPASSWD="${DEFAULTPASSWD}"
	else
	    #return_hash_password "${DEFAULTPASSWD}"
	    #[[ -n ${HASH_PASSWORD_NEW} ]] && ubconfig --noexecute --target global set [users] DEFAULTPASSWD="${HASH_PASSWORD_NEW}"
	    ubconfig set [users] DEFAULTPASSWD="$(return_hash_password hash ${HASHPASSWD} ${DEFAULTPASSWD})"
	fi
    fi
    # Проверим DEFAULTROOTPASSWD, если не указан в $1, то подгрузить из глобальной конфигурации
    [[ -n ${PARAM} ]] || DEFAULTROOTPASSWD=$(ubconfig --raw --source global get [users] DEFAULTROOTPASSWD)
    if [[ -n ${DEFAULTROOTPASSWD} && ${DEFAULTROOTPASSWD} != "(null)" ]]; then
	if [[ -n ${PARAM} && $(is_hash_password  ${DEFAULTROOTPASSWD}) ]]; then
	    ubconfig set [users] DEFAULTROOTPASSWD="${DEFAULTROOTPASSWD}"
	else
	    #return_hash_password "${DEFAULTROOTPASSWD}"
	    #[[ -n ${HASH_PASSWORD_NEW} ]] && ubconfig --noexecute --target global set [users] DEFAULTROOTPASSWD="${HASH_PASSWORD_NEW}"
	    ubconfig set [users] DEFAULTROOTPASSWD="$(return_hash_password hash ${HASHPASSWD} ${DEFAULTROOTPASSWD})"
	fi
    fi
    # Проверим USERADD, если не указан в $1, то подгрузить из глобальной конфигурации
    [[ -n ${PARAM} ]] || while IFS= read -r SELECT_USERADD; do
	if [[ ! ${SELECT_USERADD%%=*} =~ [!\$%\&()*+,/\;\<\=\>?\^\{|\}~] ]]; then
	    VAR_NAME=${SELECT_USERADD%%=*}
	    VAR_VALUE=${SELECT_USERADD#*=}; VAR_VALUE=${VAR_VALUE//(\'|\")/}
	    eval ${VAR_NAME}=${VAR_VALUE}
	fi
    done < <(ubconfig --source global get [users] USERADD[*])
    if [[ ${#USERADD[@]} != 0 ]]; then
        while IFS= read -u3 SELECT_USERNAME; do
    	    IFS=: read -r SELECT_GECOS SELECT_UID SELECT_GROUP SELECT_EXTRAGROUPS SELECT_OPTIONAL SELECT_PASSWORD NULL <<< "${USERADD[${SELECT_USERNAME}]}"
	    if [[ ${SELECT_PASSWORD} != "" ]]; then
		if [[ -n ${PARAM} && $(is_hash_password ${SELECT_PASSWORD}) ]]; then
		    ubconfig set [users] USERADD[${SELECT_USERNAME}]="${SELECT_GECOS}:${SELECT_UID}:${SELECT_GROUP}:${SELECT_EXTRAGROUPS}:${SELECT_OPTIONAL}:${SELECT_PASSWORD}"
		else
		    #return_hash_password "${SELECT_PASSWORD}"
		    #[[ -n ${HASH_PASSWORD_NEW} ]] && ubconfig --noexecute --target global set [users] USERADD[${SELECT_USERNAME}]="${SELECT_GECOS}:${SELECT_UID}:${SELECT_GROUP}:${SELECT_EXTRAGROUPS}:${SELECT_OPTIONAL}:${HASH_PASSWORD_NEW}"
		    ubconfig set [users] USERADD[${SELECT_USERNAME}]="${SELECT_GECOS}:${SELECT_UID}:${SELECT_GROUP}:${SELECT_EXTRAGROUPS}:${SELECT_OPTIONAL}:$(return_hash_password hash ${HASHPASSWD} ${SELECT_PASSWORD})"
		fi
	    fi
	done 3< <(printf "%s\n" "${!USERADD[@]}")
    fi
    # Проверим GROUPADD, если не указан в $1, то подгрузить из глобальной конфигурации
    [[ -n ${PARAM} ]] || while IFS= read -r SELECT_GROUPADD; do
	if [[ ! ${SELECT_GROUPADD%%=*} =~ [!\$%\&()*+,/\;\<\=\>?\^\{|\}~] ]]; then
	    VAR_NAME=${SELECT_GROUPADD%%=*}
	    VAR_VALUE=${SELECT_GROUPADD#*=}; VAR_VALUE=${VAR_VALUE//(\'|\")/}
	    eval ${VAR_NAME}=${VAR_VALUE}
	fi
    done < <(ubconfig --source global get [users] GROUPADD[*])
    if [[ ${#GROUPADD[@]} != 0 ]]; then
        while IFS= read -u3 SELECT_GROUP; do
    	    IFS=: read -r SELECT_USERS SELECT_GID SELECT_OPTIONAL SELECT_ADMINISTRATORS SELECT_PASSWORD NULL <<< "${GROUPADD[${SELECT_GROUP}]}"
	    if [[ ${SELECT_PASSWORD} != "" ]]; then
		if [[ -n ${PARAM} && $(is_hash_password ${SELECT_PASSWORD}) ]]; then
		    ubconfig set [users] GROUPADD[${SELECT_GROUP}]="${SELECT_USERS}:${SELECT_GID}:${SELECT_OPTIONAL}:${SELECT_ADMINISTRATORS}:${SELECT_PASSWORD}"
		else
		    #return_hash_password "${SELECT_PASSWORD}"
		    #[[ -n ${HASH_PASSWORD_NEW} ]] && ubconfig --noexecute --target global set [users] GROUPADD[${SELECT_GROUP}]="${SELECT_USERS}:${SELECT_GID}:${SELECT_OPTIONAL}:${SELECT_ADMINISTRATORS}:${HASH_PASSWORD_NEW}"
		    ubconfig set [users] GROUPADD[${SELECT_GROUP}]="${SELECT_USERS}:${SELECT_GID}:${SELECT_OPTIONAL}:${SELECT_ADMINISTRATORS}:$(return_hash_password hash ${HASHPASSWD} ${SELECT_PASSWORD})"
		fi
	    fi
	done 3< <(printf "%s\n" "${!GROUPADD[@]}")
    fi
}


#####################################################################################
###
### Функции получения от системы текущих настроек вида параметров от конфигурации ###
###
#####################################################################################

# External: ubl-settings-usergroups
#
# Получить запись вида конфигурации USERADD из системного пользователя
# Если системный пользователь имеет настройки аналогичные настройкам создаваемого пользователя через .sysusers, то не выводим
#   $1  		# Опции не обязательные
#     --not-only-changes # Отключить проверку изменений .sysusers, выводить любого пользователя системы
#   $2			# Варианты пользователей, можно указывать несколько через пробел, кроме nobody
#     <пуcто>		# Эквивалентно '@users @systems'
#     @users		# Все пользователи кроме системных, MIN_UID и MAX_UID взять из /etc/login.defs
#     @systems		# Только системные, SYS_MIN_UID и SYS_MAX_UID взять из /etc/login.defs
#     @all		# Все с UID от 0 до 65535
#     <digital>-<digital>	# Все пользователи диапазона
#     <digital>		# UID пользователя
#     <username>	# Имя пользователя
get_conf_useradd_from_system(){
    local SOURCE=${SYSCONF}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    local FILE_PASSWD="${ROOTFS}/etc/passwd"
    local FILE_SHADOW="${ROOTFS}/etc/shadow"
    local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs"
    local FILE_DEFAULT_USERADD="${ROOTFS}/etc/default/useradd"
    [[ -r ${FILE_PASSWD} ]] && local DATA_FILE_PASSWD=$(< ${FILE_PASSWD})
    [[ -r ${FILE_SHADOW} ]] && local DATA_FILE_SHADOW=$(< ${FILE_SHADOW})
    local DATA_FILE_DEFAULT_USERADD=$(< ${FILE_DEFAULT_USERADD})
    [[ ${DATA_FILE_DEFAULT_USERADD} =~ ($'\n'|^)+[[:blank:]]*HOME=([^$'\n']+)($'\n'|$)+ ]] && local DEFAULT_HOME=${BASH_REMATCH[2]:-/home}
    [[ ${DATA_FILE_DEFAULT_USERADD} =~ ($'\n'|^)+[[:blank:]]*SHELL=([^$'\n']+)($'\n'|$)+ ]] && local DEFAULT_SHELL=${BASH_REMATCH[2]:-/usr/bin/bash}
    show_user(){
	local SELECT_USER="$1"
	local SELECT_PLAINPASSWORD SELECT_UID SELECT_GROUP SELECT_GECOS SELECT_HOME SELECT_SHELL
	local SELECT_OPTIONAL=
	local SELECT_EXTRAGROUPS=
	[[ ${DATA_FILE_PASSWD} =~ ($'\n'|^)+${SELECT_USER}:([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
	&& SELECT_PLAINPASSWORD=${BASH_REMATCH[2]} \
	&& SELECT_UID=${BASH_REMATCH[3]} \
	&& SELECT_GROUP=${BASH_REMATCH[4]} \
	&& SELECT_GECOS=${BASH_REMATCH[5]} \
	&& SELECT_HOME=${BASH_REMATCH[6]} \
	&& SELECT_SHELL=${BASH_REMATCH[7]}

	[[ ${DATA_FILE_SHADOW} =~ ($'\n'|^)+${SELECT_USER}:([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
	&& SELECT_PASSWORD=${BASH_REMATCH[2]}
	[[ ${SELECT_PASSWORD} == "!*" && ${SELECT_PLAINPASSWORD} != "x" ]] && SELECT_PASSWORD="${SELECT_PLAINPASSWORD}"

	# Все дополнительные группы по умолчанию для всех пользователей ${USERGROUPS} ${DEFAULTGROUP}
	#SYSTEM_EXTRAGROUPS="${USERGROUPS//,/$'\n'}"$'\n'"${DEFAULTGROUP//,/$'\n'}"
	# Все дополнительные группы полученные из системы на пользователя ${SELECT_USER}
	# У id -nrG первая група в выводе является основной, её убираем
	USER_EXTRAGROUPS=$(${CHROOT} id -nrG ${SELECT_USER} | tr " " '\n' | tail +2 | sort -u)
	# Нет основной группы пользовтеля - это хорошо но медленнее чем id
	#local FILE_GROUP="${ROOTFS}/etc/group"
	#[[ -r ${FILE_GROUP} ]] && local DATA_FILE_GROUP=$(< ${FILE_GROUP})
#	USER_EXTRAGROUPS=$(${CHROOT} sed -Enr "s/^([^:]+):([^:]+):([^:]+):.*${SELECT_USER}.*/\1/p" <<< ${DATA_FILE_GROUP} | sort -u) #"

	#SELECT_EXTRAGROUPS=$(comm --nocheck-order -13 <(printf "%s\n" ${USERGROUPS//,/ } ${DEFAULTGROUP//,/ } | sort -u) <(printf "%s\n" $(${CHROOT} id -nrG ${SELECT_USER}) | sort -u) | xargs | tr " " ",") #'
	# Общие группы из по умолчанию и системные + только уникальные системные исключающие "по умолчанию"
	#SELECT_EXTRAGROUPS=$(sort -u <<< "$(comm --nocheck-order -12 <(printf "${SYSTEM_EXTRAGROUPS}") <(printf "${USER_EXTRAGROUPS}"))"$'\n'"$(comm --nocheck-order -13 <(printf "${SYSTEM_EXTRAGROUPS}") <(printf "${USER_EXTRAGROUPS}"))" | xargs | tr " " ",") #"

	SELECT_EXTRAGROUPS="${USER_EXTRAGROUPS//$'\n'/,}"
	[[ -n ${SELECT_HOME} && ${SELECT_HOME} != "${DEFAULT_HOME}/${SELECT_USER}" ]] && SELECT_OPTIONAL+=" --home-dir ${SELECT_HOME}"
	[[ -n ${SELECT_SHELL} && ${SELECT_SHELL} != ${DEFAULT_SHELL} ]] && SELECT_OPTIONAL+=" --shell ${SELECT_SHELL}"
	[[ -r ${SELECT_HOME}/.config/locale.conf && $(< ${SELECT_HOME}/.config/locale.conf) =~ (^|$'\n')[[:blank:]]*LANG=([^$|$'\n']+)[[:blank:]]*($|$'\n') ]] && SELECT_OPTIONAL+=" --lang ${BASH_REMATCH[2]}"
	if [[ -z ${NOT_ONLY_CHANGES} && ${SELECT_PASSWORD} == @("!*"|"!"|"*") ]]; then
	    local DATA_SYSUSERS_GROUP DATA_SYSUSERS_GECOS DATA_SYSUSERS_HOME DATA_SYSUSERS_SHELL
	    # Выриант1: u vault 319 "Vault daemon" /var/lib/vault
	    # Выриант2: u varnishlog 318:varnish "Varnish Cache Proxy"
	    [[ ${DATA_SYSUSERS} =~ ($'\n'|^)+'u'[[:blank:]]+${SELECT_USER}[[:blank:]]+(${SELECT_UID}|${SELECT_UID}:([^$'\n' ]*))[[:blank:]]*(\"([^$'\n']*)\"|\-)[[:blank:]]*([^$'\n' ]*)[[:blank:]]*([^$'\n' ]*)($'\n'|$)+ ]] \
	    && DATA_SYSUSERS_GROUP=${BASH_REMATCH[3]} \
	    && DATA_SYSUSERS_GECOS=${BASH_REMATCH[5]} \
	    && DATA_SYSUSERS_HOME=${BASH_REMATCH[6]} \
	    && DATA_SYSUSERS_SHELL=${BASH_REMATCH[7]}
	    [[ ${DATA_SYSUSERS_GECOS} == "-" ]] && unset DATA_SYSUSERS_GECOS
	    [[ ${DATA_SYSUSERS_HOME} == @(""|"-") ]] && DATA_SYSUSERS_HOME="/"
	    [[ ${DATA_SYSUSERS_SHELL} == @(""|"-") ]] && DATA_SYSUSERS_SHELL="/usr/bin/nologin"
	    # Поиск группы, если группа найдена, то номер как в системе, если не найдена, то номер должен быть по UID пользователя
	    [[ ${DATA_SYSUSERS_GROUP} != "" ]] && FIND_GROUP=${DATA_SYSUSERS_GROUP} || FIND_GROUP=${SELECT_USER}
	    [[ ${DATA_SYSUSERS} =~ ($'\n'|^)+'g'[[:blank:]]+${FIND_GROUP}[[:blank:]]+${SELECT_GROUP}[[:blank:]]*([^$'\n' ]*)[[:blank:]]*([^$'\n' ]*)($'\n'|$)+ ]] \
	    && DATA_SYSUSERS_GROUP=${SELECT_GROUP} || DATA_SYSUSERS_GROUP=${SELECT_UID}
	    DATA_SYSUSERS_EXTRAGROUPS=$(sed -Enr "s/^m ${SELECT_USER} (.*)/\1/p" <<< ${DATA_SYSUSERS} | sort -u | xargs | tr " " ",") #"
	    [[ ${SELECT_GROUP} == ${DATA_SYSUSERS_GROUP} && ${SELECT_EXTRAGROUPS} == ${DATA_SYSUSERS_EXTRAGROUPS} && ${SELECT_GECOS} == ${DATA_SYSUSERS_GECOS} && ${SELECT_HOME} == ${DATA_SYSUSERS_HOME} && ${SELECT_SHELL} == ${DATA_SYSUSERS_SHELL} ]] \
	    && return 0
	fi
	echo "USERADD[${SELECT_USER}]='${SELECT_GECOS}:${SELECT_UID}:${SELECT_GROUP}:${SELECT_EXTRAGROUPS}:${SELECT_OPTIONAL}:${SELECT_PASSWORD}'"
    }
#    is_systemd_user(){
#    # Пользователь присутстует в systemd sysusers.d
#	local SELECT_USER=$1
#	[[ $(cat ${ROOTFS}/usr/share/ublinux-sysusers/*.sysusers) =~ ($'\n'|^)+'u'[[:blank:]]+"${SELECT_USER}" ]] && return 1 || return 0
#	[[ -d ${ROOTFS}/run/sysusers.d && $(cat ${ROOTFS}/run/sysusers.d/*.conf) =~ ($'\n'|^)+'u'[[:blank:]]+"${SELECT_USER}" ]] && return 1 || return 0
#    }
    [[ ${1} == "--not-only-changes" ]] && local NOT_ONLY_CHANGES=yes && shift
    local PARAM_ALL="$@"
    [[ -n ${PARAM_ALL} ]] || PARAM_ALL="@users @systems"
    # Загрузить файлы которые совпадают в каталогах /usr/lib/sysusers.d/ и /usr/share/ublinux-sysusers/. И загрузить которые уникальные в /usr/lib/sysusers.d/
    #[[ -z ${NOT_ONLY_CHANGES} ]] && local DATA_SYSUSERS=$(cat \
    #	$(comm --nocheck-order -12 <(cd /usr/lib/sysusers.d/ && ls -v1 *.conf | sed "s/\.conf//g") <(cd /usr/share/ublinux-sysusers/ && ls -v1 *.sysusers | sed "s/\.sysusers//g") | sed 's|^|/usr/share/ublinux-sysusers/|;s|$|.sysusers|') \
    #	<(echo) \
    #	$(comm --nocheck-order -23 <(cd /usr/lib/sysusers.d/ && ls -v1 *.conf | sed "s/\.conf//g") <(cd /usr/share/ublinux-sysusers/ && ls -v1 *.sysusers | sed "s/\.sysusers//g") | sed 's|^|/usr/lib/sysusers.d/|;s|$|.conf|') \
    #)
    # Загрузить данные из /usr/share/ublinux-sysusers/*.sysusers /usr/lib/sysusers.d/*.conf. Вжно что-бы имена файлов не содержали :
    [[ -z ${NOT_ONLY_CHANGES} ]] && local DATA_SYSUSERS=$(grep -rEv '^\s*#|^\s*$' /usr/share/ublinux-sysusers/*.sysusers /usr/lib/sysusers.d/*.conf | sed -Enr "s/^[^:]+:(.*)/\1/p") #"

    while IFS= read -r SELECT_PARAM; do
	if [[ ${SELECT_PARAM} == "@users" ]]; then
	# Все пользователи кроме системных
	    UID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MIN[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    UID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MAX[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    while IFS= read -r SELECT_USER; do
		show_user "${SELECT_USER}"
	    done < <(awk -F':' -v USER_MIN=${UID_MIN:=1000} -v USER_MAX=${UID_MAX:=65534} '$3 >= USER_MIN && $3 <= USER_MAX && $1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif [[ ${SELECT_PARAM} == "@systems" ]]; then
	# Пользователи системные
	    UID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MIN[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    UID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MAX[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    while IFS= read -r SELECT_USER; do
		show_user "${SELECT_USER}"
	    done < <(awk -F':' -v USER_MIN=${UID_MIN:=500} -v USER_MAX=${UID_MAX:=999} '$3 >= USER_MIN && $3 <= USER_MAX && $1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif [[ ${SELECT_PARAM} == "@all" ]]; then
	# Все пользователи
	    while IFS= read -ru4 SELECT_USER; do
		show_user "${SELECT_USER}"
	    done 4< <(awk -F':' '$1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif [[ ${SELECT_PARAM} =~ ^([[:digit:]]+)'-'*([[:digit:]]*)$ ]]; then
	    UID_MIN=${BASH_REMATCH[1]}
	    UID_MAX=${BASH_REMATCH[2]}
	    [[ -n ${UID_MAX} ]] || UID_MAX=${UID_MIN}
	    while IFS= read -r SELECT_USER; do
		show_user "${SELECT_USER}"
	    done < <(awk -F':' -v USER_MIN=${UID_MIN:=1000} -v USER_MAX=${UID_MAX:=65534} '$3 >= USER_MIN && $3 <= USER_MAX && $1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif grep -q ^"${SELECT_PARAM}:" ${FILE_PASSWD} &>/dev/null; then
	    show_user "${SELECT_PARAM}"
	fi
    done <<< "${PARAM_ALL// /$'\n'}"
}

# External: ubl-settings-usergroups
#
# Получить запись вида конфигурации USERSHADOW из системного пользователя: USERSHADOW[superadmin]='2024-03-06:0:99999:7::'
# Если системный пользователь имеет настройки аналогичные настройкам создаваемого пользователя через .sysusers, то не выводим
#   $1  		# Опции не обязательные
#     --not-only-changes # Отключить проверку изменений .sysusers, выводить любого пользователя системы
#   $2		# Варианты пользователей, можно указывать несколько через пробел,  кроме nobody
#     <пуcто>		# Эквивалентно '@users @systems'
#     @users		# Все пользователи кроме системных, MIN_UID и MAX_UID взять из /etc/login.defs
#     @systems		# Только системные, SYS_MIN_UID и SYS_MAX_UID взять из /etc/login.defs
#     @all		# Все с UID от 0 до 65535
#     <digital>-<digital>	# Все пользователи диапазона
#     <digital>		# UID пользователя
#     <username>	# Имя пользователя
get_conf_usershadow_from_system(){
    local FILE_PASSWD="${ROOTFS}/etc/passwd"
    local FILE_SHADOW="${ROOTFS}/etc/shadow"
    local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs"
    [[ -r ${FILE_SHADOW} ]] && local DATA_FILE_SHADOW=$(< ${FILE_SHADOW})
    show_user(){
	local SELECT_USER="$1"
	[[ ${DATA_FILE_SHADOW} =~ ($'\n'|^)+${SELECT_USER}:([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
	&& SELECT_PASSWORD=${BASH_REMATCH[2]} \
	&& SELECT_LASTCHANGED=${BASH_REMATCH[3]} \
	&& SELECT_MINDAY=${BASH_REMATCH[4]} \
	&& SELECT_MAXDAY=${BASH_REMATCH[5]} \
	&& SELECT_WARN=${BASH_REMATCH[6]} \
	&& SELECT_INACTIVE=${BASH_REMATCH[7]} \
	&& SELECT_EXPIRE=${BASH_REMATCH[8]} \
	&& SELECT_NOUSE=${BASH_REMATCH[9]}
	[[ -n ${SELECT_LASTCHANGED} ]] && SELECT_LASTCHANGED=$(date -d @$((${SELECT_LASTCHANGED}*24*60*60)) +'%Y-%m-%d')
	[[ -n ${SELECT_EXPIRE} ]] && SELECT_LASTCHANGED=$(date -d @$((${SELECT_EXPIRE}*24*60*60)) +'%Y-%m-%d')
	if [[ -z ${NOT_ONLY_CHANGES} && -z ${SELECT_MINDAY} && -z ${SELECT_MAXDAY} && -z ${SELECT_WARN} && -z ${SELECT_INACTIVE} && -z ${SELECT_EXPIRE} ]]; then
	    local DATE_STARTUP_SYSTEM=$(date -d "$(cut -f1 -d. /proc/uptime) seconds ago" +'%Y-%m-%d')	#"
	    [[ ${SELECT_LASTCHANGED} == ${DATE_STARTUP_SYSTEM} ]] && return 0
	    # Дата когда был установлен пакет и впервые добавлены пользователи
	    local DATE_SYSUSERS=$(stat --printf=%y ${ROOTFS}/usr/share/ublinux-sysusers/README | cut -d' ' -f1)
	    # Сравнить дату впервые созданных пользователей с датой установки пакета ublinux-sysusers
	    [[ ${SELECT_LASTCHANGED} == ${DATE_SYSUSERS} ]] && return 0
#	    # Найти файл 'sysusers' где встречается пользователь и сравнить дату создания файла с датой создания пользователя
#	    FILE_NAME_SYSTEMD=$(grep -E "^u[[:blank:]]+${SELECT_USER}" ${ROOTFS}/usr/share/ublinux-sysusers/*.sysusers ${ROOTFS}/usr/share/ublinux-sysusers/dynamic/*.sysusers 2>/dev/null | cut -d: -f1 | xargs stat --printf=%y | cut -d' ' -f1;)
	fi
	echo "USERSHADOW[${SELECT_USER}]='${SELECT_LASTCHANGED}:${SELECT_MINDAY}:${SELECT_MAXDAY}:${SELECT_WARN}:${SELECT_INACTIVE}:${SELECT_EXPIRE}'"
    }
    [[ ${1} == "--not-only-changes" ]] && local NOT_ONLY_CHANGES=yes && shift
    local PARAM_ALL="$@"
    [[ -n ${PARAM_ALL} ]] || PARAM_ALL="@users @systems"
    while IFS= read -r SELECT_PARAM; do
	if [[ ${SELECT_PARAM} == "@users" ]]; then
	# Все пользователи кроме системных
	    UID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MIN[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    UID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*UID_MAX[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    while IFS= read -r SELECT_USER; do
		show_user "${SELECT_USER}"
	    done < <(awk -F':' -v USER_MIN=${UID_MIN:=1000} -v USER_MAX=${UID_MAX:=65534} '$3 >= USER_MIN && $3 <= USER_MAX && $1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif [[ ${SELECT_PARAM} == "@systems" ]]; then
	# Пользователи системные
	    UID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MIN[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    UID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_UID_MAX[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    while IFS= read -r SELECT_USER; do
		show_user "${SELECT_USER}"
	    done < <(awk -F':' -v USER_MIN=${UID_MIN:=500} -v USER_MAX=${UID_MAX:=999} '$3 >= USER_MIN && $3 <= USER_MAX && $1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif [[ ${SELECT_PARAM} == "@all" ]]; then
	# Все пользователи
	    while IFS= read -ru4 SELECT_USER; do
		show_user "${SELECT_USER}"
	    done 4< <(awk -F':' '$1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif [[ ${SELECT_PARAM} =~ ^([[:digit:]]+)'-'*([[:digit:]]*)$ ]]; then
	    UID_MIN=${BASH_REMATCH[1]}
	    UID_MAX=${BASH_REMATCH[2]}
	    [[ -n ${UID_MAX} ]] || UID_MAX=${UID_MIN}
	    while IFS= read -r SELECT_USER; do
		show_user "${SELECT_USER}"
	    done < <(awk -F':' -v USER_MIN=${UID_MIN:=1000} -v USER_MAX=${UID_MAX:=65534} '$3 >= USER_MIN && $3 <= USER_MAX && $1 != "nobody" { print $1}' ${FILE_PASSWD})
	elif grep -q ^"${SELECT_PARAM}:" ${FILE_PASSWD} &>/dev/null; then
	    show_user "${SELECT_PARAM}"
	fi
    done <<< "${PARAM_ALL// /$'\n'}"
}

# External: ubl-settings-usergroups
#
# Получить запись вида конфигурации GROUPADD из систеных групп
# Если системная группа имеет настройки аналогичные настройкам создаваемой группы через .sysusers, то не выводим
#   $1  		# Опции не обязательные
#     --not-only-changes # Отключить проверку изменений .sysusers, выводить любую группу системы
#   $2		# Варианты групп, можно указывать несколько через пробел,  кроме nobody
#     <пусто>		# Эквивалентно '@groups @systems'
#     @groups		# Все кроме системных, MIN_GID и MAX_GID взять из /etc/login.defs
#     @systems		# Только системные, SYS_MIN_GID и SYS_MAX_GID взять из /etc/login.defs
#     @all		# Все c GID от 0 до 65535
#     <digital>-<digital>	# Все пользователи диапазона
#     <digital>		# GID группы
#     <groupname>	# Имя группы
get_conf_groupadd_from_system(){
    local FILE_GROUP="${ROOTFS}/etc/group"
    local FILE_GSHADOW="${ROOTFS}/etc/gshadow"
    local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs"
    [[ -r ${FILE_GROUP} ]] && local DATA_FILE_GROUP=$(< ${FILE_GROUP})
    [[ -r ${FILE_GSHADOW} ]] && local DATA_FILE_GSHADOW=$(< ${FILE_GSHADOW})
    show_group(){
	local SELECT_GROUP="$1"
	local SELECT_PLAINPASSWORD SELECT_GID SELECT_MEMBERS
	[[ ${DATA_FILE_GROUP} =~ ($'\n'|^)+${SELECT_GROUP}:([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
	&& SELECT_PLAINPASSWORD=${BASH_REMATCH[2]} \
	&& SELECT_GID=${BASH_REMATCH[3]} \
	&& SELECT_MEMBERS=${BASH_REMATCH[4]}
	local SELECT_PASSWORD SELECT_ADMINISTRATORS SELECT_GMEMBERS
	[[ ${DATA_FILE_GSHADOW} =~ ($'\n'|^)+${SELECT_GROUP}:([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
	&& SELECT_PASSWORD=${BASH_REMATCH[2]} \
	&& SELECT_ADMINISTRATORS=${BASH_REMATCH[3]} \
	&& SELECT_GMEMBERS=${BASH_REMATCH[4]}
	[[ ${SELECT_PASSWORD} == "!*" && ${SELECT_PLAINPASSWORD} != "x" ]] && SELECT_PASSWORD="${SELECT_PLAINPASSWORD}"
	local SELECT_OPTIONAL
	if [[ -z ${NOT_ONLY_CHANGES} && ${SELECT_PASSWORD} == @("!*"|"!") && ${SELECT_MEMBERS} == ${SELECT_GMEMBERS} && -z ${SELECT_ADMINISTRATORS} ]]; then
	    # Выбираем пользователей которые входят в выбранную группу из systemd sysusers
	    local DATA_SYSUSERS_MEMBERS=$(sed -Enr "s/^m[[:blank:]]+(.*)[[:blank:]]+${SELECT_GROUP}/\1/p" <<< ${DATA_SYSUSERS} | sort -u | xargs | tr " " ",") #"
	    local RETURN_DATA_SYSUSERS_MEMBERS
	    [[ -n ${DATA_SYSUSERS_MEMBERS} ]] && SELECT_MEMBERS=$(sort -u <<< ${SELECT_MEMBERS//,/$'\n'} | xargs | tr " " ",") 
	    [[ ${SELECT_MEMBERS} == ${DATA_SYSUSERS_MEMBERS} ]] && RETURN_DATA_SYSUSERS_MEMBERS=yes || RETURN_DATA_SYSUSERS_MEMBERS=no
	    # Выбираем GID группы из systemd sysusers. По явному наличию 'g x2godesktopsharing 500' 
	    local DATA_SYSUSERS_GID=$(sed -Enr "s/^g[[:blank:]]+${SELECT_GROUP}[[:blank:]]+([[:digit:]]+).*/\1/p" <<< ${DATA_SYSUSERS} | head -1) #"
	    # Выбираем GID группы из systemd sysusers. Если нет явного, то GID по UID пользователя 
	    [[ -n ${DATA_SYSUSERS_GID} ]] || DATA_SYSUSERS_GID=$(sed -Enr "s/^u[[:blank:]]+${SELECT_GROUP}[[:blank:]]+([[:digit:]]+).*/\1/p" <<< ${DATA_SYSUSERS} | head -1) #"
	    local RETURN_DATA_SYSUSERS_GID
	    [[ -n ${DATA_SYSUSERS_GID} ]] && [[ ${SELECT_GID} == ${DATA_SYSUSERS_GID} ]] && RETURN_DATA_SYSUSERS_GID=yes || RETURN_DATA_SYSUSERS_GID=no
	    # Если в systemd sysusers MEMBERS и GID совпадают с системными, то выход
	    [[ ${RETURN_DATA_SYSUSERS_MEMBERS} == "yes" && ${RETURN_DATA_SYSUSERS_GID} == "yes" ]] && return 0
	    # Если в systemd sysusers MEMBERS совпадает с системным, а GID не указан (динамический), то выход
	    # Если не показывать такие группы, то можно ложно не вывести, если вдруг намеренно пользоваель указал GID у динамической группы
	    # Из за возможной ошибки, отключаю
	    #[[ ${RETURN_DATA_SYSUSERS_MEMBERS} == "yes" && -z ${RETURN_DATA_SYSUSERS_GID} ]] && return 0
	fi
	echo "GROUPADD[${SELECT_GROUP}]='${SELECT_MEMBERS}:${SELECT_GID}:${SELECT_OPTIONAL}:${SELECT_ADMINISTRATORS}:${SELECT_PASSWORD}'"
    }
    [[ ${1} == "--not-only-changes" ]] && local NOT_ONLY_CHANGES=yes && shift
    local PARAM_ALL="$@"
    [[ -n ${PARAM_ALL} ]] || PARAM_ALL="@groups @systems"
    # Загрузить файлы которые совпадают в каталогах /usr/lib/sysusers.d/ и /usr/share/ublinux-sysusers/. И загрузить которые уникальные в /usr/lib/sysusers.d/
    #[[ -z ${NOT_ONLY_CHANGES} ]] && local DATA_SYSUSERS=$(cat \
    #	$(comm --nocheck-order -12 <(cd /usr/lib/sysusers.d/ && ls -v1 *.conf | sed "s/\.conf//g") <(cd /usr/share/ublinux-sysusers/ && ls -v1 *.sysusers | sed "s/\.sysusers//g") | sed 's|^|/usr/share/ublinux-sysusers/|;s|$|.sysusers|') \
    #	<(echo) \
    #	$(comm --nocheck-order -23 <(cd /usr/lib/sysusers.d/ && ls -v1 *.conf | sed "s/\.conf//g") <(cd /usr/share/ublinux-sysusers/ && ls -v1 *.sysusers | sed "s/\.sysusers//g") | sed 's|^|/usr/lib/sysusers.d/|;s|$|.conf|') \
    #)
    # Загрузить данные из /run/sysusers.d/*.sysusers /usr/lib/sysusers.d/*.conf. Вжно что-бы имена файлов не содержали :
    [[ -z ${NOT_ONLY_CHANGES} ]] && local DATA_SYSUSERS=$(grep -rEv '^\s*#|^\s*$' /run/sysusers.d/*.conf /usr/lib/sysusers.d/*.conf | sed -Enr "s/^[^:]+:(.*)/\1/p") #"
    while IFS= read -r SELECT_PARAM_ALL; do
	if [[ ${SELECT_PARAM_ALL} == "@groups" ]]; then
	# Все группы кроме системных
	    GID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*GID_MIN[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    GID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*GID_MAX[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    while IFS= read -r SELECT_GROUP; do
		show_group "${SELECT_GROUP}"
	    done < <(awk -F':' -v GROUP_MIN=${GID_MIN:=1000} -v GROUP_MAX=${GID_MAX:=60000} '$3 >= GROUP_MIN && $3 <= GROUP_MAX && $1 != "nobody" { print $1}' ${FILE_GROUP})
	elif [[ ${SELECT_PARAM_ALL} == "@systems" ]]; then
	# Группы системные
	    GID_MIN=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_GID_MIN[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    GID_MAX=$([[ $(< "${FILE_LOGINDEFS}") =~ [^#[^:blank:]]*SYS_GID_MAX[[:blank:]]+([[:digit:]]+)  ]]; echo -n "${BASH_REMATCH[1]}")
	    while IFS= read -r SELECT_GROUP; do
		show_group "${SELECT_GROUP}"
	    done < <(awk -F':' -v GROUP_MIN=${GID_MIN:=500} -v GROUP_MAX=${GID_MAX:=999} '$3 >= GROUP_MIN && $3 <= GROUP_MAX && $1 != "nobody" { print $1}' ${FILE_GROUP})
	elif [[ ${SELECT_PARAM_ALL} == "@all" ]]; then
	# Все группы
	    while IFS= read -ru4 SELECT_GROUP; do
		show_group "${SELECT_GROUP}"
	    done 4< <(awk -F':' '$1 != "nobody" { print $1}' ${FILE_GROUP})
	elif [[ ${SELECT_PARAM_ALL} =~ ^([[:digit:]]+)'-'*([[:digit:]]*)$ ]]; then
	    GID_MIN=${BASH_REMATCH[1]}
	    GID_MAX=${BASH_REMATCH[2]}
	    [[ -n ${GID_MAX} ]] || GID_MAX=${GID_MIN}
	    while IFS= read -r SELECT_GROUP; do
		show_group "${SELECT_GROUP}"
	    done < <(awk -F':' -v GROUP_MIN=${GID_MIN:=1000} -v GROUP_MAX=${GID_MAX:=60000} '$3 >= GROUP_MIN && $3 <= GROUP_MAX && $1 != "nobody" { print $1}' ${FILE_GROUP})
	elif grep -q ^"${SELECT_PARAM_ALL}:" ${FILE_GROUP} &>/dev/null; then
	    show_group "${SELECT_PARAM_ALL}"
	fi
    done <<< "${PARAM_ALL// /$'\n'}"
}

#####################################################################################
#####################################################################################

get_de(){
    [[ -z ${SESSION} && ${KDE_FULL_SESSION} == true ]]      && SESSION=kde
    [[ -z ${SESSION} && ${XDG_CURRENT_DESKTOP} == XFCE ]]   && SESSION=xfce
    [[ -z ${SESSION} && ${DESKTOP_SESSION} == LXDE ]]       && SESSION=lxde
    [[ -z ${SESSION} && ${XDG_CURRENT_DESKTOP} == LXQt ]]   && SESSION=lxqt
    [[ -z ${SESSION} && ${DESKTOP_SESSION} == i3 ]]         && SESSION=i3
    [[ -z ${SESSION} && ${XDG_CURRENT_DESKTOP} == i3 ]]     && SESSION=i3
    [[ -z ${SESSION} && ${DESKTOP_SESSION} == i3term ]]     && SESSION=i3term
    [[ -z ${SESSION} && ${XDG_CURRENT_DESKTOP} == i3term ]] && SESSION=i3term
    [[ -z ${SESSION} && ${XDG_CURRENT_DESKTOP} == MATE ]]   && SESSION=mate
    [[ -z ${SESSION} && ${XDG_CURRENT_DESKTOP} == Pantheon ]] && SESSION=pantheon
    if [[ -z ${SESSION} ]]; then
	SESSION_COMMANDS=$(ps xo args)
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+"xfce4-session"($'\n'|$)+ ]] && SESSION=xfce
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)"kdeinit"($'\n'|$)+ ]] && SESSION=kde
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)"i3"($'\n'|$)+ ]] && SESSION=i3
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)"i3term"($'\n'|$)+ ]] && SESSION=i3term
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)"gnome-panel"($'\n'|$)+ ]] && SESSION=gnome
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)"gnome-shell"($'\n'|$)+ ]] && SESSION=gnome-shell
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)"plasmashell"($'\n'|$)+ ]] && SESSION=plasma
        [[ -z ${SESSION} && ${SESSION_COMMANDS} =~ ($'\n'|^)+([^$'\n']*)" --session=pantheon"([^$'\n']*)($'\n'|$)+ ]] && SESSION=pantheon
    fi
    [[ -z ${SESSION} && -x /usr/bin/startxfce4 ]] && SESSION=xfce
    [[ -z ${SESSION} && -x /usr/bin/startlxde ]] && SESSION=lxde
    [[ -z ${SESSION} && -x /usr/bin/startlxqt ]] && SESSION=lxqt
    [[ -z ${SESSION} && -x /usr/bin/plasmashell ]] && SESSION=plasma
    [[ ${SESSION} == "kde" && -x /usr/bin/plasmashell ]] && SESSION=plasma
    # SESSION=budgie
    # SESSION=cinnamon
    # SESSION=sway
    echo ${SESSION}
}

##########################
# liblinuxlive functions #
##########################

debug_log(){
    if [[ $(< /proc/cmdline) =~ (^| )"debug"( |$) ]]; then
        echo "- debug: $*" >&2
        log "- debug: $*"
    fi
}

log(){
    echo "$@" 2>/dev/null >> /var/log/ublinux.log
}

debug_mode(){
    if [[ $(cmdline_parameter debug) || ${DEBUGMODE} == "yes" ]]; then
        [[ ${PWD} == "/union" ]] && local ROOTFS="." || local ROOTFS=
        local PATH_LOG="${ROOTFS}/var/log/ublinux"
        [[ -z ${ROOTFS} && ${EUID:-0} -ne 0 ]] && PATH_LOG="${HOME}/.ublinux/log"
        [[ -d ${PATH_LOG} ]] || mkdir -p "${PATH_LOG}"
        if [[ -z ${SELF_FILE} && -n $1 && -e $1 ]]; then
            SELF_FILE=$1 && SELF_NAME=${1##*/} && SELF_PATH=${1%/*}
        elif [[ -z ${SELF_FILE} && -n ${SSC_ARGV0} && -e ${SSC_ARGV0} ]]; then
            SELF_FILE=${SSC_ARGV0} && SELF_NAME=${SSC_ARGV0##*/} && SELF_PATH=${SSC_ARGV0%/*}
        elif [[ -z ${SELF_FILE} && -n $0 && -e $0 && ! $0 =~ ^"/dev/".* ]]; then
            SELF_FILE=${0} && SELF_NAME=${0##*/} && SELF_PATH=${0%/*}
        else
            SELF_FILE="unknown" && SELF_NAME="unknown" && SELF_PATH="unknown"
            echo "$0 $@" >> "${PATH_LOG}/${SELF_NAME}.log"
        fi
        if [[ ! -f  "${PATH_LOG}/${SELF_NAME}.log" ]]; then
            echo "${SELF_NAME} --  debug mode enabled"
            echo $(date) > "${PATH_LOG}/${SELF_NAME}.log" || echo "ERROR: Can not create log file"
            shift
            ${SELF_FILE} "$@" 2>&1 | tee -a "${PATH_LOG}/${SELF_NAME}.log"
            exit 0
        fi
    fi
}

echodebug(){
    [[ ${DEBUG_IS_ENABLED} || ${DEBUGMODE} == "yes" ]] && echo "$1"
    if [[ -n "$2" ]]; then
        command=$2
        shift; shift
        if [[ -z $1 ]]; then
            ${command}
        else
            ${command} "$@"
        fi
    fi
}

##########################
##########################

# Create module
# call mksquashfs with apropriate arguments
# $1 = directory which will be compressed to squashfs module
# $2 = output filesystem module file
# $3..$9 = optional arguments like -keep-as-directory or -b 123456789
create_module(){
    SOURCE=${SYSCONF}/config; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SOURCE=${SYSCONF}/system; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    [[ $(< $@) =~ (^| )("-comp"|"-noD")( |$) ]] && MKSQFS_OPTS=
    mksquashfs "$1" "$2" ${MKSQFS_OPTS} $3 $4 $5 $6 $7 $8 $9 -noappend >/dev/null || return 1
    chmod 444 "$2"
}

# look into cmdline and echo $1 back if $1 is set
# $1 = value name, case sensitive, for example 'debug'
cmdline_parameter(){
    . /etc/ublinux/config 2>/dev/null || . etc/ublinux/config 2>/dev/null
    echo -n " ${CMDLINE} " | cat /proc/cmdline - 2>/dev/null | tr "[:cntrl:]" " " | grep -Em1 -o "(^|[[:space:]])$1([[:space:]]|\$)" | head -1 | tr -d " "
}

# look into cmdline and echo value of $1 option
# $1 = value name, case sensitive, for example 'changes'
cmdline_value(){
    . /etc/ublinux/config 2>/dev/null || . etc/ublinux/config 2>/dev/null
    echo -n " ${CMDLINE} " | cat /proc/cmdline - 2>/dev/null | tr "[:cntrl:]" " " | grep -Em1 -o "(^|[[:space:]])$1=[^[:space:]]+" | head -1 | cut -d "=" -f 2-
}

# Find and run all scripts from the given module
# This function is used by the activate and deactivate script when the distro
# is already started, not during live setup
# $1 = mounted module full path
# $2..$n = optional arguments for the scripts, eg. 'start'
find_n_run_scripts(){
   debug_log "find_n_run_scripts" "$*"
   local MOD="$1"; shift
   RCPATH=/etc/init.d
   [[ -d ${RCPATH} ]] || RCPATH="/etc/rc.d/init.d"
   RUNLEVEL=$(runlevel | awk '{print $2}')
   [[ -d "/etc/rc${RUNLEVEL}.d" ]] && RCPATH=/etc/rc${RUNLEVEL}.d
   [[ -d "/etc/rc.d/rc${RUNLEVEL}.d" ]] && RCPATH=/etc/rc.d/rc${RUNLEVEL}.d
   RUNSCRIPTS="${MOD}${RCPATH}|${MOD}/usr/lib/ublinux/rc.local|${MOD}/usr/lib/ublinux/rc.post"
   echo $@ | grep -q start || RUNSCRIPTS="${MOD}${RCPATH}"
   while IFS= read -ru3 SCRIPT; do
     if [[ ${SCRIPT} != "" && -x "${SCRIPT}" && ! -d "${SCRIPT}" ]]; then
        # call the script by real path, not from the module
        log "Starting '"${SCRIPT}" $@'"
        "${SCRIPT}" "$@"
     fi
   done 3< <(find "${MOD}" | grep -E "${RUNSCRIPTS}" | cut -b "${#MOD}"- | cut -b 2- | xargs -n 1 -r readlink -f | sort -u)
}

allow_only_root(){
  [[ ${UID} == 0 ]] || { echo "Only root can run ${SELF_NAME}"; exit 1; }
}


#####################
# Hotkeys functions #
#####################

notify_send(){
    local FIND_DISPLAY=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
    local FIND_USER=$(who | grep '('${FIND_DISPLAY}')' | awk '{print $1}' | head -n 1) #'
    local FIND_UID=$(id -u ${FIND_USER})
    [[ -n ${FIND_DISPLAY} && -n ${FIND_USER} && -n ${FIND_UID} ]] || return 1
    sudo -u ${FIND_USER} DISPLAY=${FIND_DISPLAY} DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${FIND_UID}/bus notify-send "$@"
}

#show_run(){
#    DE=$(get_de)
#    if [[ ${DE} == @("kde"|"plasma") ]]; then
#	krunner
#    elif [[  ${DE} == "gnome" ]]; then
#	gnome-panel-control --run-dialog
#    elif [[  ${DE} == "lxqt" ]]; then
#	lxqt-runner
#    else
#	rofi -config /usr/share/ublinux/i3/rofi.cfg -show
#    fi
#}

#lock_session(){
#    which xscreensaver-command 2>/dev/null || return 1
#    DE=$(get_de)
##  qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Lock
#    xterm -geometry 0x0+1+1 -e "dbus-send --dest=org.freedesktop.ScreenSaver --print-reply /ScreenSaver org.freedesktop.ScreenSaver.Lock"
#    if [[ ${DE} != "kde" && ${DE} != "plasma" ]]; then
#	ps -U $(id -u) | grep -q xscreensaver || xscreensaver -no-splash &
#	sleep 0.5
#	xscreensaver-command -lock
#    fi
#}

#show_hotkeys(){
#    MSG1=$(gettext -s "UBLinux magic keys:")
#    echo "$MSG1" > /tmp/listkeys
#    echo " " >> /tmp/listkeys
#    cat $HOME/.xbindkeysrc | sed -e 's/^".*"//' -e 's/Mod4/WIN/' -e '/^#.*#/ d' -e '/^ *$/ d' -e 's/^# *//' | while read a ; do
#      gettext -s "$a" >> /tmp/listkeys
#    done
#    mdialog --textbox /tmp/listkeys 600 600
#    rm -f /tmp/listkeys
#}

show_info(){
  [[ -r /usr/lib/os-release ]] && . /usr/lib/os-release || return 1
  FILE_INFO="/tmp/info.txt"
  LIVECDNAME="${NAME}"
  UPTIME=$(uptime | awk '{print "time - "$1", up - "$3}').
  RAM=$(free -m | grep Mem | awk '{ print "total - "$2",  free - "$4}')
  SWAP=$(free -m | grep Swap | awk '{ print "total - "$2",  free - "$4}')
  CPU="$(cat /proc/cpuinfo | sed -e '/model name/!d' -e 's/^.*://')"
  CPUARCH=$(uname -p)
  KERNEL=$(uname -r)
  VIDEO=$(lspci | sed -e '/VGA/!d' -e 's/^.*://')
  GLXINFO=$(glxinfo | sed '2,3!d')
  AUDIO=$(lspci | sed -e '/Audio/!d' -e 's/^.*://')
  CMDLINE=$(< /proc/cmdline)
  VERSION=$(< /etc/ublinux-release)
  if [ $(cmdline_parameter unionfs) ] ;then
     PROF_SIZE=$(df -h / |grep unionfs | awk '{print " ["$5"] total - "$2", free - "$4}')
  else
     PROF_SIZE=$(df -h / |grep aufs | awk '{print " ["$5"] total - "$2", free - "$4}')
  fi
  echo "${LIVECDNAME} (${VERSION})" > "${FILE_INFO}"
  echo "UPTIME: ${UPTIME}" >> "${FILE_INFO}"
  echo "KERNEL: ${KERNEL}" >> "${FILE_INFO}"
  echo "RAM: ${RAM}" >> "${FILE_INFO}"
  echo "SWAP: ${SWAP}" >> "${FILE_INFO}"
  [ "$(cat /proc/cmdline | grep changes= )" ] && echo "PROFILE: ${PROF_SIZE}" >> "${FILE_INFO}"
  echo -e "CPU: (${CPUARCH}) \n${CPU}" >> "${FILE_INFO}"
  echo "VIDEO: ${VIDEO}" >> "${FILE_INFO}"
  echo "${GLXINFO}" >> "${FILE_INFO}"
  echo "AUDIO: ${AUDIO}" >> "${FILE_INFO}"
  echo "CMDLINE: ${CMDLINE}" >> "${FILE_INFO}"
  echo "MODULES:" >> "${FILE_INFO}"
  grep squashfs /proc/mounts | awk '{print $2}' | sort >> "${FILE_INFO}"
  zenity --text-info \
	 --width=640 \
	 --height=480 \
         --title="Show info" \
         --filename="${FILE_INFO}"
 rm -f "${FILE_INFO}"
}

#touchpad(){
#    MSG2=$(gettext -s "Touchpad disabled, WIN+t to enable again")
#    if [ $(synclient -l | grep TouchpadOff | awk '{ print $3 }') -eq 0 ] ;then
#	synclient TouchpadOff=1
#	mdialog --passivepopup "$MSG2"
#    else
#	synclient TouchpadOff=0
#    fi
#}

#rfswitch(){
#    MSG3=$(gettext -s "bluetooth, WI-FI interfaces disabled, WIN+w to enable again")
#    rfkill list | grep yes
#    if [[ $? -eq 0 ]]; then
#	rfkill unblock all
#    else
#	rfkill block all
#	mdialog --passivepopup "$MSG3"
#    fi
#}

#recordvideo(){
#    MSG1=$(gettext -s "Recording are stoped, please wait for encoding")
#    MSG2=$(gettext -s "Video are encoded and placed to your home dir")
#    RMDOPT=
#    . /etc/ublinux/config 2>/dev/null
#    ps -U $UID | grep -q pulseaudio && RMDOPT="$RMDOPT --device pulse"
#    PID=$(ps -U $UID -o pid,comm | grep recordmydesktop | awk '{print $1}')
#    if [[ -z "$PID" ]] ;then
#	recordmydesktop $RMDOPT &
#    else
#	kill "$PID"
#	mdialog --passivepopup "$MSG1"
#	bash -c "while true ;do ps -A -o pid | grep -q ^$PID$ || break ; sleep 1s ;done ; mdialog --passivepopup \"$MSG2\""
#    fi
#}

#show_network(){
#    echo "netstat --inet" > ${HOME}/network.txt
#    netstat --inet  >> ${HOME}/network.txt
#    echo -e "\nlsof -i" >> ${HOME}/network.txt
#    /usr/sbin/lsof -i >> ${HOME}/network.txt
#    mdialog --textbox ${HOME}/network.txt 600 250
#    rm -f ${HOME}/info.txt
#}

#google_search(){
#    xclip -o | sed -r '2~1d;s/(^\s+|\s+$)//g;s/%/%25/g;s/#/%23/g;s/\$/%24/g;s/&/%26/g;s/\+/%2B/;s/,/%2C/g;s/:/%3A/g;s/;/%3B/g;s/=/%3D/g;s/\?/%3F/g;s/@/%40/g;s/\s/+/g' | awk '{print "http://www.google.ru/search?hl=ru&q=" $1}' | xargs firefox -new-tab
#}

#translate_en_rus(){
#    [[ "$1" == "passive" ]] && mdialog --passivepopup "$(wget -U "Mozilla/5.0" -qO - "http://translate.google.com/translate_a/t?client=t&text=$(xclip -o | sed "s/[\"'<>]//g")&sl=auto&tl=ru" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
#    [[ "$1" == "msgbox" ]] && mdialog --msgbox "$(wget -U "Mozilla/5.0" -qO - "http://translate.google.com/translate_a/t?client=t&text=$(xclip -o | sed "s/[\"'<>]//g")&sl=auto&tl=ru" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
#    [[ "$1" == "firefox" ]] && xclip -o | sed -r '2~1d;s/(^\s+|\s+$)//g;s/%/%25/g;s/#/%23/g;s/\$/%24/g;s/&/%26/g;s/\+/%2B/;s/,/%2C/g;s/:/%3A/g;s/;/%3B/g;s/=/%3D/g;s/\?/%3F/g;s/@/%40/g;s/\s/+/g' | awk '{print "translate.google.com/translate_t?hl=en#en|ru|" $1}' | xargs firefox -new-tab
#}

#translate_rus_en(){
#    [[ "$1" == "passive" ]] && mdialog --passivepopup "$(wget -U "Mozilla/5.0" -qO - "http://translate.google.com/translate_a/t?client=t&text=$(xclip -o | sed "s/[\"'<>]//g")&sl=auto&tl=en" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
#    [[ "$1" == "msgbox" ]] && mdialog --msgbox "$(wget -U "Mozilla/5.0" -qO - "http://translate.google.com/translate_a/t?client=t&text=$(xclip -o | sed "s/[\"'<>]//g")&sl=auto&tl=en" | sed 's/\[\[\[\"//' | cut -d \" -f 1)"
#    [[ "$1" == "firefox" ]] && xclip -o | sed -r '2~1d;s/(^\s+|\s+$)//g;s/%/%25/g;s/#/%23/g;s/\$/%24/g;s/&/%26/g;s/\+/%2B/;s/,/%2C/g;s/:/%3A/g;s/;/%3B/g;s/=/%3D/g;s/\?/%3F/g;s/@/%40/g;s/\s/+/g' | awk '{print "translate.google.com/translate_t?hl=ru#ru|en|" $1}' | xargs firefox -new-tab
#}

#open_url(){
#    xclip -o | sed -n 1p | xargs firefox -new-tab
#}

#####################################
###   :::   UBCONFIG EXEC   :::   ###
#####################################
ubconfig_exec_system(){
    SYSCONF=${SYSCONF//${ROOTFS}/}
    local SECTION_NAME=$1
    local COMMAND_MODE_VAR=$2
    local NAME_VAR=$3
    local VALUE_VAR=$4
    local NO_FIND_EXCUTE=
    case "[${SECTION_NAME}]" in
	"[${SYSCONF}/config]"|"[config]")
	    case "${NAME_VAR}" in
		# --> OLD config
		HOSTNAME)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/30-network-hostname ;;
		SERVICESSTART|SERVICESNOSTART|SERVICESMASK|SERVICESUNMASK|\
		SERVICES_ENABLE|SERVICES_DISABLE|SERVICES_MASK|SERVICES_UNMASK)
					${ROOTFS}/usr/lib/ublinux/rc.preinit.d/20-services exec_services_enabledisable "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
					${ROOTFS}/usr/lib/ublinux/rc.preinit.d/20-services exec_services_startstop_live "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
		# <-- OLD config
		;;
		DM_HINT_PASSWORD)	${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_99_dm_hint_password "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/system]"|"[system]")
	    case "${NAME_VAR}" in
		ENVIRONMENT)            ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/10-system exec_environment ;;
		HOSTNAME)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/30-network-hostname ;;
		SERVICESSTART|SERVICESNOSTART|SERVICESMASK|SERVICESUNMASK|\
		SERVICES_ENABLE|SERVICES_DISABLE|SERVICES_MASK|SERVICES_UNMASK)
					${ROOTFS}/usr/lib/ublinux/rc.preinit.d/20-services exec_services_enabledisable "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
					${ROOTFS}/usr/lib/ublinux/rc.preinit.d/20-services exec_services_startstop_live "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
		;;
		AUTHPAM)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/40-authpam "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		AUTHPAM\[*\])		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/40-authpam "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/users]"|"[users]")
	    case "${NAME_VAR}" in
		DEFAULTROOTPASSWD)	${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_01_defaultrootpasswd "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		DEFAULTPASSWD)		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_02_defaultpasswd "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		DEFAULTGROUP)		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_03_add_groups "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		ADMGROUPS)		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_03_add_groups "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		USERGROUPS)		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_03_add_groups "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		NEEDEDUSERS)		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_05_neededusers "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		USERADD\[*\])		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_06_useradd "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		USERSHADOW\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_07_usershadow "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		GROUPADD\[*\])		${ROOTFS}/usr/lib/ublinux/rc.preinit/10-accounts exec_04_groupadd "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		USERADD_SYNC)		${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_01_useradd_sync "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		USERADD_SYNC\[*\])	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_01_useradd_sync "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		GROUPADD_SYNC)		${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_02_groupadd_sync "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		GROUPADD_SYNC\[*\])	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_02_groupadd_sync "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/update]"|"[update]")
	    case "${NAME_VAR}" in
		REPOSITORY)		${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_01_repository "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		REPOSITORY\[*\])	${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_01_repository "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		REPOPUBLIC_NET)		${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_02_repopublic_net "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		REPOPUBLIC_WEB\[*\])	${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_03_repopublic_web "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		REPOPUBLIC_FTP\[*\])	${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_03_repopublic_ftp "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		REPOPUBLIC_CACHE)	${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_04_repopublic_cache "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		REPOPUBLIC_CACHE\[*\])	${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_04_repopublic_cache "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		AUTOUPDATE)		${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_autoupdate "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		AUTOUPDATE\[*\])	${ROOTFS}/usr/lib/ublinux/rc.local.d/43-repository exec_autoupdate "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/mount]"|"[mount]")
	    case "${NAME_VAR}" in
		AUTOMOUNT_SHARE\[*\])	${ROOTFS}/usr/lib/ublinux/rc.post.d/09-automount exec_mount_direct ;;
		PUBLICDIR)	        ${ROOTFS}/usr/lib/ublinux/rc.post.d/23-publicdir ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/boot]"|"[boot]")
	    case "${NAME_VAR}" in
		GRUB_TIMEOUT)		${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_timeout ;;
		GRUB_DEFAULT)		${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_default ;;
		GRUB_SUPERUSERS)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_superusers ;;
		GRUB_PASSWORD\[*\])	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_password ;;
		GRUB_BOOT_SILENT)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_boot_silent ;;
		GRUB_TERMINAL_INPUT)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_terminal_input ;;
		GRUB_TERMINAL_OUTPUT)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_terminal_output ;;
		GRUB_PLAY)		${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_play ;;
		GRUB_CMDLINE_LINUX)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_cmdline_linux ;;
		GRUB_VMLINUZ_FILES)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_vmlinuz_file ;;
		GRUB_UBLINUX_FILES)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_ublinux_file ;;
		GRUB_ADDON_FILES)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_addon_file ;;
		KERNEL_BOOT)	        ${ROOTFS}/usr/lib/ublinux/rc.halt.pre/20-grub exec_grub_kernel_boot ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/logging]"|"[logging]")
	    case "${NAME_VAR}" in
		AUDITD)			${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_auditd "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
					setsid ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_auditd_live & ;;
		AUDITD\[*\])		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_auditd "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
					setsid ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_auditd_live & ;;
		JOURNALD\[*\])		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_journald "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
					setsid ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_journald_live & ;;
		LOGROTATE\[*\])		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_logrotate "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}"
					setsid ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_logrotate_live "${NAME_VAR}" & ;;
		SYSTEMD_COREDUMP\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/24-logging exec_systemd_coredump "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		JOURNALD_NOTIFY\[*\])	${ROOTFS}/usr/lib/ublinux/rc.pamsession.d/02-journald-notify exec_01_journald_notify "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/server]"|"[server]")
	    case "${NAME_VAR}" in
		STORAGE_CONTAINERS_PATH)	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/80-server-storage exec_storage_containers_path ;;
		STORAGE_DOCKER_PATH)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/80-server-storage exec_storage_docker_path ;;
		STORAGE_LIBVIRT_PATH)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/80-server-storage exec_storage_libvirt_path ;;
		UBPILE_DB)			${ROOTFS}/usr/lib/ublinux/rc.local.d/98-ubpile exec_01_ubpile_db "${COMMAND_MODE_VAR}" ;; # Специально без параметров
		UBPILE_DB\[*\])			${ROOTFS}/usr/lib/ublinux/rc.local.d/98-ubpile exec_01_ubpile_db "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		UBPILE)				${ROOTFS}/usr/lib/ublinux/rc.local.d/98-ubpile exec_02_ubpile "${COMMAND_MODE_VAR}" ;; # Специально без параметров, что-бы читались дефолтные параметры при =admin и =worker
		UBPILE\[*\])			${ROOTFS}/usr/lib/ublinux/rc.local.d/98-ubpile exec_02_ubpile "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		UBPILE_REVERSE_PROXY)		${ROOTFS}/usr/lib/ublinux/rc.local.d/98-ubpile exec_03_ubpile_reverse_proxy "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)				NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/desktop]"|"[desktop]")
	    case "${NAME_VAR}" in
		MULTISEAT_SIMPLE\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/55-multiseat ;;
		# Не нужно запускать через ubconfig, параметр работает при запуске сессии
		#AUTOEXEC)		${ROOTFS}/usr/lib/ublinux/rc.desktop/all/autoexec "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		#AUTOEXEC\[*\])		${ROOTFS}/usr/lib/ublinux/rc.desktop/all/autoexec "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		LIGHTDM_XDMCP)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/60-lightdm-settings exec_lightdm_xdmcp "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		LIGHTDM_XDMCP\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/60-lightdm-settings exec_lightdm_xdmcp "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		LIGHTDM_GREETER\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/60-lightdm-settings exec_lightdm_greeter "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		X11VNC\[*\])	        ${ROOTFS}/usr/lib/ublinux/rc.local.d/41-x11vnc exec_x11vnc "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/video]"|"[video]")
	    case "${NAME_VAR}" in
		VGADRV_AUTO)	        ${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_vgadrv_auto ;;
		VGADRV_NOFREE)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/50-xorg ;;
		XORG_MONITOR\[*\])	${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_xorg_monitor ;;
		XORG_EXT)		${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_xorg_ext;;
		XORG_DPI)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/63-xorg-dpi
		                        ${ROOTFS}/usr/lib/ublinux/rc.profile/20-video-xorg-dpi ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/save]"|"[save]")
	    case "${NAME_VAR}" in
		SAVE_ALL_CACHE)		${ROOTFS}/usr/lib/ublinux/rc.halt.pre/85-save-cache ;;
		SAVE_ROOTCOPY_CHANGES)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/86-save-rootcopy ;;
		SAVE_ROOTCOPY_INCLUDE)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/86-save-rootcopy ;;
		SAVE_ROOTCOPY_EXCLUDE)	${ROOTFS}/usr/lib/ublinux/rc.halt.pre/86-save-rootcopy ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/network]"|"[network]")
	    case "${NAME_VAR}" in
		DOMAIN)		 	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/23-realmd exec_domain "${COMMAND_MODE_VAR}" ;;
		DOMAIN\[*\]) 		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/23-realmd domain_configure_live "${COMMAND_MODE_VAR}" ;;
		REALM_SSSD\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/23-realmd domain_configure_live "${COMMAND_MODE_VAR}" ;;
		REALM_PERMIT_USER)	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/23-realmd domain_configure_live "${COMMAND_MODE_VAR}" ;;
		REALM_PERMIT_GROUP)	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/23-realmd domain_configure_live "${COMMAND_MODE_VAR}" ;;
		NTPSERVERS)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/21-ntp "${COMMAND_MODE_VAR}" ;;
		NETWORK\[*\])		${ROOTFS}/usr/lib/ublinux/rc.network.d/10-network exec_network ;;
		PROXY_SYSTEM\[*\])	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/31-network-proxy-system ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/security]"|"[security]")
	    case "${NAME_VAR}" in
		OPENSSL_ENGINE)			 ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/56-openssl-engine ;;
		FSTEC-HARDENING-ADVISED)	 ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/66-fstec-hardening ;;
		FSTEC-HARDENING-A4)	         ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/66-fstec-hardening ;;
		ACCESS_DENIED_VTX11)		 ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/57-access-denied-vtx11 ;;
		ACCESS_ALLOWED_LOGIN)		 ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/58-access-login exec_access_allowed_login ;;
		ACCESS_DENIED_LOGIN)		 ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/58-access-login exec_access_denied_login ;;
		ACCESS_ALLOWED_SUID\[*\])	 ${ROOTFS}/usr/lib/ublinux/rc.post.d/42-access-suid-sgid exec_access_allowed_suid ;;
		ACCESS_ALLOWED_SGID\[*\])	 ${ROOTFS}/usr/lib/ublinux/rc.post.d/42-access-suid-sgid exec_access_allowed_sgid ;;
		ACCESS_ALLOWED_INTERPRETER\[*\]) ${ROOTFS}/usr/lib/ublinux/rc.post.d/43-access-interpreter ;;
		MOUNT_ATTR\[*\])		 ${ROOTFS}/usr/lib/ublinux/rc.post.d/44-mountattr ;;
		MOUNT_QUOTA\[*\])		 ${ROOTFS}/usr/lib/ublinux/rc.post.d/45-disk-quota "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		CGROUP_QUOTA\[*\])		 ${ROOTFS}/usr/lib/ublinux/rc.post.d/46-cgroup-quota "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		POLKIT\[*\])			 ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/59-polkit exec_polkit;;
		*)				 NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/kiosk]"|"[kiosk]")
    	    case "${NAME_VAR}" in
		XFCE4_KIOSK\[*\])		${ROOTFS}/usr/lib/ublinux/rc.post.d/18-kiosk-xfce4-kioskrc ;;
		XFCE4_KIOSK_USER_LOCKED)	${ROOTFS}/usr/lib/ublinux/rc.post.d/18-kiosk-xfce4-kioskrc ;;
		XFCE4_KIOSK_USER_UNLOCKED)	${ROOTFS}/usr/lib/ublinux/rc.post.d/18-kiosk-xfce4-kioskrc ;;
		APPDESKTOP_PLACEONDESKTOP_INIT)		${ROOTFS}/usr/lib/ublinux/rc.pamsession.d/01-placeondesktop exec_02_place_on_desktop_init "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		APPDESKTOP_PLACEONDESKTOP_INIT\[*\])	${ROOTFS}/usr/lib/ublinux/rc.pamsession.d/01-placeondesktop exec_02_place_on_desktop_init "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		APPDESKTOP_PLACEONDESKTOP)		${ROOTFS}/usr/lib/ublinux/rc.pamsession.d/01-placeondesktop exec_03_place_on_desktop "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		APPDESKTOP_PLACEONDESKTOP\[*\])		${ROOTFS}/usr/lib/ublinux/rc.pamsession.d/01-placeondesktop exec_03_place_on_desktop "${COMMAND_MODE_VAR}" "${NAME_VAR}=${VALUE_VAR}" ;;
		*)				 NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/clock]"|"[clock]")
	    case "${NAME_VAR}" in
		ZONE)			${ROOTFS}/usr/lib/ublinux/rc.preinit.d/10-system exec_timezone ;;
		HWCLOCK_SYNC)		${ROOTFS}/usr/lib/ublinux/rc.halt/20-timesave
					${ROOTFS}/usr/lib/ublinux/rc.post.d/02-hwclock
		;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/locale]"|"[locale]")
	    case "${NAME_VAR}" in
		LOCALE)			${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_01_set_locale ;;
		LANG)			${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_01_set_locale
					${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_02_set_lang
					${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_03_set_vconsole
					${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_mkkbdfxorg
					. ${ROOTFS}/usr/lib/ublinux/rc.profile/03-profile-locale
		                        ${ROOTFS}/usr/lib/ublinux/rc.profile/10-fixkeyboard_layout
		;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	"[${SYSCONF}/keyboard]"|"[keyboard]")
	    case "${NAME_VAR}" in
		NUMLOCK)		${ROOTFS}/usr/lib/ublinux/rc.profile/10-fixkeyboard_layout ;;
		XKBMODEL)		${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_mkkbdfxorg
		                        ${ROOTFS}/usr/lib/ublinux/rc.profile/10-fixkeyboard_layout
		;;
		XKBLAYOUT)		${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_mkkbdfxorg
		                        ${ROOTFS}/usr/lib/ublinux/rc.profile/10-fixkeyboard_layout
		;;
		XKBVARIANT)		${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_mkkbdfxorg
		                        ${ROOTFS}/usr/lib/ublinux/rc.profile/10-fixkeyboard_layout
		;;
		XKBOPTIONS)		${ROOTFS}/usr/lib/ublinux/rc.post.d/11-xorg exec_mkkbdfxorg
		                        ${ROOTFS}/usr/lib/ublinux/rc.profile/10-fixkeyboard_layout
		;;
		CONSOLE_FONT)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_03_set_vconsole ;;
		CONSOLE_FONT_MAP)	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_03_set_vconsole ;;
		CONSOLE_FONT_UNIMAP)	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_03_set_vconsole ;;
		CONSOLE_KEYMAP)		${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_03_set_vconsole ;;
		CONSOLE_KEYMAP_TOGGLE)	${ROOTFS}/usr/lib/ublinux/rc.preinit.d/53-language exec_03_set_vconsole ;;
		*)			NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	\[*\])
	    case "${NAME_VAR}" in
	        *) NO_FIND_EXCUTE=1 ;;
	    esac
	;;
	*) NO_FIND_EXCUTE=1 ;;
    esac
    [[ $? -eq 0 ]] && return 0 || return 1
}

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

    return 0 2>/dev/null && return 0

    [[ -d ${SSC_EXTRACT_DIR} ]] && rm -rf "${SSC_EXTRACT_DIR}"
    [[ -n ${SSC_ARGV0} ]] && { [[ -f /usr/bin/bash ]] && /usr/bin/bash --version | grep -q ^"GNU bash" || exit 1; }
    [[ -z ${SELF_FILE} ]] && [[ -n ${SSC_ARGV0} ]] && SELF_FILE=${SSC_ARGV0} && SELF_NAME=${SSC_ARGV0##*/} && SELF_PATH=${SSC_ARGV0%/*} || { SELF_FILE=${0} && SELF_NAME=${0##*/} && SELF_PATH=${0%/*}; }

    [[ ! -f /init ]] && { ROOTFS= ; CMD_CHROOT= ; } || { [[ -d /sysroot ]] && ROOTFS="/sysroot" || ROOTFS="."; CMD_CHROOT="chroot ${ROOTFS}"; }
    SOURCE=${ROOTFS}/usr/lib/ublinux/default; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SYSCONF="${ROOTFS}${SYSCONF}"

    #export TEXTDOMAINDIR="${ROOTFS}/usr/share/locale"
    #export TEXTDOMAIN="ublinux_functions"

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