Gentoo Archives: gentoo-commits

From: Benda XU <heroxbd@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] dev/heroxbd:master commit in: eclass/
Date: Thu, 26 May 2016 04:04:13
Message-Id: 1464235400.57177c6d001b16b81ed164de16b328d3a67cac08.heroxbd@gentoo
1 commit: 57177c6d001b16b81ed164de16b328d3a67cac08
2 Author: Benda Xu <heroxbd <AT> gentoo <DOT> org>
3 AuthorDate: Thu May 26 04:03:20 2016 +0000
4 Commit: Benda XU <heroxbd <AT> gentoo <DOT> org>
5 CommitDate: Thu May 26 04:03:20 2016 +0000
6 URL: https://gitweb.gentoo.org/dev/heroxbd.git/commit/?id=57177c6d
7
8 user.eclass: not to fail under prefix.
9
10 eclass/user.eclass | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++++
11 1 file changed, 466 insertions(+)
12
13 diff --git a/eclass/user.eclass b/eclass/user.eclass
14 new file mode 100644
15 index 0000000..860aba0
16 --- /dev/null
17 +++ b/eclass/user.eclass
18 @@ -0,0 +1,466 @@
19 +# Copyright 1999-2014 Gentoo Foundation
20 +# Distributed under the terms of the GNU General Public License v2
21 +# $Id$
22 +
23 +# @ECLASS: user.eclass
24 +# @MAINTAINER:
25 +# base-system@g.o (Linux)
26 +# Joe Jezak <josejx@×××××.com> (OS X)
27 +# usata@g.o (OS X)
28 +# Aaron Walker <ka0ttic@g.o> (FreeBSD)
29 +# @BLURB: user management in ebuilds
30 +# @DESCRIPTION:
31 +# The user eclass contains a suite of functions that allow ebuilds
32 +# to quickly make sure users in the installed system are sane.
33 +
34 +if [[ -z ${_USER_ECLASS} ]]; then
35 +_USER_ECLASS=1
36 +
37 +# @FUNCTION: _assert_pkg_ebuild_phase
38 +# @INTERNAL
39 +# @USAGE: <calling func name>
40 +_assert_pkg_ebuild_phase() {
41 + case ${EBUILD_PHASE} in
42 + setup|preinst|postinst) ;;
43 + *)
44 + eerror "'$1()' called from '${EBUILD_PHASE}' phase which is not OK:"
45 + eerror "You may only call from pkg_{setup,preinst,postinst} functions."
46 + eerror "Package fails at QA and at life. Please file a bug."
47 + die "Bad package! $1 is only for use in some pkg_* functions!"
48 + esac
49 +}
50 +
51 +# @FUNCTION: egetent
52 +# @USAGE: <database> <key>
53 +# @DESCRIPTION:
54 +# Small wrapper for getent (Linux), nidump (< Mac OS X 10.5),
55 +# dscl (Mac OS X 10.5), and pw (FreeBSD) used in enewuser()/enewgroup().
56 +#
57 +# Supported databases: group passwd
58 +egetent() {
59 + local db=$1 key=$2
60 +
61 + [[ $# -ge 3 ]] && die "usage: egetent <database> <key>"
62 +
63 + case ${db} in
64 + passwd|group) ;;
65 + *) die "sorry, database '${db}' not yet supported; file a bug" ;;
66 + esac
67 +
68 + case ${CHOST} in
69 + *-darwin[678])
70 + case ${key} in
71 + *[!0-9]*) # Non numeric
72 + nidump ${db} . | awk -F: "(\$1 ~ /^${key}\$/) {print;exit;}"
73 + ;;
74 + *) # Numeric
75 + nidump ${db} . | awk -F: "(\$3 == ${key}) {print;exit;}"
76 + ;;
77 + esac
78 + ;;
79 + *-darwin*)
80 + local mykey
81 + case ${db} in
82 + passwd) db="Users" mykey="UniqueID" ;;
83 + group) db="Groups" mykey="PrimaryGroupID" ;;
84 + esac
85 +
86 + case ${key} in
87 + *[!0-9]*) # Non numeric
88 + dscl . -read /${db}/${key} 2>/dev/null |grep RecordName
89 + ;;
90 + *) # Numeric
91 + dscl . -search /${db} ${mykey} ${key} 2>/dev/null
92 + ;;
93 + esac
94 + ;;
95 + *-freebsd*|*-dragonfly*)
96 + case ${db} in
97 + passwd) db="user" ;;
98 + *) ;;
99 + esac
100 +
101 + # lookup by uid/gid
102 + local opts
103 + if [[ ${key} == [[:digit:]]* ]] ; then
104 + [[ ${db} == "user" ]] && opts="-u" || opts="-g"
105 + fi
106 +
107 + pw show ${db} ${opts} "${key}" -q
108 + ;;
109 + *-netbsd*|*-openbsd*)
110 + grep "${key}:\*:" /etc/${db}
111 + ;;
112 + *)
113 + # ignore output if nscd doesn't exist, or we're not running as root
114 + nscd -i "${db}" 2>/dev/null
115 + getent "${db}" "${key}"
116 + ;;
117 + esac
118 +}
119 +
120 +# @FUNCTION: enewuser
121 +# @USAGE: <user> [uid] [shell] [homedir] [groups]
122 +# @DESCRIPTION:
123 +# Same as enewgroup, you are not required to understand how to properly add
124 +# a user to the system. The only required parameter is the username.
125 +# Default uid is (pass -1 for this) next available, default shell is
126 +# /bin/false, default homedir is /dev/null, and there are no default groups.
127 +enewuser() {
128 + _assert_pkg_ebuild_phase ${FUNCNAME}
129 +
130 + # get the username
131 + local euser=$1; shift
132 + if [[ -z ${euser} ]] ; then
133 + eerror "No username specified !"
134 + die "Cannot call enewuser without a username"
135 + fi
136 +
137 + # lets see if the username already exists
138 + if [[ -n $(egetent passwd "${euser}") ]] ; then
139 + return 0
140 + fi
141 + einfo "Adding user '${euser}' to your system ..."
142 +
143 + # options to pass to useradd
144 + local opts=()
145 +
146 + # handle uid
147 + local euid=$1; shift
148 + if [[ -n ${euid} && ${euid} != -1 ]] ; then
149 + if [[ ${euid} -gt 0 ]] ; then
150 + if [[ -n $(egetent passwd ${euid}) ]] ; then
151 + euid="next"
152 + fi
153 + else
154 + eerror "Userid given but is not greater than 0 !"
155 + die "${euid} is not a valid UID"
156 + fi
157 + else
158 + euid="next"
159 + fi
160 + if [[ ${euid} == "next" ]] ; then
161 + for ((euid = 101; euid <= 999; euid++)); do
162 + [[ -z $(egetent passwd ${euid}) ]] && break
163 + done
164 + fi
165 + opts+=( -u ${euid} )
166 + einfo " - Userid: ${euid}"
167 +
168 + # handle shell
169 + local eshell=$1; shift
170 + if [[ ! -z ${eshell} ]] && [[ ${eshell} != "-1" ]] ; then
171 + if [[ ! -e ${ROOT}${eshell} ]] ; then
172 + eerror "A shell was specified but it does not exist !"
173 + die "${eshell} does not exist in ${ROOT}"
174 + fi
175 + if [[ ${eshell} == */false || ${eshell} == */nologin ]] ; then
176 + eerror "Do not specify ${eshell} yourself, use -1"
177 + die "Pass '-1' as the shell parameter"
178 + fi
179 + else
180 + for eshell in /sbin/nologin /usr/sbin/nologin /bin/false /usr/bin/false /dev/null ; do
181 + [[ -x ${ROOT}${eshell} ]] && break
182 + done
183 +
184 + if [[ ${eshell} == "/dev/null" ]] ; then
185 + eerror "Unable to identify the shell to use, proceeding with userland default."
186 + case ${USERLAND} in
187 + GNU) eshell="/bin/false" ;;
188 + BSD) eshell="/sbin/nologin" ;;
189 + Darwin) eshell="/usr/sbin/nologin" ;;
190 + *) die "Unable to identify the default shell for userland ${USERLAND}"
191 + esac
192 + fi
193 + fi
194 + einfo " - Shell: ${eshell}"
195 + opts+=( -s "${eshell}" )
196 +
197 + # handle homedir
198 + local ehome=$1; shift
199 + if [[ -z ${ehome} ]] || [[ ${ehome} == "-1" ]] ; then
200 + ehome="/dev/null"
201 + fi
202 + einfo " - Home: ${ehome}"
203 + opts+=( -d "${ehome}" )
204 +
205 + # handle groups
206 + local egroups=$1; shift
207 + local g egroups_arr
208 + IFS="," read -r -a egroups_arr <<<"${egroups}"
209 + shift
210 + if [[ ${#egroups_arr[@]} -gt 0 ]] ; then
211 + local defgroup exgroups
212 + for g in "${egroups_arr[@]}" ; do
213 + if [[ -z $(egetent group "${g}") ]] ; then
214 + eerror "You must add group ${g} to the system first"
215 + die "${g} is not a valid GID"
216 + fi
217 + if [[ -z ${defgroup} ]] ; then
218 + defgroup=${g}
219 + else
220 + exgroups+=",${g}"
221 + fi
222 + done
223 + opts+=( -g "${defgroup}" )
224 + if [[ ! -z ${exgroups} ]] ; then
225 + opts+=( -G "${exgroups:1}" )
226 + fi
227 + fi
228 + einfo " - Groups: ${egroups:-(none)}"
229 +
230 + # handle extra args
231 + if [[ $# -gt 0 ]] ; then
232 + die "extra arguments no longer supported; please file a bug"
233 + else
234 + local comment="added by portage for ${PN}"
235 + opts+=( -c "${comment}" )
236 + einfo " - GECOS: ${comment}"
237 + fi
238 +
239 + # add the user
240 + case ${CHOST} in
241 + *-darwin*)
242 + ### Make the user
243 + dscl . create "/users/${euser}" uid ${euid}
244 + dscl . create "/users/${euser}" shell "${eshell}"
245 + dscl . create "/users/${euser}" home "${ehome}"
246 + dscl . create "/users/${euser}" realname "added by portage for ${PN}"
247 + ### Add the user to the groups specified
248 + for g in "${egroups_arr[@]}" ; do
249 + dscl . merge "/groups/${g}" users "${euser}"
250 + done
251 + ;;
252 +
253 + *-freebsd*|*-dragonfly*)
254 + pw useradd "${euser}" "${opts[@]}" || die
255 + ;;
256 +
257 + *-netbsd*)
258 + useradd "${opts[@]}" "${euser}" || die
259 + ;;
260 +
261 + *-openbsd*)
262 + # all ops the same, except the -g vs -g/-G ...
263 + useradd -u ${euid} -s "${eshell}" \
264 + -d "${ehome}" -g "${egroups}" "${euser}" || die
265 + ;;
266 +
267 + *)
268 + useradd -r "${opts[@]}" "${euser}" || use prefix || die
269 + ;;
270 + esac
271 +
272 + if [[ ! -e ${ROOT}/${ehome} ]] ; then
273 + einfo " - Creating ${ehome} in ${ROOT}"
274 + mkdir -p "${ROOT}/${ehome}"
275 + chown "${euser}" "${ROOT}/${ehome}"
276 + chmod 755 "${ROOT}/${ehome}"
277 + fi
278 +}
279 +
280 +# @FUNCTION: enewgroup
281 +# @USAGE: <group> [gid]
282 +# @DESCRIPTION:
283 +# This function does not require you to understand how to properly add a
284 +# group to the system. Just give it a group name to add and enewgroup will
285 +# do the rest. You may specify the gid for the group or allow the group to
286 +# allocate the next available one.
287 +enewgroup() {
288 + _assert_pkg_ebuild_phase ${FUNCNAME}
289 +
290 + # get the group
291 + local egroup=$1; shift
292 + if [[ -z ${egroup} ]] ; then
293 + eerror "No group specified !"
294 + die "Cannot call enewgroup without a group"
295 + fi
296 +
297 + # see if group already exists
298 + if [[ -n $(egetent group "${egroup}") ]] ; then
299 + return 0
300 + fi
301 + einfo "Adding group '${egroup}' to your system ..."
302 +
303 + # handle gid
304 + local egid=$1; shift
305 + if [[ ! -z ${egid} ]] ; then
306 + if [[ ${egid} -gt 0 ]] ; then
307 + if [[ -n $(egetent group ${egid}) ]] ; then
308 + egid="next available; requested gid taken"
309 + fi
310 + else
311 + eerror "Groupid given but is not greater than 0 !"
312 + die "${egid} is not a valid GID"
313 + fi
314 + else
315 + egid="next available"
316 + fi
317 + einfo " - Groupid: ${egid}"
318 +
319 + # handle extra
320 + if [[ $# -gt 0 ]] ; then
321 + die "extra arguments no longer supported; please file a bug"
322 + fi
323 +
324 + # Some targets need to find the next available GID manually
325 + _enewgroup_next_gid() {
326 + if [[ ${egid} == *[!0-9]* ]] ; then
327 + # Non numeric
328 + for ((egid = 101; egid <= 999; egid++)) ; do
329 + [[ -z $(egetent group ${egid}) ]] && break
330 + done
331 + fi
332 + }
333 +
334 + # add the group
335 + case ${CHOST} in
336 + *-darwin*)
337 + _enewgroup_next_gid
338 + dscl . create "/groups/${egroup}" gid ${egid}
339 + dscl . create "/groups/${egroup}" passwd '*'
340 + ;;
341 +
342 + *-freebsd*|*-dragonfly*)
343 + _enewgroup_next_gid
344 + pw groupadd "${egroup}" -g ${egid} || die
345 + ;;
346 +
347 + *-netbsd*)
348 + _enewgroup_next_gid
349 + groupadd -g ${egid} "${egroup}" || die
350 + ;;
351 +
352 + *)
353 + local opts
354 + if [[ ${egid} == *[!0-9]* ]] ; then
355 + # Non numeric; let groupadd figure out a GID for us
356 + opts=""
357 + else
358 + opts="-g ${egid}"
359 + fi
360 + # We specify -r so that we get a GID in the system range from login.defs
361 + groupadd -r ${opts} "${egroup}" || use prefix || die
362 + ;;
363 + esac
364 +}
365 +
366 +# @FUNCTION: egethome
367 +# @USAGE: <user>
368 +# @DESCRIPTION:
369 +# Gets the home directory for the specified user.
370 +egethome() {
371 + local pos
372 +
373 + [[ $# -eq 1 ]] || die "usage: egethome <user>"
374 +
375 + case ${CHOST} in
376 + *-darwin*|*-freebsd*|*-dragonfly*)
377 + pos=9
378 + ;;
379 + *) # Linux, NetBSD, OpenBSD, etc...
380 + pos=6
381 + ;;
382 + esac
383 +
384 + egetent passwd "$1" | cut -d: -f${pos}
385 +}
386 +
387 +# @FUNCTION: egetshell
388 +# @USAGE: <user>
389 +# @DESCRIPTION:
390 +# Gets the shell for the specified user.
391 +egetshell() {
392 + local pos
393 +
394 + [[ $# -eq 1 ]] || die "usage: egetshell <user>"
395 +
396 + case ${CHOST} in
397 + *-darwin*|*-freebsd*|*-dragonfly*)
398 + pos=10
399 + ;;
400 + *) # Linux, NetBSD, OpenBSD, etc...
401 + pos=7
402 + ;;
403 + esac
404 +
405 + egetent passwd "$1" | cut -d: -f${pos}
406 +}
407 +
408 +# @FUNCTION: esethome
409 +# @USAGE: <user> <homedir>
410 +# @DESCRIPTION:
411 +# Update the home directory in a platform-agnostic way.
412 +# Required parameters is the username and the new home directory.
413 +# Specify -1 if you want to set home to the enewuser default
414 +# of /dev/null.
415 +# If the new home directory does not exist, it is created.
416 +# Any previously existing home directory is NOT moved.
417 +esethome() {
418 + _assert_pkg_ebuild_phase ${FUNCNAME}
419 +
420 + # get the username
421 + local euser=$1; shift
422 + if [[ -z ${euser} ]] ; then
423 + eerror "No username specified !"
424 + die "Cannot call esethome without a username"
425 + fi
426 +
427 + # lets see if the username already exists
428 + if [[ -z $(egetent passwd "${euser}") ]] ; then
429 + ewarn "User does not exist, cannot set home dir -- skipping."
430 + return 1
431 + fi
432 +
433 + # handle homedir
434 + local ehome=$1; shift
435 + if [[ -z ${ehome} ]] ; then
436 + eerror "No home directory specified !"
437 + die "Cannot call esethome without a home directory or '-1'"
438 + fi
439 +
440 + if [[ ${ehome} == "-1" ]] ; then
441 + ehome="/dev/null"
442 + fi
443 +
444 + # exit with no message if home dir is up to date
445 + if [[ $(egethome "${euser}") == ${ehome} ]]; then
446 + return 0
447 + fi
448 +
449 + einfo "Updating home for user '${euser}' ..."
450 + einfo " - Home: ${ehome}"
451 +
452 + # ensure home directory exists, otherwise update will fail
453 + if [[ ! -e ${ROOT}/${ehome} ]] ; then
454 + einfo " - Creating ${ehome} in ${ROOT}"
455 + mkdir -p "${ROOT}/${ehome}"
456 + chown "${euser}" "${ROOT}/${ehome}"
457 + chmod 755 "${ROOT}/${ehome}"
458 + fi
459 +
460 + # update the home directory
461 + case ${CHOST} in
462 + *-darwin*)
463 + dscl . change "/users/${euser}" home "${ehome}"
464 + ;;
465 +
466 + *-freebsd*|*-dragonfly*)
467 + pw usermod "${euser}" -d "${ehome}" && return 0
468 + [[ $? == 8 ]] && eerror "${euser} is in use, cannot update home"
469 + eerror "There was an error when attempting to update the home directory for ${euser}"
470 + eerror "Please update it manually on your system:"
471 + eerror "\t pw usermod \"${euser}\" -d \"${ehome}\""
472 + ;;
473 +
474 + *)
475 + usermod -d "${ehome}" "${euser}" && return 0
476 + [[ $? == 8 ]] && eerror "${euser} is in use, cannot update home"
477 + eerror "There was an error when attempting to update the home directory for ${euser}"
478 + eerror "Please update it manually on your system (as root):"
479 + eerror "\t usermod -d \"${ehome}\" \"${euser}\""
480 + ;;
481 + esac
482 +}
483 +
484 +fi