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

Contents of /eclass/eutils.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.366 - (hide annotations) (download)
Fri Sep 30 16:51:01 2011 UTC (3 years, 2 months ago) by vapier
Branch: MAIN
Changes since 1.365: +3 -2 lines
edos2unix now dies when sed fails

1 vapier 1.356 # Copyright 1999-2011 Gentoo Foundation
2 azarah 1.1 # Distributed under the terms of the GNU General Public License v2
3 vapier 1.366 # $Header: /var/cvsroot/gentoo-x86/eclass/eutils.eclass,v 1.365 2011/09/29 02:32:20 vapier Exp $
4 vapier 1.283
5     # @ECLASS: eutils.eclass
6     # @MAINTAINER:
7     # base-system@gentoo.org
8     # @BLURB: many extra (but common) functions that are used in ebuilds
9     # @DESCRIPTION:
10     # The eutils eclass contains a suite of functions that complement
11     # the ones that ebuild.sh already contain. The idea is that the functions
12     # are not required in all ebuilds but enough utilize them to have a common
13     # home rather than having multiple ebuilds implementing the same thing.
14 swegener 1.286 #
15 vapier 1.283 # Due to the nature of this eclass, some functions may have maintainers
16     # different from the overall eclass!
17 azarah 1.1
18 flameeyes 1.197 inherit multilib portability
19 azarah 1.1
20 vapier 1.22 DESCRIPTION="Based on the ${ECLASS} eclass"
21 azarah 1.1
22 betelgeuse 1.329 if has "${EAPI:-0}" 0 1 2; then
23    
24 vapier 1.283 # @FUNCTION: epause
25     # @USAGE: [seconds]
26     # @DESCRIPTION:
27     # Sleep for the specified number of seconds (default of 5 seconds). Useful when
28     # printing a message the user should probably be reading and often used in
29     # conjunction with the ebeep function. If the EPAUSE_IGNORE env var is set,
30 betelgeuse 1.329 # don't wait at all. Defined in EAPIs 0 1 and 2.
31 ciaranm 1.98 epause() {
32 vapier 1.245 [[ -z ${EPAUSE_IGNORE} ]] && sleep ${1:-5}
33 ciaranm 1.98 }
34    
35 vapier 1.283 # @FUNCTION: ebeep
36     # @USAGE: [number of beeps]
37     # @DESCRIPTION:
38     # Issue the specified number of beeps (default of 5 beeps). Useful when
39     # printing a message the user should probably be reading and often used in
40     # conjunction with the epause function. If the EBEEP_IGNORE env var is set,
41 betelgeuse 1.329 # don't beep at all. Defined in EAPIs 0 1 and 2.
42 ciaranm 1.98 ebeep() {
43     local n
44 vapier 1.245 if [[ -z ${EBEEP_IGNORE} ]] ; then
45 ciaranm 1.98 for ((n=1 ; n <= ${1:-5} ; n++)) ; do
46     echo -ne "\a"
47     sleep 0.1 &>/dev/null ; sleep 0,1 &>/dev/null
48     echo -ne "\a"
49     sleep 1
50     done
51     fi
52     }
53    
54 reavertm 1.331 else
55    
56 reavertm 1.332 ebeep() {
57 reavertm 1.337 ewarn "QA Notice: ebeep is not defined in EAPI=${EAPI}, please file a bug at http://bugs.gentoo.org"
58 reavertm 1.332 }
59 reavertm 1.331
60 reavertm 1.332 epause() {
61 reavertm 1.337 ewarn "QA Notice: epause is not defined in EAPI=${EAPI}, please file a bug at http://bugs.gentoo.org"
62 reavertm 1.332 }
63 reavertm 1.331
64 betelgeuse 1.329 fi
65    
66 betelgeuse 1.348 # @FUNCTION: eqawarn
67     # @USAGE: [message]
68     # @DESCRIPTION:
69 mgorny 1.363 # Proxy to ewarn for package managers that don't provide eqawarn and use the PM
70     # implementation if available. Reuses PORTAGE_ELOG_CLASSES as set by the dev
71     # profile.
72 betelgeuse 1.348 if ! declare -F eqawarn >/dev/null ; then
73     eqawarn() {
74 mgorny 1.363 has qa ${PORTAGE_ELOG_CLASSES} && ewarn "$@"
75 betelgeuse 1.348 }
76     fi
77    
78 hollow 1.298 # @FUNCTION: ecvs_clean
79 vapier 1.299 # @USAGE: [list of dirs]
80 hollow 1.298 # @DESCRIPTION:
81 vapier 1.299 # Remove CVS directories recursiveley. Useful when a source tarball contains
82     # internal CVS directories. Defaults to $PWD.
83 hollow 1.298 ecvs_clean() {
84 vapier 1.299 [[ -z $* ]] && set -- .
85 hollow 1.298 find "$@" -type d -name 'CVS' -prune -print0 | xargs -0 rm -rf
86     find "$@" -type f -name '.cvs*' -print0 | xargs -0 rm -rf
87     }
88    
89     # @FUNCTION: esvn_clean
90 vapier 1.299 # @USAGE: [list of dirs]
91 hollow 1.298 # @DESCRIPTION:
92 vapier 1.299 # Remove .svn directories recursiveley. Useful when a source tarball contains
93     # internal Subversion directories. Defaults to $PWD.
94 hollow 1.298 esvn_clean() {
95 vapier 1.299 [[ -z $* ]] && set -- .
96 hollow 1.298 find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf
97     }
98    
99 vapier 1.322 # @FUNCTION: eshopts_push
100 vapier 1.330 # @USAGE: [options to `set` or `shopt`]
101 vapier 1.322 # @DESCRIPTION:
102     # Often times code will want to enable a shell option to change code behavior.
103     # Since changing shell options can easily break other pieces of code (which
104     # assume the default state), eshopts_push is used to (1) push the current shell
105     # options onto a stack and (2) pass the specified arguments to set.
106     #
107 vapier 1.330 # If the first argument is '-s' or '-u', we assume you want to call `shopt`
108     # rather than `set` as there are some options only available via that.
109     #
110 vapier 1.322 # A common example is to disable shell globbing so that special meaning/care
111     # may be used with variables/arguments to custom functions. That would be:
112     # @CODE
113     # eshopts_push -o noglob
114     # for x in ${foo} ; do
115     # if ...some check... ; then
116     # eshopts_pop
117     # return 0
118     # fi
119     # done
120     # eshopts_pop
121     # @CODE
122     eshopts_push() {
123     # have to assume __ESHOPTS_SAVE__ isn't screwed with
124     # as a `declare -a` here will reset its value
125     local i=${#__ESHOPTS_SAVE__[@]}
126 vapier 1.330 if [[ $1 == -[su] ]] ; then
127     __ESHOPTS_SAVE__[$i]=$(shopt -p)
128     [[ $# -eq 0 ]] && return 0
129     shopt "$@" || die "eshopts_push: bad options to shopt: $*"
130     else
131     __ESHOPTS_SAVE__[$i]=$-
132     [[ $# -eq 0 ]] && return 0
133     set "$@" || die "eshopts_push: bad options to set: $*"
134     fi
135 vapier 1.322 }
136    
137     # @FUNCTION: eshopts_pop
138     # @USAGE:
139     # @DESCRIPTION:
140     # Restore the shell options to the state saved with the corresponding
141     # eshopts_push call. See that function for more details.
142     eshopts_pop() {
143     [[ $# -ne 0 ]] && die "eshopts_pop takes no arguments"
144     local i=$(( ${#__ESHOPTS_SAVE__[@]} - 1 ))
145     [[ ${i} -eq -1 ]] && die "eshopts_{push,pop}: unbalanced pair"
146     local s=${__ESHOPTS_SAVE__[$i]}
147     unset __ESHOPTS_SAVE__[$i]
148 vapier 1.330 if [[ ${s} == "shopt -"* ]] ; then
149     eval "${s}" || die "eshopts_pop: sanity: invalid shopt options: ${s}"
150     else
151     set +$- || die "eshopts_pop: sanity: invalid shell settings: $-"
152     set -${s} || die "eshopts_pop: sanity: unable to restore saved shell settings: ${s}"
153     fi
154 vapier 1.322 }
155    
156 vapier 1.325 # @VARIABLE: EPATCH_SOURCE
157     # @DESCRIPTION:
158     # Default directory to search for patches.
159 azarah 1.2 EPATCH_SOURCE="${WORKDIR}/patch"
160 vapier 1.325 # @VARIABLE: EPATCH_SUFFIX
161     # @DESCRIPTION:
162     # Default extension for patches (do not prefix the period yourself).
163 azarah 1.2 EPATCH_SUFFIX="patch.bz2"
164 vapier 1.325 # @VARIABLE: EPATCH_OPTS
165     # @DESCRIPTION:
166     # Default options for patch:
167     # @CODE
168     # -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571
169     # --no-backup-if-mismatch - do not leave .orig files behind
170     # -E - automatically remove empty files
171     # @CODE
172 vapier 1.230 EPATCH_OPTS="-g0 -E --no-backup-if-mismatch"
173 vapier 1.325 # @VARIABLE: EPATCH_EXCLUDE
174     # @DESCRIPTION:
175 mr_bones_ 1.308 # List of patches not to apply. Note this is only file names,
176 vapier 1.325 # and not the full path. Globs accepted.
177 azarah 1.6 EPATCH_EXCLUDE=""
178 vapier 1.325 # @VARIABLE: EPATCH_SINGLE_MSG
179     # @DESCRIPTION:
180 azarah 1.9 # Change the printed message for a single patch.
181     EPATCH_SINGLE_MSG=""
182 vapier 1.325 # @VARIABLE: EPATCH_MULTI_MSG
183     # @DESCRIPTION:
184 vapier 1.173 # Change the printed message for multiple patches.
185     EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..."
186 vapier 1.325 # @VARIABLE: EPATCH_FORCE
187     # @DESCRIPTION:
188     # Only require patches to match EPATCH_SUFFIX rather than the extended
189     # arch naming style.
190 azarah 1.29 EPATCH_FORCE="no"
191 azarah 1.2
192 vapier 1.325 # @FUNCTION: epatch
193     # @USAGE: [patches] [dirs of patches]
194     # @DESCRIPTION:
195     # epatch is designed to greatly simplify the application of patches. It can
196     # process patch files directly, or directories of patches. The patches may be
197     # compressed (bzip/gzip/etc...) or plain text. You generally need not specify
198     # the -p option as epatch will automatically attempt -p0 to -p5 until things
199     # apply successfully.
200 azarah 1.2 #
201 vapier 1.325 # If you do not specify any options, then epatch will default to the directory
202     # specified by EPATCH_SOURCE.
203 azarah 1.2 #
204 vapier 1.325 # When processing directories, epatch will apply all patches that match:
205     # @CODE
206 vapier 1.350 # if ${EPATCH_FORCE} != "yes"
207 vapier 1.325 # ??_${ARCH}_foo.${EPATCH_SUFFIX}
208     # else
209     # *.${EPATCH_SUFFIX}
210     # @CODE
211     # The leading ?? are typically numbers used to force consistent patch ordering.
212     # The arch field is used to apply patches only for the host architecture with
213     # the special value of "all" means apply for everyone. Note that using values
214     # other than "all" is highly discouraged -- you should apply patches all the
215     # time and let architecture details be detected at configure/compile time.
216 azarah 1.2 #
217 vapier 1.325 # If EPATCH_SUFFIX is empty, then no period before it is implied when searching
218     # for patches to apply.
219 azarah 1.2 #
220 vapier 1.325 # Refer to the other EPATCH_xxx variables for more customization of behavior.
221 azarah 1.2 epatch() {
222 swegener 1.231 _epatch_draw_line() {
223 vapier 1.325 # create a line of same length as input string
224 agriffis 1.229 [[ -z $1 ]] && set "$(printf "%65s" '')"
225     echo "${1//?/=}"
226 vapier 1.219 }
227 azarah 1.3
228 vapier 1.195 unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402
229    
230 vapier 1.325 # Let the rest of the code process one user arg at a time --
231     # each arg may expand into multiple patches, and each arg may
232     # need to start off with the default global EPATCH_xxx values
233     if [[ $# -gt 1 ]] ; then
234     local m
235 vapier 1.94 for m in "$@" ; do
236     epatch "${m}"
237     done
238     return 0
239 azarah 1.3 fi
240    
241 vapier 1.325 local SINGLE_PATCH="no"
242     # no args means process ${EPATCH_SOURCE}
243     [[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}"
244    
245     if [[ -f $1 ]] ; then
246 azarah 1.3 SINGLE_PATCH="yes"
247 vapier 1.325 set -- "$1"
248     # Use the suffix from the single patch (localize it); the code
249     # below will find the suffix for us
250     local EPATCH_SUFFIX=$1
251    
252     elif [[ -d $1 ]] ; then
253     # Some people like to make dirs of patches w/out suffixes (vim)
254     set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"}
255 danarmak 1.32
256 vapier 1.359 elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then
257     # Re-use EPATCH_SOURCE as a search dir
258     epatch "${EPATCH_SOURCE}/$1"
259     return $?
260    
261 azarah 1.3 else
262 vapier 1.325 # sanity check ... if it isn't a dir or file, wtf man ?
263     [[ $# -ne 0 ]] && EPATCH_SOURCE=$1
264     echo
265     eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE is:"
266     eerror
267     eerror " ${EPATCH_SOURCE}"
268     eerror " ( ${EPATCH_SOURCE##*/} )"
269     echo
270     die "Cannot find \$EPATCH_SOURCE!"
271 azarah 1.3 fi
272 azarah 1.2
273 vapier 1.325 local PIPE_CMD
274 azarah 1.2 case ${EPATCH_SUFFIX##*\.} in
275 vapier 1.325 xz) PIPE_CMD="xz -dc" ;;
276     lzma) PIPE_CMD="lzma -dc" ;;
277     bz2) PIPE_CMD="bzip2 -dc" ;;
278     gz|Z|z) PIPE_CMD="gzip -dc" ;;
279     ZIP|zip) PIPE_CMD="unzip -p" ;;
280     *) ;;
281 azarah 1.2 esac
282    
283 vapier 1.325 [[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}"
284    
285     local x
286     for x in "$@" ; do
287     # If the patch dir given contains subdirs, or our EPATCH_SUFFIX
288     # didn't match anything, ignore continue on
289     [[ ! -f ${x} ]] && continue
290    
291     local patchname=${x##*/}
292    
293     # Apply single patches, or forced sets of patches, or
294     # patches with ARCH dependant names.
295 flameeyes 1.266 # ???_arch_foo.patch
296 vapier 1.325 # Else, skip this input altogether
297     local a=${patchname#*_} # strip the ???_
298     a=${a%%_*} # strip the _foo.patch
299     if ! [[ ${SINGLE_PATCH} == "yes" || \
300 ulm 1.354 ${EPATCH_FORCE} == "yes" || \
301     ${a} == all || \
302     ${a} == ${ARCH} ]]
303 azarah 1.2 then
304 vapier 1.325 continue
305     fi
306 azarah 1.6
307 vapier 1.325 # Let people filter things dynamically
308     if [[ -n ${EPATCH_EXCLUDE} ]] ; then
309     # let people use globs in the exclude
310     eshopts_push -o noglob
311    
312 scarabeus 1.328 local ex
313 vapier 1.325 for ex in ${EPATCH_EXCLUDE} ; do
314 scarabeus 1.328 if [[ ${patchname} == ${ex} ]] ; then
315     eshopts_pop
316     continue 2
317     fi
318 vapier 1.325 done
319 vapier 1.326
320 vapier 1.325 eshopts_pop
321     fi
322 danarmak 1.32
323 vapier 1.325 if [[ ${SINGLE_PATCH} == "yes" ]] ; then
324     if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then
325     einfo "${EPATCH_SINGLE_MSG}"
326 azarah 1.3 else
327 vapier 1.325 einfo "Applying ${patchname} ..."
328 azarah 1.3 fi
329 vapier 1.325 else
330     einfo " ${patchname} ..."
331     fi
332 azarah 1.2
333 vapier 1.325 # most of the time, there will only be one run per unique name,
334     # but if there are more, make sure we get unique log filenames
335     local STDERR_TARGET="${T}/${patchname}.out"
336     if [[ -e ${STDERR_TARGET} ]] ; then
337     STDERR_TARGET="${T}/${patchname}-$$.out"
338     fi
339 azarah 1.2
340 vapier 1.325 printf "***** %s *****\n\n" "${patchname}" > "${STDERR_TARGET}"
341 vapier 1.304
342 vapier 1.325 # Decompress the patch if need be
343     local count=0
344     local PATCH_TARGET
345     if [[ -n ${PIPE_CMD} ]] ; then
346     PATCH_TARGET="${T}/$$.patch"
347     echo "PIPE_COMMAND: ${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> "${STDERR_TARGET}"
348 vapier 1.304
349 vapier 1.325 if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; then
350     echo
351     eerror "Could not extract patch!"
352     #die "Could not extract patch!"
353     count=5
354     break
355 vapier 1.305 fi
356 vapier 1.325 else
357     PATCH_TARGET=${x}
358     fi
359 vapier 1.305
360 vapier 1.325 # Check for absolute paths in patches. If sandbox is disabled,
361     # people could (accidently) patch files in the root filesystem.
362     # Or trigger other unpleasantries #237667. So disallow -p0 on
363     # such patches.
364     local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk '$2 != "/dev/null" { print }')
365     if [[ -n ${abs_paths} ]] ; then
366     count=1
367     printf "NOTE: skipping -p0 due to absolute paths in patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}"
368     fi
369 vapier 1.353 # Similar reason, but with relative paths.
370     local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' "${PATCH_TARGET}")
371     if [[ -n ${rel_paths} ]] ; then
372     eqawarn "QA Notice: Your patch uses relative paths '../'."
373     eqawarn " In the future this will cause a failure."
374     eqawarn "${rel_paths}"
375     fi
376 vapier 1.325
377     # Dynamically detect the correct -p# ... i'm lazy, so shoot me :/
378     while [[ ${count} -lt 5 ]] ; do
379     # Generate some useful debug info ...
380     (
381     _epatch_draw_line "***** ${patchname} *****"
382     echo
383     echo "PATCH COMMAND: patch -p${count} ${EPATCH_OPTS} < '${PATCH_TARGET}'"
384     echo
385     _epatch_draw_line "***** ${patchname} *****"
386 vapier 1.360 patch -p${count} ${EPATCH_OPTS} --dry-run -f < "${PATCH_TARGET}" 2>&1
387     ret=$?
388     echo
389     echo "patch program exited with status ${ret}"
390     exit ${ret}
391 vapier 1.325 ) >> "${STDERR_TARGET}"
392 azarah 1.8
393 vapier 1.360 if [ $? -eq 0 ] ; then
394 vapier 1.325 (
395     _epatch_draw_line "***** ${patchname} *****"
396     echo
397     echo "ACTUALLY APPLYING ${patchname} ..."
398     echo
399     _epatch_draw_line "***** ${patchname} *****"
400     patch -p${count} ${EPATCH_OPTS} < "${PATCH_TARGET}" 2>&1
401 vapier 1.360 ret=$?
402     echo
403     echo "patch program exited with status ${ret}"
404     exit ${ret}
405 vapier 1.325 ) >> "${STDERR_TARGET}"
406 danarmak 1.32
407 vapier 1.325 if [ $? -ne 0 ] ; then
408     echo
409     eerror "A dry-run of patch command succeeded, but actually"
410     eerror "applying the patch failed!"
411     #die "Real world sux compared to the dreamworld!"
412     count=5
413 azarah 1.2 fi
414 vapier 1.325 break
415 azarah 1.8 fi
416    
417 vapier 1.325 : $(( count++ ))
418     done
419 azarah 1.8
420 vapier 1.325 # if we had to decompress the patch, delete the temp one
421     if [[ -n ${PIPE_CMD} ]] ; then
422     rm -f "${PATCH_TARGET}"
423     fi
424 azarah 1.3
425 vapier 1.325 if [[ ${count} -ge 5 ]] ; then
426     echo
427     eerror "Failed Patch: ${patchname} !"
428     eerror " ( ${PATCH_TARGET} )"
429     eerror
430     eerror "Include in your bugreport the contents of:"
431     eerror
432     eerror " ${STDERR_TARGET}"
433     echo
434     die "Failed Patch: ${patchname}!"
435 azarah 1.2 fi
436 vapier 1.325
437     # if everything worked, delete the patch log
438     rm -f "${STDERR_TARGET}"
439     eend 0
440 azarah 1.2 done
441 vapier 1.325
442     [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching"
443     : # everything worked
444 azarah 1.26 }
445 vapier 1.361
446     # @FUNCTION: epatch_user
447     # @USAGE:
448     # @DESCRIPTION:
449     # Applies user-provided patches to the source tree. The patches are
450     # taken from /etc/portage/patches/<CATEGORY>/<PF|P|PN>/, where the first
451     # of these three directories to exist will be the one to use, ignoring
452     # any more general directories which might exist as well.
453     #
454     # User patches are intended for quick testing of patches without ebuild
455     # modifications, as well as for permanent customizations a user might
456     # desire. Obviously, there can be no official support for arbitrarily
457     # patched ebuilds. So whenever a build log in a bug report mentions that
458     # user patches were applied, the user should be asked to reproduce the
459     # problem without these.
460     #
461     # Not all ebuilds do call this function, so placing patches in the
462     # stated directory might or might not work, depending on the package and
463     # the eclasses it inherits and uses. It is safe to call the function
464     # repeatedly, so it is always possible to add a call at the ebuild
465     # level. The first call is the time when the patches will be
466     # applied.
467     #
468     # Ideally, this function should be called after gentoo-specific patches
469     # have been applied, so that their code can be modified as well, but
470     # before calls to e.g. eautoreconf, as the user patches might affect
471     # autotool input files as well.
472 vapier 1.318 epatch_user() {
473     [[ $# -ne 0 ]] && die "epatch_user takes no options"
474    
475 vapier 1.361 # Allow multiple calls to this function; ignore all but the first
476 vapier 1.362 local applied="${T}/epatch_user.applied"
477 vapier 1.361 [[ -e ${applied} ]] && return 2
478    
479 vapier 1.318 # don't clobber any EPATCH vars that the parent might want
480 zmedico 1.323 local EPATCH_SOURCE check base=${PORTAGE_CONFIGROOT%/}/etc/portage/patches
481 vapier 1.318 for check in {${CATEGORY}/${PF},${CATEGORY}/${P},${CATEGORY}/${PN}}; do
482     EPATCH_SOURCE=${base}/${CTARGET}/${check}
483     [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${base}/${CHOST}/${check}
484     [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${base}/${check}
485     if [[ -d ${EPATCH_SOURCE} ]] ; then
486     EPATCH_SOURCE=${EPATCH_SOURCE} \
487     EPATCH_SUFFIX="patch" \
488     EPATCH_FORCE="yes" \
489     EPATCH_MULTI_MSG="Applying user patches from ${EPATCH_SOURCE} ..." \
490     epatch
491 vapier 1.361 echo "${EPATCH_SOURCE}" > "${applied}"
492 vapier 1.349 return 0
493 vapier 1.318 fi
494     done
495 vapier 1.361 echo "none" > "${applied}"
496 vapier 1.349 return 1
497 vapier 1.318 }
498 azarah 1.26
499 vapier 1.283 # @FUNCTION: emktemp
500     # @USAGE: [temp dir]
501     # @DESCRIPTION:
502 vapier 1.52 # Cheap replacement for when debianutils (and thus mktemp)
503 vapier 1.283 # does not exist on the users system.
504 vapier 1.117 emktemp() {
505 vapier 1.119 local exe="touch"
506 vapier 1.194 [[ $1 == -d ]] && exe="mkdir" && shift
507     local topdir=$1
508 mr_bones_ 1.100
509 vapier 1.194 if [[ -z ${topdir} ]] ; then
510     [[ -z ${T} ]] \
511 vapier 1.117 && topdir="/tmp" \
512 vapier 1.194 || topdir=${T}
513 vapier 1.117 fi
514    
515 vapier 1.280 if ! type -P mktemp > /dev/null ; then
516     # system lacks `mktemp` so we have to fake it
517 vapier 1.117 local tmp=/
518 vapier 1.194 while [[ -e ${tmp} ]] ; do
519     tmp=${topdir}/tmp.${RANDOM}.${RANDOM}.${RANDOM}
520 vapier 1.117 done
521 vapier 1.194 ${exe} "${tmp}" || ${exe} -p "${tmp}"
522 vapier 1.117 echo "${tmp}"
523 vapier 1.52 else
524 vapier 1.280 # the args here will give slightly wierd names on BSD,
525     # but should produce a usable file on all userlands
526 flameeyes 1.223 if [[ ${exe} == "touch" ]] ; then
527 vapier 1.280 TMPDIR="${topdir}" mktemp -t tmp.XXXXXXXXXX
528 flameeyes 1.223 else
529 vapier 1.280 TMPDIR="${topdir}" mktemp -dt tmp.XXXXXXXXXX
530 flameeyes 1.223 fi
531 vapier 1.52 fi
532     }
533    
534 vapier 1.283 # @FUNCTION: egetent
535     # @USAGE: <database> <key>
536     # @MAINTAINER:
537     # base-system@gentoo.org (Linux)
538     # Joe Jezak <josejx@gmail.com> (OS X)
539     # usata@gentoo.org (OS X)
540     # Aaron Walker <ka0ttic@gentoo.org> (FreeBSD)
541     # @DESCRIPTION:
542 grobian 1.310 # Small wrapper for getent (Linux),
543     # nidump (< Mac OS X 10.5), dscl (Mac OS X 10.5),
544 ka0ttic 1.108 # and pw (FreeBSD) used in enewuser()/enewgroup()
545 usata 1.91 egetent() {
546 flameeyes 1.205 case ${CHOST} in
547 grobian 1.319 *-darwin[678])
548 grobian 1.310 case "$2" in
549     *[!0-9]*) # Non numeric
550 betelgeuse 1.357 nidump $1 . | awk -F":" "{ if (\$1 ~ /^$2\$/) {print \$0;exit;} }"
551 grobian 1.310 ;;
552     *) # Numeric
553 grobian 1.319 nidump $1 . | awk -F":" "{ if (\$3 == $2) {print \$0;exit;} }"
554 grobian 1.310 ;;
555     esac
556     ;;
557 flameeyes 1.205 *-darwin*)
558 grobian 1.319 local mytype=$1
559     [[ "passwd" == $mytype ]] && mytype="Users"
560     [[ "group" == $mytype ]] && mytype="Groups"
561 usata 1.91 case "$2" in
562 flameeyes 1.205 *[!0-9]*) # Non numeric
563 grobian 1.319 dscl . -read /$mytype/$2 2>/dev/null |grep RecordName
564 usata 1.91 ;;
565 flameeyes 1.205 *) # Numeric
566 grobian 1.319 local mykey="UniqueID"
567     [[ $mytype == "Groups" ]] && mykey="PrimaryGroupID"
568     dscl . -search /$mytype $mykey $2 2>/dev/null
569 usata 1.91 ;;
570     esac
571 flameeyes 1.205 ;;
572 flameeyes 1.220 *-freebsd*|*-dragonfly*)
573 ka0ttic 1.203 local opts action="user"
574     [[ $1 == "passwd" ]] || action="group"
575    
576     # lookup by uid/gid
577     if [[ $2 == [[:digit:]]* ]] ; then
578     [[ ${action} == "user" ]] && opts="-u" || opts="-g"
579 ka0ttic 1.108 fi
580 ka0ttic 1.203
581     pw show ${action} ${opts} "$2" -q
582 flameeyes 1.205 ;;
583 flameeyes 1.218 *-netbsd*|*-openbsd*)
584 flameeyes 1.206 grep "$2:\*:" /etc/$1
585     ;;
586 flameeyes 1.205 *)
587     type -p nscd >& /dev/null && nscd -i "$1"
588 vapier 1.107 getent "$1" "$2"
589 flameeyes 1.205 ;;
590     esac
591 usata 1.91 }
592    
593 vapier 1.283 # @FUNCTION: enewuser
594     # @USAGE: <user> [uid] [shell] [homedir] [groups] [params]
595     # @DESCRIPTION:
596     # Same as enewgroup, you are not required to understand how to properly add
597     # a user to the system. The only required parameter is the username.
598     # Default uid is (pass -1 for this) next available, default shell is
599     # /bin/false, default homedir is /dev/null, there are no default groups,
600     # and default params sets the comment as 'added by portage for ${PN}'.
601 vapier 1.23 enewuser() {
602 vapier 1.233 case ${EBUILD_PHASE} in
603     unpack|compile|test|install)
604     eerror "'enewuser()' called from '${EBUILD_PHASE}()' which is not a pkg_* function."
605     eerror "Package fails at QA and at life. Please file a bug."
606     die "Bad package! enewuser is only for use in pkg_* functions!"
607     esac
608    
609 vapier 1.23 # get the username
610 vapier 1.182 local euser=$1; shift
611     if [[ -z ${euser} ]] ; then
612 vapier 1.23 eerror "No username specified !"
613     die "Cannot call enewuser without a username"
614     fi
615    
616 vapier 1.84 # lets see if the username already exists
617 agriffis 1.256 if [[ -n $(egetent passwd "${euser}") ]] ; then
618 vapier 1.23 return 0
619     fi
620 wolf31o2 1.44 einfo "Adding user '${euser}' to your system ..."
621 vapier 1.23
622     # options to pass to useradd
623 azarah 1.59 local opts=
624 vapier 1.23
625     # handle uid
626 vapier 1.182 local euid=$1; shift
627 agriffis 1.256 if [[ -n ${euid} && ${euid} != -1 ]] ; then
628 vapier 1.182 if [[ ${euid} -gt 0 ]] ; then
629 agriffis 1.256 if [[ -n $(egetent passwd ${euid}) ]] ; then
630 vapier 1.84 euid="next"
631 vapier 1.82 fi
632 vapier 1.23 else
633     eerror "Userid given but is not greater than 0 !"
634     die "${euid} is not a valid UID"
635     fi
636     else
637 vapier 1.84 euid="next"
638     fi
639 vapier 1.182 if [[ ${euid} == "next" ]] ; then
640 agriffis 1.256 for ((euid = 101; euid <= 999; euid++)); do
641 vapier 1.182 [[ -z $(egetent passwd ${euid}) ]] && break
642 vapier 1.84 done
643 vapier 1.23 fi
644 vapier 1.84 opts="${opts} -u ${euid}"
645 vapier 1.23 einfo " - Userid: ${euid}"
646    
647     # handle shell
648 vapier 1.182 local eshell=$1; shift
649     if [[ ! -z ${eshell} ]] && [[ ${eshell} != "-1" ]] ; then
650 vapier 1.221 if [[ ! -e ${ROOT}${eshell} ]] ; then
651 vapier 1.23 eerror "A shell was specified but it does not exist !"
652 vapier 1.221 die "${eshell} does not exist in ${ROOT}"
653     fi
654     if [[ ${eshell} == */false || ${eshell} == */nologin ]] ; then
655     eerror "Do not specify ${eshell} yourself, use -1"
656     die "Pass '-1' as the shell parameter"
657 vapier 1.23 fi
658     else
659 vapier 1.204 for shell in /sbin/nologin /usr/sbin/nologin /bin/false /usr/bin/false /dev/null ; do
660     [[ -x ${ROOT}${shell} ]] && break
661 flameeyes 1.198 done
662    
663 vapier 1.204 if [[ ${shell} == "/dev/null" ]] ; then
664 flameeyes 1.253 eerror "Unable to identify the shell to use, proceeding with userland default."
665     case ${USERLAND} in
666     GNU) shell="/bin/false" ;;
667     BSD) shell="/sbin/nologin" ;;
668     Darwin) shell="/usr/sbin/nologin" ;;
669     *) die "Unable to identify the default shell for userland ${USERLAND}"
670     esac
671 flameeyes 1.198 fi
672    
673     eshell=${shell}
674 vapier 1.23 fi
675     einfo " - Shell: ${eshell}"
676     opts="${opts} -s ${eshell}"
677    
678     # handle homedir
679 vapier 1.182 local ehome=$1; shift
680     if [[ -z ${ehome} ]] || [[ ${ehome} == "-1" ]] ; then
681 azarah 1.59 ehome="/dev/null"
682 vapier 1.23 fi
683     einfo " - Home: ${ehome}"
684     opts="${opts} -d ${ehome}"
685    
686     # handle groups
687 vapier 1.182 local egroups=$1; shift
688     if [[ ! -z ${egroups} ]] ; then
689     local oldifs=${IFS}
690 vapier 1.107 local defgroup="" exgroups=""
691    
692 vapier 1.23 export IFS=","
693 vapier 1.182 for g in ${egroups} ; do
694     export IFS=${oldifs}
695     if [[ -z $(egetent group "${g}") ]] ; then
696 vapier 1.85 eerror "You must add group ${g} to the system first"
697 vapier 1.23 die "${g} is not a valid GID"
698     fi
699 vapier 1.182 if [[ -z ${defgroup} ]] ; then
700     defgroup=${g}
701 vapier 1.107 else
702     exgroups="${exgroups},${g}"
703     fi
704 usata 1.115 export IFS=","
705 vapier 1.23 done
706 vapier 1.182 export IFS=${oldifs}
707 vapier 1.107
708     opts="${opts} -g ${defgroup}"
709 vapier 1.182 if [[ ! -z ${exgroups} ]] ; then
710 vapier 1.107 opts="${opts} -G ${exgroups:1}"
711     fi
712 vapier 1.23 else
713     egroups="(none)"
714     fi
715     einfo " - Groups: ${egroups}"
716    
717     # handle extra and add the user
718 vapier 1.182 local oldsandbox=${SANDBOX_ON}
719 vapier 1.23 export SANDBOX_ON="0"
720 flameeyes 1.205 case ${CHOST} in
721     *-darwin*)
722 usata 1.91 ### Make the user
723 vapier 1.182 if [[ -z $@ ]] ; then
724 usata 1.91 dscl . create /users/${euser} uid ${euid}
725     dscl . create /users/${euser} shell ${eshell}
726     dscl . create /users/${euser} home ${ehome}
727     dscl . create /users/${euser} realname "added by portage for ${PN}"
728     ### Add the user to the groups specified
729 vapier 1.182 local oldifs=${IFS}
730 usata 1.115 export IFS=","
731 vapier 1.182 for g in ${egroups} ; do
732 usata 1.91 dscl . merge /groups/${g} users ${euser}
733     done
734 vapier 1.182 export IFS=${oldifs}
735 usata 1.91 else
736 vapier 1.182 einfo "Extra options are not supported on Darwin yet"
737 usata 1.91 einfo "Please report the ebuild along with the info below"
738 vapier 1.182 einfo "eextra: $@"
739 usata 1.91 die "Required function missing"
740     fi
741 vapier 1.182 ;;
742 flameeyes 1.220 *-freebsd*|*-dragonfly*)
743 vapier 1.182 if [[ -z $@ ]] ; then
744 ka0ttic 1.108 pw useradd ${euser} ${opts} \
745     -c "added by portage for ${PN}" \
746     die "enewuser failed"
747     else
748 vapier 1.182 einfo " - Extra: $@"
749 ka0ttic 1.108 pw useradd ${euser} ${opts} \
750 vapier 1.182 "$@" || die "enewuser failed"
751 ka0ttic 1.108 fi
752 vapier 1.182 ;;
753 flameeyes 1.207
754     *-netbsd*)
755     if [[ -z $@ ]] ; then
756     useradd ${opts} ${euser} || die "enewuser failed"
757     else
758     einfo " - Extra: $@"
759     useradd ${opts} ${euser} "$@" || die "enewuser failed"
760     fi
761     ;;
762 flameeyes 1.218
763     *-openbsd*)
764     if [[ -z $@ ]] ; then
765     useradd -u ${euid} -s ${eshell} \
766     -d ${ehome} -c "Added by portage for ${PN}" \
767     -g ${egroups} ${euser} || die "enewuser failed"
768     else
769     einfo " - Extra: $@"
770     useradd -u ${euid} -s ${eshell} \
771     -d ${ehome} -c "Added by portage for ${PN}" \
772     -g ${egroups} ${euser} "$@" || die "enewuser failed"
773     fi
774     ;;
775    
776 vapier 1.182 *)
777     if [[ -z $@ ]] ; then
778 cardoe 1.345 useradd -r ${opts} \
779 usata 1.91 -c "added by portage for ${PN}" \
780 grobian 1.321 ${euser} \
781 usata 1.91 || die "enewuser failed"
782     else
783 vapier 1.182 einfo " - Extra: $@"
784 cardoe 1.345 useradd -r ${opts} "$@" \
785 grobian 1.321 ${euser} \
786 usata 1.91 || die "enewuser failed"
787     fi
788 vapier 1.182 ;;
789     esac
790 vapier 1.23
791 vapier 1.193 if [[ ! -e ${ROOT}/${ehome} ]] ; then
792     einfo " - Creating ${ehome} in ${ROOT}"
793     mkdir -p "${ROOT}/${ehome}"
794     chown ${euser} "${ROOT}/${ehome}"
795     chmod 755 "${ROOT}/${ehome}"
796 vapier 1.23 fi
797 vapier 1.193
798     export SANDBOX_ON=${oldsandbox}
799 vapier 1.23 }
800    
801 vapier 1.283 # @FUNCTION: enewgroup
802     # @USAGE: <group> [gid]
803     # @DESCRIPTION:
804     # This function does not require you to understand how to properly add a
805     # group to the system. Just give it a group name to add and enewgroup will
806     # do the rest. You may specify the gid for the group or allow the group to
807     # allocate the next available one.
808 vapier 1.23 enewgroup() {
809 vapier 1.233 case ${EBUILD_PHASE} in
810     unpack|compile|test|install)
811     eerror "'enewgroup()' called from '${EBUILD_PHASE}()' which is not a pkg_* function."
812     eerror "Package fails at QA and at life. Please file a bug."
813     die "Bad package! enewgroup is only for use in pkg_* functions!"
814     esac
815    
816 vapier 1.23 # get the group
817     local egroup="$1"; shift
818 azarah 1.59 if [ -z "${egroup}" ]
819     then
820 vapier 1.23 eerror "No group specified !"
821     die "Cannot call enewgroup without a group"
822     fi
823    
824     # see if group already exists
825 agriffis 1.256 if [[ -n $(egetent group "${egroup}") ]]; then
826 vapier 1.23 return 0
827     fi
828 wolf31o2 1.44 einfo "Adding group '${egroup}' to your system ..."
829 vapier 1.23
830     # options to pass to useradd
831 azarah 1.59 local opts=
832 vapier 1.23
833     # handle gid
834     local egid="$1"; shift
835 azarah 1.59 if [ ! -z "${egid}" ]
836     then
837     if [ "${egid}" -gt 0 ]
838     then
839 usata 1.91 if [ -z "`egetent group ${egid}`" ]
840 vapier 1.83 then
841 flameeyes 1.205 if [[ "${CHOST}" == *-darwin* ]]; then
842 usata 1.91 opts="${opts} ${egid}"
843     else
844     opts="${opts} -g ${egid}"
845     fi
846 vapier 1.83 else
847 vapier 1.84 egid="next available; requested gid taken"
848 vapier 1.83 fi
849 vapier 1.23 else
850     eerror "Groupid given but is not greater than 0 !"
851     die "${egid} is not a valid GID"
852     fi
853     else
854     egid="next available"
855     fi
856     einfo " - Groupid: ${egid}"
857    
858     # handle extra
859     local eextra="$@"
860     opts="${opts} ${eextra}"
861    
862     # add the group
863 azarah 1.59 local oldsandbox="${SANDBOX_ON}"
864 vapier 1.23 export SANDBOX_ON="0"
865 flameeyes 1.205 case ${CHOST} in
866     *-darwin*)
867 usata 1.91 if [ ! -z "${eextra}" ];
868     then
869 vapier 1.179 einfo "Extra options are not supported on Darwin/OS X yet"
870 usata 1.91 einfo "Please report the ebuild along with the info below"
871     einfo "eextra: ${eextra}"
872     die "Required function missing"
873     fi
874 mr_bones_ 1.100
875 usata 1.91 # If we need the next available
876     case ${egid} in
877 flameeyes 1.205 *[!0-9]*) # Non numeric
878 agriffis 1.256 for ((egid = 101; egid <= 999; egid++)); do
879     [[ -z $(egetent group ${egid}) ]] && break
880 usata 1.91 done
881     esac
882     dscl . create /groups/${egroup} gid ${egid}
883 mr_bones_ 1.100 dscl . create /groups/${egroup} passwd '*'
884 flameeyes 1.205 ;;
885    
886 flameeyes 1.220 *-freebsd*|*-dragonfly*)
887 ka0ttic 1.108 case ${egid} in
888     *[!0-9]*) # Non numeric
889 agriffis 1.256 for ((egid = 101; egid <= 999; egid++)); do
890     [[ -z $(egetent group ${egid}) ]] && break
891 ka0ttic 1.108 done
892     esac
893     pw groupadd ${egroup} -g ${egid} || die "enewgroup failed"
894 flameeyes 1.205 ;;
895 flameeyes 1.206
896     *-netbsd*)
897     case ${egid} in
898     *[!0-9]*) # Non numeric
899 agriffis 1.256 for ((egid = 101; egid <= 999; egid++)); do
900     [[ -z $(egetent group ${egid}) ]] && break
901 flameeyes 1.206 done
902     esac
903 flameeyes 1.207 groupadd -g ${egid} ${egroup} || die "enewgroup failed"
904 flameeyes 1.206 ;;
905    
906 flameeyes 1.205 *)
907 cardoe 1.345 # We specify -r so that we get a GID in the system range from login.defs
908     groupadd -r ${opts} ${egroup} || die "enewgroup failed"
909 flameeyes 1.205 ;;
910     esac
911 vapier 1.23 export SANDBOX_ON="${oldsandbox}"
912 vapier 1.24 }
913    
914 vapier 1.283 # @FUNCTION: edos2unix
915     # @USAGE: <file> [more files ...]
916     # @DESCRIPTION:
917     # A handy replacement for dos2unix, recode, fixdos, etc... This allows you
918     # to remove all of these text utilities from DEPEND variables because this
919     # is a script based solution. Just give it a list of files to convert and
920     # they will all be changed from the DOS CRLF format to the UNIX LF format.
921 vapier 1.24 edos2unix() {
922 vapier 1.366 [[ $# -eq 0 ]] && return 0
923     sed -i 's/\r$//' -- "$@" || die
924 vapier 1.39 }
925    
926     # Make a desktop file !
927     # Great for making those icons in kde/gnome startmenu !
928 flameeyes 1.266 # Amaze your friends ! Get the women ! Join today !
929 vapier 1.39 #
930 vapier 1.341 # make_desktop_entry(<command>, [name], [icon], [type], [fields])
931 vapier 1.39 #
932 tupone 1.238 # binary: what command does the app run with ?
933 vapier 1.39 # name: the name that will show up in the menu
934     # icon: give your little like a pretty little icon ...
935 vapier 1.118 # this can be relative (to /usr/share/pixmaps) or
936     # a full path to an icon
937 flameeyes 1.266 # type: what kind of application is this ? for categories:
938 vapier 1.284 # http://standards.freedesktop.org/menu-spec/latest/apa.html
939 vapier 1.341 # fields: extra fields to append to the desktop file; a printf string
940 vapier 1.39 make_desktop_entry() {
941 vapier 1.341 [[ -z $1 ]] && die "make_desktop_entry: You must specify the executable"
942 vapier 1.39
943 vapier 1.158 local exec=${1}
944     local name=${2:-${PN}}
945 wolf31o2 1.293 local icon=${3:-${PN}}
946 vapier 1.158 local type=${4}
947 vapier 1.341 local fields=${5}
948 vapier 1.158
949     if [[ -z ${type} ]] ; then
950     local catmaj=${CATEGORY%%-*}
951     local catmin=${CATEGORY##*-}
952     case ${catmaj} in
953     app)
954     case ${catmin} in
955 vapier 1.284 accessibility) type=Accessibility;;
956 vapier 1.338 admin) type=System;;
957     antivirus) type=System;;
958     arch) type=Archiving;;
959     backup) type=Archiving;;
960     cdr) type=DiscBurning;;
961     dicts) type=Dictionary;;
962     doc) type=Documentation;;
963     editors) type=TextEditor;;
964     emacs) type=TextEditor;;
965     emulation) type=Emulator;;
966     laptop) type=HardwareSettings;;
967     office) type=Office;;
968     pda) type=PDA;;
969     vim) type=TextEditor;;
970     xemacs) type=TextEditor;;
971 vapier 1.158 esac
972 azarah 1.59 ;;
973 vapier 1.158
974     dev)
975 vapier 1.159 type="Development"
976 vapier 1.158 ;;
977    
978     games)
979     case ${catmin} in
980 wolf31o2 1.265 action|fps) type=ActionGame;;
981 vapier 1.338 arcade) type=ArcadeGame;;
982     board) type=BoardGame;;
983     emulation) type=Emulator;;
984     kids) type=KidsGame;;
985     puzzle) type=LogicGame;;
986     roguelike) type=RolePlaying;;
987     rpg) type=RolePlaying;;
988 vapier 1.158 simulation) type=Simulation;;
989 vapier 1.338 sports) type=SportsGame;;
990     strategy) type=StrategyGame;;
991 vapier 1.158 esac
992 vapier 1.159 type="Game;${type}"
993 vapier 1.158 ;;
994    
995 vapier 1.284 gnome)
996     type="Gnome;GTK"
997     ;;
998    
999     kde)
1000     type="KDE;Qt"
1001     ;;
1002    
1003 vapier 1.158 mail)
1004 vapier 1.159 type="Network;Email"
1005 vapier 1.158 ;;
1006    
1007     media)
1008     case ${catmin} in
1009 vapier 1.339 gfx)
1010     type=Graphics
1011     ;;
1012     *)
1013     case ${catmin} in
1014     radio) type=Tuner;;
1015     sound) type=Audio;;
1016     tv) type=TV;;
1017     video) type=Video;;
1018     esac
1019     type="AudioVideo;${type}"
1020     ;;
1021 vapier 1.158 esac
1022 wolf31o2 1.65 ;;
1023 vapier 1.158
1024     net)
1025     case ${catmin} in
1026     dialup) type=Dialup;;
1027 vapier 1.338 ftp) type=FileTransfer;;
1028     im) type=InstantMessaging;;
1029     irc) type=IRCClient;;
1030     mail) type=Email;;
1031     news) type=News;;
1032     nntp) type=News;;
1033     p2p) type=FileTransfer;;
1034     voip) type=Telephony;;
1035 vapier 1.158 esac
1036 vapier 1.159 type="Network;${type}"
1037 vapier 1.158 ;;
1038    
1039     sci)
1040     case ${catmin} in
1041 vapier 1.284 astro*) type=Astronomy;;
1042 vapier 1.338 bio*) type=Biology;;
1043     calc*) type=Calculator;;
1044     chem*) type=Chemistry;;
1045 vapier 1.284 elec*) type=Electronics;;
1046 vapier 1.338 geo*) type=Geology;;
1047     math*) type=Math;;
1048 vapier 1.284 physics) type=Physics;;
1049     visual*) type=DataVisualization;;
1050 vapier 1.159 esac
1051 abcd 1.336 type="Education;Science;${type}"
1052 vapier 1.158 ;;
1053    
1054 vapier 1.284 sys)
1055     type="System"
1056     ;;
1057    
1058 vapier 1.158 www)
1059     case ${catmin} in
1060     client) type=WebBrowser;;
1061     esac
1062 abcd 1.336 type="Network;${type}"
1063 azarah 1.59 ;;
1064 vapier 1.158
1065 azarah 1.59 *)
1066     type=
1067     ;;
1068 vapier 1.39 esac
1069     fi
1070 carlo 1.177 if [ "${SLOT}" == "0" ] ; then
1071     local desktop_name="${PN}"
1072     else
1073     local desktop_name="${PN}-${SLOT}"
1074     fi
1075 vapier 1.272 local desktop="${T}/$(echo ${exec} | sed 's:[[:space:]/:]:_:g')-${desktop_name}.desktop"
1076 vapier 1.271 #local desktop=${T}/${exec%% *:-${desktop_name}}.desktop
1077 vapier 1.39
1078 abcd 1.336 # Don't append another ";" when a valid category value is provided.
1079     type=${type%;}${type:+;}
1080    
1081     eshopts_push -s extglob
1082     if [[ -n ${icon} && ${icon} != /* ]] && [[ ${icon} == *.xpm || ${icon} == *.png || ${icon} == *.svg ]]; then
1083     ewarn "As described in the Icon Theme Specification, icon file extensions are not"
1084     ewarn "allowed in .desktop files if the value is not an absolute path."
1085     icon=${icon%.@(xpm|png|svg)}
1086     fi
1087     eshopts_pop
1088    
1089 vapier 1.271 cat <<-EOF > "${desktop}"
1090     [Desktop Entry]
1091     Name=${name}
1092     Type=Application
1093     Comment=${DESCRIPTION}
1094     Exec=${exec}
1095     TryExec=${exec%% *}
1096     Icon=${icon}
1097 abcd 1.336 Categories=${type}
1098 vapier 1.271 EOF
1099 vapier 1.39
1100 vapier 1.341 if [[ ${fields:-=} != *=* ]] ; then
1101     # 5th arg used to be value to Path=
1102     ewarn "make_desktop_entry: update your 5th arg to read Path=${fields}"
1103     fields="Path=${fields}"
1104     fi
1105 vapier 1.342 [[ -n ${fields} ]] && printf '%b\n' "${fields}" >> "${desktop}"
1106 wolf31o2 1.293
1107 vapier 1.204 (
1108     # wrap the env here so that the 'insinto' call
1109     # doesn't corrupt the env of the caller
1110     insinto /usr/share/applications
1111     doins "${desktop}"
1112 vapier 1.340 ) || die "installing desktop file failed"
1113 danarmak 1.32 }
1114    
1115 vapier 1.283 # @FUNCTION: validate_desktop_entries
1116     # @USAGE: [directories]
1117     # @MAINTAINER:
1118     # Carsten Lohrke <carlo@gentoo.org>
1119     # @DESCRIPTION:
1120 carlo 1.278 # Validate desktop entries using desktop-file-utils
1121 carlo 1.277 validate_desktop_entries() {
1122     if [[ -x /usr/bin/desktop-file-validate ]] ; then
1123     einfo "Checking desktop entry validity"
1124     local directories=""
1125 carlo 1.279 for d in /usr/share/applications $@ ; do
1126     [[ -d ${D}${d} ]] && directories="${directories} ${D}${d}"
1127 carlo 1.277 done
1128 carlo 1.279 if [[ -n ${directories} ]] ; then
1129     for FILE in $(find ${directories} -name "*\.desktop" \
1130     -not -path '*.hidden*' | sort -u 2>/dev/null)
1131     do
1132     local temp=$(desktop-file-validate ${FILE} | grep -v "warning:" | \
1133     sed -e "s|error: ||" -e "s|${FILE}:|--|g" )
1134     [[ -n $temp ]] && elog ${temp/--/${FILE/${D}/}:}
1135     done
1136     fi
1137 carlo 1.277 echo ""
1138     else
1139     einfo "Passing desktop entry validity check. Install dev-util/desktop-file-utils, if you want to help to improve Gentoo."
1140     fi
1141     }
1142    
1143 vapier 1.283 # @FUNCTION: make_session_desktop
1144 vapier 1.314 # @USAGE: <title> <command> [command args...]
1145 vapier 1.283 # @DESCRIPTION:
1146     # Make a GDM/KDM Session file. The title is the file to execute to start the
1147     # Window Manager. The command is the name of the Window Manager.
1148 vapier 1.314 #
1149     # You can set the name of the file via the ${wm} variable.
1150 lanius 1.133 make_session_desktop() {
1151 vapier 1.314 [[ -z $1 ]] && eerror "$0: You must specify the title" && return 1
1152     [[ -z $2 ]] && eerror "$0: You must specify the command" && return 1
1153 lanius 1.133
1154 vapier 1.167 local title=$1
1155     local command=$2
1156 vapier 1.314 local desktop=${T}/${wm:-${PN}}.desktop
1157     shift 2
1158 lanius 1.133
1159 vapier 1.271 cat <<-EOF > "${desktop}"
1160     [Desktop Entry]
1161     Name=${title}
1162     Comment=This session logs you into ${title}
1163 vapier 1.314 Exec=${command} $*
1164 vapier 1.271 TryExec=${command}
1165 vapier 1.314 Type=XSession
1166 vapier 1.271 EOF
1167 lanius 1.133
1168 vapier 1.271 (
1169     # wrap the env here so that the 'insinto' call
1170     # doesn't corrupt the env of the caller
1171 lanius 1.133 insinto /usr/share/xsessions
1172     doins "${desktop}"
1173 vapier 1.271 )
1174 lanius 1.133 }
1175    
1176 vapier 1.283 # @FUNCTION: domenu
1177     # @USAGE: <menus>
1178     # @DESCRIPTION:
1179     # Install the list of .desktop menu files into the appropriate directory
1180     # (/usr/share/applications).
1181 lanius 1.133 domenu() {
1182 vapier 1.271 (
1183     # wrap the env here so that the 'insinto' call
1184     # doesn't corrupt the env of the caller
1185     local i j ret=0
1186 lanius 1.133 insinto /usr/share/applications
1187 vapier 1.167 for i in "$@" ; do
1188     if [[ -f ${i} ]] ; then
1189     doins "${i}"
1190 vapier 1.271 ((ret+=$?))
1191 vapier 1.167 elif [[ -d ${i} ]] ; then
1192     for j in "${i}"/*.desktop ; do
1193     doins "${j}"
1194 vapier 1.271 ((ret+=$?))
1195 lanius 1.133 done
1196 vapier 1.285 else
1197     ((++ret))
1198 swegener 1.190 fi
1199 lanius 1.133 done
1200 vapier 1.271 exit ${ret}
1201     )
1202 lanius 1.133 }
1203 vapier 1.283
1204     # @FUNCTION: newmenu
1205     # @USAGE: <menu> <newname>
1206     # @DESCRIPTION:
1207     # Like all other new* functions, install the specified menu as newname.
1208 vapier 1.167 newmenu() {
1209 vapier 1.271 (
1210     # wrap the env here so that the 'insinto' call
1211     # doesn't corrupt the env of the caller
1212 vapier 1.167 insinto /usr/share/applications
1213 vapier 1.271 newins "$@"
1214     )
1215 vapier 1.167 }
1216 lanius 1.133
1217 vapier 1.283 # @FUNCTION: doicon
1218     # @USAGE: <list of icons>
1219     # @DESCRIPTION:
1220     # Install the list of icons into the icon directory (/usr/share/pixmaps).
1221     # This is useful in conjunction with creating desktop/menu files.
1222 lanius 1.133 doicon() {
1223 vapier 1.271 (
1224     # wrap the env here so that the 'insinto' call
1225     # doesn't corrupt the env of the caller
1226     local i j ret
1227 lanius 1.133 insinto /usr/share/pixmaps
1228 vapier 1.167 for i in "$@" ; do
1229     if [[ -f ${i} ]] ; then
1230     doins "${i}"
1231 vapier 1.271 ((ret+=$?))
1232 vapier 1.167 elif [[ -d ${i} ]] ; then
1233     for j in "${i}"/*.png ; do
1234     doins "${j}"
1235 vapier 1.271 ((ret+=$?))
1236 lanius 1.133 done
1237 vapier 1.285 else
1238     ((++ret))
1239 swegener 1.190 fi
1240 lanius 1.133 done
1241 vapier 1.271 exit ${ret}
1242     )
1243 lanius 1.133 }
1244 vapier 1.283
1245     # @FUNCTION: newicon
1246     # @USAGE: <icon> <newname>
1247     # @DESCRIPTION:
1248     # Like all other new* functions, install the specified icon as newname.
1249 vapier 1.167 newicon() {
1250 vapier 1.271 (
1251     # wrap the env here so that the 'insinto' call
1252     # doesn't corrupt the env of the caller
1253 vapier 1.167 insinto /usr/share/pixmaps
1254 vapier 1.271 newins "$@"
1255     )
1256 vapier 1.167 }
1257 lanius 1.133
1258 vapier 1.70 # for internal use only (unpack_pdv and unpack_makeself)
1259     find_unpackable_file() {
1260 vapier 1.196 local src=$1
1261     if [[ -z ${src} ]] ; then
1262     src=${DISTDIR}/${A}
1263 vapier 1.50 else
1264 vapier 1.196 if [[ -e ${DISTDIR}/${src} ]] ; then
1265     src=${DISTDIR}/${src}
1266     elif [[ -e ${PWD}/${src} ]] ; then
1267     src=${PWD}/${src}
1268     elif [[ -e ${src} ]] ; then
1269     src=${src}
1270 vapier 1.50 fi
1271     fi
1272 vapier 1.196 [[ ! -e ${src} ]] && return 1
1273 vapier 1.70 echo "${src}"
1274     }
1275    
1276 vapier 1.283 # @FUNCTION: unpack_pdv
1277     # @USAGE: <file to unpack> <size of off_t>
1278     # @DESCRIPTION:
1279 vapier 1.70 # Unpack those pesky pdv generated files ...
1280     # They're self-unpacking programs with the binary package stuffed in
1281     # the middle of the archive. Valve seems to use it a lot ... too bad
1282     # it seems to like to segfault a lot :(. So lets take it apart ourselves.
1283 swegener 1.286 #
1284 vapier 1.283 # You have to specify the off_t size ... I have no idea how to extract that
1285     # information out of the binary executable myself. Basically you pass in
1286     # the size of the off_t type (in bytes) on the machine that built the pdv
1287     # archive.
1288 vapier 1.70 #
1289 vapier 1.283 # One way to determine this is by running the following commands:
1290 ulm 1.288 #
1291     # @CODE
1292     # strings <pdv archive> | grep lseek
1293     # strace -elseek <pdv archive>
1294     # @CODE
1295     #
1296 vapier 1.283 # Basically look for the first lseek command (we do the strings/grep because
1297     # sometimes the function call is _llseek or something) and steal the 2nd
1298     # parameter. Here is an example:
1299 ulm 1.288 #
1300     # @CODE
1301     # vapier@vapier 0 pdv_unpack # strings hldsupdatetool.bin | grep lseek
1302     # lseek
1303     # vapier@vapier 0 pdv_unpack # strace -elseek ./hldsupdatetool.bin
1304     # lseek(3, -4, SEEK_END) = 2981250
1305     # @CODE
1306     #
1307 vapier 1.283 # Thus we would pass in the value of '4' as the second parameter.
1308 vapier 1.70 unpack_pdv() {
1309 vapier 1.271 local src=$(find_unpackable_file "$1")
1310 vapier 1.196 local sizeoff_t=$2
1311 vapier 1.70
1312 vapier 1.196 [[ -z ${src} ]] && die "Could not locate source for '$1'"
1313     [[ -z ${sizeoff_t} ]] && die "No idea what off_t size was used for this pdv :("
1314 vapier 1.70
1315 vapier 1.212 local shrtsrc=$(basename "${src}")
1316 vapier 1.70 echo ">>> Unpacking ${shrtsrc} to ${PWD}"
1317 vapier 1.271 local metaskip=$(tail -c ${sizeoff_t} "${src}" | hexdump -e \"%i\")
1318     local tailskip=$(tail -c $((${sizeoff_t}*2)) "${src}" | head -c ${sizeoff_t} | hexdump -e \"%i\")
1319 vapier 1.70
1320     # grab metadata for debug reasons
1321 vapier 1.271 local metafile=$(emktemp)
1322     tail -c +$((${metaskip}+1)) "${src}" > "${metafile}"
1323 vapier 1.70
1324     # rip out the final file name from the metadata
1325 vapier 1.271 local datafile=$(tail -c +$((${metaskip}+1)) "${src}" | strings | head -n 1)
1326     datafile=$(basename "${datafile}")
1327 vapier 1.70
1328 vapier 1.71 # now lets uncompress/untar the file if need be
1329 vapier 1.271 local tmpfile=$(emktemp)
1330 vapier 1.70 tail -c +$((${tailskip}+1)) ${src} 2>/dev/null | head -c 512 > ${tmpfile}
1331 vapier 1.71
1332 vapier 1.271 local iscompressed=$(file -b "${tmpfile}")
1333     if [[ ${iscompressed:0:8} == "compress" ]] ; then
1334 vapier 1.71 iscompressed=1
1335     mv ${tmpfile}{,.Z}
1336     gunzip ${tmpfile}
1337     else
1338     iscompressed=0
1339     fi
1340 vapier 1.271 local istar=$(file -b "${tmpfile}")
1341     if [[ ${istar:0:9} == "POSIX tar" ]] ; then
1342 vapier 1.71 istar=1
1343     else
1344     istar=0
1345     fi
1346    
1347     #for some reason gzip dies with this ... dd cant provide buffer fast enough ?
1348     #dd if=${src} ibs=${metaskip} count=1 \
1349     # | dd ibs=${tailskip} skip=1 \
1350     # | gzip -dc \
1351     # > ${datafile}
1352     if [ ${iscompressed} -eq 1 ] ; then
1353     if [ ${istar} -eq 1 ] ; then
1354     tail -c +$((${tailskip}+1)) ${src} 2>/dev/null \
1355     | head -c $((${metaskip}-${tailskip})) \
1356     | tar -xzf -
1357     else
1358 vapier 1.70 tail -c +$((${tailskip}+1)) ${src} 2>/dev/null \
1359     | head -c $((${metaskip}-${tailskip})) \
1360     | gzip -dc \
1361     > ${datafile}
1362 vapier 1.71 fi
1363     else
1364     if [ ${istar} -eq 1 ] ; then
1365     tail -c +$((${tailskip}+1)) ${src} 2>/dev/null \
1366     | head -c $((${metaskip}-${tailskip})) \
1367 vapier 1.73 | tar --no-same-owner -xf -
1368 vapier 1.71 else
1369 vapier 1.70 tail -c +$((${tailskip}+1)) ${src} 2>/dev/null \
1370     | head -c $((${metaskip}-${tailskip})) \
1371     > ${datafile}
1372 vapier 1.71 fi
1373     fi
1374     true
1375     #[ -s "${datafile}" ] || die "failure unpacking pdv ('${metaskip}' '${tailskip}' '${datafile}')"
1376 vapier 1.70 #assert "failure unpacking pdv ('${metaskip}' '${tailskip}' '${datafile}')"
1377     }
1378    
1379 vapier 1.283 # @FUNCTION: unpack_makeself
1380     # @USAGE: [file to unpack] [offset] [tail|dd]
1381     # @DESCRIPTION:
1382 vapier 1.70 # Unpack those pesky makeself generated files ...
1383     # They're shell scripts with the binary package tagged onto
1384     # the end of the archive. Loki utilized the format as does
1385     # many other game companies.
1386 swegener 1.286 #
1387 vapier 1.283 # If the file is not specified, then ${A} is used. If the
1388     # offset is not specified then we will attempt to extract
1389     # the proper offset from the script itself.
1390 vapier 1.70 unpack_makeself() {
1391 vapier 1.217 local src_input=${1:-${A}}
1392     local src=$(find_unpackable_file "${src_input}")
1393 vapier 1.196 local skip=$2
1394     local exe=$3
1395    
1396 vapier 1.217 [[ -z ${src} ]] && die "Could not locate source for '${src_input}'"
1397 vapier 1.50
1398 vapier 1.196 local shrtsrc=$(basename "${src}")
1399 vapier 1.41 echo ">>> Unpacking ${shrtsrc} to ${PWD}"
1400 vapier 1.212 if [[ -z ${skip} ]] ; then
1401 mr_bones_ 1.343 local ver=$(grep -m1 -a '#.*Makeself' "${src}" | awk '{print $NF}')
1402 vapier 1.41 local skip=0
1403 vapier 1.112 exe=tail
1404 vapier 1.41 case ${ver} in
1405 wolf31o2 1.240 1.5.*|1.6.0-nv) # tested 1.5.{3,4,5} ... guessing 1.5.x series is same
1406 vapier 1.112 skip=$(grep -a ^skip= "${src}" | cut -d= -f2)
1407 vapier 1.41 ;;
1408     2.0|2.0.1)
1409 vapier 1.112 skip=$(grep -a ^$'\t'tail "${src}" | awk '{print $2}' | cut -b2-)
1410 vapier 1.41 ;;
1411 wolf31o2 1.48 2.1.1)
1412 vapier 1.112 skip=$(grep -a ^offset= "${src}" | awk '{print $2}' | cut -b2-)
1413 vapier 1.344 (( skip++ ))
1414 wolf31o2 1.48 ;;
1415 vapier 1.49 2.1.2)
1416 vapier 1.112 skip=$(grep -a ^offset= "${src}" | awk '{print $3}' | head -n 1)
1417 vapier 1.344 (( skip++ ))
1418 vapier 1.49 ;;
1419 wolf31o2 1.48 2.1.3)
1420 vapier 1.112 skip=`grep -a ^offset= "${src}" | awk '{print $3}'`
1421 vapier 1.344 (( skip++ ))
1422 vapier 1.41 ;;
1423 wolf31o2 1.211 2.1.4|2.1.5)
1424 vapier 1.112 skip=$(grep -a offset=.*head.*wc "${src}" | awk '{print $3}' | head -n 1)
1425     skip=$(head -n ${skip} "${src}" | wc -c)
1426     exe="dd"
1427     ;;
1428 vapier 1.41 *)
1429     eerror "I'm sorry, but I was unable to support the Makeself file."
1430     eerror "The version I detected was '${ver}'."
1431     eerror "Please file a bug about the file ${shrtsrc} at"
1432     eerror "http://bugs.gentoo.org/ so that support can be added."
1433     die "makeself version '${ver}' not supported"
1434     ;;
1435     esac
1436     debug-print "Detected Makeself version ${ver} ... using ${skip} as offset"
1437     fi
1438 vapier 1.112 case ${exe} in
1439     tail) exe="tail -n +${skip} '${src}'";;
1440 vapier 1.344 dd) exe="dd ibs=${skip} skip=1 if='${src}'";;
1441 vapier 1.112 *) die "makeself cant handle exe '${exe}'"
1442     esac
1443 vapier 1.41
1444 vapier 1.68 # lets grab the first few bytes of the file to figure out what kind of archive it is
1445 vapier 1.356 local filetype tmpfile=$(emktemp)
1446 vapier 1.112 eval ${exe} 2>/dev/null | head -c 512 > "${tmpfile}"
1447 vapier 1.356 filetype=$(file -b "${tmpfile}") || die
1448 vapier 1.68 case ${filetype} in
1449 vapier 1.257 *tar\ archive*)
1450 vapier 1.112 eval ${exe} | tar --no-same-owner -xf -
1451 vapier 1.68 ;;
1452     bzip2*)
1453 vapier 1.112 eval ${exe} | bzip2 -dc | tar --no-same-owner -xf -
1454 mr_bones_ 1.69 ;;
1455 vapier 1.68 gzip*)
1456 vapier 1.112 eval ${exe} | tar --no-same-owner -xzf -
1457 vapier 1.68 ;;
1458 vapier 1.93 compress*)
1459 vapier 1.112 eval ${exe} | gunzip | tar --no-same-owner -xf -
1460 vapier 1.93 ;;
1461 vapier 1.68 *)
1462 vapier 1.93 eerror "Unknown filetype \"${filetype}\" ?"
1463 vapier 1.68 false
1464     ;;
1465     esac
1466     assert "failure unpacking (${filetype}) makeself ${shrtsrc} ('${ver}' +${skip})"
1467 wolf31o2 1.56 }
1468    
1469 vapier 1.283 # @FUNCTION: check_license
1470     # @USAGE: [license]
1471     # @DESCRIPTION:
1472     # Display a license for user to accept. If no license is
1473     # specified, then ${LICENSE} is used.
1474 wolf31o2 1.56 check_license() {
1475 vapier 1.60 local lic=$1
1476     if [ -z "${lic}" ] ; then
1477     lic="${PORTDIR}/licenses/${LICENSE}"
1478 wolf31o2 1.56 else
1479 wolf31o2 1.199 if [ -e "${PORTDIR}/licenses/${lic}" ] ; then
1480     lic="${PORTDIR}/licenses/${lic}"
1481     elif [ -e "${PWD}/${lic}" ] ; then
1482     lic="${PWD}/${lic}"
1483     elif [ -e "${lic}" ] ; then
1484     lic="${lic}"
1485 wolf31o2 1.56 fi
1486     fi
1487 vapier 1.64 local l="`basename ${lic}`"
1488 wolf31o2 1.56
1489 vapier 1.60 # here is where we check for the licenses the user already
1490     # accepted ... if we don't find a match, we make the user accept
1491     local alic
1492 vapier 1.322 eshopts_push -o noglob # so that bash doesn't expand "*"
1493 wolf31o2 1.104 for alic in ${ACCEPT_LICENSE} ; do
1494 wolf31o2 1.255 if [[ ${alic} == ${l} ]]; then
1495 vapier 1.322 eshopts_pop
1496 wolf31o2 1.106 return 0
1497     fi
1498 vapier 1.60 done
1499 vapier 1.322 eshopts_pop
1500 zmedico 1.324 [ ! -f "${lic}" ] && die "Could not find requested license ${lic}"
1501 vapier 1.60
1502 vapier 1.271 local licmsg=$(emktemp)
1503     cat <<-EOF > ${licmsg}
1504     **********************************************************
1505     The following license outlines the terms of use of this
1506     package. You MUST accept this license for installation to
1507     continue. When you are done viewing, hit 'q'. If you
1508     CTRL+C out of this, the install will not run!
1509     **********************************************************
1510 swegener 1.286
1511 vapier 1.271 EOF
1512 vapier 1.60 cat ${lic} >> ${licmsg}
1513     ${PAGER:-less} ${licmsg} || die "Could not execute pager (${PAGER}) to accept ${lic}"
1514 vapier 1.64 einfon "Do you accept the terms of this license (${l})? [yes/no] "
1515 vapier 1.60 read alic
1516     case ${alic} in
1517     yes|Yes|y|Y)
1518     return 0
1519     ;;
1520     *)
1521     echo;echo;echo
1522     eerror "You MUST accept the license to continue! Exiting!"
1523     die "Failed to accept license"
1524     ;;
1525     esac
1526 vapier 1.23 }
1527 vapier 1.75
1528 vapier 1.283 # @FUNCTION: cdrom_get_cds
1529     # @USAGE: <file on cd1> [file on cd2] [file on cd3] [...]
1530     # @DESCRIPTION:
1531 vapier 1.75 # Aquire cd(s) for those lovely cd-based emerges. Yes, this violates
1532     # the whole 'non-interactive' policy, but damnit I want CD support !
1533 swegener 1.286 #
1534 vapier 1.283 # With these cdrom functions we handle all the user interaction and
1535     # standardize everything. All you have to do is call cdrom_get_cds()
1536 vapier 1.75 # and when the function returns, you can assume that the cd has been
1537     # found at CDROM_ROOT.
1538 swegener 1.286 #
1539 vapier 1.283 # The function will attempt to locate a cd based upon a file that is on
1540     # the cd. The more files you give this function, the more cds
1541     # the cdrom functions will handle.
1542 swegener 1.286 #
1543 vapier 1.283 # Normally the cdrom functions will refer to the cds as 'cd #1', 'cd #2',
1544     # etc... If you want to give the cds better names, then just export
1545 vapier 1.243 # the appropriate CDROM_NAME variable before calling cdrom_get_cds().
1546 vapier 1.283 # Use CDROM_NAME for one cd, or CDROM_NAME_# for multiple cds. You can
1547     # also use the CDROM_NAME_SET bash array.
1548 swegener 1.286 #
1549 vapier 1.283 # For those multi cd ebuilds, see the cdrom_load_next_cd() function.
1550 vapier 1.75 cdrom_get_cds() {
1551     # first we figure out how many cds we're dealing with by
1552     # the # of files they gave us
1553     local cdcnt=0
1554     local f=
1555     for f in "$@" ; do
1556 vapier 1.214 ((++cdcnt))
1557 vapier 1.75 export CDROM_CHECK_${cdcnt}="$f"
1558     done
1559     export CDROM_TOTAL_CDS=${cdcnt}
1560     export CDROM_CURRENT_CD=1
1561    
1562     # now we see if the user gave use CD_ROOT ...
1563     # if they did, let's just believe them that it's correct
1564 vapier 1.215 if [[ -n ${CD_ROOT}${CD_ROOT_1} ]] ; then
1565 vapier 1.75 local var=
1566     cdcnt=0
1567 vapier 1.131 while [[ ${cdcnt} -lt ${CDROM_TOTAL_CDS} ]] ; do
1568 vapier 1.214 ((++cdcnt))
1569 vapier 1.75 var="CD_ROOT_${cdcnt}"
1570 vapier 1.215 [[ -z ${!var} ]] && var="CD_ROOT"
1571 vapier 1.131 if [[ -z ${!var} ]] ; then
1572 vapier 1.75 eerror "You must either use just the CD_ROOT"
1573     eerror "or specify ALL the CD_ROOT_X variables."
1574     eerror "In this case, you will need ${CDROM_TOTAL_CDS} CD_ROOT_X variables."
1575     die "could not locate CD_ROOT_${cdcnt}"
1576     fi
1577     done
1578 vapier 1.215 export CDROM_ROOT=${CD_ROOT_1:-${CD_ROOT}}
1579 vapier 1.75 einfo "Found CD #${CDROM_CURRENT_CD} root at ${CDROM_ROOT}"
1580 vapier 1.215 export CDROM_SET=-1
1581     for f in ${CDROM_CHECK_1//:/ } ; do
1582     ((++CDROM_SET))
1583 cardoe 1.346 [[ -e ${CDROM_ROOT}/${f} ]] && break
1584 vapier 1.215 done
1585     export CDROM_MATCH=${f}
1586 vapier 1.75 return
1587     fi
1588    
1589 vapier 1.215 # User didn't help us out so lets make sure they know they can
1590     # simplify the whole process ...
1591 vapier 1.131 if [[ ${CDROM_TOTAL_CDS} -eq 1 ]] ; then
1592 vapier 1.215 einfo "This ebuild will need the ${CDROM_NAME:-cdrom for ${PN}}"
1593 vapier 1.75 echo
1594     einfo "If you do not have the CD, but have the data files"
1595     einfo "mounted somewhere on your filesystem, just export"
1596     einfo "the variable CD_ROOT so that it points to the"
1597     einfo "directory containing the files."
1598     echo
1599 vapier 1.132 einfo "For example:"
1600     einfo "export CD_ROOT=/mnt/cdrom"
1601     echo
1602 vapier 1.75 else
1603 vapier 1.243 if [[ -n ${CDROM_NAME_SET} ]] ; then
1604     # Translate the CDROM_NAME_SET array into CDROM_NAME_#
1605     cdcnt=0
1606     while [[ ${cdcnt} -lt ${CDROM_TOTAL_CDS} ]] ; do
1607     ((++cdcnt))
1608     export CDROM_NAME_${cdcnt}="${CDROM_NAME_SET[$((${cdcnt}-1))]}"
1609     done
1610     fi
1611    
1612 vapier 1.75 einfo "This package will need access to ${CDROM_TOTAL_CDS} cds."
1613     cdcnt=0
1614 vapier 1.131 while [[ ${cdcnt} -lt ${CDROM_TOTAL_CDS} ]] ; do
1615 vapier 1.214 ((++cdcnt))
1616 vapier 1.75 var="CDROM_NAME_${cdcnt}"
1617 vapier 1.131 [[ ! -z ${!var} ]] && einfo " CD ${cdcnt}: ${!var}"
1618 vapier 1.75 done
1619     echo
1620     einfo "If you do not have the CDs, but have the data files"
1621     einfo "mounted somewhere on your filesystem, just export"
1622     einfo "the following variables so they point to the right place:"
1623 nyhm 1.347 einfon ""
1624 vapier 1.75 cdcnt=0
1625 vapier 1.131 while [[ ${cdcnt} -lt ${CDROM_TOTAL_CDS} ]] ; do
1626 vapier 1.214 ((++cdcnt))
1627 vapier 1.75 echo -n " CD_ROOT_${cdcnt}"
1628     done
1629     echo
1630     einfo "Or, if you have all the files in the same place, or"
1631     einfo "you only have one cdrom, you can export CD_ROOT"
1632     einfo "and that place will be used as the same data source"
1633     einfo "for all the CDs."
1634     echo
1635 vapier 1.132 einfo "For example:"
1636     einfo "export CD_ROOT_1=/mnt/cdrom"
1637     echo
1638 vapier 1.75 fi
1639 vapier 1.215
1640 vapier 1.214 export CDROM_SET=""
1641 vapier 1.75 export CDROM_CURRENT_CD=0
1642     cdrom_load_next_cd
1643     }
1644    
1645 vapier 1.283 # @FUNCTION: cdrom_load_next_cd
1646     # @DESCRIPTION:
1647     # Some packages are so big they come on multiple CDs. When you're done reading
1648     # files off a CD and want access to the next one, just call this function.
1649     # Again, all the messy details of user interaction are taken care of for you.
1650     # Once this returns, just read the variable CDROM_ROOT for the location of the
1651     # mounted CD. Note that you can only go forward in the CD list, so make sure
1652     # you only call this function when you're done using the current CD.
1653 vapier 1.75 cdrom_load_next_cd() {
1654 vapier 1.215 local var
1655     ((++CDROM_CURRENT_CD))
1656 vapier 1.79
1657 vapier 1.75 unset CDROM_ROOT
1658 vapier 1.215 var=CD_ROOT_${CDROM_CURRENT_CD}
1659     [[ -z ${!var} ]] && var="CD_ROOT"
1660 vapier 1.131 if [[ -z ${!var} ]] ; then
1661 vapier 1.75 var="CDROM_CHECK_${CDROM_CURRENT_CD}"
1662 vapier 1.215 _cdrom_locate_file_on_cd ${!var}
1663 vapier 1.75 else
1664 vapier 1.131 export CDROM_ROOT=${!var}
1665 vapier 1.75 fi
1666    
1667     einfo "Found CD #${CDROM_CURRENT_CD} root at ${CDROM_ROOT}"
1668     }
1669    
1670     # this is used internally by the cdrom_get_cds() and cdrom_load_next_cd()
1671     # functions. this should *never* be called from an ebuild.
1672     # all it does is try to locate a give file on a cd ... if the cd isn't
1673     # found, then a message asking for the user to insert the cdrom will be
1674     # displayed and we'll hang out here until:
1675     # (1) the file is found on a mounted cdrom
1676     # (2) the user hits CTRL+C
1677 vapier 1.215 _cdrom_locate_file_on_cd() {
1678 vapier 1.214 local mline=""
1679 wolf31o2 1.296 local showedmsg=0 showjolietmsg=0
1680 vapier 1.214
1681 vapier 1.131 while [[ -z ${CDROM_ROOT} ]] ; do
1682 vapier 1.214 local i=0
1683     local -a cdset=(${*//:/ })
1684     if [[ -n ${CDROM_SET} ]] ; then
1685     cdset=(${cdset[${CDROM_SET}]})
1686     fi
1687    
1688     while [[ -n ${cdset[${i}]} ]] ; do
1689     local dir=$(dirname ${cdset[${i}]})
1690     local file=$(basename ${cdset[${i}]})
1691    
1692 uberlord 1.259 local point= node= fs= foo=
1693     while read point node fs foo ; do
1694 nyhm 1.281 [[ " cd9660 iso9660 udf " != *" ${fs} "* ]] && \
1695 uberlord 1.264 ! [[ ${fs} == "subfs" && ",${opts}," == *",fs=cdfss,"* ]] \
1696     && continue
1697 uberlord 1.259 point=${point//\040/ }
1698 vapier 1.292 [[ ! -d ${point}/${dir} ]] && continue
1699 uberlord 1.259 [[ -z $(find "${point}/${dir}" -maxdepth 1 -iname "${file}") ]] && continue
1700     export CDROM_ROOT=${point}
1701     export CDROM_SET=${i}
1702     export CDROM_MATCH=${cdset[${i}]}
1703     return
1704 kanaka 1.262 done <<< "$(get_mounts)"
1705 vapier 1.214
1706     ((++i))
1707 vapier 1.75 done
1708    
1709 vapier 1.214 echo
1710     if [[ ${showedmsg} -eq 0 ]] ; then
1711     if [[ ${CDROM_TOTAL_CDS} -eq 1 ]] ; then
1712     if [[ -z ${CDROM_NAME} ]] ; then
1713     einfo "Please insert+mount the cdrom for ${PN} now !"
1714     else
1715     einfo "Please insert+mount the ${CDROM_NAME} cdrom now !"
1716     fi
1717     else
1718     if [[ -z ${CDROM_NAME_1} ]] ; then
1719     einfo "Please insert+mount cd #${CDROM_CURRENT_CD} for ${PN} now !"
1720 vapier 1.75 else
1721 vapier 1.214 local var="CDROM_NAME_${CDROM_CURRENT_CD}"
1722     einfo "Please insert+mount the ${!var} cdrom now !"
1723 vapier 1.75 fi
1724     fi
1725 vapier 1.214 showedmsg=1
1726 vapier 1.75 fi
1727 vapier 1.214 einfo "Press return to scan for the cd again"
1728     einfo "or hit CTRL+C to abort the emerge."
1729     echo
1730 wolf31o2 1.296 if [[ ${showjolietmsg} -eq 0 ]] ; then
1731     showjolietmsg=1
1732     else
1733     ewarn "If you are having trouble with the detection"
1734     ewarn "of your CD, it is possible that you do not have"
1735     ewarn "Joliet support enabled in your kernel. Please"
1736     ewarn "check that CONFIG_JOLIET is enabled in your kernel."
1737     ebeep 5
1738     fi
1739 vapier 1.222 read || die "something is screwed with your system"
1740 vapier 1.75 done
1741     }
1742 vapier 1.92
1743 vapier 1.287 # @FUNCTION: strip-linguas
1744     # @USAGE: [<allow LINGUAS>|<-i|-u> <directories of .po files>]
1745     # @DESCRIPTION:
1746 mr_bones_ 1.100 # Make sure that LINGUAS only contains languages that
1747 vapier 1.287 # a package can support. The first form allows you to
1748     # specify a list of LINGUAS. The -i builds a list of po
1749     # files found in all the directories and uses the
1750     # intersection of the lists. The -u builds a list of po
1751     # files found in all the directories and uses the union
1752     # of the lists.
1753 vapier 1.92 strip-linguas() {
1754 vapier 1.242 local ls newls nols
1755 vapier 1.154 if [[ $1 == "-i" ]] || [[ $1 == "-u" ]] ; then
1756     local op=$1; shift
1757 vapier 1.315 ls=$(find "$1" -name '*.po' -exec basename {} .po ';'); shift
1758 vapier 1.92 local d f
1759     for d in "$@" ; do
1760 vapier 1.154 if [[ ${op} == "-u" ]] ; then
1761     newls=${ls}
1762 vapier 1.92 else
1763     newls=""
1764     fi
1765 vapier 1.315 for f in $(find "$d" -name '*.po' -exec basename {} .po ';') ; do
1766 vapier 1.154 if [[ ${op} == "-i" ]] ; then
1767 ssuominen 1.358 has ${f} ${ls} && newls="${newls} ${f}"
1768 vapier 1.92 else
1769 ssuominen 1.358 has ${f} ${ls} || newls="${newls} ${f}"
1770 vapier 1.92 fi
1771     done
1772 vapier 1.154 ls=${newls}
1773 vapier 1.92 done
1774     else
1775 vapier 1.236 ls="$@"
1776 vapier 1.92 fi
1777    
1778 vapier 1.242 nols=""
1779 vapier 1.92 newls=""
1780     for f in ${LINGUAS} ; do
1781 ssuominen 1.358 if has ${f} ${ls} ; then
1782 vapier 1.120 newls="${newls} ${f}"
1783 vapier 1.92 else
1784 vapier 1.242 nols="${nols} ${f}"
1785 vapier 1.92 fi
1786     done
1787 vapier 1.244 [[ -n ${nols} ]] \
1788 vapier 1.316 && ewarn "Sorry, but ${PN} does not support the LINGUAS:" ${nols}
1789 vapier 1.237 export LINGUAS=${newls:1}
1790 vapier 1.92 }
1791 iggy 1.110
1792 vapier 1.283 # @FUNCTION: preserve_old_lib
1793     # @USAGE: <libs to preserve> [more libs]
1794     # @DESCRIPTION:
1795     # These functions are useful when a lib in your package changes ABI SONAME.
1796     # An example might be from libogg.so.0 to libogg.so.1. Removing libogg.so.0
1797 eradicator 1.111 # would break packages that link against it. Most people get around this
1798     # by using the portage SLOT mechanism, but that is not always a relevant
1799 vapier 1.283 # solution, so instead you can call this from pkg_preinst. See also the
1800     # preserve_old_lib_notify function.
1801 eradicator 1.111 preserve_old_lib() {
1802 vapier 1.268 if [[ ${EBUILD_PHASE} != "preinst" ]] ; then
1803 vapier 1.267 eerror "preserve_old_lib() must be called from pkg_preinst() only"
1804 vapier 1.276 die "Invalid preserve_old_lib() usage"
1805 vapier 1.267 fi
1806     [[ -z $1 ]] && die "Usage: preserve_old_lib <library to preserve> [more libraries to preserve]"
1807    
1808 vapier 1.297 # let portage worry about it
1809     has preserve-libs ${FEATURES} && return 0
1810    
1811 vapier 1.267 local lib dir
1812     for lib in "$@" ; do
1813     [[ -e ${ROOT}/${lib} ]] || continue
1814     dir=${lib%/*}
1815     dodir ${dir} || die "dodir ${dir} failed"
1816     cp "${ROOT}"/${lib} "${D}"/${lib} || die "cp ${lib} failed"
1817     touch "${D}"/${lib}
1818     done
1819 eradicator 1.111 }
1820    
1821 vapier 1.283 # @FUNCTION: preserve_old_lib_notify
1822     # @USAGE: <libs to notify> [more libs]
1823     # @DESCRIPTION:
1824     # Spit helpful messages about the libraries preserved by preserve_old_lib.
1825 eradicator 1.111 preserve_old_lib_notify() {
1826 vapier 1.268 if [[ ${EBUILD_PHASE} != "postinst" ]] ; then
1827 vapier 1.267 eerror "preserve_old_lib_notify() must be called from pkg_postinst() only"
1828 vapier 1.276 die "Invalid preserve_old_lib_notify() usage"
1829 vapier 1.267 fi
1830    
1831 vapier 1.297 # let portage worry about it
1832     has preserve-libs ${FEATURES} && return 0
1833    
1834 vapier 1.267 local lib notice=0
1835     for lib in "$@" ; do
1836     [[ -e ${ROOT}/${lib} ]] || continue
1837     if [[ ${notice} -eq 0 ]] ; then
1838     notice=1
1839     ewarn "Old versions of installed libraries were detected on your system."
1840     ewarn "In order to avoid breaking packages that depend on these old libs,"
1841     ewarn "the libraries are not being removed. You need to run revdep-rebuild"
1842     ewarn "in order to remove these old dependencies. If you do not have this"
1843     ewarn "helper program, simply emerge the 'gentoolkit' package."
1844     ewarn
1845     fi
1846 vapier 1.355 # temp hack for #348634 #357225
1847     [[ ${PN} == "mpfr" ]] && lib=${lib##*/}
1848 vapier 1.352 ewarn " # revdep-rebuild --library '${lib}'"
1849 vapier 1.267 done
1850 vapier 1.291 if [[ ${notice} -eq 1 ]] ; then
1851     ewarn
1852     ewarn "Once you've finished running revdep-rebuild, it should be safe to"
1853 vapier 1.300 ewarn "delete the old libraries. Here is a copy & paste for the lazy:"
1854     for lib in "$@" ; do
1855     ewarn " # rm '${lib}'"
1856     done
1857 vapier 1.291 fi
1858 eradicator 1.111 }
1859 vapier 1.125
1860 vapier 1.283 # @FUNCTION: built_with_use
1861     # @USAGE: [--hidden] [--missing <action>] [-a|-o] <DEPEND ATOM> <List of USE flags>
1862     # @DESCRIPTION:
1863 betelgeuse 1.329 #
1864     # Deprecated: Use EAPI 2 use deps in DEPEND|RDEPEND and with has_version calls.
1865     #
1866 vapier 1.283 # A temporary hack until portage properly supports DEPENDing on USE
1867     # flags being enabled in packages. This will check to see if the specified
1868     # DEPEND atom was built with the specified list of USE flags. The
1869     # --missing option controls the behavior if called on a package that does
1870     # not actually support the defined USE flags (aka listed in IUSE).
1871     # The default is to abort (call die). The -a and -o flags control
1872     # the requirements of the USE flags. They correspond to "and" and "or"
1873     # logic. So the -a flag means all listed USE flags must be enabled
1874 opfer 1.302 # while the -o flag means at least one of the listed IUSE flags must be
1875 vapier 1.283 # enabled. The --hidden option is really for internal use only as it
1876     # means the USE flag we're checking is hidden expanded, so it won't be found
1877     # in IUSE like normal USE flags.
1878 swegener 1.286 #
1879 vapier 1.283 # Remember that this function isn't terribly intelligent so order of optional
1880     # flags matter.
1881 vapier 1.125 built_with_use() {
1882 vapier 1.275 local hidden="no"
1883     if [[ $1 == "--hidden" ]] ; then
1884     hidden="yes"
1885     shift
1886     fi
1887    
1888 vapier 1.269 local missing_action="die"
1889     if [[ $1 == "--missing" ]] ; then
1890     missing_action=$2
1891     shift ; shift
1892     case ${missing_action} in
1893     true|false|die) ;;
1894     *) die "unknown action '${missing_action}'";;
1895     esac
1896     fi
1897    
1898 vapier 1.130 local opt=$1
1899     [[ ${opt:0:1} = "-" ]] && shift || opt="-a"
1900    
1901     local PKG=$(best_version $1)
1902 vapier 1.247 [[ -z ${PKG} ]] && die "Unable to resolve $1 to an installed package"
1903 vapier 1.130 shift
1904    
1905 vapier 1.213 local USEFILE=${ROOT}/var/db/pkg/${PKG}/USE
1906 vapier 1.249 local IUSEFILE=${ROOT}/var/db/pkg/${PKG}/IUSE
1907 vapier 1.213
1908 cardoe 1.273 # if the IUSE file doesn't exist, the read will error out, we need to handle
1909     # this gracefully
1910 vapier 1.275 if [[ ! -e ${USEFILE} ]] || [[ ! -e ${IUSEFILE} && ${hidden} == "no" ]] ; then
1911 cardoe 1.273 case ${missing_action} in
1912     true) return 0;;
1913     false) return 1;;
1914     die) die "Unable to determine what USE flags $PKG was built with";;
1915     esac
1916     fi
1917    
1918 vapier 1.275 if [[ ${hidden} == "no" ]] ; then
1919 zmedico 1.301 local IUSE_BUILT=( $(<"${IUSEFILE}") )
1920 vapier 1.275 # Don't check USE_EXPAND #147237
1921     local expand
1922     for expand in $(echo ${USE_EXPAND} | tr '[:upper:]' '[:lower:]') ; do
1923     if [[ $1 == ${expand}_* ]] ; then
1924     expand=""
1925     break
1926     fi
1927     done
1928     if [[ -n ${expand} ]] ; then
1929 zmedico 1.301 if ! has $1 ${IUSE_BUILT[@]#[-+]} ; then
1930 vapier 1.275 case ${missing_action} in
1931     true) return 0;;
1932     false) return 1;;
1933     die) die "$PKG does not actually support the $1 USE flag!";;
1934     esac
1935     fi
1936 vapier 1.269 fi
1937 vapier 1.250 fi
1938 vapier 1.249
1939 vapier 1.125 local USE_BUILT=$(<${USEFILE})
1940 vapier 1.130 while [[ $# -gt 0 ]] ; do
1941     if [[ ${opt} = "-o" ]] ; then
1942     has $1 ${USE_BUILT} && return 0
1943     else
1944     has $1 ${USE_BUILT} || return 1
1945     fi
1946 vapier 1.125 shift
1947     done
1948 vapier 1.130 [[ ${opt} = "-a" ]]
1949 vapier 1.125 }
1950 vapier 1.126
1951 vapier 1.289 # @FUNCTION: epunt_cxx
1952 vapier 1.283 # @USAGE: [dir to scan]
1953     # @DESCRIPTION:
1954     # Many configure scripts wrongly bail when a C++ compiler could not be
1955     # detected. If dir is not specified, then it defaults to ${S}.
1956     #
1957     # http://bugs.gentoo.org/73450
1958 vapier 1.126 epunt_cxx() {
1959 vapier 1.127 local dir=$1
1960     [[ -z ${dir} ]] && dir=${S}
1961     ebegin "Removing useless C++ checks"
1962     local f
1963 vapier 1.294 find "${dir}" -name configure | while read f ; do
1964     patch --no-backup-if-mismatch -p0 "${f}" "${PORTDIR}/eclass/ELT-patches/nocxx/nocxx.patch" > /dev/null
1965 vapier 1.127 done
1966     eend 0
1967 vapier 1.126 }
1968 ka0ttic 1.143
1969 vapier 1.283 # @FUNCTION: make_wrapper
1970 wolf31o2 1.295 # @USAGE: <wrapper> <target> [chdir] [libpaths] [installpath]
1971 vapier 1.283 # @DESCRIPTION:
1972     # Create a shell wrapper script named wrapper in installpath
1973     # (defaults to the bindir) to execute target (default of wrapper) by
1974     # first optionally setting LD_LIBRARY_PATH to the colon-delimited
1975     # libpaths followed by optionally changing directory to chdir.
1976 wolf31o2 1.160 make_wrapper() {
1977 wolf31o2 1.164 local wrapper=$1 bin=$2 chdir=$3 libdir=$4 path=$5
1978 wolf31o2 1.160 local tmpwrapper=$(emktemp)
1979 vapier 1.202 # We don't want to quote ${bin} so that people can pass complex
1980     # things as $bin ... "./someprog --args"
1981 wolf31o2 1.160 cat << EOF > "${tmpwrapper}"
1982     #!/bin/sh
1983 vapier 1.201 cd "${chdir:-.}"
1984 vapier 1.210 if [ -n "${libdir}" ] ; then
1985     if [ "\${LD_LIBRARY_PATH+set}" = "set" ] ; then
1986     export LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}:${libdir}"
1987     else
1988     export LD_LIBRARY_PATH="${libdir}"
1989     fi
1990 vapier 1.201 fi
1991 vapier 1.202 exec ${bin} "\$@"
1992 wolf31o2 1.160 EOF
1993     chmod go+rx "${tmpwrapper}"
1994 vapier 1.201 if [[ -n ${path} ]] ; then
1995 vapier 1.283 (
1996 vapier 1.201 exeinto "${path}"
1997 wolf31o2 1.164 newexe "${tmpwrapper}" "${wrapper}"
1998 vapier 1.283 ) || die
1999 wolf31o2 1.164 else
2000 vapier 1.283 newbin "${tmpwrapper}" "${wrapper}" || die
2001 wolf31o2 1.164 fi
2002 wolf31o2 1.160 }
2003 mr_bones_ 1.311
2004 vapier 1.351 # @FUNCTION: path_exists
2005     # @USAGE: [-a|-o] <paths>
2006     # @DESCRIPTION:
2007     # Check if the specified paths exist. Works for all types of paths
2008     # (files/dirs/etc...). The -a and -o flags control the requirements
2009     # of the paths. They correspond to "and" and "or" logic. So the -a
2010     # flag means all the paths must exist while the -o flag means at least
2011     # one of the paths must exist. The default behavior is "and". If no
2012     # paths are specified, then the return value is "false".
2013     path_exists() {
2014     local opt=$1
2015     [[ ${opt} == -[ao] ]] && shift || opt="-a"
2016    
2017     # no paths -> return false
2018     # same behavior as: [[ -e "" ]]
2019     [[ $# -eq 0 ]] && return 1
2020    
2021     local p r=0
2022     for p in "$@" ; do
2023     [[ -e ${p} ]]
2024     : $(( r += $? ))
2025     done
2026    
2027     case ${opt} in
2028     -a) return $(( r != 0 )) ;;
2029     -o) return $(( r == $# )) ;;
2030     esac
2031     }
2032 mgorny 1.364
2033     # @FUNCTION: in_iuse
2034     # @USAGE: <flag>
2035     # @DESCRIPTION:
2036     # Determines whether the given flag is in IUSE. Strips IUSE default prefixes
2037     # as necessary.
2038     #
2039     # Note that this function should not be used in the global scope.
2040     in_iuse() {
2041     debug-print-function ${FUNCNAME} "${@}"
2042     [[ ${#} -eq 1 ]] || die "Invalid args to ${FUNCNAME}()"
2043    
2044     local flag=${1}
2045     local liuse=( ${IUSE} )
2046    
2047     has "${flag}" "${liuse[@]#[+-]}"
2048     }
2049 vapier 1.365
2050     # @FUNCTION: usex
2051     # @USAGE: <USE flag> [true output] [false output] [true suffix] [false suffix]
2052     # @DESCRIPTION:
2053     # If USE flag is set, echo [true output][true suffix] (defaults to "yes"),
2054     # otherwise echo [false output][false suffix] (defaults to "no").
2055     usex() { use "$1" && echo "${2-yes}$4" || echo "${3-no}$5" ; } #382963

  ViewVC Help
Powered by ViewVC 1.1.20