/[gentoo-x86]/eclass/user.eclass
Gentoo

Contents of /eclass/user.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Thu Oct 27 07:26:55 2011 UTC (2 years, 8 months ago) by vapier
Branch: MAIN
Changes since 1.1: +28 -27 lines
unify/update EBUILD_PHASE checks, and simplify egethome/egetshell/is-login-disabled funcs a bit

1 vapier 1.1 # Copyright 1999-2011 Gentoo Foundation
2     # Distributed under the terms of the GNU General Public License v2
3 vapier 1.2 # $Header: /var/cvsroot/gentoo-x86/eclass/user.eclass,v 1.1 2011/10/27 07:16:08 vapier Exp $
4 vapier 1.1
5     # @ECLASS: user.eclass
6     # @MAINTAINER:
7     # base-system@gentoo.org (Linux)
8     # Joe Jezak <josejx@gmail.com> (OS X)
9     # usata@gentoo.org (OS X)
10     # Aaron Walker <ka0ttic@gentoo.org> (FreeBSD)
11     # @BLURB: user management in ebuilds
12     # @DESCRIPTION:
13     # The user eclass contains a suite of functions that allow ebuilds
14     # to quickly make sure users in the installed system are sane.
15    
16 vapier 1.2 # @FUNCTION: _assert_pkg_ebuild_phase
17     # @INTERNAL
18     # @USAGE: <calling func name>
19     _assert_pkg_ebuild_phase() {
20     case ${EBUILD_PHASE} in
21     unpack|prepare|configure|compile|test|install)
22     eerror "'$1()' called from '${EBUILD_PHASE}()' which is not a pkg_* function."
23     eerror "Package fails at QA and at life. Please file a bug."
24     die "Bad package! $1 is only for use in pkg_* functions!"
25     esac
26     }
27    
28 vapier 1.1 # @FUNCTION: egetent
29     # @USAGE: <database> <key>
30     # @DESCRIPTION:
31     # Small wrapper for getent (Linux), nidump (< Mac OS X 10.5),
32     # dscl (Mac OS X 10.5), and pw (FreeBSD) used in enewuser()/enewgroup().
33     egetent() {
34     case ${CHOST} in
35     *-darwin[678])
36     case "$2" in
37     *[!0-9]*) # Non numeric
38     nidump $1 . | awk -F":" "{ if (\$1 ~ /^$2\$/) {print \$0;exit;} }"
39     ;;
40     *) # Numeric
41     nidump $1 . | awk -F":" "{ if (\$3 == $2) {print \$0;exit;} }"
42     ;;
43     esac
44     ;;
45     *-darwin*)
46     local mytype=$1
47     [[ "passwd" == $mytype ]] && mytype="Users"
48     [[ "group" == $mytype ]] && mytype="Groups"
49     case "$2" in
50     *[!0-9]*) # Non numeric
51     dscl . -read /$mytype/$2 2>/dev/null |grep RecordName
52     ;;
53     *) # Numeric
54     local mykey="UniqueID"
55     [[ $mytype == "Groups" ]] && mykey="PrimaryGroupID"
56     dscl . -search /$mytype $mykey $2 2>/dev/null
57     ;;
58     esac
59     ;;
60     *-freebsd*|*-dragonfly*)
61     local opts action="user"
62     [[ $1 == "passwd" ]] || action="group"
63    
64     # lookup by uid/gid
65     if [[ $2 == [[:digit:]]* ]] ; then
66     [[ ${action} == "user" ]] && opts="-u" || opts="-g"
67     fi
68    
69     pw show ${action} ${opts} "$2" -q
70     ;;
71     *-netbsd*|*-openbsd*)
72     grep "$2:\*:" /etc/$1
73     ;;
74     *)
75     type -p nscd >& /dev/null && nscd -i "$1"
76     getent "$1" "$2"
77     ;;
78     esac
79     }
80    
81     # @FUNCTION: enewuser
82     # @USAGE: <user> [uid] [shell] [homedir] [groups] [params]
83     # @DESCRIPTION:
84     # Same as enewgroup, you are not required to understand how to properly add
85     # a user to the system. The only required parameter is the username.
86     # Default uid is (pass -1 for this) next available, default shell is
87     # /bin/false, default homedir is /dev/null, there are no default groups,
88     # and default params sets the comment as 'added by portage for ${PN}'.
89     enewuser() {
90 vapier 1.2 _assert_pkg_ebuild_phase enewuser
91 vapier 1.1
92     # get the username
93     local euser=$1; shift
94     if [[ -z ${euser} ]] ; then
95     eerror "No username specified !"
96     die "Cannot call enewuser without a username"
97     fi
98    
99     # lets see if the username already exists
100     if [[ -n $(egetent passwd "${euser}") ]] ; then
101     return 0
102     fi
103     einfo "Adding user '${euser}' to your system ..."
104    
105     # options to pass to useradd
106     local opts=
107    
108     # handle uid
109     local euid=$1; shift
110     if [[ -n ${euid} && ${euid} != -1 ]] ; then
111     if [[ ${euid} -gt 0 ]] ; then
112     if [[ -n $(egetent passwd ${euid}) ]] ; then
113     euid="next"
114     fi
115     else
116     eerror "Userid given but is not greater than 0 !"
117     die "${euid} is not a valid UID"
118     fi
119     else
120     euid="next"
121     fi
122     if [[ ${euid} == "next" ]] ; then
123     for ((euid = 101; euid <= 999; euid++)); do
124     [[ -z $(egetent passwd ${euid}) ]] && break
125     done
126     fi
127     opts="${opts} -u ${euid}"
128     einfo " - Userid: ${euid}"
129    
130     # handle shell
131     local eshell=$1; shift
132     if [[ ! -z ${eshell} ]] && [[ ${eshell} != "-1" ]] ; then
133     if [[ ! -e ${ROOT}${eshell} ]] ; then
134     eerror "A shell was specified but it does not exist !"
135     die "${eshell} does not exist in ${ROOT}"
136     fi
137     if [[ ${eshell} == */false || ${eshell} == */nologin ]] ; then
138     eerror "Do not specify ${eshell} yourself, use -1"
139     die "Pass '-1' as the shell parameter"
140     fi
141     else
142     for shell in /sbin/nologin /usr/sbin/nologin /bin/false /usr/bin/false /dev/null ; do
143     [[ -x ${ROOT}${shell} ]] && break
144     done
145    
146     if [[ ${shell} == "/dev/null" ]] ; then
147     eerror "Unable to identify the shell to use, proceeding with userland default."
148     case ${USERLAND} in
149     GNU) shell="/bin/false" ;;
150     BSD) shell="/sbin/nologin" ;;
151     Darwin) shell="/usr/sbin/nologin" ;;
152     *) die "Unable to identify the default shell for userland ${USERLAND}"
153     esac
154     fi
155    
156     eshell=${shell}
157     fi
158     einfo " - Shell: ${eshell}"
159     opts="${opts} -s ${eshell}"
160    
161     # handle homedir
162     local ehome=$1; shift
163     if [[ -z ${ehome} ]] || [[ ${ehome} == "-1" ]] ; then
164     ehome="/dev/null"
165     fi
166     einfo " - Home: ${ehome}"
167     opts="${opts} -d ${ehome}"
168    
169     # handle groups
170     local egroups=$1; shift
171     if [[ ! -z ${egroups} ]] ; then
172     local oldifs=${IFS}
173     local defgroup="" exgroups=""
174    
175     export IFS=","
176     for g in ${egroups} ; do
177     export IFS=${oldifs}
178     if [[ -z $(egetent group "${g}") ]] ; then
179     eerror "You must add group ${g} to the system first"
180     die "${g} is not a valid GID"
181     fi
182     if [[ -z ${defgroup} ]] ; then
183     defgroup=${g}
184     else
185     exgroups="${exgroups},${g}"
186     fi
187     export IFS=","
188     done
189     export IFS=${oldifs}
190    
191     opts="${opts} -g ${defgroup}"
192     if [[ ! -z ${exgroups} ]] ; then
193     opts="${opts} -G ${exgroups:1}"
194     fi
195     else
196     egroups="(none)"
197     fi
198     einfo " - Groups: ${egroups}"
199    
200     # handle extra and add the user
201     local oldsandbox=${SANDBOX_ON}
202     export SANDBOX_ON="0"
203     case ${CHOST} in
204     *-darwin*)
205     ### Make the user
206     if [[ -z $@ ]] ; then
207     dscl . create /users/${euser} uid ${euid}
208     dscl . create /users/${euser} shell ${eshell}
209     dscl . create /users/${euser} home ${ehome}
210     dscl . create /users/${euser} realname "added by portage for ${PN}"
211     ### Add the user to the groups specified
212     local oldifs=${IFS}
213     export IFS=","
214     for g in ${egroups} ; do
215     dscl . merge /groups/${g} users ${euser}
216     done
217     export IFS=${oldifs}
218     else
219     einfo "Extra options are not supported on Darwin yet"
220     einfo "Please report the ebuild along with the info below"
221     einfo "eextra: $@"
222     die "Required function missing"
223     fi
224     ;;
225     *-freebsd*|*-dragonfly*)
226     if [[ -z $@ ]] ; then
227     pw useradd ${euser} ${opts} \
228     -c "added by portage for ${PN}" \
229     die "enewuser failed"
230     else
231     einfo " - Extra: $@"
232     pw useradd ${euser} ${opts} \
233     "$@" || die "enewuser failed"
234     fi
235     ;;
236    
237     *-netbsd*)
238     if [[ -z $@ ]] ; then
239     useradd ${opts} ${euser} || die "enewuser failed"
240     else
241     einfo " - Extra: $@"
242     useradd ${opts} ${euser} "$@" || die "enewuser failed"
243     fi
244     ;;
245    
246     *-openbsd*)
247     if [[ -z $@ ]] ; then
248     useradd -u ${euid} -s ${eshell} \
249     -d ${ehome} -c "Added by portage for ${PN}" \
250     -g ${egroups} ${euser} || die "enewuser failed"
251     else
252     einfo " - Extra: $@"
253     useradd -u ${euid} -s ${eshell} \
254     -d ${ehome} -c "Added by portage for ${PN}" \
255     -g ${egroups} ${euser} "$@" || die "enewuser failed"
256     fi
257     ;;
258    
259     *)
260     if [[ -z $@ ]] ; then
261     useradd -r ${opts} \
262     -c "added by portage for ${PN}" \
263     ${euser} \
264     || die "enewuser failed"
265     else
266     einfo " - Extra: $@"
267     useradd -r ${opts} "$@" \
268     ${euser} \
269     || die "enewuser failed"
270     fi
271     ;;
272     esac
273    
274     if [[ ! -e ${ROOT}/${ehome} ]] ; then
275     einfo " - Creating ${ehome} in ${ROOT}"
276     mkdir -p "${ROOT}/${ehome}"
277     chown ${euser} "${ROOT}/${ehome}"
278     chmod 755 "${ROOT}/${ehome}"
279     fi
280    
281     export SANDBOX_ON=${oldsandbox}
282     }
283    
284     # @FUNCTION: enewgroup
285     # @USAGE: <group> [gid]
286     # @DESCRIPTION:
287     # This function does not require you to understand how to properly add a
288     # group to the system. Just give it a group name to add and enewgroup will
289     # do the rest. You may specify the gid for the group or allow the group to
290     # allocate the next available one.
291     enewgroup() {
292 vapier 1.2 _assert_pkg_ebuild_phase enewgroup
293 vapier 1.1
294     # get the group
295     local egroup="$1"; shift
296     if [ -z "${egroup}" ]
297     then
298     eerror "No group specified !"
299     die "Cannot call enewgroup without a group"
300     fi
301    
302     # see if group already exists
303     if [[ -n $(egetent group "${egroup}") ]]; then
304     return 0
305     fi
306     einfo "Adding group '${egroup}' to your system ..."
307    
308     # options to pass to useradd
309     local opts=
310    
311     # handle gid
312     local egid="$1"; shift
313     if [ ! -z "${egid}" ]
314     then
315     if [ "${egid}" -gt 0 ]
316     then
317     if [ -z "`egetent group ${egid}`" ]
318     then
319     if [[ "${CHOST}" == *-darwin* ]]; then
320     opts="${opts} ${egid}"
321     else
322     opts="${opts} -g ${egid}"
323     fi
324     else
325     egid="next available; requested gid taken"
326     fi
327     else
328     eerror "Groupid given but is not greater than 0 !"
329     die "${egid} is not a valid GID"
330     fi
331     else
332     egid="next available"
333     fi
334     einfo " - Groupid: ${egid}"
335    
336     # handle extra
337     local eextra="$@"
338     opts="${opts} ${eextra}"
339    
340     # add the group
341     local oldsandbox="${SANDBOX_ON}"
342     export SANDBOX_ON="0"
343     case ${CHOST} in
344     *-darwin*)
345     if [ ! -z "${eextra}" ];
346     then
347     einfo "Extra options are not supported on Darwin/OS X yet"
348     einfo "Please report the ebuild along with the info below"
349     einfo "eextra: ${eextra}"
350     die "Required function missing"
351     fi
352    
353     # If we need the next available
354     case ${egid} in
355     *[!0-9]*) # Non numeric
356     for ((egid = 101; egid <= 999; egid++)); do
357     [[ -z $(egetent group ${egid}) ]] && break
358     done
359     esac
360     dscl . create /groups/${egroup} gid ${egid}
361     dscl . create /groups/${egroup} passwd '*'
362     ;;
363    
364     *-freebsd*|*-dragonfly*)
365     case ${egid} in
366     *[!0-9]*) # Non numeric
367     for ((egid = 101; egid <= 999; egid++)); do
368     [[ -z $(egetent group ${egid}) ]] && break
369     done
370     esac
371     pw groupadd ${egroup} -g ${egid} || die "enewgroup failed"
372     ;;
373    
374     *-netbsd*)
375     case ${egid} in
376     *[!0-9]*) # Non numeric
377     for ((egid = 101; egid <= 999; egid++)); do
378     [[ -z $(egetent group ${egid}) ]] && break
379     done
380     esac
381     groupadd -g ${egid} ${egroup} || die "enewgroup failed"
382     ;;
383    
384     *)
385     # We specify -r so that we get a GID in the system range from login.defs
386     groupadd -r ${opts} ${egroup} || die "enewgroup failed"
387     ;;
388     esac
389     export SANDBOX_ON="${oldsandbox}"
390     }
391    
392     # Gets the home directory for the specified user
393     # it's a wrap around egetent as the position of the home directory in the line
394     # varies depending on the os used.
395     #
396     # To use that, inherit eutils, not portability!
397     egethome() {
398 vapier 1.2 local pos
399 vapier 1.1
400     case ${CHOST} in
401     *-darwin*|*-freebsd*|*-dragonfly*)
402 vapier 1.2 pos=9
403 vapier 1.1 ;;
404 vapier 1.2 *) # Linux, NetBSD, OpenBSD, etc...
405     pos=6
406 vapier 1.1 ;;
407     esac
408 vapier 1.2
409     egetent passwd $1 | cut -d: -f${pos}
410 vapier 1.1 }
411    
412     # Gets the shell for the specified user
413     # it's a wrap around egetent as the position of the home directory in the line
414     # varies depending on the os used.
415     #
416     # To use that, inherit eutils, not portability!
417     egetshell() {
418 vapier 1.2 local pos
419 vapier 1.1
420     case ${CHOST} in
421     *-darwin*|*-freebsd*|*-dragonfly*)
422 vapier 1.2 pos=10
423 vapier 1.1 ;;
424 vapier 1.2 *) # Linux, NetBSD, OpenBSD, etc...
425     pos=7
426 vapier 1.1 ;;
427     esac
428 vapier 1.2
429     egetent passwd "$1" | cut -d: -f${pos}
430 vapier 1.1 }
431    
432     # Returns true if specified user has a shell that precludes logins
433     # on whichever operating system.
434     is-login-disabled() {
435    
436 vapier 1.2 case $(egetshell "$1") in
437 vapier 1.1 /bin/false|/usr/bin/false|/sbin/nologin|/usr/sbin/nologin)
438     return 0 ;;
439     *)
440     return 1 ;;
441     esac
442     }

  ViewVC Help
Powered by ViewVC 1.1.20