@ -190,6 +190,584 @@ globalconf_convert_pass_plain_to_hash(){
fi
}
#####################################################################################
###
### Функции управления пользователями и группами с помощью тектовых процессоров ###
###
#####################################################################################
# Добавить пользователя в /etc/passwd /etc/shadow
# user_add $1:$2:$3:$4:$5:$6:$7:$8:$9:$10:$11:$12:$13
# $1 # Имя пользователя
# $2 # GECOS пользователя
# $3 # UID идентификатор пользователя
# # = 's' | 'system' # Вычисляется автоматически, первый свободный системного диапазона
# # Если не задан, то вычисляется автоматически, первый свободный пользовательского диапазона
# $4 # GID первичной группы пользователя
# # Если не задана, то создать группу по имени пользователя и взять GID
# $5 # Зашифрованный пароль
# # = '' # Если не задано, то пароль '!*' запрет авторизации
# # = ' ' # Если пробел, то без пароля
# # = 'lock' | 'l' # Заблокировать авторизация, добавив '!' перед хешем
# # = 'unlock' | 'u' # Разблокировать авторизация, убрав '!' или '!!' или '!*' или '*' перед хешем
# $6 # HOME пользователя
# $7 # SHELL пользователя
# $8 # LASTCHANGED
# $9 # MINDAY
# $10 # MAXDAY
# $11 # WARN
# $12 # INACTIVE
# $13 # EXPIRE
# Для изменения параметров существующего пользователя, обязательный параметр: $1 или $3 пользователя
# Если одно из полей содержит "+" то значение поля не менять в файле
# Пример: user_add user-1:Пользователь-1
# Пример: user_add user-1:Пользователь-1:1001:1001
# Пример: user_add user-1:Пользователь-1:1001:1001:!*:/home/user-1:/bin/bash:19788:0:99999:7:2:19800
# Пример: user_add root:+:+:+:!*:+:+::+:+:+:+:+
user_add(){
[[ $1 == @("-v"|"--verbose") ]] && local VERBOSE='yes' && shift
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"
local DATA_FILE_PASSWD=$(cat ${FILE_PASSWD})
local DATA_FILE_SHADOW=$(cat ${FILE_SHADOW})
local DATA_FILE_LOGINDEFS=$(cat ${FILE_LOGINDEFS})
local DATA_FILE_DEFAULT_USERADD=$(cat ${FILE_DEFAULT_USERADD})
[[ ${DATA_FILE_DEFAULT_USERADD} =~ ($'\n'|^)+HOME=([^$'\n']*)($'\n'|$)+ ]] && local DEFAULT_HOME_USER=${BASH_REMATCH[2]:-/home}
[[ ${DATA_FILE_DEFAULT_USERADD} =~ ($'\n'|^)+SHELL=([^$'\n']*)($'\n'|$)+ ]] && local DEFAULT_SHELL_USER=${BASH_REMATCH[2]:-/bin/bash}
local DEFAULT_HOME_SYSTEM="/"
local DEFAULT_SHELL_SYSTEM="/usr/bin/nologin"
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+PASS_MAX_DAYS[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && local DEFAULT_MAXDAY=${BASH_REMATCH[2]:-99999}
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+PASS_MIN_DAYS[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && local DEFAULT_MINDAY=${BASH_REMATCH[2]:-0}
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+PASS_WARN_AGE[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && local DEFAULT_WARN=${BASH_REMATCH[2]:-7}
get_free_uid(){
local PARAM="$@"
local UID_MIN= UID_MAX= UID_NEW=
if [[ ${PARAM} == "@system" ]]; then
# Свободный номер системного списка группы
#UID_MIN=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*SYS_UID_MIN[[:blank:]]+([[:digit:]]+) ]]; printf "%d" "${BASH_REMATCH[1]}")
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+SYS_UID_MIN[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && UID_MIN=${BASH_REMATCH[2]:-500}
#UID_MAX=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*SYS_UID_MAX[[:blank:]]+([[:digit:]]+) ]]; printf "%d" "${BASH_REMATCH[1]}")
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+SYS_UID_MAX[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && UID_MAX=${BASH_REMATCH[2]:-999}
UID_NEW=$(awk -F':' -v USER_MIN=${UID_MIN} -v USER_MAX=${UID_MAX} '{ uid[$3]=USER_MAX } END {for (x=USER_MAX; x>=USER_MIN; x--) if (!uid[x]) {print x; exit}}' ${FILE_PASSWD}) #'
[[ ${UID_NEW} == "" ]] && UID_NEW=${UID_MAX}
else
# Свободный номер списка групп, кроме системного списка
#UID_MIN=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*UID_MIN[[:blank:]]+([[:digit:]]+) ]]; printf "%d" "${BASH_REMATCH[1]}")
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+UID_MIN[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && UID_MIN=${BASH_REMATCH[2]:-1000}
#UID_MAX=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*UID_MAX[[:blank:]]+([[:digit:]]+) ]]; printf "%d" "${BASH_REMATCH[1]}")
[[ ${DATA_FILE_LOGINDEFS} =~ ($'\n'|^)+UID_MAX[[:blank:]]+([[:digit:]]+)($'\n'|$)+ ]] && UID_MAX=${BASH_REMATCH[2]:-60000}
UID_NEW=$(awk -F':' -v USER_MIN=${UID_MIN} -v USER_MAX=${UID_MAX} '{ uid[$3]=USER_MIN } END {for (x=USER_MIN; x<=USER_MAX; x++) if (!uid[x]) {print x; exit}}' ${FILE_PASSWD}) #'
[[ ${UID_NEW} == "" ]] && UID_NEW=${UID_MIN}
fi
printf "%d" "${UID_NEW}"
}
is_uid_system(){
local UID_MIN=
UID_MIN=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*UID_MIN[[:blank:]]+([[:digit:]]+) ]]; printf "%d" "${BASH_REMATCH[1]}")
[[ ${SELECT_UID} -lt ${UID_MIN:=1000} ]] && printf "%d" "1" || printf "%d" "0"
}
local PARAM="$@"
# Получаем из аргумента значения
local IS_USER_SYSTEM=
local SELECT_NOUSE=
local SELECT_USERNAME= SELECT_GECOS= SELECT_UID= SELECT_GID= SELECT_PASSWORD= SELECT_HOME= SELECT_SHELL= SELECT_LASTCHANGED= SELECT_MINDAY= SELECT_MAXDAY= SELECT_WARN= SELECT_INACTIVE= SELECT_EXPIRE= NULL=
IFS=: read -r SELECT_USERNAME SELECT_GECOS SELECT_UID SELECT_GID SELECT_PASSWORD SELECT_HOME SELECT_SHELL SELECT_LASTCHANGED SELECT_MINDAY SELECT_MAXDAY SELECT_WARN SELECT_INACTIVE SELECT_EXPIRE NULL <<< "${PARAM}"
[[ ${SELECT_USERNAME} == "" && ${SELECT_UID} == "" ]] && { >&2 echo "ERROR: not added/changed '${SELECT_USERNAME}' username"; return 1; }
# Получаем из файла значения
local VOL_FILEP_PLAINPASSWORD= VOL_FILEP_UID= VOL_FILEP_GID= VOL_FILEP_GECOS= VOL_FILEP_HOME= VOL_FILEP_SHELL= VOL_FILEP_USERNAME=
if [[ ${SELECT_USERNAME} != @(""|"+") ]]; then
[[ ${DATA_FILE_PASSWD} =~ ($'\n'|^)+"${SELECT_USERNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEP_PLAINPASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEP_UID=${BASH_REMATCH[3]} \
&& VOL_FILEP_GID=${BASH_REMATCH[4]} \
&& VOL_FILEP_GECOS=${BASH_REMATCH[5]} \
&& VOL_FILEP_HOME=${BASH_REMATCH[6]} \
&& VOL_FILEP_SHELL=${BASH_REMATCH[7]}
VOL_FILEP_USERNAME=${SELECT_USERNAME}
elif [[ ${SELECT_USERNAME} == @(""|"+") && ${SELECT_UID} =~ ^[[:digit:]]+$ ]]; then
[[ ${DATA_FILE_PASSWD} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_UID}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEP_USERNAME=${BASH_REMATCH[2]} \
&& VOL_FILEP_PLAINPASSWORD=${BASH_REMATCH[3]} \
&& VOL_FILEP_GID=${BASH_REMATCH[4]} \
&& VOL_FILEP_GECOS=${BASH_REMATCH[5]} \
&& VOL_FILEP_HOME=${BASH_REMATCH[6]} \
&& VOL_FILEP_SHELL=${BASH_REMATCH[7]}
VOL_FILEP_UID=${SELECT_UID}
SELECT_USERNAME=${VOL_FILEP_USERNAME}
fi
[[ ${SELECT_USERNAME} == @(""|"+") ]] && { >&2 echo "ERROR: not added/changed empty username"; return 1; }
[[ ${SELECT_PASSWORD} == "+" ]] && SELECT_PLAINPASSWORD=${VOL_FILEP_PLAINPASSWORD}
[[ ${SELECT_PLAINPASSWORD} == "" ]] && SELECT_PLAINPASSWORD='x'
if [[ ${SELECT_UID} == "+" && ${VOL_FILEP_UID} != "" ]]; then
SELECT_UID=${VOL_FILEP_UID}
elif [[ ${SELECT_UID} == @("s"|"system") ]]; then
SELECT_UID=$(get_free_uid @system)
elif [[ ${SELECT_UID} =~ ^[[:digit:]]+$ ]]; then
true
else
# Если UID не задан, то берём первый свободный
SELECT_UID=$(get_free_uid)
fi
if [[ ${SELECT_GID} == "+" && ${VOL_FILEP_GID} != "" ]]; then
SELECT_GID=${VOL_FILEP_GID}
elif [[ ${SELECT_GID} =~ ^[[:digit:]]+$ ]]; then
true
else
# Если GID не задан, то создаём группу по имени пользователя ${SELECT_UID} и получаем GID от созданной группы
IFS=: read -r NULL SELECT_GID NULL NULL NULL NULL <<< $(group_add --verbose "${SELECT_USERNAME}:+:+:+:+")
[[ ${SELECT_GID} == "" ]] && SELECT_GID=${SELECT_UID}
fi
[[ ${SELECT_GECOS} == "+" ]] && SELECT_GECOS=${VOL_FILEP_GECOS}
if [[ ${SELECT_HOME} == "+" && ${VOL_FILEP_HOME} != "" ]]; then
SELECT_HOME=${VOL_FILEP_HOME}
elif [[ ${SELECT_HOME} == @(""|"+") ]]; then
[[ $(is_uid_system) == 1 ]] && SELECT_HOME=${DEFAULT_HOME_SYSTEM} || SELECT_HOME="${DEFAULT_HOME_USER}/${SELECT_USERNAME}"
fi
if [[ ${SELECT_SHELL} == "+" && ${VOL_FILEP_SHELL} != "" ]]; then
SELECT_SHELL=${VOL_FILEP_SHELL}
elif [[ ${SELECT_SHELL} == @(""|"+") ]]; then
[[ $(is_uid_system) == 1 ]] && SELECT_SHELL=${DEFAULT_SHELL_SYSTEM} || SELECT_SHELL=${DEFAULT_SHELL_USER}
fi
local VOL_FILEPS_PASSWORD= VOL_FILEPS_LASTCHANGED= VOL_FILEPS_MINDAY= VOL_FILEPS_MAXDAY= VOL_FILEPS_WARN= VOL_FILEPS_INACTIVE= VOL_FILEPS_EXPIRE= VOL_FILEPS_NOUSE=
[[ ${DATA_FILE_SHADOW} =~ ($'\n'|^)+"${SELECT_USERNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEPS_PASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEPS_LASTCHANGED=${BASH_REMATCH[3]} \
&& VOL_FILEPS_MINDAY=${BASH_REMATCH[4]} \
&& VOL_FILEPS_MAXDAY=${BASH_REMATCH[5]} \
&& VOL_FILEPS_WARN=${BASH_REMATCH[6]} \
&& VOL_FILEPS_INACTIVE=${BASH_REMATCH[7]} \
&& VOL_FILEPS_EXPIRE=${BASH_REMATCH[8]} \
&& VOL_FILEPS_NOUSE=${BASH_REMATCH[9]}
if [[ ${SELECT_PASSWORD} == "+" && ${VOL_FILEPS_PASSWORD} != "" ]]; then
SELECT_PASSWORD=${VOL_FILEPS_PASSWORD}
elif [[ ${SELECT_PASSWORD} == @("lock"|"l") && ${VOL_FILEPS_PASSWORD} != "" ]]; then
if [[ ${VOL_FILEPS_PASSWORD:0:1} == "!" ]]; then
SELECT_PASSWORD=${VOL_FILEPS_PASSWORD}
else
SELECT_PASSWORD="!${VOL_FILEPS_PASSWORD}"
fi
elif [[ ${SELECT_PASSWORD} == @("unlock"|"u") && ${VOL_FILEPS_PASSWORD} != "" ]]; then
if [[ ${VOL_FILEPS_PASSWORD:0:2} == "!!" ]]; then
SELECT_PASSWORD="${VOL_FILEPS_PASSWORD:2}"
elif [[ ${VOL_FILEPS_PASSWORD:0:2} == "!*" ]]; then
SELECT_PASSWORD="${VOL_FILEPS_PASSWORD:2}"
elif [[ ${VOL_FILEPS_PASSWORD:0:1} == "*" ]]; then
SELECT_PASSWORD="${VOL_FILEPS_PASSWORD:1}"
elif [[ ${VOL_FILEPS_PASSWORD:0:1} == "!" ]]; then
SELECT_PASSWORD="${VOL_FILEPS_PASSWORD:1}"
else
SELECT_PASSWORD="${VOL_FILEPS_PASSWORD}"
fi
elif [[ ${SELECT_PASSWORD} == " " ]]; then
SELECT_PASSWORD=
elif [[ ${SELECT_PASSWORD} == @(""|"+") ]]; then
SELECT_PASSWORD="!*"
fi
if [[ ${SELECT_LASTCHANGED} == "+" && ${VOL_FILEPS_LASTCHANGED} != "" ]]; then
SELECT_LASTCHANGED=${VOL_FILEPS_LASTCHANGED}
elif [[ ${SELECT_LASTCHANGED} =~ ^[[:digit:]]{4,4}'-'[[:digit:]]{1,2}'-'[[:digit:]]{1,2}$ ]]; then
SELECT_LASTCHANGED=$(( $(${CMD_CHROOT} date --date="${SELECT_LASTCHANGED} 0000" +"%s")/(60*60*24) ))
elif [[ ${SELECT_LASTCHANGED} =~ ^[[:digit:]]{1,5}$ ]]; then
true
else
SELECT_LASTCHANGED=$(( $(${CMD_CHROOT} date +%s)/(60*60*24) )) # (60*60*24)=18400 second on day
fi
if [[ ${SELECT_MINDAY} == "+" && ${VOL_FILEPS_MINDAY} != "" ]]; then
SELECT_MINDAY=${VOL_FILEPS_MINDAY}
elif [[ ${SELECT_MINDAY} =~ ^[[:digit:]]+$ ]]; then
true
else
[[ $(is_uid_system) == 1 ]] && SELECT_MINDAY= || SELECT_MINDAY=${DEFAULT_MINDAY}
fi
if [[ ${SELECT_MAXDAY} == "+" && ${VOL_FILEPS_MAXDAY} != "" ]]; then
SELECT_MAXDAY=${VOL_FILEPS_MAXDAY}
elif [[ ${SELECT_MAXDAY} =~ ^[[:digit:]]+$ ]]; then
true
else
[[ $(is_uid_system) == 1 ]] && SELECT_MAXDAY= || SELECT_MAXDAY=${DEFAULT_MAXDAY}
fi
if [[ ${SELECT_WARN} == "+" && ${VOL_FILEPS_WARN} != "" ]]; then
SELECT_WARN=${VOL_FILEPS_WARN}
elif [[ ${SELECT_WARN} =~ ^[[:digit:]]+$ ]]; then
true
else
[[ $(is_uid_system) == 1 ]] && SELECT_WARN= || SELECT_WARN=${DEFAULT_WARN}
fi
if [[ ${SELECT_INACTIVE} == "+" && ${VOL_FILEPS_INACTIVE} != "" ]]; then
SELECT_INACTIVE=${VOL_FILEPS_INACTIVE}
elif [[ ${SELECT_INACTIVE} =~ (-1|^[[:digit:]]+$) ]]; then
true
else
SELECT_INACTIVE=
fi
if [[ ${SELECT_EXPIRE} == "+" && ${VOL_FILEPS_EXPIRE} != "" ]]; then
SELECT_EXPIRE=${VOL_FILEPS_EXPIRE}
elif [[ ${SELECT_EXPIRE} =~ ^[[:digit:]]{4,4}'-'[[:digit:]]{1,2}'-'[[:digit:]]{1,2}$ ]]; then
SELECT_EXPIRE=$(( $(${CMD_CHROOT} date --date="${SELECT_EXPIRE} 0000" +"%s")/(60*60*24) ))
elif [[ ${SELECT_EXPIRE} =~ ^[[:digit:]]{1,5}$ ]]; then
true
else
SELECT_EXPIRE=
fi
SELECT_NOUSE=""
# Если нет изменений, то ничего не делать
if [[ "${SELECT_USERNAME}" != "${VOL_FILEP_USERNAME}" && "${SELECT_PLAINPASSWORD}" != "${VOL_FILEP_PLAINPASSWORD}" || "${SELECT_UID}" != "${VOL_FILEP_UID}" || "${SELECT_GID}" != "${VOL_FILEP_GID}" || "${SELECT_GECOS}" != "${VOL_FILEP_GECOS}" \
|| "${SELECT_HOME}" != "${VOL_FILEP_HOME}" || "${SELECT_SHELL}" != "${VOL_FILEP_SHELL}" ]]; then
sed "/^${SELECT_USERNAME}:/d" -i "${FILE_PASSWD}"
printf "%s:%s:%d:%d:%s:%s:%s\n" "${SELECT_USERNAME}" "${SELECT_PLAINPASSWORD}" "${SELECT_UID}" "${SELECT_GID}" "${SELECT_GECOS}" "${SELECT_HOME}" "${SELECT_SHELL}" >> "${FILE_PASSWD}"
fi
if [[ "${SELECT_PASSWORD}" != "${VOL_FILEPS_PASSWORD}" || "${SELECT_LASTCHANGED}" != "${VOL_FILEPS_LASTCHANGED}" || "${SELECT_MINDAY}" != "${VOL_FILEPS_MINDAY}" || "${SELECT_MAXDAY}" != "${VOL_FILEPS_MAXDAY}" \
|| "${SELECT_WARN}" != "${VOL_FILEPS_WARN}" || "${SELECT_INACTIVE}" != "${VOL_FILEPS_INACTIVE}" || "${SELECT_EXPIRE}" != "${VOL_FILEPS_EXPIRE}" ]]; then
sed "/^${SELECT_USERNAME}:/d" -i "${FILE_SHADOW}"
printf "%s:%s:%d:%s:%s:%s:%s:%s:%s\n" "${SELECT_USERNAME}" "${SELECT_PASSWORD}" "${SELECT_LASTCHANGED}" "${SELECT_MINDAY}" "${SELECT_MAXDAY}" "${SELECT_WARN}" "${SELECT_INACTIVE}" "${SELECT_EXPIRE}" "${SELECT_NOUSE}" >> "${FILE_SHADOW}"
fi
[[ -n ${VERBOSE} ]] && printf "%s:%s:%d:%d:%s:%s:%s:%d:%s:%s:%s:%s:%s\n" "${SELECT_USERNAME}" "${SELECT_GECOS}" "${SELECT_UID}" "${SELECT_GID}" "${SELECT_PASSWORD}" "${SELECT_HOME}" "${SELECT_SHELL}" "${SELECT_LASTCHANGED}" "${SELECT_MINDAY}" "${SELECT_MAXDAY}" "${SELECT_WARN}" "${SELECT_INACTIVE}" "${SELECT_EXPIRE}"
}
# Удалить пользователя из /etc/passwd /etc/shadow
# user_del $1:$2
# $1 # Имя пользователя
# $2 # UID идентификатор пользователя
# Что-бы удалить пользователя можно указать $1 или $2 или о б а одновременно $1:$2
# Пример: user_del user-1
# user_del :1001
# user_del user-2:1002
user_del(){
local FILE_PASSWD="${ROOTFS}/etc/passwd"
local FILE_SHADOW="${ROOTFS}/etc/shadow"
local DATA_FILE_PASSWD=$(cat ${FILE_PASSWD})
local FILE_GROUP="${ROOTFS}/etc/group"
local FILE_GSHADOW="${ROOTFS}/etc/gshadow"
local DATA_FILE_GROUP=$(cat ${FILE_GROUP})
local PARAM="$@"
local SELECT_USERNAME= SELECT_UID=
IFS=: read -r SELECT_USERNAME SELECT_UID NULL <<< "${PARAM}"
[[ ${SELECT_USERNAME} == "" && ${SELECT_UID} == "" ]] && { >&2 echo "ERROR: not delete '${SELECT_USERNAME}' username"; return 1; }
SELECT_USERNAME=$@
local VOL_FILEP_PLAINPASSWORD VOL_FILEP_UID VOL_FILEP_GID VOL_FILEP_GECOS VOL_FILEP_HOME VOL_FILEP_SHELL
# Ищем пользователя вначале по имени, после по UID
[[ -n ${SELECT_USERNAME} && ${DATA_FILE_PASSWD} =~ ($'\n'|^)+"${SELECT_USERNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEP_PLAINPASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEP_UID=${BASH_REMATCH[3]} \
&& VOL_FILEP_GID=${BASH_REMATCH[4]} \
&& VOL_FILEP_GECOS=${BASH_REMATCH[5]} \
&& VOL_FILEP_HOME=${BASH_REMATCH[6]} \
&& VOL_FILEP_SHELL=${BASH_REMATCH[7]}
[[ -n ${SELECT_UID} && ${DATA_FILE_PASSWD} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_UID}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& SELECT_USERNAME=${BASH_REMATCH[2]} \
&& VOL_FILEP_PLAINPASSWORD=${BASH_REMATCH[3]} \
&& VOL_FILEP_UID=${SELECT_UID} \
&& VOL_FILEP_GID=${BASH_REMATCH[4]} \
&& VOL_FILEP_GECOS=${BASH_REMATCH[5]} \
&& VOL_FILEP_HOME=${BASH_REMATCH[6]} \
&& VOL_FILEP_SHELL=${BASH_REMATCH[7]}
sed "/^${SELECT_USERNAME}:/d" -i "${FILE_PASSWD}"
sed "/^${SELECT_USERNAME}:/d" -i "${FILE_SHADOW}"
# Если имеется группа с таким же именем пользователя и она является основной группой указанного пользователя и в ней нет других пользователей, то удаляем группу
local VOL_FILEG_PLAINPASSWORD= VOL_FILEG_GID= VOL_FILEG_MEMBERS=
[[ ${DATA_FILE_GROUP} =~ ($'\n'|^)+"${SELECT_USERNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEG_PLAINPASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEG_GID=${BASH_REMATCH[3]} \
&& VOL_FILEG_MEMBERS=${BASH_REMATCH[4]}
if [[ ${VOL_FILEP_GID} == ${VOL_FILEG_GID} && -z ${VOL_FILEG_MEMBERS} ]]; then
sed /^${SELECT_USERNAME}:/d -i "${FILE_GROUP}"
sed /^${SELECT_USERNAME}:/d -i "${FILE_GSHADOW}"
fi
# Удаляем пользователя из всех групп
sed "s/:${SELECT_USERNAME}$/:/g;s/:${SELECT_USERNAME},/:/g;s/,${SELECT_USERNAME}$//g;s/,${SELECT_USERNAME},/,/g" -i "${FILE_GROUP}"
sed "s/:${SELECT_USERNAME}$/:/g;s/:${SELECT_USERNAME},/:/g;s/,${SELECT_USERNAME}$//g;s/,${SELECT_USERNAME},/,/g" -i "${FILE_GSHADOW}"
}
# Добавить группу в /etc/group /etc/gshadow
# group_add $1:$2:$3:$4:$5
# $1 # Имя группы
# $2 # GID идентификатор группы
# # = 's' | 'system' # Вычисляется автоматически, первый свободный системного диапазона
# # Если не задан, то вычисляется автоматически, первый свободный пользовательского диапазона
# $3 # Члены группы, разделённые запятыми
# $4 # Зашифрованный пароль
# # = '' # Если не задано, то пароль '!*' запрет авторизации
# # = ' ' # Если пробел, то без пароля
# # = 'lock' | 'l' # Заблокировать авторизация, добавив '!' перед хешем
# # = 'unlock' | 'u' # Разблокировать авторизация, убрав '!' или '!!' или '!*' или '*' перед хешем
# $5 # Администраторы группы, разделённые запятыми
# Для изменения параметров существующей группы, обязательный параметр: $1 или $2 пользователя
# Если одно из полей содержит "+" то значение поля не менять в файле
# Пример: g_department_1
# Пример: g_department_1:1010
# Пример: g_department_1:1010:user-1,user-2::superadmin
# Пример: g_department_1:+:+:+:+
# Пример: g_department_1:1010:+:+:+
group_add(){
[[ $1 == @("-v"|"--verbose") ]] && local VERBOSE='yes' && shift
local FILE_GROUP="${ROOTFS}/etc/group"
local FILE_GSHADOW="${ROOTFS}/etc/gshadow"
local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs"
local DATA_FILE_GROUP=$(cat ${FILE_GROUP})
local DATA_FILE_GSHADOW=$(cat ${FILE_GSHADOW})
local DATA_FILE_LOGINDEFS=$(cat ${FILE_LOGINDEFS})
get_free_gid(){
local PARAM="$@"
local GID_MIN= GID_MAX= GID_NEW=
if [[ ${PARAM} == "@system" ]]; then
# Свободный номер системного списка группы
GID_MIN=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*SYS_GID_MIN[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
GID_MAX=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*SYS_GID_MAX[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
GID_NEW=$(awk -F':' -v GROUP_MIN=${GID_MIN:=500} -v GROUP_MAX=${GID_MAX:=999} '{ gid[$3]=GROUP_MAX } END {for (x=GROUP_MAX; x>=GROUP_MIN; x--) if (!gid[x]) {print x; exit}}' ${FILE_GROUP}) #'
[[ ${GID_NEW} == "" ]] && GID_NEW=${GID_MAX}
else
# Свободный номер списка групп, кроме системного списка
GID_MIN=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*GID_MIN[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
GID_MAX=$([[ ${DATA_FILE_LOGINDEFS} =~ [^#[^:blank:]]*GID_MAX[[:blank:]]+([[:digit:]]+) ]]; echo -n "${BASH_REMATCH[1]}")
# Предоставить свободный номер с начала списка
GID_NEW=$(awk -F':' -v GROUP_MIN=${GID_MIN:=1000} -v GROUP_MAX=${GID_MAX:=6000} '{ gid[$3]=GROUP_MIN } END {for (x=GROUP_MIN; x<=GROUP_MAX; x++) if (!gid[x]) {print x; exit}}' ${FILE_GROUP}) #'
[[ ${GID_NEW} == "" ]] && GID_NEW=${GID_MIN}
# Предоставить свободный номер с конца списка
#GID_NEW=$(awk -F':' -v GROUP_MIN=${GID_MIN:=1000} -v GROUP_MAX=${GID_MAX:=60000} '{ gid[$3]=GROUP_MAX } END {for (x=GROUP_MAX; x>=GROUP_MIN; x--) if (!gid[x]) {print x; exit}}' ${FILE_GROUP}) #'
#[[ ${GID_NEW} == "" ]] && GID_NEW=${GID_MAX}
fi
printf "%d" "${GID_NEW}"
}
local PARAM="$@"
# Получаем из аргумента значения
local SELECT_GROUPNAME= SELECT_GID= SELECT_MEMBERS= SELECT_PASSWORD= SELECT_ADMINISTRATORS= NULL=
IFS=: read -r SELECT_GROUPNAME SELECT_GID SELECT_MEMBERS SELECT_PASSWORD SELECT_ADMINISTRATORS NULL <<< "${PARAM}"
[[ ${SELECT_GROUPNAME} == "" && ${SELECT_GID} == "" ]] && { >&2 echo "ERROR: not added/changed '${SELECT_GROUPNAME}' groupname"; return 1; }
# Получаем из файла значения
local VOL_FILEG_PLAINPASSWORD= VOL_FILEG_GID= VOL_FILEG_MEMBERS= VOL_FILEG_GROUPNAME=
local SELECT_PLAINPASSWORD=
if [[ ${SELECT_GROUPNAME} != @(""|"+") ]]; then
[[ ${DATA_FILE_GROUP} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEG_PLAINPASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEG_GID=${BASH_REMATCH[3]} \
&& VOL_FILEG_MEMBERS=${BASH_REMATCH[4]}
VOL_FILEG_GROUPNAME=${SELECT_GROUPNAME}
elif [[ ${SELECT_GROUPNAME} == @(""|"+") && ${SELECT_GID} =~ ^[[:digit:]]+$ ]]; then
[[ ${DATA_FILE_GROUP} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_GID}":([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEG_GROUPNAME=${BASH_REMATCH[2]} \
&& VOL_FILEG_PLAINPASSWORD=${BASH_REMATCH[3]} \
&& VOL_FILEG_MEMBERS=${BASH_REMATCH[4]}
VOL_FILEG_GID=${SELECT_GID}
SELECT_GROUPNAME=${VOL_FILEG_GROUPNAME}
fi
[[ ${SELECT_GROUPNAME} == @(""|"+") ]] && { >&2 echo "ERROR: not added/changed empty groupname"; return 1; }
[[ ${SELECT_PASSWORD} == "+" ]] && SELECT_PLAINPASSWORD=${VOL_FILEG_PLAINPASSWORD} || SELECT_PLAINPASSWORD='x'
[[ ${SELECT_PASSWORD} == "" || ${SELECT_PLAINPASSWORD} == "" ]] && SELECT_PLAINPASSWORD='x'
if [[ ${SELECT_GID} == "+" && ${VOL_FILEG_GID} != "" ]]; then
SELECT_GID=${VOL_FILEG_GID}
elif [[ ${SELECT_GID} == @("s"|"system") ]]; then
SELECT_GID=$(get_free_gid @system)
elif [[ ${SELECT_GID} =~ ^[[:digit:]]+$ ]]; then
true
else
SELECT_GID=$(get_free_gid)
fi
[[ ${SELECT_MEMBERS} == "+" ]] && SELECT_MEMBERS=${VOL_FILEG_MEMBERS}
local VOL_FILEGS_PASSWORD= VOL_FILEGS_ADMINISTRATORS= VOL_FILEGS_MEMBERS=
[[ ${DATA_FILE_GSHADOW} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEGS_PASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEGS_ADMINISTRATORS=${BASH_REMATCH[3]} \
&& VOL_FILEGS_MEMBERS=${BASH_REMATCH[4]}
if [[ ${SELECT_PASSWORD} == "+" && ${VOL_FILEGS_PASSWORD} != "" ]]; then
SELECT_PASSWORD=${VOL_FILEGS_PASSWORD}
elif [[ ${SELECT_PASSWORD} == @("lock"|"l") && ${VOL_FILEGS_PASSWORD} != "" ]]; then
if [[ ${VOL_FILEGS_PASSWORD:0:1} == "!" ]]; then
SELECT_PASSWORD=${VOL_FILEGS_PASSWORD}
else
SELECT_PASSWORD="!${VOL_FILEGS_PASSWORD}"
fi
elif [[ ${SELECT_PASSWORD} == @("unlock"|"u") && ${VOL_FILEGS_PASSWORD} != "" ]]; then
if [[ ${VOL_FILEGS_PASSWORD:0:2} == "!!" ]]; then
SELECT_PASSWORD="${VOL_FILEGS_PASSWORD:2}"
elif [[ ${VOL_FILEGS_PASSWORD:0:2} == "!*" ]]; then
SELECT_PASSWORD="${VOL_FILEGS_PASSWORD:2}"
elif [[ ${VOL_FILEGS_PASSWORD:0:1} == "*" ]]; then
SELECT_PASSWORD="${VOL_FILEGS_PASSWORD:1}"
elif [[ ${VOL_FILEGS_PASSWORD:0:1} == "!" ]]; then
SELECT_PASSWORD="${VOL_FILEGS_PASSWORD:1}"
else
SELECT_PASSWORD="${VOL_FILEGS_PASSWORD}"
fi
elif [[ ${SELECT_PASSWORD} == " " ]]; then
SELECT_PASSWORD=
elif [[ ${SELECT_PASSWORD} == @(""|"+") ]]; then
SELECT_PASSWORD="!*"
fi
[[ ${SELECT_ADMINISTRATORS} == "+" ]] && SELECT_ADMINISTRATORS=${VOL_FILEGS_ADMINISTRATORS}
# Если нет изменений, то ничего не делать
if [[ "${SELECT_GROUPNAME}" != "${VOL_FILEG_GROUPNAME}" && "${SELECT_PLAINPASSWORD}" != "${VOL_FILEG_PLAINPASSWORD}" || "${SELECT_GID}" != "${VOL_FILEG_GID}" || "${SELECT_MEMBERS}" != "${VOL_FILEG_MEMBERS}" ]]; then
sed /^${SELECT_GROUPNAME}:/d -i "${FILE_GROUP}"
printf "%s:%s:%d:%s\n" "${SELECT_GROUPNAME}" "${SELECT_PLAINPASSWORD}" "${SELECT_GID}" "${SELECT_MEMBERS}" >> "${FILE_GROUP}"
#printf "%s:%s:%d:%s\n" "${SELECT_GROUPNAME}" "${SELECT_PLAINPASSWORD}" "${SELECT_GID}" "${SELECT_MEMBERS}"
fi
if [[ "${SELECT_PASSWORD}" != "${VOL_FILEGS_PASSWORD}" || "${SELECT_ADMINISTRATORS}" != "${VOL_FILEGS_ADMINISTRATORS}" || "${SELECT_MEMBERS}" != "${VOL_FILEGS_MEMBERS}" ]]; then
sed /^${SELECT_GROUPNAME}:/d -i "${FILE_GSHADOW}"
printf "%s:%s:%s:%s\n" "${SELECT_GROUPNAME}" "${SELECT_PASSWORD}" "${SELECT_ADMINISTRATORS}" "${SELECT_MEMBERS}" >> "${FILE_GSHADOW}"
#printf "%s:%s:%s:%s\n" "${SELECT_GROUPNAME}" "${SELECT_PASSWORD}" "${SELECT_ADMINISTRATORS}" "${SELECT_MEMBERS}"
fi
[[ -n ${VERBOSE} ]] && printf "%s:%d:%s:%s:%s\n" "${SELECT_GROUPNAME}" "${SELECT_GID}" "${SELECT_MEMBERS}" "${SELECT_PASSWORD}" "${SELECT_ADMINISTRATORS}"
}
# Удалить группу из /etc/group /etc/gshadow
# group_del $1
# $1 # Имя группы
# $2 # GID идентификатор группы
# Что-бы удалить группу можно указать $1 или $2 или о б а одновременно $1:$2
# Пример: group_del user-1
# group_del :1001
# group_del user-2:1002
group_del(){
local FILE_GROUP="${ROOTFS}/etc/group"
local FILE_GSHADOW="${ROOTFS}/etc/gshadow"
local DATA_FILE_GROUP=$(cat ${FILE_GROUP})
local FILE_PASSWD="${ROOTFS}/etc/passwd"
local DATA_FILE_PASSWD=$(cat ${FILE_PASSWD})
local PARAM="$@"
local SELECT_GROUPNAME= SELECT_GID= NULL=
IFS=: read -r SELECT_GROUPNAME SELECT_GID NULL <<< "${PARAM}"
local VOL_FILEG_PLAINPASSWORD= VOL_FILEG_GID= VOL_FILEG_MEMBERS=
[[ -n ${SELECT_GROUPNAME} && ${DATA_FILE_GROUP} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEG_PLAINPASSWORD=${BASH_REMATCH[2]} \
&& VOL_FILEG_GID=${BASH_REMATCH[3]} \
&& VOL_FILEG_MEMBERS=${BASH_REMATCH[4]}
[[ -n ${SELECT_GID} && ${DATA_FILE_GROUP} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_GID}":([^$'\n']*)($'\n'|$)+ ]] \
&& SELECT_GROUPNAME=${BASH_REMATCH[2]} \
&& VOL_FILEG_PLAINPASSWORD=${BASH_REMATCH[3]} \
&& VOL_FILEG_GID=${SELECT_GID} \
&& VOL_FILEG_MEMBERS=${BASH_REMATCH[4]}
local VOL_FILEP_PLAINPASSWORD VOL_FILEP_UID VOL_FILEP_GID VOL_FILEP_GECOS VOL_FILEP_HOME VOL_FILEP_SHELL
[[ ${DATA_FILE_PASSWD} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):([^$'\n']*):"${VOL_FILEG_GID}":([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEP_USERNAME=${BASH_REMATCH[2]} \
&& VOL_FILEP_PLAINPASSWORD=${BASH_REMATCH[3]} \
&& VOL_FILEP_UID=${BASH_REMATCH[4]} \
&& VOL_FILEP_GECOS=${BASH_REMATCH[5]} \
&& VOL_FILEP_HOME=${BASH_REMATCH[6]} \
&& VOL_FILEP_SHELL=${BASH_REMATCH[7]}
if [[ -n ${VOL_FILEP_USERNAME} ]]; then
>&2 echo "ERROR: cannot remove the primary group of user '${VOL_FILEP_USERNAME}'"
else
sed "/^${SELECT_GROUPNAME}:/d" -i "${FILE_GROUP}"
sed "/^${SELECT_GROUPNAME}:/d" -i "${FILE_GSHADOW}"
fi
}
# Добавить пользователей в группы /etc/group /etc/gshadow
# user_add_group $1,$1,... $2,$2,$2,...
# $1 # Имя пользователя и/или UID. Разделённых ','
# # <username_1>:<uid_1>,<username_1>:<uid_1>,...
# $2 # Имена групп разделённых ','
# Пример: user_add_group user-1 wheel,lp,disk
# Пример: user_add_group user-1,user-2 wheel,lp,disk
# Пример: user_add_group :1001 wheel,lp,disk
# Пример: user_add_group user-1:1001 wheel,lp,disk
user_add_group(){
local FILE_PASSWD="${ROOTFS}/etc/passwd"
local DATA_FILE_PASSWD=$(cat ${FILE_PASSWD})
local FILE_GROUP="${ROOTFS}/etc/group"
local FILE_GSHADOW="${ROOTFS}/etc/gshadow"
local DATA_FILE_GROUP=$(cat ${FILE_GROUP})
local DATA_FILE_GSHADOW=$(cat ${FILE_GSHADOW})
local SELECT_USERNAME_UID_LIST=$1
local SELECT_GROUPS=$2
while IFS= read -r SELECT_USERNAME_UID; do
[[ ${SELECT_USERNAME_UID_LIST} == "" ]] && continue
local SELECT_USERNAME= SELECT_UID= NULL=
IFS=: read -ru3 SELECT_USERNAME SELECT_UID NULL 3<<< "${SELECT_USERNAME_UID}"
local SELECT_GID= SELECT_GROUPNAME= VOL_FILEP_GID=
# Ищем пользователя вначале по имени, после по UID
[[ -n ${SELECT_USERNAME} && ${DATA_FILE_PASSWD} =~ ($'\n'|^)+"${SELECT_USERNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& VOL_FILEP_GID=${BASH_REMATCH[4]}
[[ -n ${SELECT_UID} && ${DATA_FILE_PASSWD} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_UID}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& SELECT_USERNAME=${BASH_REMATCH[2]} \
&& VOL_FILEP_GID=${BASH_REMATCH[4]}
[[ ${DATA_FILE_PASSWD} =~ ($'\n'|^)+"${SELECT_USERNAME}": ]] || { >&2 echo "ERROR: user '${SELECT_USERNAME}' not found"; return 1; }
[[ -n ${SELECT_GROUPS} ]] || { >&2 echo "ERROR: groups should not be empty"; return 1; }
SELECT_GID=${VOL_FILEP_GID}
[[ -n ${SELECT_GID} && ${DATA_FILE_GROUP} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_GID}":([^$'\n']*)($'\n'|$)+ ]] \
&& SELECT_GROUPNAME=${BASH_REMATCH[2]}
# Проверяем, если группа является основной у пользователя, то исключить из списка групп
SELECT_GROUPS=$(sed "s/^${SELECT_GROUPNAME}$//g;s/^${SELECT_GROUPNAME},//g;s/,${SELECT_GROUPNAME}$//g;s/,${SELECT_GROUPNAME},/,/g" <<< "${SELECT_GROUPS}")
while IFS= read -ru4 SELECT_GROUPNAME; do
[[ ${SELECT_GROUPNAME} == "" ]] && continue
if [[ ! ${DATA_FILE_GROUP} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*)(:|:[-a-z0-9_,]+,)"${SELECT_USERNAME}"(,|$'\n'|$)+ ]]; then
DATA_FILE_GROUP=$(sed "/^${SELECT_GROUPNAME}:.*[^:]$/ s/$/,${SELECT_USERNAME}/" <<< ${DATA_FILE_GROUP})
DATA_FILE_GROUP=$(sed "/^${SELECT_GROUPNAME}:.*:$/ s/$/${SELECT_USERNAME}/" <<< ${DATA_FILE_GROUP})
fi
if [[ ! ${DATA_FILE_GSHADOW} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*)(:|:[-a-z0-9_,]+,)"${SELECT_USERNAME}"(,|$'\n'|$)+ ]]; then
DATA_FILE_GSHADOW=$(sed "/^${SELECT_GROUPNAME}:.*[^:]$/ s/$/,${SELECT_USERNAME}/" <<< ${DATA_FILE_GSHADOW})
DATA_FILE_GSHADOW=$(sed "/^${SELECT_GROUPNAME}:.*:$/ s/$/${SELECT_USERNAME}/" <<< ${DATA_FILE_GSHADOW})
fi
done 4<<< ${SELECT_GROUPS//,/$'\n'}
done <<< ${SELECT_USERNAME_UID_LIST//,/$'\n'}
echo "${DATA_FILE_GROUP}" > "${FILE_GROUP}"
echo "${DATA_FILE_GSHADOW}" > "${FILE_GSHADOW}"
}
# Удалить пользователя из групп /etc/group /etc/gshadow
# user_remove_group $1,$1,$1 $2,$2,$2,...
# $1 # Список имён пользователей и/или UID. Разделитель ','
# # <username1>:<uid1>,<username2>:<uid2>,...
# $2 # Имена групп разделённых ','
# # Если указано '%all' то все группы
# Пример: user_remove_group user-1 wheel,lp,disk
# Пример: user_remove_group user-1,user-2 wheel,lp,disk
# Пример: user_remove_group :1001 wheel,lp,disk
# Пример: user_remove_group user-1:1001 %all
user_remove_group(){
local FILE_PASSWD="${ROOTFS}/etc/passwd"
local DATA_FILE_PASSWD=$(cat ${FILE_PASSWD})
local FILE_GROUP="${ROOTFS}/etc/group"
local FILE_GSHADOW="${ROOTFS}/etc/gshadow"
local DATA_FILE_GROUP=$(cat ${FILE_GROUP})
local DATA_FILE_GSHADOW=$(cat ${FILE_GSHADOW})
local SELECT_USERNAME_UID_LIST=$1
local SELECT_GROUPS=$2
local SELECT_USERNAME_UID=
while IFS= read -r SELECT_USERNAME_UID; do
[[ ${SELECT_USERNAME_UID} == "" ]] && continue
local SELECT_USERNAME= SELECT_UID= NULL=
IFS=: read -ru3 SELECT_USERNAME SELECT_UID NULL 3<<< "${SELECT_USERNAME_UID}"
if [[ ${SELECT_GROUPS} == '%all' ]]; then
DATA_FILE_GROUP=$(sed "s/:${SELECT_USERNAME}$/:/g;s/:${SELECT_USERNAME},/:/g;s/,${SELECT_USERNAME}$//g;s/,${SELECT_USERNAME},/,/g" <<< ${DATA_FILE_GROUP})
DATA_FILE_GSHADOW=$(sed "s/:${SELECT_USERNAME}$/:/g;s/:${SELECT_USERNAME},/:/g;s/,${SELECT_USERNAME}$//g;s/,${SELECT_USERNAME},/,/g" <<< ${DATA_FILE_GSHADOW})
else
# Ищем пользователя вначале по имени, после по UID
#[[ -n ${SELECT_USERNAME} && ${DATA_FILE_PASSWD} =~ ($'\n'|^)+"${SELECT_USERNAME}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]]
[[ -n ${SELECT_UID} && ${DATA_FILE_PASSWD} =~ ($'\n'|^)+([^$'\n']*):([^$'\n']*):"${SELECT_UID}":([^$'\n']*):([^$'\n']*):([^$'\n']*):([^$'\n']*)($'\n'|$)+ ]] \
&& SELECT_USERNAME=${BASH_REMATCH[2]}
# Если пользователя нет среди пользователей. Отключил, чтобы всех без проверки удалять.
#[[ ${DATA_FILE_PASSWD} =~ ($'\n'|^)+"${SELECT_USERNAME}": ]] || { >&2 echo "ERROR: user '${SELECT_USERNAME}' not found"; continue; }
[[ -n ${SELECT_GROUPS} ]] || { >&2 echo "ERROR: groups should not be empty"; return 1; }
#[[ ${SELECT_GROUPS} == '%all' ]] && SELECT_GROUPS=$(sed -En 's/^([^:]+):.*/\1/p' <<< ${DATA_FILE_GROUP}) #'
locale SELECT_GROUPNAME=
while IFS= read -ru4 SELECT_GROUPNAME; do
[[ ${SELECT_GROUPNAME} == "" ]] && continue
if [[ ${DATA_FILE_GROUP} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*)(:|:[-a-z0-9_,]+,)"${SELECT_USERNAME}"(,|$'\n'|$)+ ]]; then
DATA_FILE_GROUP=$(sed "/^${SELECT_GROUPNAME}:/ s/:${SELECT_USERNAME}$/:/g;\
/^${SELECT_GROUPNAME}:/ s/:${SELECT_USERNAME},/:/g;\
/^${SELECT_GROUPNAME}:/ s/,${SELECT_USERNAME}$//g;\
/^${SELECT_GROUPNAME}:/ s/,${SELECT_USERNAME},/,/g" <<< ${DATA_FILE_GROUP})
fi
if [[ ${DATA_FILE_GSHADOW} =~ ($'\n'|^)+"${SELECT_GROUPNAME}":([^$'\n']*):([^$'\n']*)(:|:[-a-z0-9_,]+,)"${SELECT_USERNAME}"(,|$'\n'|$)+ ]]; then
DATA_FILE_GSHADOW=$(sed "/^${SELECT_GROUPNAME}:/ s/:${SELECT_USERNAME}$/:/g;\
/^${SELECT_GROUPNAME}:/ s/:${SELECT_USERNAME},/:/g;\
/^${SELECT_GROUPNAME}:/ s/,${SELECT_USERNAME}$//g;\
/^${SELECT_GROUPNAME}:/ s/,${SELECT_USERNAME},/,/g" <<< ${DATA_FILE_GSHADOW})
fi
done 4<<< "${SELECT_GROUPS//,/$'\n'}"
fi
done <<< "${SELECT_USERNAME_UID_LIST//,/$'\n'}"
echo "${DATA_FILE_GROUP}" > "${FILE_GROUP}"
echo "${DATA_FILE_GSHADOW}" > "${FILE_GSHADOW}"
}
#####################################################################################
###
### Функции получения от системы текущих настроек вида параметров от конфигурации ###