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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
|
# $NetBSD: usergroup,v 1.14 2006/03/19 23:58:14 jlam Exp $
#
# Generate a +USERGROUP script that reference-counts users and groups
# that are required for the proper functioning of the package.
#
case "${STAGE},$1" in
UNPACK,|UNPACK,+USERGROUP)
${CAT} > ./+USERGROUP << 'EOF'
#!@SH@
#
# +USERGROUP - users and groups management script
#
# Usage: ./+USERGROUP ADD|REMOVE [metadatadir]
# ./+USERGROUP CHECK-ADD|CHECK-REMOVE [metadatadir]
#
# This script supports two actions, ADD and REMOVE, that will add or
# remove the users and groups needed by the package associated with
# <metadatadir>. The CHECK-ADD action will check whether any users or
# groups needed by the package are missing, and print an informative
# message noting those users and groups. The CHECK-REMOVE action will
# check whether any users and groups needed by the package still exist,
# and print an informative message noting those users and groups. The
# CHECK-ADD and CHECK-REMOVE actions return non-zero if they detect
# either missing or existing users/groups, respectively.
#
# Lines starting with "# USER: " or "# GROUP: " are data read by this
# script that name the users and groups that this package requires to
# exist to function correctly, e.g.
#
# # USER: foo:foogrp::The Foomister
# # GROUP: foogrp
#
# The USER lines are of the form:
#
# user:group[:[userid][:[descr][:[home][:shell]]]]
#
# Only the user and group are required; everything else is optional,
# but the colons must be in the right places when specifying optional
# bits.
#
# The GROUP lines are of the form:
#
# group[:groupid]
#
# Only the group is required; the groupid is optional.
#
CAT="@CAT@"
CHGRP="@CHGRP@"
ECHO="@ECHO@"
GREP="@GREP@"
ID="@ID@"
MKDIR="@MKDIR@"
PWD_CMD="@PWD_CMD@"
RM="@RM@"
RMDIR="@RMDIR@"
SED="@SED@"
SORT="@SORT@"
TEST="@TEST@"
TRUE="@TRUE@"
SELF=$0
ACTION=$1
PKG_METADATA_DIR="${2-`${PWD_CMD}`}"
: ${PKGNAME=${PKG_METADATA_DIR##*/}}
: ${PKG_DBDIR=${PKG_METADATA_DIR%/*}}
: ${PKG_REFCOUNT_DBDIR=${PKG_DBDIR}.refcount}
PKG_REFCOUNT_USERS_DBDIR="${PKG_REFCOUNT_DBDIR}/users"
PKG_REFCOUNT_GROUPS_DBDIR="${PKG_REFCOUNT_DBDIR}/groups"
case "${PKG_CREATE_USERGROUP:-@PKG_CREATE_USERGROUP@}" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
_PKG_CREATE_USERGROUP=yes
;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
_PKG_CREATE_USERGROUP=no
;;
esac
group_exists()
{
_group="$1"
case $_group in
"") return 2 ;;
esac
# Check using chgrp to work properly in an NIS environment.
testfile="./grouptest.tmp.$$"
${ECHO} > $testfile
if ${CHGRP} $_group $testfile >/dev/null 2>&1; then
${RM} -f $testfile
return 0
fi
${RM} -f $testfile
return 1
}
user_exists()
{
_user="$1"
case $_user in
"") return 2 ;;
esac
# Check using id to work properly in an NIS environment.
if ${ID} $_user >/dev/null 2>&1; then
return 0
fi
return 1
}
listwrap()
{
_length=$1
_buffer=
while read _line; do
set -- $_line
for _word; do
case $_buffer in
"") _buffer="$_word" ;;
*) _buffer="$_buffer $_word" ;;
esac
if ${TEST} ${#_buffer} -gt $_length; then
${ECHO} " $_buffer"
_buffer=
fi
done
done
case $_buffer in
"") ;;
*) ${ECHO} " $_buffer" ;;
esac
}
# DO NOT CHANGE THE FOLLOWING LINE!
# platform-specific adduser/addgroup functions
exitcode=0
case $ACTION in
ADD)
${SED} -n "/^\# GROUP: /{s/^\# GROUP: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
group="$1"; groupid="$2"
IFS="$SAVEIFS"
case $group in
"") continue ;;
esac
shadow_dir="${PKG_REFCOUNT_GROUPS_DBDIR}/$group"
preexist="$shadow_dir/+PREEXISTING"
token="$shadow_dir/${PKGNAME}"
if ${TEST} ! -d "$shadow_dir"; then
${MKDIR} $shadow_dir
group_exists $group &&
${ECHO} "${PKGNAME}" > $preexist
fi
if ${TEST} -f "$token" && \
${GREP} "^${PKG_METADATA_DIR}$" $token >/dev/null; then
:
else
${ECHO} "${PKG_METADATA_DIR}" >> $token
fi
case ${_PKG_CREATE_USERGROUP} in
yes)
if group_exists $group; then
:
else
addgroup "$group" "$groupid"
fi
;;
esac
done; }
${SED} -n "/^\# USER: /{s/^\# USER: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
user="$1"; group="$2"; userid="$3"
descr="$4"; home="$5" shell="$6"
IFS="$SAVEIFS"
case $user in
"") continue ;;
esac
case $group in
"") continue ;;
esac
shadow_dir="${PKG_REFCOUNT_USERS_DBDIR}/$user"
preexist="$shadow_dir/+PREEXISTING"
token="$shadow_dir/${PKGNAME}"
if ${TEST} ! -d "$shadow_dir"; then
${MKDIR} $shadow_dir
user_exists $user &&
${ECHO} "${PKGNAME}" > $preexist
fi
if ${TEST} -f "$token" && \
${GREP} "^${PKG_METADATA_DIR}$" $token >/dev/null; then
:
else
${ECHO} "${PKG_METADATA_DIR}" >> $token
fi
case ${_PKG_CREATE_USERGROUP} in
yes)
if user_exists $user && group_exists $group; then
:
else
adduser "$user" "$group" "$userid" \
"$descr" "$home" "$shell"
fi
;;
esac
done; }
;;
REMOVE)
${SED} -n "/^\# USER: /{s/^\# USER: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
user="$1"; group="$2"; userid="$3"
descr="$4"; home="$5" shell="$6"
IFS="$SAVEIFS"
case $user in
"") continue ;;
esac
shadow_dir="${PKG_REFCOUNT_USERS_DBDIR}/$user"
preexist="$shadow_dir/+PREEXISTING"
token="$shadow_dir/${PKGNAME}"
tokentmp="$token.tmp.$$"
if ${TEST} -f "$token" && \
${GREP} "^${PKG_METADATA_DIR}$" $token >/dev/null; then
${CAT} "$token" | ${GREP} -v "^${PKG_METADATA_DIR}$" > $tokentmp
case `${CAT} $tokentmp | ${SED} -n "$="` in
"")
${RM} -f $preexist $token $token.tmp.*
${RMDIR} -p $shadow_dir 2>/dev/null || ${TRUE}
;;
*)
${MV} -f $tokentmp $token
;;
esac
fi
done; }
${SED} -n "/^\# GROUP: /{s/^\# GROUP: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
group="$1"; groupid="$2"
IFS="$SAVEIFS"
case $group in
"") continue ;;
esac
shadow_dir="${PKG_REFCOUNT_GROUPS_DBDIR}/$group"
preexist="$shadow_dir/+PREEXISTING"
token="$shadow_dir/${PKGNAME}"
tokentmp="$token.tmp.$$"
if ${TEST} -f "$token" && \
${GREP} "^${PKG_METADATA_DIR}$" $token >/dev/null; then
${CAT} "$token" | ${GREP} -v "^${PKG_METADATA_DIR}$" > $tokentmp
case `${CAT} $tokentmp | ${SED} -n "$="` in
"")
${RM} -f $preexist $token $token.tmp.*
${RMDIR} -p $shadow_dir 2>/dev/null || ${TRUE}
;;
*)
${MV} -f $tokentmp $token
;;
esac
fi
done; }
;;
CHECK-ADD)
${SED} -n "/^\# GROUP: /{s/^\# GROUP: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
group="$1"; groupid="$2"
IFS="$SAVEIFS"
case $group in
"") continue ;;
*) group_exists $group && continue ;;
esac
case "$printed_header" in
yes) ;;
*) printed_header=yes
${ECHO} "==========================================================================="
${ECHO} "The following groups need to be created for ${PKGNAME}:"
${ECHO} ""
;;
esac
case $groupid in
"") ${ECHO} " $group" ;;
*) ${ECHO} " $group ($groupid)" ;;
esac
done
case "$printed_header" in
yes) ${ECHO} ""
${ECHO} "==========================================================================="
exit 1
;;
esac; }
${TEST} $? -eq 0 || exitcode=1
${SED} -n "/^\# USER: /{s/^\# USER: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
user="$1"; group="$2"; userid="$3"
descr="$4"; home="$5" shell="$6"
IFS="$SAVEIFS"
case $user in
"") continue ;;
*) user_exists $user && continue ;;
esac
case "$printed_header" in
yes) ;;
*) printed_header=yes
${ECHO} "==========================================================================="
${ECHO} "The following users need to be created for ${PKGNAME}:"
${ECHO} ""
;;
esac
: ${home:="${PKG_USER_HOME}"}
: ${shell:="${PKG_USER_SHELL}"}
case $userid in
"") ${ECHO} " $user: $group, $home, $shell" ;;
*) ${ECHO} " $user ($userid): $group, $home, $shell" ;;
esac
done
case "$printed_header" in
yes) ${ECHO} ""
${ECHO} "==========================================================================="
exit 1
;;
esac; }
${TEST} $? -eq 0 || exitcode=1
;;
CHECK-REMOVE)
${SED} -n "/^\# USER: /{s/^\# USER: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
user="$1"; group="$2"; userid="$3"
descr="$4"; home="$5" shell="$6"
IFS="$SAVEIFS"
case $user in
"") continue ;;
*) user_exists $user || continue ;;
esac
shadow_dir="${PKG_REFCOUNT_USERS_DBDIR}/$user"
${TEST} ! -d "$shadow_dir" || continue # refcount isn't zero
existing_users="$existing_users $user"
done
case $existing_users in
"") ;;
*) ${ECHO} "==========================================================================="
${ECHO} "The following users are no longer being used by ${PKGNAME},"
${ECHO} "and they can be removed if no other software is using them:"
${ECHO} ""
${ECHO} "$existing_users" | listwrap 40
${ECHO} ""
${ECHO} "==========================================================================="
exit 1
;;
esac; }
${TEST} $? -eq 0 || exitcode=1
${SED} -n "/^\# GROUP: /{s/^\# GROUP: //;p;}" ${SELF} | ${SORT} -u |
{ while read line; do
SAVEIFS="$IFS"; IFS=":"
set -- $line
group="$1"; groupid="$2"
IFS="$SAVEIFS"
case $group in
"") continue ;;
*) group_exists $group || continue ;;
esac
shadow_dir="${PKG_REFCOUNT_GROUPS_DBDIR}/$group"
${TEST} ! -d "$shadow_dir" || continue # refcount isn't zero
existing_groups="$existing_groups $group"
done
case $existing_groups in
"") ;;
*) ${ECHO} "==========================================================================="
${ECHO} "The following groups are no longer being used by ${PKGNAME},"
${ECHO} "and they can be removed if no other software is using them:"
${ECHO} ""
${ECHO} "$existing_groups" | listwrap 40
${ECHO} ""
${ECHO} "==========================================================================="
exit 1
;;
esac; }
${TEST} $? -eq 0 || exitcode=1
;;
*)
${ECHO} "Usage: ./+USERGROUP ADD|REMOVE [metadatadir]"
${ECHO} " ./+USERGROUP CHECK-ADD|CHECK-REMOVE [metadatadir]"
;;
esac
exit $exitcode
EOF
${SED} -n "/^\# GROUP: /p" ${SELF} >> ./+USERGROUP
${SED} -n "/^\# USER: /p" ${SELF} >> ./+USERGROUP
${CHMOD} +x ./+USERGROUP
;;
esac
|