#!/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 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 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=${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}" } # Если параметр $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 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#*=} 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 } ##################################################################################### ### ### Функции управления пользователями и группами с помощью тектовых процессоров ### ### ##################################################################################### # Добавить пользователя в /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=$(< ${FILE_PASSWD}) local DATA_FILE_SHADOW=$(< ${FILE_SHADOW}) local DATA_FILE_LOGINDEFS=$(< ${FILE_LOGINDEFS}) local DATA_FILE_DEFAULT_USERADD=$(< ${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}" #sed -e "/^${SELECT_USERNAME}:/d" -e "\$a${SELECT_USERNAME}:${SELECT_PLAINPASSWORD}:${SELECT_UID}:${SELECT_GID}:${SELECT_GECOS}:${SELECT_HOME}:${SELECT_SHELL}" -i "${FILE_PASSWD}" #sed -e "\$a${SELECT_USERNAME}:${SELECT_PLAINPASSWORD}:${SELECT_UID}:${SELECT_GID}:${SELECT_GECOS}:${SELECT_HOME}:${SELECT_SHELL}" -i "${FILE_PASSWD}" while [[ ${DATA_FILE_PASSWD} =~ ^(.*)(^|$'\n')"${SELECT_USERNAME}:"([^$'\n'])+($'\n'|$)(.*)$ ]]; do DATA_FILE_PASSWD="${BASH_REMATCH[1]}${BASH_REMATCH[5]}"; done [[ ${DATA_FILE_PASSWD} =~ ^(.*)($'\n')+$ ]] && DATA_FILE_PASSWD="${BASH_REMATCH[1]}" printf "%s\n%s:%s:%d:%d:%s:%s:%s\n" "${DATA_FILE_PASSWD}" "${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}" #sed -e "/^${SELECT_USERNAME}:/d" -e "\$a${SELECT_USERNAME}:${SELECT_PASSWORD}:${SELECT_LASTCHANGED}:${SELECT_MINDAY}:${SELECT_MAXDAY}:${SELECT_WARN}:${SELECT_INACTIVE}:${SELECT_EXPIRE}:${SELECT_NOUSE}" -i "${FILE_SHADOW}" #sed -e "\$a${SELECT_USERNAME}:${SELECT_PASSWORD}:${SELECT_LASTCHANGED}:${SELECT_MINDAY}:${SELECT_MAXDAY}:${SELECT_WARN}:${SELECT_INACTIVE}:${SELECT_EXPIRE}:${SELECT_NOUSE}" -i "${FILE_SHADOW}" while [[ ${DATA_FILE_SHADOW} =~ ^(.*)(^|$'\n')"${SELECT_USERNAME}:"([^$'\n'])+($'\n'|$)(.*)$ ]]; do DATA_FILE_SHADOW="${BASH_REMATCH[1]}${BASH_REMATCH[5]}"; done [[ ${DATA_FILE_SHADOW} =~ ^(.*)($'\n')+$ ]] && DATA_FILE_SHADOW="${BASH_REMATCH[1]}" printf "%s\n%s:%s:%d:%s:%s:%s:%s:%s:%s\n" "${DATA_FILE_SHADOW}" "${SELECT_USERNAME}" "${SELECT_PASSWORD}" "${SELECT_LASTCHANGED}" "${SELECT_MINDAY}" "${SELECT_MAXDAY}" "${SELECT_WARN}" "${SELECT_INACTIVE}" "${SELECT_EXPIRE}" "${SELECT_NOUSE}" > "${FILE_SHADOW}" fi [[ -z ${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=$(< ${FILE_PASSWD}) local FILE_GROUP="${ROOTFS}/etc/group" local FILE_GSHADOW="${ROOTFS}/etc/gshadow" local DATA_FILE_GROUP=$(< ${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=$(< ${FILE_GROUP}) local DATA_FILE_GSHADOW=$(< ${FILE_GSHADOW}) local DATA_FILE_LOGINDEFS=$(< ${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}" #sed -e "/^${SELECT_GROUPNAME}:/d" -e "\$a${SELECT_GROUPNAME}:${SELECT_PLAINPASSWORD}:${SELECT_GID}:${SELECT_MEMBERS}" -i "${FILE_GROUP}" while [[ ${DATA_FILE_GROUP} =~ ^(.*)(^|$'\n')"${SELECT_GROUPNAME}:"([^$'\n'])+($'\n'|$)(.*)$ ]]; do DATA_FILE_GROUP="${BASH_REMATCH[1]}${BASH_REMATCH[5]}"; done [[ ${DATA_FILE_GROUP} =~ ^(.*)($'\n')+$ ]] && DATA_FILE_GROUP="${BASH_REMATCH[1]}" printf "%s\n%s:%s:%d:%s\n" "${DATA_FILE_GROUP}" "${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}" #sed -e "/^${SELECT_GROUPNAME}:/d" -e "\$a${SELECT_GROUPNAME}:${SELECT_PASSWORD}:${SELECT_ADMINISTRATORS}:${SELECT_MEMBERS}" -i "${FILE_GSHADOW}" while [[ ${DATA_FILE_GSHADOW} =~ ^(.*)(^|$'\n')"${SELECT_GROUPNAME}:"([^$'\n'])+($'\n'|$)(.*)$ ]]; do DATA_FILE_GSHADOW="${BASH_REMATCH[1]}${BASH_REMATCH[5]}"; done [[ ${DATA_FILE_GSHADOW} =~ ^(.*)($'\n')+$ ]] && DATA_FILE_GSHADOW="${BASH_REMATCH[1]}" printf "%s\n%s:%s:%d:%s\n" "${DATA_FILE_GSHADOW}" "${SELECT_GROUPNAME}" "${SELECT_PLAINPASSWORD}" "${SELECT_GID}" "${SELECT_MEMBERS}" > "${FILE_GSHADOW}" #printf "%s:%s:%s:%s\n" "${SELECT_GROUPNAME}" "${SELECT_PASSWORD}" "${SELECT_ADMINISTRATORS}" "${SELECT_MEMBERS}" fi [[ -z ${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=$(< ${FILE_GROUP}) local FILE_PASSWD="${ROOTFS}/etc/passwd" local DATA_FILE_PASSWD=$(< ${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. Разделённых ',' # # :,:,... # $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=$(< ${FILE_PASSWD}) local FILE_GROUP="${ROOTFS}/etc/group" local FILE_GSHADOW="${ROOTFS}/etc/gshadow" local DATA_FILE_GROUP=$(< ${FILE_GROUP}) local DATA_FILE_GSHADOW=$(< ${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. Разделитель ',' # # :,:,... # $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=$(< ${FILE_PASSWD}) local FILE_GROUP="${ROOTFS}/etc/group" local FILE_GSHADOW="${ROOTFS}/etc/gshadow" local DATA_FILE_GROUP=$(< ${FILE_GROUP}) local DATA_FILE_GSHADOW=$(< ${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}" } ##################################################################################### ### ### Функции получения от системы текущих настроек вида параметров от конфигурации ### ### ##################################################################################### # Получить запись вида конфигурации 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 # - # Все пользователи диапазона # # Имя пользователя 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 DATA_FILE_PASSWD=$(< ${FILE_PASSWD}) local DATA_FILE_SHADOW=$(< ${FILE_SHADOW}) local DEFAULT_HOME="/home" local DEFAULT_SHELL="/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}" #SELECT_EXTRAGROUPS=$(printf "%s\n" $(${CHROOT} id -nrG ${SELECT_USER}) | sort -u | xargs | tr " " ",") #SELECT_EXTRAGROUPS=${SELECT_EXTRAGROUPS//,nobody/}; SELECT_EXTRAGROUPS=${SELECT_EXTRAGROUPS//nobody/} # У id убираем первую группу, это основная группа SELECT_EXTRAGROUPS=$(comm --nocheck-order -13 <(printf "%s\n" ${USERGROUPS//,/ } ${DEFAULTGROUP//,/ } | sort -u) <(printf "%s\n" $(${CHROOT} id -nrG ${SELECT_USER} | sed -E 's/([^ ]*) (.*)/\2/') | sort -u) | xargs | tr " " ",") #' [[ -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}" if [[ -z ${NOT_ONLY_CHANGES} && ${SELECT_PASSWORD} == @("!*"|"!") ]]; then # Загрузить файлы которые совпадают в каталогах /usr/lib/sysusers.d/ и /usr/share/ublinux-sysusers/. И загрузить которые уникальные в /usr/lib/sysusers.d/ 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|') \ $(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|') \ ) 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}) #" #[[ -n ${DATA_SYSUSERS_EXTRAGROUPS} ]] && DATA_SYSUSERS_EXTRAGROUPS="${SELECT_USER},${DATA_SYSUSERS_EXTRAGROUPS//$'\n'/,}" || DATA_SYSUSERS_EXTRAGROUPS="${SELECT_USER}" [[ -n ${DATA_SYSUSERS_EXTRAGROUPS} ]] && DATA_SYSUSERS_EXTRAGROUPS=$(printf "%s\n" ${SELECT_USER} ${DATA_SYSUSERS_EXTRAGROUPS} | sort -u | xargs | tr " " ",") \ || DATA_SYSUSERS_EXTRAGROUPS="${FIND_GROUP}" # [[ ${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" 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'}" } # Получить запись вида конфигурации 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 # - # Все пользователи диапазона # # Имя пользователя get_conf_usershadow_from_system(){ local FILE_PASSWD="${ROOTFS}/etc/passwd" local FILE_SHADOW="${ROOTFS}/etc/shadow" local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs" 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') #" # Дата когда был установлен пакет и впервые добавлены пользователи local DATE_SYSUSERS=$(stat --printf=%y ${ROOTFS}/usr/share/ublinux-sysusers/README | cut -d' ' -f1) [[ ${SELECT_LASTCHANGED} == ${DATE_STARTUP_SYSTEM} ]] && return 0 # Сравнить дату впервые созданных пользователей с датой установки пакета 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'}" } # Получить запись вида конфигурации 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 # - # Все пользователи диапазона # # Имя группы get_conf_groupadd_from_system(){ local FILE_GROUP="${ROOTFS}/etc/group" local FILE_GSHADOW="${ROOTFS}/etc/gshadow" local FILE_LOGINDEFS="${ROOTFS}/etc/login.defs" local DATA_FILE_GROUP=$(< ${FILE_GROUP}) 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 # Загрузить файлы которые совпадают в каталогах /usr/lib/sysusers.d/ и /usr/share/ublinux-sysusers/. И загрузить которые уникальные в /usr/lib/sysusers.d/ 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|') \ $(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|') \ ) local DATA_SYSUSERS_MEMBERS=$(sed -Enr "s/^m (.*) ${SELECT_GROUP}/\1/p" <<< ${DATA_SYSUSERS}) #" [[ -n ${DATA_SYSUSERS_MEMBERS} ]] && DATA_SYSUSERS_MEMBERS=$(printf "%s\n" ${DATA_SYSUSERS_MEMBERS} | sort -u | xargs | tr " " ",") || unset DATA_SYSUSERS_MEMBERS [[ ${SELECT_MEMBERS} == ${DATA_SYSUSERS_MEMBERS} ]] && 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" while IFS= read -r SELECT_PARAM; do if [[ ${SELECT_PARAM} == "@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} == "@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" ]]; 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} =~ ^([[: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}:" ${FILE_GROUP} &>/dev/null; then show_group "${SELECT_PARAM}" fi done <<< "${PARAM_ALL// /$'\n'}" } ##################################################################################### ##################################################################################### 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 [[ -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 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(){ . /usr/lib/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=$(< /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" > ~/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 } ##################################### ### ::: 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 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_useradd_sync ;; USERADD_SYNC\[*\]) ${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_useradd_sync ;; GROUPADD_SYNC) ${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_groupadd_sync ;; GROUPADD_SYNC\[*\]) ${ROOTFS}/usr/lib/ublinux/rc.halt.pre/25-accounts-sync exec_groupadd_sync ;; *) 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_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}/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 & ;; 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}" ;; *) 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}/server]"|"[server]") case "${NAME_VAR}" in STORAGE_CONTAINERS_PATH) ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/80-server-containers-storage ;; STORAGE_LIBVIRT_PATH) ${ROOTFS}/usr/lib/ublinux/rc.preinit.d/81-server-libvirt-storage ;; 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 ;; 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 ;; *) 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}" ;; 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 ;; 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 ;; *) 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 ;; \[*\]) 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 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