#!/usr/bin/env bash
#
#   Script name: ubconfig
#   Description: Script for configure UBLinux (ublinux.ini)
#   GitLab: https://gitlab.ublinux.ru/
#   Author: Dmitry Razumov asmeron@ublinux.ru
#   Contributors: asmeron@ublinux.ru
#
#   Copyright (c) 2021-2022 UBLinux Development Team <support@ublinux.ru>
#
#   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 2 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 <http://www.gnu.org/licenses/>.

VERSION_SCRIPT="1.1"

# Exit Immediately if a command fails
#set -o errexit

#################################
###   :::   C O L O R S   :::   #
#################################
set_color(){
#http://abload.de/img/bash-color-chartmxjbp.png
    export BBC=$'\e[1;34m'
    export RBC=$'\e[1;31m'
    export WBC=$'\e[1m'
    export EC=$'\e[0m'

    export txtblk='\033[0;30m' # Black - Regular
    export txtred='\033[0;31m' # Red			# prompt: error color
    export txtgrn='\033[0;32m' # Green			# prompt: success color
    export txtylw='\033[0;33m' # Yellow			# prompt: waring color
    export txtblu='\033[0;34m' # Blue			
    export txtpur='\033[0;35m' # Purple
    export txtcyn='\033[0;36m' # Cyan			# prompt: info color
    export txtwht='\033[0;37m' # White
    export bldblk='\033[1;30m' # Black - Bold
    export bldred='\033[1;31m' # Red			# prompt: bold error color
    export bldgrn='\033[1;32m' # Green			# prompt: bold success color
    export bldylw="\033[1;33m" # Yellow                 # prompt: bold warning color
    export bldblu='\033[1;34m' # Blue				
    export bldpur='\033[1;35m' # Purple
    export bldcyn="\033[1;36m" # Cyan                   # prompt: bold info color
    export bldwht="\033[1;37m" # White			# prompt: bold default color

    export undblk='\033[4;30m' # Black - Underline
    export undred='\033[4;31m' # Red

    export bakblk='\033[40m'   # Black - Background
    export bakred='\033[41m'   # Red
    export badgrn='\033[42m'   # Green

    export txtrst='\033[0m'    # Text Reset		# prompt: default color
}


#######################################
###   :::   F U N C T I O N S   :::   #
#######################################

check_root(){
    if [[ ${EUID:-$(id -u)} > 0 ]]; then
	case ${1} in
	    -w  | --warning)	  shift; prompt -w "Please run as root! ${@}" && return 1 ;;
	    -wq | --warning-quit) shift; prompt -wq "Please run as root!" ;;
    	    *) 			  prompt -wq "Please run as root!" ;;
        esac
    fi
}

# Check command availability
has_command(){ command -v $1 &> /dev/null; }

# echo like ... with flag type and display message colors
prompt(){
    [[ -n ${QUIET} ]] && return
    case ${1} in
	-s  | --success)	shift; echo -e "${bldgrn}${@}${txtrst}" ;;    			# print success message
	-sq | --success-quit)	shift; echo -e "${bldgrn}${@}${txtrst}"; exit 1 ;;    		# print success message
	-e  | --error)   	shift; echo -e "${bldred}ERROR:${@}${txtrst}" ;;   		# print error message
	-eq | --error-quit)   	shift; echo -e "${bldred}ERROR:${@}${txtrst}"; exit 1 ;;	# print error message
	-w  | --warning) 	shift; echo -e "${bldylw}WARNING:${bldwht}${@}${txtrst}" ;; 	# print warning message
	-wq | --warning-quit) 	shift; echo -e "${bldylw}WARNING:${bldwht}${@}${txtrst}"; exit 1 ;; # print warning message
	-i  | --info)    	shift; echo -e "${bldcyn}INFO:${txtcyn}${@}${txtrst}" ;;    	# print info message
	-iq | --info-quit)    	shift; echo -e "${bldcyn}INFO:${txtcyn}${@}${txtrst}"; exit 1 ;; # print info message
	*)    			echo -e "$@" ;;							# print all message
    esac
}

