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

Contents of /eclass/user.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Thu Oct 27 07:16:08 2011 UTC (2 years, 11 months ago) by vapier
Branch: MAIN
split out user management helpers into a dedicated eclass

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

  ViewVC Help
Powered by ViewVC 1.1.20