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

Contents of /eclass/user.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations) (download)
Thu Oct 27 07:49:53 2011 UTC (2 years, 8 months ago) by vapier
Branch: MAIN
Changes since 1.2: +3 -2 lines
send nscd output to /dev/null so we don't dump ugly warnings when running as non-root

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

  ViewVC Help
Powered by ViewVC 1.1.20