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

Contents of /eclass/user.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (show annotations) (download)
Sat Dec 10 20:03:17 2011 UTC (2 years, 7 months ago) by vapier
Branch: MAIN
Changes since 1.17: +6 -1 lines
avoid multiple inclusions when possible to speed caching up

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/user.eclass,v 1.17 2011/11/29 19:32:23 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 if [[ ${___ECLASS_ONCE_USER} != "recur -_+^+_- spank" ]] ; then
17 ___ECLASS_ONCE_USER="recur -_+^+_- spank"
18
19 # @FUNCTION: _assert_pkg_ebuild_phase
20 # @INTERNAL
21 # @USAGE: <calling func name>
22 _assert_pkg_ebuild_phase() {
23 case ${EBUILD_PHASE} in
24 setup|preinst|postinst) ;;
25 *)
26 eerror "'$1()' called from '${EBUILD_PHASE}' phase which is not OK:"
27 eerror "You may only call from pkg_{setup,preinst,postinst} functions."
28 eerror "Package fails at QA and at life. Please file a bug."
29 die "Bad package! $1 is only for use in some pkg_* functions!"
30 esac
31 }
32
33 # @FUNCTION: egetent
34 # @USAGE: <database> <key>
35 # @DESCRIPTION:
36 # Small wrapper for getent (Linux), nidump (< Mac OS X 10.5),
37 # dscl (Mac OS X 10.5), and pw (FreeBSD) used in enewuser()/enewgroup().
38 #
39 # Supported databases: group passwd
40 egetent() {
41 local db=$1 key=$2
42
43 [[ $# -ge 3 ]] && die "usage: egetent <database> <key>"
44
45 case ${db} in
46 passwd|group) ;;
47 *) die "sorry, database '${db}' not yet supported; file a bug" ;;
48 esac
49
50 case ${CHOST} in
51 *-darwin[678])
52 case ${key} in
53 *[!0-9]*) # Non numeric
54 nidump ${db} . | awk -F: "(\$1 ~ /^${key}\$/) {print;exit;}"
55 ;;
56 *) # Numeric
57 nidump ${db} . | awk -F: "(\$3 == ${key}) {print;exit;}"
58 ;;
59 esac
60 ;;
61 *-darwin*)
62 local mykey
63 case ${db} in
64 passwd) db="Users" mykey="UniqueID" ;;
65 group) db="Groups" mykey="PrimaryGroupID" ;;
66 esac
67
68 case ${key} in
69 *[!0-9]*) # Non numeric
70 dscl . -read /${db}/${key} 2>/dev/null |grep RecordName
71 ;;
72 *) # Numeric
73 dscl . -search /${db} ${mykey} ${key} 2>/dev/null
74 ;;
75 esac
76 ;;
77 *-freebsd*|*-dragonfly*)
78 case ${db} in
79 passwd) db="user" ;;
80 *) ;;
81 esac
82
83 # lookup by uid/gid
84 local opts
85 if [[ ${key} == [[:digit:]]* ]] ; then
86 [[ ${db} == "user" ]] && opts="-u" || opts="-g"
87 fi
88
89 pw show ${db} ${opts} "${key}" -q
90 ;;
91 *-netbsd*|*-openbsd*)
92 grep "${key}:\*:" /etc/${db}
93 ;;
94 *)
95 # ignore output if nscd doesn't exist, or we're not running as root
96 nscd -i "${db}" 2>/dev/null
97 getent "${db}" "${key}"
98 ;;
99 esac
100 }
101
102 # @FUNCTION: enewuser
103 # @USAGE: <user> [uid] [shell] [homedir] [groups]
104 # @DESCRIPTION:
105 # Same as enewgroup, you are not required to understand how to properly add
106 # a user to the system. The only required parameter is the username.
107 # Default uid is (pass -1 for this) next available, default shell is
108 # /bin/false, default homedir is /dev/null, and there are no default groups.
109 enewuser() {
110 _assert_pkg_ebuild_phase ${FUNCNAME}
111
112 # get the username
113 local euser=$1; shift
114 if [[ -z ${euser} ]] ; then
115 eerror "No username specified !"
116 die "Cannot call enewuser without a username"
117 fi
118
119 # lets see if the username already exists
120 if [[ -n $(egetent passwd "${euser}") ]] ; then
121 return 0
122 fi
123 einfo "Adding user '${euser}' to your system ..."
124
125 # options to pass to useradd
126 local opts=()
127
128 # handle uid
129 local euid=$1; shift
130 if [[ -n ${euid} && ${euid} != -1 ]] ; then
131 if [[ ${euid} -gt 0 ]] ; then
132 if [[ -n $(egetent passwd ${euid}) ]] ; then
133 euid="next"
134 fi
135 else
136 eerror "Userid given but is not greater than 0 !"
137 die "${euid} is not a valid UID"
138 fi
139 else
140 euid="next"
141 fi
142 if [[ ${euid} == "next" ]] ; then
143 for ((euid = 101; euid <= 999; euid++)); do
144 [[ -z $(egetent passwd ${euid}) ]] && break
145 done
146 fi
147 opts+=( -u ${euid} )
148 einfo " - Userid: ${euid}"
149
150 # handle shell
151 local eshell=$1; shift
152 if [[ ! -z ${eshell} ]] && [[ ${eshell} != "-1" ]] ; then
153 if [[ ! -e ${ROOT}${eshell} ]] ; then
154 eerror "A shell was specified but it does not exist !"
155 die "${eshell} does not exist in ${ROOT}"
156 fi
157 if [[ ${eshell} == */false || ${eshell} == */nologin ]] ; then
158 eerror "Do not specify ${eshell} yourself, use -1"
159 die "Pass '-1' as the shell parameter"
160 fi
161 else
162 for eshell in /sbin/nologin /usr/sbin/nologin /bin/false /usr/bin/false /dev/null ; do
163 [[ -x ${ROOT}${eshell} ]] && break
164 done
165
166 if [[ ${eshell} == "/dev/null" ]] ; then
167 eerror "Unable to identify the shell to use, proceeding with userland default."
168 case ${USERLAND} in
169 GNU) eshell="/bin/false" ;;
170 BSD) eshell="/sbin/nologin" ;;
171 Darwin) eshell="/usr/sbin/nologin" ;;
172 *) die "Unable to identify the default shell for userland ${USERLAND}"
173 esac
174 fi
175 fi
176 einfo " - Shell: ${eshell}"
177 opts+=( -s "${eshell}" )
178
179 # handle homedir
180 local ehome=$1; shift
181 if [[ -z ${ehome} ]] || [[ ${ehome} == "-1" ]] ; then
182 ehome="/dev/null"
183 fi
184 einfo " - Home: ${ehome}"
185 opts+=( -d "${ehome}" )
186
187 # handle groups
188 local egroups=$1; shift
189 local g egroups_arr
190 IFS="," read -r -a egroups_arr <<<"${egroups}"
191 shift
192 if [[ ${#egroups_arr[@]} -gt 0 ]] ; then
193 local defgroup exgroups
194 for g in "${egroups_arr[@]}" ; do
195 if [[ -z $(egetent group "${g}") ]] ; then
196 eerror "You must add group ${g} to the system first"
197 die "${g} is not a valid GID"
198 fi
199 if [[ -z ${defgroup} ]] ; then
200 defgroup=${g}
201 else
202 exgroups+=",${g}"
203 fi
204 done
205 opts+=( -g "${defgroup}" )
206 if [[ ! -z ${exgroups} ]] ; then
207 opts+=( -G "${exgroups:1}" )
208 fi
209 fi
210 einfo " - Groups: ${egroups:-(none)}"
211
212 # handle extra args
213 if [[ $# -gt 0 ]] ; then
214 die "extra arguments no longer supported; please file a bug"
215 else
216 local comment="added by portage for ${PN}"
217 opts+=( -c "${comment}" )
218 einfo " - GECOS: ${comment}"
219 fi
220
221 # add the user
222 case ${CHOST} in
223 *-darwin*)
224 ### Make the user
225 dscl . create "/users/${euser}" uid ${euid}
226 dscl . create "/users/${euser}" shell "${eshell}"
227 dscl . create "/users/${euser}" home "${ehome}"
228 dscl . create "/users/${euser}" realname "added by portage for ${PN}"
229 ### Add the user to the groups specified
230 for g in "${egroups_arr[@]}" ; do
231 dscl . merge "/groups/${g}" users "${euser}"
232 done
233 ;;
234
235 *-freebsd*|*-dragonfly*)
236 pw useradd "${euser}" "${opts[@]}" || die
237 ;;
238
239 *-netbsd*)
240 useradd "${opts[@]}" "${euser}" || die
241 ;;
242
243 *-openbsd*)
244 # all ops the same, except the -g vs -g/-G ...
245 useradd -u ${euid} -s "${eshell}" \
246 -d "${ehome}" -g "${egroups}" "${euser}" || die
247 ;;
248
249 *)
250 useradd -r "${opts[@]}" "${euser}" || die
251 ;;
252 esac
253
254 if [[ ! -e ${ROOT}/${ehome} ]] ; then
255 einfo " - Creating ${ehome} in ${ROOT}"
256 mkdir -p "${ROOT}/${ehome}"
257 chown "${euser}" "${ROOT}/${ehome}"
258 chmod 755 "${ROOT}/${ehome}"
259 fi
260 }
261
262 # @FUNCTION: enewgroup
263 # @USAGE: <group> [gid]
264 # @DESCRIPTION:
265 # This function does not require you to understand how to properly add a
266 # group to the system. Just give it a group name to add and enewgroup will
267 # do the rest. You may specify the gid for the group or allow the group to
268 # allocate the next available one.
269 enewgroup() {
270 _assert_pkg_ebuild_phase ${FUNCNAME}
271
272 # get the group
273 local egroup=$1; shift
274 if [[ -z ${egroup} ]] ; then
275 eerror "No group specified !"
276 die "Cannot call enewgroup without a group"
277 fi
278
279 # see if group already exists
280 if [[ -n $(egetent group "${egroup}") ]] ; then
281 return 0
282 fi
283 einfo "Adding group '${egroup}' to your system ..."
284
285 # handle gid
286 local egid=$1; shift
287 if [[ ! -z ${egid} ]] ; then
288 if [[ ${egid} -gt 0 ]] ; then
289 if [[ -n $(egetent group ${egid}) ]] ; then
290 egid="next available; requested gid taken"
291 fi
292 else
293 eerror "Groupid given but is not greater than 0 !"
294 die "${egid} is not a valid GID"
295 fi
296 else
297 egid="next available"
298 fi
299 einfo " - Groupid: ${egid}"
300
301 # handle extra
302 if [[ $# -gt 0 ]] ; then
303 die "extra arguments no longer supported; please file a bug"
304 fi
305
306 # Some targets need to find the next available GID manually
307 _enewgroup_next_gid() {
308 if [[ ${egid} == *[!0-9]* ]] ; then
309 # Non numeric
310 for ((egid = 101; egid <= 999; egid++)) ; do
311 [[ -z $(egetent group ${egid}) ]] && break
312 done
313 fi
314 }
315
316 # add the group
317 case ${CHOST} in
318 *-darwin*)
319 _enewgroup_next_gid
320 dscl . create "/groups/${egroup}" gid ${egid}
321 dscl . create "/groups/${egroup}" passwd '*'
322 ;;
323
324 *-freebsd*|*-dragonfly*)
325 _enewgroup_next_gid
326 pw groupadd "${egroup}" -g ${egid} || die
327 ;;
328
329 *-netbsd*)
330 _enewgroup_next_gid
331 groupadd -g ${egid} "${egroup}" || die
332 ;;
333
334 *)
335 local opts
336 if [[ ${egid} == *[!0-9]* ]] ; then
337 # Non numeric; let groupadd figure out a GID for us
338 opts=""
339 else
340 opts="-g ${egid}"
341 fi
342 # We specify -r so that we get a GID in the system range from login.defs
343 groupadd -r ${opts} "${egroup}" || die
344 ;;
345 esac
346 }
347
348 # @FUNCTION: egethome
349 # @USAGE: <user>
350 # @DESCRIPTION:
351 # Gets the home directory for the specified user.
352 egethome() {
353 local pos
354
355 [[ $# -eq 1 ]] || die "usage: egethome <user>"
356
357 case ${CHOST} in
358 *-darwin*|*-freebsd*|*-dragonfly*)
359 pos=9
360 ;;
361 *) # Linux, NetBSD, OpenBSD, etc...
362 pos=6
363 ;;
364 esac
365
366 egetent passwd "$1" | cut -d: -f${pos}
367 }
368
369 # @FUNCTION: egetshell
370 # @USAGE: <user>
371 # @DESCRIPTION:
372 # Gets the shell for the specified user.
373 egetshell() {
374 local pos
375
376 [[ $# -eq 1 ]] || die "usage: egetshell <user>"
377
378 case ${CHOST} in
379 *-darwin*|*-freebsd*|*-dragonfly*)
380 pos=10
381 ;;
382 *) # Linux, NetBSD, OpenBSD, etc...
383 pos=7
384 ;;
385 esac
386
387 egetent passwd "$1" | cut -d: -f${pos}
388 }
389
390 fi

  ViewVC Help
Powered by ViewVC 1.1.20