#!/usr/bin/env bash

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

export TEXTDOMAINDIR=/usr/share/locale
export TEXTDOMAIN=ublinux_functions

    # 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
return_hash_password(){
    SOURCE=${SYSCONF}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    DEFAULT_HASHPASSWD="yescrypt"
    [[ $1 == @(hash|phash) ]] && local 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) ]] && local 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}
    [[ -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=${ARG_PASSWORD:2} && HASH_PASSWORD=${ARG_PASSWORD} || ARG_MODE='hash'
	if [[ ${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 "${HASH_PASSWORD}"
}

# Если параметр $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
}

# 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 -rdf ${ROOTFS}/home/"${SELECT_USERNAME}"
    done < <(tr ',;' '\n' <<< ${LIST_USERNAME})
}

# 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
    SOURCE=${SYSCONF}/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    SOURCE=${ROOTFS}/root/.ublinux/users; [[ -f ${SOURCE} ]] && . ${SOURCE} 2>/dev/null
    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%%=*} =~ [!\$%\&()*+,/\;\<\=\>?\^\{|\}~] ]] || eval "${PARAM%%=*}=\${PARAM#*=}"
    fi
    # Проверим DEFAULTPASSWD, если не указан в $1, то подгрузить из глобальной конфигурации
    [[ -n ${PARAM} ]] || DEFAULTPASSWD=$(ubconfig --raw --source global get [users] DEFAULTPASSWD)
    if [[ -n ${DEFAULTPASSWD} && ${DEFAULTPASSWD} != "(null)" ]]; then
	if [[ -n ${PARAM} && ${DEFAULTPASSWD} =~ ^'%%'(.*)$ ]]; then
	    ubconfig --noexecute --target global set [users] DEFAULTPASSWD="${BASH_REMATCH[1]}"
	else
	    #return_hash_password "${DEFAULTPASSWD}"
	    #[[ -n ${HASH_PASSWORD_NEW} ]] && ubconfig --noexecute --target global set [users] DEFAULTPASSWD="${HASH_PASSWORD_NEW}"
	    ubconfig --noexecute --target global 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} && ${DEFAULTROOTPASSWD} =~ ^'%%'(.*)$ ]]; then
	    ubconfig --noexecute --target global set [users] DEFAULTROOTPASSWD="${BASH_REMATCH[1]}"
	else
	    #return_hash_password "${DEFAULTROOTPASSWD}"
	    #[[ -n ${HASH_PASSWORD_NEW} ]] && ubconfig --noexecute --target global set [users] DEFAULTROOTPASSWD="${HASH_PASSWORD_NEW}"
	    ubconfig --noexecute --target global 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} && ${SELECT_PASSWORD} =~ ^'%%'(.*)$ ]]; then
		    ubconfig --noexecute --target global set [users] USERADD[${SELECT_USERNAME}]="${SELECT_GECOS}:${SELECT_UID}:${SELECT_GROUP}:${SELECT_EXTRAGROUPS}:${SELECT_OPTIONAL}:${BASH_REMATCH[1]}"
		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 --noexecute --target global 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} && ${SELECT_PASSWORD} =~ ^'%%'(.*)$ ]]; then
		    ubconfig --noexecute --target global set [users] GROUPADD[${SELECT_GROUP}]="${SELECT_USERS}:${SELECT_GID}:${SELECT_OPTIONAL}:${SELECT_ADMINISTRATORS}:${BASH_REMATCH[1]}"
		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 --noexecute --target global 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
}

