This repository has been archived by the owner on Aug 13, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsysusers
executable file
·166 lines (149 loc) · 4.55 KB
/
sysusers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/bin/sh
# Copyright (c) 2018 Chris Cromer
# Released under the 2-clause BSD license.
#
# This is an implementation of the systemd-sysusers command
sysusersver=0.6
warninvalid() {
printf "sysusers: %s on line %d of '%s'\n" "${1:-ignoring invalid entry}" \
"${lineno}" "${file}"
: "$((error += 1))"
} >&2
add_group() {
# add_group <name> <id>
if [ "$2" = '-' ]; then
grep -q "^$1:" /etc/group || groupadd -r "$1"
elif ! grep -q "^$1:\|^[^:]*:[^:]*:$2:[^:]*$" /etc/group; then
groupadd -g "$2" "$1"
fi
}
add_user() {
# add_user <name> <id> <gecos> <home>
if ! id "$1" >/dev/null 2>&1; then
if [ "$2" = '-' ]; then
useradd -rc "$3" -g "$1" -d "$4" -s '/sbin/nologin' "$1"
else
useradd -rc "$3" -u "$2" -g "$1" -d "$4" -s '/sbin/nologin' "$1"
fi
passwd -l "$1" >/dev/null 2>&1
fi
}
update_login_defs() {
# update_login_defs <name> <id>
[ "$1" != '-' ] && warninvalid && return
min="${2%%-*}" max="${2#*-}"
[ "${max}" != "${max#*-}" ] && warninvalid && return
[ "${min}" -ge "${max}" ] && warninvalid "invalid range" && return
while read -r key val; do
case "${key}" in
SYS_UID_MAX) suid_max="${val}" ;;
SYS_GID_MAX) sgid_max="${val}" ;;
esac
done < "${root}/etc/login.defs"
[ "${min}" -lt "${suid_max}" ] && warninvalid "invalid range" && return
[ "${min}" -lt "${sgid_max}" ] && warninvalid "invalid range" && return
sed -e "/[GU]ID_MIN[[:space:]]\+/s/[^[:space:]]*$/${min}/" \
-e "/[GU]ID_MAX[[:space:]]\+/s/[^[:space:]]*$/${max}/" \
-i "${root}/etc/login.defs"
}
parse_file() {
while read -r conf; do
lineno=0
while read -r line; do
parse_string "${line}" "$((lineno += 1))"
done < "${conf}"
[ -n "${line}" ] && parse_string "${line}"
done
}
parse_string() {
[ -n "${1%%#*}" ] || return
eval "set -- $1"
type="$1" name="$2" id="$3" gecos="$4" home="$5"
case "${type}" in
[gu])
case "${id}" in 65535|4294967295) warninvalid; return; esac
[ "${home:--}" = '-' ] && home='/'
add_group "${name}" "${id}"
if [ "${type}" = u ]; then
add_user "${name}" "${id}" "${gecos}" "${home}"
fi
;;
m)
add_group "${name}" '-'
if id "${name}" >/dev/null 2>&1; then
usermod -a -G "${id}" "${name}"
else
useradd -r -g "${id}" -s '/sbin/nologin' "${name}"
passwd -l "${name}" >/dev/null 2>&1
fi
;;
r)
update_login_defs "${name}" "${id}"
;;
*) warninvalid; return ;;
esac
}
usage() {
printf '%s\n' \
"${0##*/}" '' \
"${0##*/} creates system users and groups, based on the file" \
'format and location specified in sysusers.d(5).' '' \
"Usage: ${0##*/} [OPTIONS...] [CONFIGFILE...]" '' \
'Options:' \
' --root=root All paths will be prefixed with the' \
' given alternate root path, including' \
' config search paths.' \
" --replace=PATH Don't run check in the package" \
' --inline Treat each positional argument as a' \
' separate configuration line instead of a' \
' file name.' \
' -h, --help Print a short help text and exit.' \
' --version Print a short version string and exit.'
exit "$1"
}
error=0 inline=0 replace='' root='' seen=''
# opensysusers is an implementation of sysusers.d spec without
# systemd command, it doesn't accept options or arguments
[ "${0##*/}" = opensysusers ] && set --
while [ "$#" -ne 0 ]; do
case "$1" in
--root=*) root="${1#--root=}" ;;
--root) root="$2"; shift ;;
--replace=*) replace="${1#--replace=}" ;;
--replace) replace="$2"; shift ;;
--inline) inline=1 ;;
--version) printf '%s\n' "${sysusersver}"; exit 0 ;;
-h|--help) usage 0 ;;
-[!-]|--?*) usage 1 ;;
--) shift; break ;;
*) break ;;
esac
shift
done
if [ "${inline}" -eq 0 ]; then
for file do
[ "${file}" = '--' ] && continue
for dir in etc run usr/lib; do
if [ -f "${root}/${dir}/sysusers.d/${file}" ]; then
sed -i -e '$a\' "${root}/${dir}/sysusers.d/${file}"
printf '%s/%s/sysusers.d/%s\n' "${root}" "${dir}" "${file}" |
parse_file
break
fi
done
done
else
for string in "$@"; do
parse_string "${string}"
done
fi
if [ "$#" -eq 0 ] || [ -n "${replace}" ]; then
set -- "${root}/etc/sysusers.d/"*.conf "${root}/run/sysusers.d/"*.conf \
"${root}/usr/lib/sysusers.d/"*.conf
for f do printf '%s %s\n' "${f##*/}" "${f%/*}"; done | sort -k1,1 |
while read -r b d; do
[ "${seen}" = "${seen#* ${b} }" ] && [ -f "${d}/${b}" ] &&
{ seen="${seen:- }${b} "; printf '%s/%s\n' "${d}" "${b}"; }
done | parse_file
fi
exit "${error}"