usage_version(){
    printf "%s  %s\n" "${0##*/}" "version: ${VERSION_SCRIPT}"
}
usage(){
    cat <<EOF
Configure UBLinux

Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Commands:
  get		Get configuration option | Получить параметр конфигурации
  set 		Set configuration option | Установить параметр конфигурации
  remove 	Remove option of a configuration | Удалить параметр конфигурации

Meta Commands:
  help          Show this help

Options for get:
  -r, --raw	  Show only values, without name variables | Показать только значения, без имен переменных
  -s, --source=<SOURCE>
		  Configuration as source| Источник конфигурации
   *glo | global  Configuration file as source: ublinux.ini
    sys | system  Configuration file as source: /etc/ublinux/*
    def | default Configuration file as source: /usr/lib/ublinux/os-config
    <file>        Configuration file as source, global ublinux.ini format: <FILE.ini>
  -d, --default   Before loading the source, additionally include the default 
		  settings file /usr/lib/ublinux/os-config
  -c, --compare   Compare configuration, system and global configuration files

Options for set:
  -t, --target
   *		  Without the specified option, are used *global *system
   *glo | global  Only configuration file as target: ublinux.ini
   *sys | system  Only configuration file as target: /etc/ublinux/*
    <file>        Configuration file as target, global ublinux.ini format: <FILE.ini>
  -n, --noexecute Do not execute system configuration commands for option

Options for remove:
  -t, --target
   *		  Without the specified option, are used *global *system
   *glo | global  Only configuration file as target: ublinux.ini
   *sys | system  Only configuration file as target: /etc/ublinux/*
    <file>        Configuration file as target, global ublinux.ini format: <FILE.ini>
  -n, --noexecute Do not execute system configuration commands for option

Options:
  -h, --help	  Show this help
  -h, --help=<SECTION>
	    	  Show help by section
  -q, --quiet	  Quiet mode
  -V, --version	  Show package version

Known sections:
  config 	/etc/ublinux/config
  network 	/etc/ublinux/network
  kiosk		/etc/ublinux/kiosk

Examples:
${0##*/} get config HOSTNAME
## Get HOSTNAME, from source default+system config
${0##*/} get --default --source system config HOSTNAME
## Get DOMAIN, only
${0##*/} get DOMAIN
${0##*/} set HOSTNAME myhost
${0##*/} set DOMAIN domain.ru
${0##*/} remove DOMAIN
EOF
}
usage_config(){
    cat <<EOF
Configure UBLinux
Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Options section: config
  HOSTNAME=<HOSTNAME>   Host name | Имя машины
EOF
}
usage_network(){
    cat <<EOF
Configure UBLinux
Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Options section: network
  DOMAIN=<DOMAIN>	Domain configuration | Подключение к AD серверу

EOF
}
usage_kiosk(){
    cat <<EOF
Configure UBLinux
Usage:  ${0##*/} {COMMAND} {SECTION} [OPTIONS...] ...

Options section: kiosk
    cat <<EOF
EOF
}
help(){
    usage_version
    [[ -n $1 ]] || usage
    [[ $1 == "config" ]] && usage_config
    [[ $1 == "network" ]] && usage_network
    [[ $1 == "kiosk" ]] && usage_kiosk
    exit 0
}
arguments(){
# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
    local ARGV=()
    local END_OF_OPT=
    while [[ $# -gt 0 ]]; do
	arg="$1"; shift
	case "${END_OF_OPT}${arg}" in
	    --) ARGV+=("$arg"); END_OF_OPT=1 ;;
	    --*=*)ARGV+=("${arg%%=*}" "${arg#*=}") ;;
	    --*) ARGV+=("$arg") ;;
	    -*) for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
	    *) ARGV+=("$arg") ;;
	esac
    done
# Apply pre-processed options
    set -- "${ARGV[@]}"
# Parse options
    local END_OF_OPT=
    local POSITIONAL_ARGS=()
    [[ -z $@ ]] && usage && exit 0
    while [[ $# -gt 0 ]]; do
	case "${END_OF_OPT}${1}" in
	    get | GET)		   COMMAND="${1,,}"; END_OF_OPT=1 ;;
	    set | SET)		   COMMAND=${1,,}; END_OF_OPT=1 ;;
	    remove | REMOVE)	   COMMAND=${1,,}; END_OF_OPT=1 ;;
	    -r | --raw)    	   RAW=1 ;;	    
	    -c | --compare)    	   COMPARE=1 ;;
	    -s | --source) 	   shift; SOURCE="$1" ;;
	    -d | --default)	   LOAD_DEFAULT=1 ;;
	    -t | --target) 	   shift; TARGET="$1" ;;
	    -n | --noexecute) 	   SET_NOEXECUTE=1 ;;
	    -h | --help | help)	   shift; help $1;;
	    -q | --quiet)     	   QUIET=1; QUIET_ARG="-q" ;;
	    -V | --version)	   usage_version; exit 0 ;;
	    --stdin)        	   READ_STDIN=1 ;;
	    --)             	   END_OF_OPT=1 ;;
	    -*|--*)         	   prompt -w "Unrecognized argument, skiped: $1" >&2  ;;
	    *)              	   POSITIONAL_ARGS+=("$1") ;;
	esac
	shift
    done