detectDE(){
    [[ -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
    if [[ -z ${SESSION} ]]; then
         ps -A | grep -q " xfce4-session$" && SESSION=xfce
         ps -A | grep -q " kdeinit$"       && SESSION=kde
         ps -A | grep -q " i3$"          && SESSION=i3
         ps -A | grep -q " i3term$"      && SESSION=i3term
         ps -A | grep -q " gnome-panel$"   && SESSION=gnome
         ps -A | grep -q " gnome-shell$"   && SESSION=gnome-shell
         ps -A | grep -q " plasmashell$"   && SESSION=plasma
    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 grep -q "debug" /proc/cmdline ; then
      echo "- debug: $*" >&2
      log "- debug: $*"
   fi
}

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

debug_mode(){
  if [ "$(cmdline_parameter debug)" -o "$DEBUGMODE" == "yes" ] ; then
     name=$(basename $0)
     slash="/"
     [ "$(pwd)" == "/union" ] && slash=""
     if ! test -f  ${slash}var/log/ublinux/${name}.log ; then
        echo "$0 --  debug mode enabled"
        test -d ${slash}var/log/ublinux || mkdir -p ${slash}var/log/ublinux
        echo $(date) >   ${slash}var/log/ublinux/${name}.log || echo "can not create log file"
        $0 "$@" 2>&1 | tee -a ${slash}var/log/ublinux/${name}.log
        exit 0
     fi
  fi
}

echodebug(){
  [ "$DEBUG_IS_ENABLED" -o "$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(){
   . /usr/lib/ublinux/default
   . /etc/ublinux/config 2>/dev/null
   . /etc/ublinux/system 2>/dev/null
   echo " $@ " | grep -Eq ' -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

   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"

   find "$MOD" | grep -E "$RUNSCRIPTS" | cut -b "${#MOD}"- | cut -b 2- | xargs -n 1 -r readlink -f | sort -u | \
       while read SCRIPT; do
         if [ "$SCRIPT" != "" -a -x "$SCRIPT" -a ! -d "$SCRIPT" ]; then
            # call the script by real path, not from the module
            log "starting '"$SCRIPT" $@'"
            "${SCRIPT}" "$@"
         fi
       done
}

# test if the script is started by root user. If not, exit
allow_only_root(){
  if [ "0$UID" -ne 0 ]; then
     echo "Only root can run $(basename $0)"; exit 1
  fi
}


#####################
# 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=$(detectDE)
  if [ "$DE" = "kde" -o "$DE" = "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(){
  DE=$(detectDE)
#  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" -a "$DE" != "plasma" ] ; then
    ps -U $(id -u) | grep -q xscreensaver || xscreensaver -no-splash &
    sleep 0.5s
    xscreensaver-command -lock
  fi
}

xss_slideshow(){
  chbg -xscreensaver -randomize -R -effect 1 -interval 0.2 -mode smart -max_size 100 -R /usr/share/ublinux/screensaver/Default >/dev/null 2>&1
}

xss_heartbeat(){
  . /usr/lib/ublinux/default
  . /etc/ublinux/config 2>/dev/null
  SSAVERBLOCKAPPS="$(echo "$SSAVERBLOCKAPPS"| tr ',; ' '|' )"
  bash -c "while true ;do top -bn1 -u $(id -un) | awk '{ print \$7 FS \$NF }' | grep ^[1-9] | grep -Eq \"$SSAVERBLOCKAPPS\" && xscreensaver-command -deactivate >/dev/null ; sleep 20s ; done " &
}


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(){
  . /etc/os-release
  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=$(cat /proc/cmdline)
  VERSION=$(cat /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" > ~/network.txt
  netstat --inet  >> ~/network.txt
  echo -e "\nlsof -i" >> ~/network.txt
  /usr/sbin/lsof -i >> ~/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
}

userkeys(){
  string=$(head -n $1 $HOME/.userkeys | tail -n 1)
  TMPFILE=$HOME/tmp/userkey-$(id -un)
  > $TMPFILE
  echo "#!/bin/bash" > $TMPFILE
  echo "$string" >> $TMPFILE
  chmod +x $TMPFILE
  $TMPFILE
  rm -f $TMPFILE
}

screen_scale(){
  scale_[1]=1x1
  scale_[2]=1x1.2
  scale_[3]=1.2x1.2
  scale_[4]=1.2x1.5
  scale_[5]=1.5x1.5
  scale=2
  [ -f /tmp/scale ] && scale=$(cat /tmp/scale)
  xrandr --output LVDS1  --scale ${scale_[$scale]}
  if [ $scale == 5 ] ; then
    echo 1 > /tmp/scale
  else
    echo $(expr $scale + 1) > /tmp/scale
  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
	while [[ $# -gt 0 ]]; do
	    declare -f ${1} &>/dev/null && FUNCTION+="; ${1}" && shift || { FUNCTION+=" '${1}'" && shift; }
	done
	eval ${FUNCTION#*; }
    fi

