/[polypkg]/trunk/pp.util
ViewVC logotype

Contents of /trunk/pp.util

Parent Directory Parent Directory | Revision Log Revision Log


Revision 214 - (show annotations)
Fri Feb 27 18:04:28 2009 UTC (8 months, 3 weeks ago) by tperciva
File size: 15046 byte(s)
Change unstripped tarfile name to $name-dbg-$version.tar.gz
1 #
2 # misc utilities
3 #
4
5 #@ $pp_errors: true if pp_error() has been called
6 pp_errors=false
7
8 #-- define some colour strings
9 #@ $pp_col_redfg: terminal string to change foreground colour to red
10 #@ $pp_col_bluefg: terminal string to change foreground colour to blue
11 #@ $pp_col_reset: terminal string to reset colours to default
12 if test -n "$TERM" -a -t 1 && (tput op) >/dev/null 2>/dev/null; then
13 pp_col_redfg=`tput setf 4` 2>/dev/null
14 pp_col_bluefg=`tput setf 1` 2>/dev/null
15 pp_col_reset=`tput op` 2>/dev/null
16 else
17 pp_col_redfg='['
18 pp_col_bluefg='['
19 pp_col_reset=']'
20 fi
21
22 #@ pp__warn(type,msg): prints a warning message including $pp_lineno if nonnull
23 pp__warn () {
24 if test x"" = x"$pp_lineno"; then
25 echo "$1 $2" >&2
26 else
27 echo "$1 line $pp_lineno: $2" >&2
28 fi
29 }
30
31 #@ pp_warn(msg): prints a warning message
32 pp_warn () {
33 pp__warn "pp: ${pp_col_redfg}warning${pp_col_reset}" "$*"
34 }
35
36 # pp_error(msg): prints an error message and sets $pp_errors to 'true'
37 pp_error () {
38 pp__warn "pp: ${pp_col_redfg}error${pp_col_reset}" "$*"
39 pp_errors=true
40 }
41
42 #@ pp_die(msg): prints an error message and dies with exit code 1
43 pp_die () {
44 pp_error "$@"
45 exit 1
46 }
47
48 #@ pp_die_if_errors(msg): dies with an error if previous errors had occurred
49 pp_die_if_errors () {
50 $pp_errors && pp_die "$@"
51 }
52
53 #@ pp_debug(msg): writes a message only if the --debug option was given
54 pp_debug () {
55 $pp_opt_debug && echo "${pp_col_bluefg}debug${pp_col_reset} $*" >&2
56 }
57
58 #@ pp_verbose(msg): executes a command, printing it if --verbose flag
59 pp_verbose () {
60 $pp_opt_verbose && echo "pp: ${pp_col_bluefg}info${pp_col_reset} $*" >&2
61 "$@";
62 }
63
64 #@ pp_substitute(): expands %{} and %() in standard input stream
65 # - substitutes each %{var} with shell variable $var
66 # - substitutes each %(cmd) with the output of `cmd`
67 # - otherwise passes characters unchanged.
68 # - assumes input does not contain ^U ^V or ^W characters
69 pp_substitute () {
70 sed -e 's,%(\([^)]*\)),`\1`,g' \
71 -e 's,%{\([^}]*\)},${\1},g' \
72 -e 's,$,,' |
73 tr '' '\012' |
74 sed -e '/^[^]/s/["$`\\]/\\&/g' \
75 -e 's/^//' \
76 -e '1s/^/echo "/' \
77 -e '$s,$,",' \
78 -e 's,,"echo ",g' |
79 tr -d '\012' |
80 tr '' '\012'
81 echo
82 }
83
84 #@ pp_incr(var): increements variable $var by one
85 pp_incr () {
86 eval "$1=\`expr \$$1 + 1\`"
87 }
88
89 #@ pp_decr(var): decrements variable $var by one
90 pp_decr () {
91 eval "$1=\`expr \$$1 - 1\`"
92 }
93
94 #@ pp_check_var_is_defined(): check the variable is set and/or non-empty
95 # Otherwise, generates an error, and sets the variable to "undefined"
96 pp_check_var_is_defined () {
97 if eval test -z "\"\$$1\""; then
98 pp_error "\$$1: not set"
99 eval "$1=undefined"
100 fi
101 }
102
103 #@ pp_contains(list word): true if list contains word. list is space-delimited
104 pp_contains () {
105 case " $1 " in
106 *" $2 "*) return 0;;
107 *) return 1;;
108 esac
109 }
110
111 #@ pp_contains_all(list word...): true if all words are found in the list
112 pp_contains_all () {
113 typeset _s _c
114 _l="$1"; shift
115 for _w
116 do
117 pp_contains "$_l" "$_w" || return 1
118 done
119 return 0
120 }
121
122 #@ pp_contains_any(list word...): true if any word is found in the list
123 pp_contains_any () {
124 typeset _s _c
125 _l="$1"; shift
126 for _w
127 do
128 pp_contains "$_l" "$_w" && return 0
129 done
130 return 1
131 }
132
133 #@ pp_add_to_list(list word): adds word into $list, if not there already
134 pp_add_to_list () {
135 if eval test -z \"\$$1\"; then
136 eval $1='"$2"'
137 elif eval pp_contains '"$'$1'"' '"$2"'; then
138 : already there
139 else
140 eval $1='"$'$1' $2"'
141 fi
142 }
143
144 #@ pp_unique(word...): removes duplicates from the input
145 pp_unique () {
146 typeset result element
147 result=
148 for element
149 do
150 pp_add_to_list result $element
151 done
152 echo $result
153 }
154
155 #@ pp_mode_strip_altaccess(str): given a string `ls` mode pattern, remove a
156 # trailing '+' if there is one. '+' indicates an "alternate access mode",
157 # usually an ACL.
158 pp_mode_strip_altaccess () {
159 case "$1" in
160 ??????????+)
161 echo `echo "$1" | cut -b -10`;;
162 *)
163 echo "$1";;
164 esac
165 }
166
167 #@ pp_mode_from_ls(str): converts an ls mode pattern into an octal mode number
168 # e.g. "-rw-rw-r--" becomes "664"
169 pp_mode_from_ls () {
170 typeset umode gmode omode smode
171
172 set -- `pp_mode_strip_altaccess "$1"`
173
174 case "$1" in
175 ?--[-X]??????) umode=0;;
176 ?--[xs]??????) umode=1;;
177 ?-w[-X]??????) umode=2;;
178 ?-w[xs]??????) umode=3;;
179 ?r-[-X]??????) umode=4;;
180 ?r-[xs]??????) umode=5;;
181 ?rw[-X]??????) umode=6;;
182 ?rw[xs]??????) umode=7;;
183 *) pp_error "bad user mode $1";;
184 esac
185
186 case "$1" in
187 ????--[-S]???) gmode=0;;
188 ????--[xs]???) gmode=1;;
189 ????-w[-S]???) gmode=2;;
190 ????-w[xs]???) gmode=3;;
191 ????r-[-X]???) gmode=4;;
192 ????r-[xs]???) gmode=5;;
193 ????rw[-X]???) gmode=6;;
194 ????rw[xs]???) gmode=7;;
195 *) pp_error "bad group mode $1";;
196 esac
197
198 case "$1" in
199 ???????--[-T]) omode=0;;
200 ???????--[xt]) omode=1;;
201 ???????-w[-T]) omode=2;;
202 ???????-w[xt]) omode=3;;
203 ???????r-[-T]) omode=4;;
204 ???????r-[xt]) omode=5;;
205 ???????rw[-T]) omode=6;;
206 ???????rw[xt]) omode=7;;
207 *) pp_error "bad other mode $1";;
208 esac
209
210 case "$1" in
211 ???[-x]??[-x]??[-x]) smode=;;
212 ???[-x]??[-x]??[tT]) smode=1;;
213 ???[-x]??[Ss]??[-x]) smode=2;;
214 ???[-x]??[Ss]??[tT]) smode=3;;
215 ???[Ss]??[-x]??[-x]) smode=4;;
216 ???[Ss]??[-x]??[tT]) smode=5;;
217 ???[Ss]??[Ss]??[-x]) smode=6;;
218 ???[Ss]??[Ss]??[tT]) smode=7;;
219 *) pp_error "bad set-id mode $1";;
220 esac
221
222 echo "$smode$umode$gmode$omode"
223 }
224
225 #@ pp_find_recurse($pp_destdir/dir): recursive find (don't follow symlinks)
226 pp_find_recurse () {
227 pp_debug "find: ${1#$pp_destdir}/"
228 for f in "$1"/.* "$1"/*; do
229 case "$f" in */.|*/..) continue;; esac # should never happen!
230 if test -d "$f" -o -f "$f" -o -h "$f"; then
231 if test -d "$f" -a ! -h "$f"; then
232 echo "${f#$pp_destdir}/"
233 pp_find_recurse "$f"
234 else
235 echo "${f#$pp_destdir}"
236 fi
237 fi
238 done
239 }
240
241 #@ pp_prepend(file) <text: prepend text to the beginning of the file
242 # if file does not exist, it is created
243 pp_prepend () {
244 #test -t && pp_warn "pp_prepend: stdin is a tty?"
245 if test -f $1; then
246 pp_debug "prepending to $1"
247 mv $1 $1._prepend
248 cat - $1._prepend >$1
249 rm -f $1._prepend
250 else
251 pp_debug "prepend: creating $1"
252 cat >$1
253 fi
254 }
255
256 #@ pp_note_file_used(path): record file used for later coverage analysis
257 pp_note_file_used() {
258 echo "$1" >> $pp_wrkdir/all.files
259 }
260
261 #@ pp_create_dir_if_missing(path,mode): add directory if missing
262 # - cleans up afterwards
263 pp_create_dir_if_missing () {
264 case "$1" in
265 */) pp_error "pp_create_dir_if_missing: trailing / forbidden";;
266 "") return 0;;
267 *) if test ! -d "$pp_destdir$1"; then
268 pp_debug "fabricating directory $1/"
269 pp_create_dir_if_missing "${1%/*}"
270 mkdir "$pp_destdir$1" &&
271 pp_note_file_used "$1/"
272 pp_remove_later "$1" &&
273 chmod ${2:-755} "$pp_destdir$1"
274 fi;;
275 esac
276 }
277
278 #@ pp_add_file_if_missing(path,cpt,mode,flag): add file to component only if missing
279 # returns false if the file already exists; otherwise adds
280 # adds an entry to the %files.$cpt list. If the path is in a missing
281 # directory, that directory is also created under $pp_destdir.
282 # This is usually used for system scripts. The mode defaults to 755
283 # and the component defaults to run. The file is scheduled for removal
284 # after packaing is complete.
285 pp_add_file_if_missing () {
286 typeset dir
287 #-- check that the file isn't already declared in the component
288 if test -s $pp_wrkdir/%files.${2:-run}; then
289 awk "\$6 == \"$1\" {exit 1}" < $pp_wrkdir/%files.${2:-run} || return 1
290 fi
291
292 pp_create_dir_if_missing "${1%/*}"
293 pp_debug "fabricating file $1"
294 echo "f ${3:-755} - - ${4:--} $1" >> $pp_wrkdir/%files.${2:-run}
295 pp_note_file_used "$1"
296 pp_remove_later "$1"
297 return 0
298 }
299
300 #@ pp_add_transient_file(path): notify of creation of a transient file
301 pp_add_transient_file () {
302 test -f "$pp_destdir$1" && pp_die "$pp_destdir$1: exists"
303 pp_create_dir_if_missing "${1%/*}"
304 pp_debug "transient file $1"
305 pp_note_file_used "$1"
306 pp_remove_later "$1"
307 }
308
309 #@ pp_remove_later(path): adds file for deletion during cleanup
310 # the file is prepended to $pp_wrkdir/pp_cleanup
311 pp_remove_later () {
312 {
313 echo "$1"
314 test -s $pp_wrkdir/pp_cleanup && cat $pp_wrkdir/pp_cleanup
315 } > $pp_wrkdir/pp_cleanup.new
316 mv $pp_wrkdir/pp_cleanup.new $pp_wrkdir/pp_cleanup
317 }
318
319 #@ pp_ls_readlink(file): print the content of a symbolic link using ls
320 pp_ls_readlink () {
321 if test -h "$1"; then
322 ls -1ld "$1" | sed -ne 's,.* -> ,,p'
323 else
324 echo "$1: not a symbolic link" >&2
325 return 1
326 fi
327 }
328
329 #@ pp_remove_later_now(): removes all files registered with pp_remove_later
330 pp_remove_later_now () {
331 typeset f
332 if test -s $pp_wrkdir/pp_cleanup; then
333 pp_debug "pp_remove_later_now"
334 while read f; do
335 pp_debug "removing $pp_destdir$f"
336 if test -d $pp_destdir$f; then
337 rmdir $pp_destdir$f
338 else
339 rm $pp_destdir$f
340 fi
341 done < $pp_wrkdir/pp_cleanup
342 rm $pp_wrkdir/pp_cleanup
343 fi
344 }
345
346 #@ pp_readlink()
347 pp_readlink() {
348
349 pp_debug "&& pp_readlink_fn=$pp_readlink_fn"
350
351 if test -n "$pp_readlink_fn"; then
352 pp_debug "&& calling $pp_readlink_fn $*"
353 "$pp_readlink_fn" "$@"
354 else
355 readlink "$@"
356 fi
357 }
358
359
360 #@ pp_install_script_common(): generate common code in the install script
361 pp_install_script_common () {
362 cat <<-.
363
364 # Automatically generated for
365 # $name $version ($pp_platform)
366 # by PolyPackage $pp_version
367
368 usage () {
369 case "$1" in
370 "list-services")
371 echo "usage: \$0 list-services" ;;
372 "list-components")
373 echo "usage: \$0 list-components" ;;
374 "list-files")
375 echo "usage: \$0 list-files {cpt...|all}" ;;
376 "install")
377 echo "usage: \$0 install {cpt...|all}" ;;
378 "uninstall")
379 echo "usage: \$0 uninstall {cpt...|all}" ;;
380 "start")
381 echo "usage: \$0 start {svc...}" ;;
382 "stop")
383 echo "usage: \$0 stop {svc...}" ;;
384 "print-platform")
385 echo "usage: \$0 print-platform" ;;
386 *)
387 echo "usage: \$0 [-q] command [args]"
388 echo " list-services"
389 echo " list-components"
390 echo " list-files {cpt...|all}"
391 echo " install {cpt...|all}"
392 echo " uninstall {cpt...|all}"
393 echo " start {svc...}"
394 echo " stop {svc...}"
395 echo " print-platform"
396 ;;
397 esac >&2
398 exit 1
399 }
400
401 if test x"\$1" = x"-q"; then
402 shift
403 verbose () { "\$@"; }
404 verbosemsg () { : ; }
405 else
406 verbose () { echo "+ \$*"; "\$@"; }
407 verbosemsg () { echo "\$*"; }
408 fi
409 .
410 }
411
412
413 #@ pp_functions(func...): emit platform-dependent function definitions
414 pp_functions () {
415 typeset func deps allfuncs
416 allfuncs=
417 while test $# -gt 0; do
418 pp_add_to_list allfuncs "$1"
419 deps=`pp_backend_function "$1:depends"`
420 shift
421 set -- `pp_unique "$@" $deps`
422 done
423
424 for func in $allfuncs
425 do
426 pp_debug "generating function code for '$1'"
427 echo ""
428 echo "$func () {"
429 case "$func" in
430 pp_mkgroup|pp_mkuser|pp_havelib) echo <<.;;
431 if test \$# -lt 1; then
432 echo "$func: not enough arguments" >&2
433 return 1
434 fi
435 .
436 esac
437 pp_backend_function "$func" || cat <<.
438 echo "$func: not implemented" >&2
439 return 1
440 .
441 echo "}"
442 done
443 }
444
445 #@ pp_function(func): emits a single platform-dependent function definition
446 pp_function () {
447 pp_functions "$1"
448 }
449
450 #@ pp_makevar(str): makes a variable name out of a string
451 pp_makevar () {
452 #-- convert all non alpha/digits to underscores
453 echo "$*" | tr -c '[a-z][A-Z][0-9]\012' '[_*]'
454 }
455
456 #@ pp_getpwuid(uid): returns username for a LOCAL uid
457 pp_getpwuid () {
458 awk -F: '$3 == uid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' uid="$1" \
459 < /etc/passwd || pp_error "no local username for uid $1"
460 }
461
462 #@ pp_getgruid(gid): returns group for a LOCAL gid
463 pp_getgrgid () {
464 awk -F: '$3 == gid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' gid="$1" \
465 < /etc/group || pp_error "no local group for gid $1"
466 }
467
468 #@ pp_backend_function_getopt(): emits code for pp_getopt
469 pp_backend_function_getopt () {
470 cat <<'..'
471 # Portable getopt; normalises command line arguments
472 # Usage: eval `pp_getopt abc: "$@"`
473 pp_getopt () {
474 _pp_optstring="$1"; shift; eval `_pp_getopt "$_pp_optstring"`
475 }
476 _pp_getopt_meta=s,[\\\\\"\'\`\$\&\;\(\)\{\}\#\%\ \ ],\\\\\&,g
477 _pp_protect () {
478 sed "$_pp_getopt_meta" <<. | tr '\012' ' '
479 $*
480 .
481 }
482 _pp_protect2 () {
483 sed "s,^..,,$pp_getopt_meta" <<. | tr '\012' ' '
484 $*
485 .
486 }
487 _pp_nonl () {
488 tr '\012' ' ' <<.
489 $*
490 .
491 }
492 _pp_getopt () {
493 _pp_nonl '_pp_nonl set --; while test $# -gt 0; do case "$1" in "--") shift; break;;'
494 sed 's/\([^: ]:*\)/<@<\1>@>/g;
495 s/<@<\(.\):>@>/"-\1") _pp_nonl -"\1"; _pp_protect "$2"; shift; shift;; "-\1"*) _pp_nonl -"\1"; _pp_protect2 "$1"; shift;;/g;s/<@<\(.\)>@>/ "-\1") _pp_nonl -"\1"; shift;; "-\1"*) _pp_nonl -"\1"; _pp_tmp="$1"; shift; set -- -`_pp_protect2 "$_pp_tmp"` "$@";;/g' <<.
496 $1
497 .
498 _pp_nonl '-*) echo "$1: unknown option">&2; return 1;; *) break;; esac; done; _pp_nonl --; while test $# -gt 0; do _pp_nonl "$1"; shift; done; echo'
499 echo
500 }
501 ..
502 }
503
504 #@ pp_copy_unstripped(file): keep a copy of $file with the unstripped binaries
505 pp_copy_unstripped () {
506 typeset filedir realdir
507 filedir="`dirname ${1#$pp_destdir}`"
508 realdir="$pp_wrkdir/unstripped/$filedir"
509
510 mkdir -p "$realdir"
511 # Can't use hardlinks because `strip` modifies the original file in-place
512 cp "$1" "$realdir"
513 }
514
515 #@ pp_package_stripped_binaries(): tar.gz the unstripped directory tree
516 pp_package_stripped_binaries () {
517 (cd "$pp_wrkdir/unstripped" && tar -c .) \
518 | gzip > "$name-dbg-$version.tar.gz"
519 rm -rf "$pp_wrkdir/unstripped"
520 }
521
522 #@ pp_strip_binaries(): Strip all ELF binaries in $pp_destdir
523 pp_strip_binaries () {
524 if test x"$pp_opt_save_unstripped" = x"true"; then
525 rm -rf "$pp_wrkdir/unstripped"
526 mkdir "$pp_wrkdir/unstripped"
527 fi
528
529 for f in `find "$pp_destdir" -type f`; do
530 if file "$f" | awk '{print $2}' | grep ^ELF >/dev/null 2>&1; then
531 if test x"$pp_opt_save_unstripped" = x"true"; then
532 if file "$f" | LC_MESSAGES=C grep 'not stripped' >/dev/null 2>&1; then
533 pp_debug "Saving unstripped binary $f"
534 pp_copy_unstripped "$f"
535 else
536 pp_debug "$f is already stripped; not saving a copy"
537 fi
538 fi
539 pp_debug "Stripping unnecessary symbols from $f"
540 strip "$f"
541 fi
542 done
543
544 if test x"$pp_opt_save_unstripped" = x"true"; then
545 pp_package_stripped_binaries
546 fi
547 }

Ted.Percival@quest.com
ViewVC Help
Powered by ViewVC 1.1.2