# Restore positional parameters
    set -- "${POSITIONAL_ARGS[@]}"
    [[ ${COMMAND} == 'get' ]] && REQUEST_ARGS="$@"
    [[ ${COMMAND} == 'set' ]] && REQUEST_ARGS="$@"
    [[ ${COMMAND} == 'remove' ]] && REQUEST_ARGS="$@"
    [[ ${COMMAND} == 'get' && -z ${SOURCE} ]] && SOURCE="global"
    [[ -n ${SOURCE} ]] && case "${SOURCE}" in
	glob | global)	SOURCE="global" ;;
	sys  | system)	SOURCE="system" ;;
	def  | default)	SOURCE="default" ;;
	*)		[[ -f ${SOURCE} ]] || prompt -eq " Unrecognized sources !" ;;
    esac
    [[ -n ${TARGET} ]] && case "${TARGET}" in
	glob | global)	TARGET="global" ;;
	sys  | system)	TARGET="system" ;;
	*)		[[ -f ${TARGET} ]] || prompt -eq " Unrecognized target !" ;;
    esac
}

prepare_section(){
    SECTION=$(egrep '^([\[\/]){,1}([\/A-Za-z0-9.-_])+([\/\]]){,1}$' <<< ${1} | tr -d '[]') #'
    [[ ${SECTION} == "" ]] && SECTION="unknown"
    grep -q '^/' <<< ${SECTION} 2>/dev/null || SECTION="/etc/ublinux/${SECTION}"
    SECTION="[${SECTION}]"
}

get_value(){
    # $1 Перечень опций для поиска
    # $2 Имя переменной из внешней функции, для заполнения данными
    # $3 Имя файла, как источник данных
    get_value_config(){
	declare -n VALUE_CONFIG=$2
	# Из полученных переменных сформировать вывод в зависимости от опции --raw
	write_value_config(){
	    while read -r LINE; do
	        [[ -n ${RAW} ]] && VALUE_CONFIG+="${LINE#*=}\n" || VALUE_CONFIG+="${LINE}\n"
	    done <<< "${1}"
	}
	local REQUEST_ARGS_LOCAL=${1// /$'\n'}
	local FIND_VALUE_CONFIG=$3
	# Если сектор не указан, то выводим весь файл
	if [[ ${REQUEST_ARGS_LOCAL} == "" || ${REQUEST_ARGS_LOCAL} == "/" ]]; then
	    FIND_VALUE_CONFIG=$(egrep -v '^declare|^\[' <<< ${FIND_VALUE_CONFIG})
	    write_value_config "${FIND_VALUE_CONFIG}"
	# Сектор указан, ищем запрошенные переменные и выводим
        else
	    # Вырезать искомый сектор из файла конфигурации
    	    if [[ ${SECTION} != "" && ${SECTION} != "[/]" && ${!VALUE_CONFIG} != "VALUE_SYSTEM" ]]; then
    		# Экранировать все символы в имени сектора
		ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._+@%-]/\\&/g' <<< "${SECTION}")
		FIND_VALUE_CONFIG=$(sed -n "/${ESC_SECTION}/,/^\[/p" <<< "${FIND_VALUE_CONFIG}" | grep -v '^\[')
	    fi
	    # Если указан только сектор и нет переменных для фильтра
	    if [[ -n ${SECTION} && ${REQUEST_ARGS_LOCAL} == $(tr -d '[]' <<< ${SECTION##*/}) ]]; then
		write_value_config "${FIND_VALUE_CONFIG}"
	    # Указан сектор и присутствуют переменные для фильтра
	    elif [[ -n ${SECTION} ]]; then
		while read -r REQUEST_ITEM; do
		    if [[ ${REQUEST_ITEM%%=*} =~ "[]"$|"[*]"$ ]]; then
	    		REQUEST_ITEM=$(sed 's/[^a-zA-Z0-9 ]/\\&/g' <<< "${REQUEST_ITEM%%[*}[")
    	    		FIND_VALUE=$(egrep "^${REQUEST_ITEM}" <<< ${FIND_VALUE_CONFIG})
			
		    else
	    		REQUEST_ITEM=$(sed 's/[^a-zA-Z0-9 ]/\\&/g' <<< "${REQUEST_ITEM%%=*}=")
    	    		FIND_VALUE=$(egrep "^${REQUEST_ITEM}" <<< ${FIND_VALUE_CONFIG} | tail -1)
    	    	    fi
    	    	    [[ ${FIND_VALUE} != "" ]] || FIND_VALUE="(null)"
		    write_value_config "${FIND_VALUE}"
		done <<< ${REQUEST_ARGS_LOCAL}
	    fi
	fi
    }
    get_value_compare(){
	while read -r REQUEST_ITEM; do
	    egrep -q "^$|(null)" <<< ${REQUEST_ITEM} && continue
	    REQUEST_ITEM_ESC=$(sed 's/[^a-zA-Z0-9 ]/\\&/g' <<< ${REQUEST_ITEM})
	    FIND_VALUE=$(egrep "^${REQUEST_ITEM_ESC}" <<< ${2//\\n/$'\n'})
	    [[ ${FIND_VALUE} == "" ]] && FIND_VALUE="${REQUEST_ITEM}" || continue
	    if [[ -n ${RAW} ]]; then 
		while read -r LINE; do
		    VALUE_COMPARE+="${3}${LINE#*=}\n"
		done <<< ${FIND_VALUE}
	    else
		while read -r LINE; do
		    VALUE_COMPARE+="${3}${LINE}\n"
		done <<< ${FIND_VALUE}
	    fi
	done <<< ${1//\\n/$'\n'}
    }
    local VALUE_COMPARE=
    local VALUE_GLOBAL=
    local VALUE_SYSTEM=
    local VALUE_DEFAULT=
    local VALUE_MANUAL=
    if [[ -n ${COMPARE} ]]; then
        get_value_config "$1" "VALUE_GLOBAL" "$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_CONF})"
    	if [[ ${SECTION} == "[/]" ]]; then
    	    get_value_config "$1" "VALUE_SYSTEM" "$(cat ${PATH_UBLINUX_CURRENT}/* | egrep -v '^\s*#|^\s*$')"
	elif [[ -f ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) ]]; then
    	    get_value_config "$1" "VALUE_SYSTEM" "$(cat ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) | egrep -v '^\s*#|^\s*$')"
    	fi
        get_value_compare "${VALUE_GLOBAL}" "${VALUE_SYSTEM}" "Global:"
        get_value_compare "${VALUE_SYSTEM}" "${VALUE_GLOBAL}" "System:"
	echo -en "${VALUE_COMPARE}"
    elif [[ ${SOURCE} == global ]]; then 
	[[ -f ${FILE_UBLINUX_CONF} ]] || return 1
	FILE_UBLINUX_DATA=$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_CONF})
	if [[ ${SECTION} != "" && ${SECTION} != "[/]" && -n ${LOAD_DEFAULT} ]]; then
	    ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._+@%-]/\\&/g' <<< "${SECTION}")
	    FILE_UBLINUX_DATA=$(sed "/${ESC_SECTION}/r"<(echo "$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_DEFAULT})") <<< ${FILE_UBLINUX_DATA}) #"
	fi
        get_value_config "$1" "VALUE_GLOBAL" "${FILE_UBLINUX_DATA}"
        echo -en "${VALUE_GLOBAL}"
    elif [[ ${SOURCE} == system ]]; then
    	if [[ ${SECTION} == "" || ${SECTION} == "[/]" ]]; then
    	    get_value_config "$1" "VALUE_SYSTEM" "$(cat ${PATH_UBLINUX_CURRENT}/* | egrep -v '^\s*#|^\s*$')"
	elif [[ -f ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) ]]; then
	    [[ -n ${LOAD_DEFAULT} ]] && FILE_DEFAULT_DATA="$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_DEFAULT})\n"
    	    get_value_config "$1" "VALUE_SYSTEM" "${FILE_DEFAULT_DATA/%\\n/$'\n'}$(cat ${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/}) | egrep -v '^\s*#|^\s*$')"
    	fi
        echo -en "${VALUE_SYSTEM}"
    elif [[ ${SOURCE} == default ]]; then
	[[ -f ${FILE_UBLINUX_DEFAULT} ]] || return 1
	get_value_config "$1" "VALUE_DEFAULT" "$(egrep -v '^\s*#|^\s*$' ${FILE_UBLINUX_DEFAULT})"
	echo -en "${VALUE_DEFAULT}"
    else
	[[ -f ${SOURCE} ]] || return 1
	get_value_config "$1" "VALUE_MANUAL" "$(egrep -v '^\s*#|^\s*$' ${SOURCE})"
	echo -en "${VALUE_MANUAL}"
    fi

}
remove_value(){
    remove_value_local(){
	remove_value_global(){
		ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._+@%-]/\\&/g' <<< "${SECTION}")
		grep -q "^${ESC_SECTION}" "${FILE_UBLINUX_CONF}" \
		|| { grep -q "^\[$(tr -d '[]' <<< ${SECTION##*/})\]" "${FILE_UBLINUX_CONF}" \
		     && ESC_SECTION="\[$(tr -d '[]' <<< ${SECTION##*/})\]" \
		     || prompt -wq " not find section ${SECTION}"; \
		   }
		FIND_VALUE_CONFIG=$(grep -n "" "${FILE_UBLINUX_CONF}" | sed -n "/^[0-9]*:${ESC_SECTION}/,/^[0-9]*:\[/p" | grep -v '^[0-9]*:\[')
		# Поиск прямое совпадение переменной, номер строки в переменную
		if SECTOR_DATA="$(egrep "^[0-9]*:${NAME_VAR//[/\\[}=" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTOR_DATA} ]]; then 
		    # Прямое совпадение найдено, замена по номеру строки
		    sed -e "${SECTOR_DATA}d" -i "${FILE_UBLINUX_CONF}"
		else 
		    return 1
		fi
	}
	remove_value_system(){
#		echo "set_value_system:${NAME_VAR}=${VALUE_VAR}"
		local FILE_CONFIG="${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/})"
		if [[ -f ${FILE_CONFIG} ]]; then
		    egrep -q "^${NAME_VAR//[/\\[}=" ${FILE_CONFIG} || return 1
		    sed "/^${NAME_VAR//[/\\[}=/d" -i ${FILE_CONFIG}
		fi
	}
	if [[ -z ${TARGET} ]]; then
	    remove_value_global; STATUS_GLOBAL=$?
	    remove_value_system; STATUS_SYSTEM=$?
	elif [[ ${TARGET} == global ]]; then
	    remove_value_global; STATUS_GLOBAL=$?
	elif [[ ${TARGET} == system ]]; then
	    remove_value_system; STATUS_SYSTEM=$?
	elif [[ -f ${TARGET} ]]; then
	    FILE_UBLINUX_CONF=${TARGET}
	    remove_value_global; STATUS_GLOBAL=$?
	fi
	[[ ${STATUS_GLOBAL} == 0 ]] && prompt -s "${NAME_VAR} variable remove from global configuration ${FILE_UBLINUX_CONF}" \
	    || { prompt -e " ${NAME_VAR} variable not remove from global configuration ${FILE_UBLINUX_CONF}"; STATUS=1; }
	[[ ${STATUS_SYSTEM} == 0 ]] && prompt -s "${NAME_VAR} variable remove from system configuration ${PATH_UBLINUX_CURRENT}/*" \
	    || { prompt -e " ${NAME_VAR} variable not remove from system configuration ${PATH_UBLINUX_CURRENT}/*"; STATUS=1; }
	[[ ${STATUS} == 1 ]] && return 1 || return 0
    }
    local SET_ARG=$1
    [[ -n ${SET_ARG} ]] || prompt -eq " not found arguments !"
    while read -r ARG; do
	NAME_VAR=${ARG%%=*}
	remove_value_local && [[ -z ${SET_NOEXECUTE} ]] && exec_network_domain
    done <<< ${SET_ARG// /$'\n'}
}
set_value(){
    set_value_local(){
	set_value_global(){
		ESC_SECTION=$(sed 's/[^a-zA-Z0-9,._+@%-]/\\&/g' <<< "${SECTION}")
		grep -q "^${ESC_SECTION}" "${FILE_UBLINUX_CONF}" \
		|| { grep -q "^\[$(tr -d '[]' <<< ${SECTION##*/})\]" "${FILE_UBLINUX_CONF}" \
		     && ESC_SECTION="\[$(tr -d '[]' <<< ${SECTION##*/})\]" \
		     || prompt -wq " not find section ${SECTION}"; \
		   }
		FIND_VALUE_CONFIG=$(grep -n "" "${FILE_UBLINUX_CONF}" | sed -n "/^[0-9]*:${ESC_SECTION}/,/^[0-9]*:\[/p" | grep -v '^[0-9]*:\[')
		# Поиск прямое совпадение переменной, номер строки в переменную
		if SECTOR_DATA="$(egrep "^[0-9]*:${NAME_VAR//[/\\[}=" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTOR_DATA} ]]; then 
		    # Прямое совпадение найдено, замена по номеру строки
		    sed -i "${SECTOR_DATA}s/.*/${NAME_VAR}=${VALUE_VAR}/" "${FILE_UBLINUX_CONF}"
		# Поиск по косвенному совпадению, песле # коментария имя переменной
		elif SECTOR_DATA="$(egrep "^[0-9]*:\s*#*\s*${NAME_VAR//[/\\[}=" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTOR_DATA} ]]; then
		    # Косвенное сопадение найдено, вставка после номера строки
		    sed -i "${SECTOR_DATA}a ${NAME_VAR}=${VALUE_VAR}" "${FILE_UBLINUX_CONF}"
		# Поиск по косвенному совпадению, песле # коментария имя переменной обрезанное до [
		elif SECTOR_DATA="$(egrep "^[0-9]*:\s*#*\s*${NAME_VAR%%[*}" <<< ${FIND_VALUE_CONFIG} | tail -1 | cut -d: -f1)" && [[ -n ${SECTOR_DATA} ]]; then 
		    # Косвенное сопадение найдено, вставка после номера строки
		    sed -i "${SECTOR_DATA}a \ \n${NAME_VAR}=${VALUE_VAR}" "${FILE_UBLINUX_CONF}"
		# Совпадений не найдено, поиск последней строки блока
		elif SECTOR_DATA="$(tail -1 <<< $(grep -v '^[0-9]*:#' <<< ${FIND_VALUE_CONFIG}) | cut -d: -f1)" && [[ -n ${SECTOR_DATA} ]]; then
		    # Совпадений не найдено, вставляем в конец блока новой строкой
		    sed -i "${SECTOR_DATA}i \ \n${NAME_VAR}=${VALUE_VAR}" "${FILE_UBLINUX_CONF}"
		fi
	}
	set_value_system(){
		local FILE_CONFIG="${PATH_UBLINUX_CURRENT}/$(tr -d '[]' <<< ${SECTION##*/})"
		if [[ -f ${FILE_CONFIG} ]]; then		    
		    sed "/^${NAME_VAR//[/\\[}=/d" -i ${FILE_CONFIG}
		    echo "${NAME_VAR}=${VALUE_VAR}" >> ${FILE_CONFIG}
		fi
		# Mark associative array
		for FILE_CFG in ${PATH_UBLINUX_CURRENT}/*; do
		    DECLARE_A=$(cat ${FILE_CFG} | grep "^[A-z0-9_]*\[.*\]=.*" | sed "s/\[.*//" | uniq | xargs)
		    [[ ${DECLARE_A} != "" ]] && sed "/^declare -A/d" -i ${FILE_CFG} && sed -i "1i declare -A ${DECLARE_A}" -i ${FILE_CFG}
		done
		return 0
	}
	if [[ -z ${TARGET} ]]; then
	    set_value_global; STATUS_GLOBAL=$?
	    set_value_system; STATUS_SYSTEM=$?
	elif [[ ${TARGET} == global ]]; then
	    set_value_global; STATUS_GLOBAL=$?
	elif [[ ${TARGET} == system ]]; then
	    set_value_system; STATUS_SYSTEM=$?
	elif [[ -f ${TARGET} ]]; then
	    FILE_UBLINUX_CONF="${TARGET}"
	    set_value_global; STATUS_GLOBAL=$?
	fi
	[[ ${STATUS_GLOBAL} == 0 ]] && prompt -s "${NAME_VAR} variable added to global configuration ${FILE_UBLINUX_CONF}" \
	    || { prompt -e " ${NAME_VAR} variable not added to global configuration ${FILE_UBLINUX_CONF}"; STATUS=1; }
	[[ ${STATUS_SYSTEM} == 0 ]] && prompt -s "${NAME_VAR} variable added to system configuration ${PATH_UBLINUX_CURRENT}/*" \
	    || { prompt -e " ${NAME_VAR} variable not added to system configuration ${PATH_UBLINUX_CURRENT}/*"; STATUS=1; }
	[[ ${STATUS} == 1 ]] && return 1 || return 0
    }
    local SET_ARG=$1
    local NAME_VAR=
    local VALUE_VAR=
    [[ ${SET_ARG} == ${SET_ARG%%=*} ]] && prompt -eq " not found arguments !"
    case "${SECTION}" in
	"[/etc/ublinux/config]"|"[config]")
	    while read -r ARG; do
		NAME_VAR=${ARG%%=*}; VALUE_VAR=${ARG#*=}
		case "${NAME_VAR}" in
		    HOSTNAME)		set_value_local && [[ -z ${SET_NOEXECUTE} ]] && exec_config_hostname ;;
		    MACHINEID)		set_value_local ;;
		    SAVE_ALL_CACHE)	set_value_local ;;
		    *)			set_value_local ;;
		esac
	    done <<< ${SET_ARG// /$'\n'}
	;;
	"[/etc/ublinux/network]"|"[network]")
	    while read -r ARG; do
		NAME_VAR=${ARG%%=*}; VALUE_VAR=${ARG#*=}
		case "${NAME_VAR}" in
		    'DOMAIN')		set_value_local && [[ -z ${SET_NOEXECUTE} ]] && exec_network_domain ;;
		    'DOMAIN[server]')	set_value_local ;;
		    *)			set_value_local ;;
		esac
	    done <<< ${SET_ARG// /$'\n'}
	;;
	*)
	    prompt -i " not found section ${SECTION}"
	;;
    esac
}

exec_config_hostname(){
    if [[ ${COMMAND} == 'set' ]]; then
	/usr/bin/hostnamectl set-hostname ${VALUE_VAR}
	[[ ${VALUE_VAR} != ${VALUE_VAR#*.} ]] && /usr/bin/ubconfig -q set network DOMAIN="${VALUE_VAR#*.}"
    elif [[ ${COMMAND} == 'remove' ]]; then
	/usr/bin/hostnamectl set-hostname "ublinux"
    fi
}

exec_network_domain(){
    export PARENT="${PKGNAME}"
    if [[ ${COMMAND} == 'set' ]]; then
	/usr/bin/ubdomain-client -q configure
    elif [[ ${COMMAND} == 'remove' ]]; then
	/usr/bin/ubdomain-client -q unconfigure
    fi
}

###############################
###   :::   M A I N   :::   ###
###############################

    PKGNAME=${0##*/}
    PATH_WORK=${PWD}
    set_color

    PATH_UBLINUX_CURRENT="/etc/ublinux"
#PATH_UBLINUX_CURRENT="/tmp/0/etc/ublinux"
    PATH_UBLINUX_CONF="/memory/layer-base/1"
    FILE_UBLINUX_CONF="${PATH_UBLINUX_CONF}/ublinux.ini"
#FILE_UBLINUX_CONF="/tmp/0/ublinux.ini"
    FILE_UBLINUX_DEFAULT="/usr/lib/ublinux/os-config"
#FILE_UBLINUX_DEFAULT="/tmp/0/os-config"
    
    arguments $@
    [[ ${REQUEST_ARGS} == "" ]] || prepare_section "${REQUEST_ARGS%% *}"

    if [[ ${COMMAND} == 'get' ]]; then
        get_value "${REQUEST_ARGS#* }"
    elif [[ ${COMMAND} == 'set' ]]; then
	[[ ${REQUEST_ARGS} == "" ]] || set_value "${REQUEST_ARGS#* }"
    elif [[ ${COMMAND} == 'remove' ]]; then
	[[ ${REQUEST_ARGS} == "" ]] || remove_value "${REQUEST_ARGS#* }"
    fi






#_init_(){
#    export BIN_MKMOD="mkubm"
#    export mnctlPath="/etc/NetworkManager"
#    export tmpUblinuxChng="/tmp/ublinux/connections"
#
#    export excludeFiles=$(mktemp -p /dev/shm)
#    export arg_modules_path=$(realpath /memory/layer-base/*/modules | tail -n1)
#    export path_tmp="$tmpUblinuxChng/$(date '+%Y.%m.%d')-connections"
#}
#_init_
#mkdir -p $path_tmp || exit 1
#[[ -n $arg_modules_path ]] && rsync -aAXruR --exclude-from="$excludeFiles" "$mnctlPath" "$path_tmp" && cd $arg_modules_path || exit 1
#eval ${BIN_MKMOD} -l $(find $tmpUblinuxChng -maxdepth 1 -mindepth 1 -iname '*connections') -o "$(date '+%Y.%m.%d')-connections.ubm" || exit 1
#rm -rf $path_tmp || exit 1
