Imported Upstream version 1.8.7
[debian/sudo] / pp
1 #!/bin/sh
2 # Copyright 2012 Quest Software, Inc. ALL RIGHTS RESERVED
3 pp_revision="371"
4  # Copyright 2012 Quest Software, Inc.  ALL RIGHTS RESERVED.
5  #
6  # Redistribution and use in source and binary forms, with or without
7  # modification, are permitted provided that the following conditions
8  # are met:
9  #
10  # 1. Redistributions of source code must retain the above copyright
11  #    notice, this list of conditions and the following disclaimer.
12  # 2. Redistributions in binary form must reproduce the above copyright
13  #    notice, this list of conditions and the following disclaimer in the
14  #    documentation and/or other materials provided with the distribution.
15  # 3. Neither the name of Quest Software, Inc. nor the names of its
16  #    contributors may be used to endorse or promote products derived from
17  #    this software without specific prior written permission.
18  #
19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25  # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31  # Please see <http://rc.quest.com/topics/polypkg/> for more information
32
33 pp_version="1.0.0.$pp_revision"
34 pp_copyright="Copyright 2012, Quest Software, Inc. ALL RIGHTS RESERVED."
35
36 pp_opt_debug=false
37 pp_opt_destdir="$DESTDIR"
38 pp_opt_install_script=
39 pp_opt_list=false
40 pp_opt_no_clean=false
41 pp_opt_no_package=false
42 pp_opt_only_front=false
43 pp_opt_platform=
44 pp_opt_probe=false
45 pp_opt_strip=false
46 pp_opt_save_unstripped=false
47 pp_opt_vas_platforms=false
48 pp_opt_wrkdir="`pwd`/pp.work.$$"
49 pp_opt_verbose=false
50 pp_opt_version=false
51 pp_opt_input="-"
52 pp_opt_init_vars=""
53 pp_opt_eval=
54
55 test -n "$PP_NO_CLEAN" && pp_opt_no_clean=true
56 test -n "$PP_DEBUG" && pp_opt_debug=true
57 test -n "$PP_VERBOSE" && pp_opt_verbose=true
58
59 pp_main_cleanup () {
60         pp_debug "main_cleanup"
61         pp_remove_later_now
62         if $pp_opt_no_clean || test x"$pp_platform" = x"unknown"; then
63             : no cleanup
64         else
65             pp_backend_${pp_platform}_cleanup
66             $pp_errors && pp_die "Errors during cleanup"
67             if test -d "$pp_wrkdir"; then
68                 if $pp_opt_debug; then
69                     pp_debug "not removing $pp_wrkdir"
70                 else
71                     pp_verbose rm -rf "$pp_wrkdir"
72                 fi
73             fi
74         fi
75 }
76
77 pp_parseopts () {
78         typeset a n _var _val
79         while test $# -gt 0; do
80
81           # convert -[dilpv] to --long-options
82           case "$1" in
83             --?*=?*) n=`echo "$1" | sed -ne 's/^--\([^=]*\)=.*/\1/p'`
84                    a=`echo "$1" | sed -ne 's/^--[^=]*=\(.*\)/\1/p'`
85                    shift
86                    set -- "--$n" "$a" "$@";;
87             --?*) : ;;
88
89             -d)  shift; set -- "--debug" "$@";;
90             -d*) a=`echo "$1" | sed -ne 's/^-.//'`
91                  shift; set -- "--debug" "$@";;
92
93             -i) shift; set -- "--install-script" "$@";;
94             -i*) a=`echo "$1" | sed -ne 's/^-.//'`
95                  shift; set -- "--install-script" "$a" "$@";;
96
97             -l)  shift; set -- "--list" "$@";;
98             -l*) a=`echo "$1" | sed -ne 's/^-.//'`
99                  shift; set -- "--list" "$@";;
100
101             -p) shift; set -- "--platform" "$@";;
102             -p*) a=`echo "$1" | sed -ne 's/^-.//'`
103                  shift; set -- "--platform" "$a" "$@";;
104
105             -v)  shift; set -- "--verbose" "$@";;
106             -v*) a=`echo "$1" | sed -ne 's/^-.//'`
107                  shift; set -- "--verbose" "$@";;
108
109             -\?)  shift; set -- "--help" "$@";;
110             -\?*) a=`echo "$1" | sed -ne 's/^-.//'`
111                  shift; set -- "--help" "$@";;
112           esac
113
114           case "$1" in
115             --destdir|--eval|--install-script|--platform|--wrkdir)
116                 test $# -ge 2 || pp_error "missing argument to $1";;
117           esac
118
119           case "$1" in
120             --)                                        shift;break;;
121             --debug)           pp_opt_debug=true;      shift;;
122             --destdir)         pp_opt_destdir="$2";    shift;shift;;
123             --eval)            pp_opt_eval="$2";       shift;shift;; # undoc
124             --install-script)  pp_opt_install_script="$2"; shift;shift;;
125             --list)            pp_opt_list=true;       shift;;
126             --no-clean)        pp_opt_no_clean=true;   shift;;
127             --no-package)      pp_opt_no_package=true; shift;;
128             --only-front)      pp_opt_only_front=true; shift;;
129             --platform)        pp_opt_platform="$2";   shift;shift;;
130             --probe)           pp_opt_probe=true;      shift;;
131             --strip)           pp_opt_strip=true;      shift;;
132             --save-unstripped) pp_opt_save_unstripped=true; shift;;
133             --wrkdir)          pp_opt_wrkdir="$2";     shift;shift;;
134             --vas-platforms)   pp_opt_vas_platforms=true; shift;;
135             --verbose)         pp_opt_verbose=true;    shift;;
136             --version)         pp_opt_version=true;    shift;;
137             --help)            pp_errors=true;         shift;;
138             -) break;;
139             -*) pp_error "unknown option $1"; shift;;
140             *) break;;
141           esac
142
143         done
144
145         pp_opt_input=-
146         if test $# -gt 0; then
147             pp_opt_input="$1"
148             shift
149         fi
150
151         #-- extra arguments of the form Foo=bar alter *global* vars
152         while test $# -gt 0; do
153             case "$1" in
154                 -*)     pp_error "unexpected option '$1'"
155                         shift;;
156                 *=*)    _val="${1#*=}"
157                         _var=${1%="$_val"}
158                         _val=`echo "$_val"|sed -e 's/[$"\\]/\\&/g'`
159                         pp_debug "setting $_var = \"$_val\""
160                         pp_opt_init_vars="$pp_opt_init_vars$_var=\"$_val\";"
161                         shift;;
162                 *)      pp_error "unexpected argument $1'"
163                         shift;;
164             esac
165         done
166
167         test $# -gt 0 &&
168             pp_error "unknown argument $1"
169
170         if $pp_errors; then
171             cat <<. >&2
172 polypkg $pp_version $pp_copyright
173 usage: $0 [options] [input.pp] [var=value ...]
174     -d --debug                  -- write copious info to stderr
175        --destdir=path           -- file root, defaults to \$DESTDIR
176     -? --help                   -- display this information
177     -i --install-script=path    -- create an install helper script
178     -l --list                   -- write package filenames to stdout
179        --no-clean               -- don't remove temporary files
180        --no-package             -- do everything but create packages
181        --only-front             -- only perform front-end actions
182     -p --platform=platform      -- defaults to local platform
183        --probe                  -- print local system identifier, then exit
184        --strip                  -- strip debug symbols from binaries before
185                                    packaging (modifies files in destdir)
186        --save-unstripped        -- save unstripped binaries to
187                                    \$name-\$version-unstripped.tar.gz
188        --wrkdir=path            -- defaults to subdirectory of \$TMPDIR or /tmp
189     -v --verbose                -- write info to stderr
190        --version                -- display version and quit
191 .
192             exit 1
193         fi
194 }
195
196 pp_drive () {
197         # initialise the front and back ends
198         pp_model_init
199         pp_frontend_init
200         $pp_opt_only_front || pp_backend_init
201
202         # run the front-end to generate the intermediate files
203         # set $pp_input_dir to be the 'include dir' if needed
204         pp_debug "calling frontend on $pp_opt_input"
205         case "$pp_opt_input" in
206             -)   pp_input_dir=.
207                  test -t 1<&0 &&
208                     pp_warn "reading directives from standard input"
209                  pp_frontend
210                  ;;
211             */*) pp_input_dir=${pp_opt_input%/*}
212                  pp_frontend <"$pp_opt_input"
213                  ;;
214             *)   pp_input_dir=.
215                  pp_frontend <"$pp_opt_input"
216                  ;;
217         esac
218
219         pp_files_ignore_others
220         pp_service_scan_groups
221
222         # some sanity checks after front-end processing
223         if test x"$pp_platform" != x"null"; then
224             pp_debug "sanity checks"
225             test -n "$pp_components" || pp_error "No components?"
226             pp_check_var_is_defined  "name"
227             pp_check_var_is_defined  "version"
228             pp_files_check_duplicates
229             pp_files_check_coverage
230             pp_die_if_errors "Errors during sanity checks"
231         fi
232
233         # stop now if we're only running the front
234         $pp_opt_only_front && return
235
236         if test x"$pp_opt_strip" = x"true"; then
237             pp_strip_binaries
238         fi
239
240         # run the back-end to generate the package
241         pp_debug "calling backend"
242         pp_backend
243         pp_die_if_errors "Errors during backend processing"
244
245         # copy the resulting package files to PP_PKGDESTDIR or .
246         for f in `pp_backend_names` -; do
247            test x"$f" = x"-" && continue
248            pp_debug "copying: $f to `pwd`"
249            if pp_verbose cp -r $pp_wrkdir/$f ${PP_PKGDESTDIR:-.}; then
250                echo "${PP_PKGDESTDIR:+$PP_PKGDESTDIR/}$f"
251            else
252                pp_error "$f: missing package"
253            fi
254         done
255         pp_die_if_errors "Errors during package copying"
256 }
257
258 pp_install_script () {
259         pp_debug "writing install script to $pp_opt_install_script"
260         rm -f $pp_opt_install_script
261         pp_backend_install_script > $pp_opt_install_script
262         pp_die_if_errors "Errors during package install script"
263         chmod +x $pp_opt_install_script
264 }
265
266 pp_main () {
267         # If PP_DEV_PATH is set, then jump to that script.
268         # (Useful when working on polypkg source that isn't installed)
269         if test -n "$PP_DEV_PATH" -a x"$PP_DEV_PATH" != x"$0"; then
270             pp_warn "switching from $0 to $PP_DEV_PATH ..."
271             exec "$PP_DEV_PATH" "$@" || exit 1
272         fi
273
274         pp_set_expand_converter_or_reexec "$@"
275         pp_parseopts "$@"
276
277         if $pp_opt_version; then
278             #-- print version and exit
279             echo "polypkg $pp_version"
280             exit 0
281         fi
282
283         pp_set_platform
284
285         trap 'pp_main_cleanup' 0
286
287         pp_wrkdir="$pp_opt_wrkdir"
288         pp_debug "pp_wrkdir = $pp_wrkdir"
289         rm -rf "$pp_wrkdir"
290         mkdir -p "$pp_wrkdir"
291
292         pp_destdir="$pp_opt_destdir"
293         pp_debug "pp_destdir = $pp_destdir"
294
295         if $pp_opt_probe; then
296             pp_backend_init
297             pp_backend_probe
298         elif $pp_opt_vas_platforms; then
299             pp_backend_init
300             pp_backend_vas_platforms
301         elif test -n "$pp_opt_eval"; then
302             #-- execute a shell command
303             eval "$pp_opt_eval" || exit
304         else
305             pp_drive
306             if test -n "$pp_opt_install_script"; then
307                 pp_install_script
308             fi
309         fi
310
311         exit 0
312 }
313
314
315 pp_errors=false
316
317 if test -n "$TERM" -a -t 1 && (tput op) >/dev/null 2>/dev/null; then
318    pp_col_redfg=`tput setf 4` 2>/dev/null
319    pp_col_bluefg=`tput setf 1` 2>/dev/null
320    pp_col_reset=`tput op` 2>/dev/null
321 else
322    pp_col_redfg='['
323    pp_col_bluefg='['
324    pp_col_reset=']'
325 fi
326
327 pp__warn () {
328         if test x"" = x"$pp_lineno"; then
329             echo "$1 $2" >&2
330         else
331             echo "$1 line $pp_lineno: $2" >&2
332         fi
333 }
334
335 pp_warn () {
336         pp__warn "pp: ${pp_col_redfg}warning${pp_col_reset}" "$*"
337 }
338
339 pp_error () {
340         pp__warn "pp: ${pp_col_redfg}error${pp_col_reset}" "$*"
341         pp_errors=true
342 }
343
344 pp_die () {
345         pp_error "$@"
346         exit 1
347 }
348
349 pp_die_if_errors () {
350         $pp_errors && pp_die "$@"
351 }
352
353 pp_debug () {
354         $pp_opt_debug && echo "${pp_col_bluefg}debug${pp_col_reset} $*" >&2
355 }
356
357 pp_verbose () {
358         $pp_opt_verbose && echo "pp: ${pp_col_bluefg}info${pp_col_reset} $*" >&2
359         "$@";
360 }
361
362 pp_substitute () {
363   sed -e 's,%(\([^)]*\)),\16\15`\1`\16,g' \
364       -e 's,%{\([^}]*\)},\16\15${\1}\16,g' \
365       -e 's,$,\17,' |
366   tr '\16' '\012' |
367   sed -e '/^[^\15]/s/["$`\\]/\\&/g' \
368       -e 's/^\15//' \
369       -e '1s/^/echo "/' \
370       -e '$s,\17$,",' \
371       -e 's,\17,"\16echo ",g' |
372   tr -d '\012' |
373   tr '\16' '\012'
374   echo
375 }
376
377 pp_incr () {
378     eval "$1=\`expr \$$1 + 1\`"
379 }
380
381 pp_decr () {
382     eval "$1=\`expr \$$1 - 1\`"
383 }
384
385 pp_check_var_is_defined () {
386     if eval test -z "\"\$$1\""; then
387         pp_error "\$$1: not set"
388         eval "$1=undefined"
389     fi
390 }
391
392 pp_contains () {
393     case " $1 " in
394        *" $2 "*) return 0;;
395        *) return 1;;
396     esac
397 }
398
399 pp_contains_all () {
400     typeset _s _c
401     _l="$1"; shift
402     for _w
403     do
404         pp_contains "$_l" "$_w" || return 1
405     done
406     return 0
407 }
408
409 pp_contains_any () {
410     typeset _s _c
411     _l="$1"; shift
412     for _w
413     do
414         pp_contains "$_l" "$_w" && return 0
415     done
416     return 1
417 }
418
419 pp_add_to_list () {
420     if eval test -z \"\$$1\"; then
421         eval $1='"$2"'
422     elif eval pp_contains '"$'$1'"' '"$2"'; then
423         : already there
424     else
425         eval $1='"$'$1' $2"'
426     fi
427 }
428
429 pp_unique () {
430     typeset result element
431     result=
432     for element
433     do
434         pp_add_to_list result $element
435     done
436     echo $result
437 }
438
439 pp_mode_strip_altaccess () {
440     case "$1" in
441         ??????????[+.])
442             echo `echo "$1" | cut -b -10`;;
443         *)
444             echo "$1";;
445     esac
446 }
447
448 pp_mode_from_ls () {
449    typeset umode gmode omode smode
450
451    set -- `pp_mode_strip_altaccess "$1"`
452
453    case "$1" in
454         ?--[-X]??????) umode=0;;
455         ?--[xs]??????) umode=1;;
456         ?-w[-X]??????) umode=2;;
457         ?-w[xs]??????) umode=3;;
458         ?r-[-X]??????) umode=4;;
459         ?r-[xs]??????) umode=5;;
460         ?rw[-X]??????) umode=6;;
461         ?rw[xs]??????) umode=7;;
462         *) pp_error "bad user mode $1";;
463    esac
464
465    case "$1" in
466         ????--[-S]???) gmode=0;;
467         ????--[xs]???) gmode=1;;
468         ????-w[-S]???) gmode=2;;
469         ????-w[xs]???) gmode=3;;
470         ????r-[-X]???) gmode=4;;
471         ????r-[xs]???) gmode=5;;
472         ????rw[-X]???) gmode=6;;
473         ????rw[xs]???) gmode=7;;
474         *) pp_error "bad group mode $1";;
475    esac
476
477    case "$1" in
478         ???????--[-T]) omode=0;;
479         ???????--[xt]) omode=1;;
480         ???????-w[-T]) omode=2;;
481         ???????-w[xt]) omode=3;;
482         ???????r-[-T]) omode=4;;
483         ???????r-[xt]) omode=5;;
484         ???????rw[-T]) omode=6;;
485         ???????rw[xt]) omode=7;;
486         *) pp_error "bad other mode $1";;
487    esac
488
489    case "$1" in
490         ???[-x]??[-x]??[-x]) smode=;;
491         ???[-x]??[-x]??[tT]) smode=1;;
492         ???[-x]??[Ss]??[-x]) smode=2;;
493         ???[-x]??[Ss]??[tT]) smode=3;;
494         ???[Ss]??[-x]??[-x]) smode=4;;
495         ???[Ss]??[-x]??[tT]) smode=5;;
496         ???[Ss]??[Ss]??[-x]) smode=6;;
497         ???[Ss]??[Ss]??[tT]) smode=7;;
498         *) pp_error "bad set-id mode $1";;
499    esac
500
501    echo "$smode$umode$gmode$omode"
502 }
503
504 pp_find_recurse () {
505   pp_debug "find: ${1#$pp_destdir}/"
506   for f in "$1"/.* "$1"/*; do
507     case "$f" in */.|*/..) continue;; esac  # should never happen!
508     if test -d "$f" -o -f "$f" -o -h "$f"; then
509         if test -d "$f" -a ! -h "$f"; then
510             echo "${f#$pp_destdir}/"
511             pp_find_recurse "$f"
512         else
513             echo "${f#$pp_destdir}"
514         fi
515     fi
516   done
517 }
518
519 pp_prepend () {
520     #test -t && pp_warn "pp_prepend: stdin is a tty?"
521     if test -f $1; then
522         pp_debug "prepending to $1"
523         mv $1 $1._prepend
524         cat - $1._prepend >$1
525         rm -f $1._prepend
526     else
527         pp_debug "prepend: creating $1"
528         cat >$1
529     fi
530 }
531
532 pp_note_file_used() {
533     echo "$1" >> $pp_wrkdir/all.files
534 }
535
536 pp_create_dir_if_missing () {
537     case "$1" in
538         */) pp_error "pp_create_dir_if_missing: trailing / forbidden";;
539         "") return 0;;
540         *)  if test ! -d "$pp_destdir$1"; then
541                 pp_debug "fabricating directory $1/"
542                 pp_create_dir_if_missing "${1%/*}"
543                 mkdir "$pp_destdir$1" &&
544                     pp_note_file_used "$1/"
545                 pp_remove_later "$1" &&
546                 chmod ${2:-755} "$pp_destdir$1"
547             fi;;
548     esac
549 }
550
551 pp_add_file_if_missing () {
552     typeset dir
553     #-- check that the file isn't already declared in the component
554     if test -s $pp_wrkdir/%files.${2:-run}; then
555       awk "\$6 == \"$1\" {exit 1}" < $pp_wrkdir/%files.${2:-run} || return 1
556     fi
557
558     pp_create_dir_if_missing "${1%/*}"
559     pp_debug "fabricating file $1"
560     echo "f ${3:-755} - - ${4:--} $1" >> $pp_wrkdir/%files.${2:-run}
561     pp_note_file_used "$1"
562     pp_remove_later "$1"
563     return 0
564 }
565
566 pp_add_transient_file () {
567     test -f "$pp_destdir$1" && pp_die "$pp_destdir$1: exists"
568     pp_create_dir_if_missing "${1%/*}"
569     pp_debug "transient file $1"
570     pp_note_file_used "$1"
571     pp_remove_later "$1"
572 }
573
574 pp_remove_later () {
575    {
576         echo "$1"
577         test -s $pp_wrkdir/pp_cleanup && cat $pp_wrkdir/pp_cleanup
578    } > $pp_wrkdir/pp_cleanup.new
579    mv $pp_wrkdir/pp_cleanup.new $pp_wrkdir/pp_cleanup
580 }
581
582 pp_ls_readlink () {
583     if test -h "$1"; then
584         ls -1ld "$1" | sed -ne 's,.* -> ,,p'
585     else
586         echo "$1: not a symbolic link" >&2
587         return 1
588     fi
589 }
590
591 pp_remove_later_now () {
592     typeset f
593     if test -s $pp_wrkdir/pp_cleanup; then
594         pp_debug "pp_remove_later_now"
595         while read f; do
596             pp_debug "removing $pp_destdir$f"
597             if test -d $pp_destdir$f; then
598                 rmdir $pp_destdir$f
599             else
600                 rm $pp_destdir$f
601             fi
602         done < $pp_wrkdir/pp_cleanup
603         rm $pp_wrkdir/pp_cleanup
604     fi
605 }
606
607 pp_readlink() {
608
609 pp_debug "&& pp_readlink_fn=$pp_readlink_fn"
610
611     if test -n "$pp_readlink_fn"; then
612 pp_debug "&& calling $pp_readlink_fn $*"
613         "$pp_readlink_fn" "$@"
614     else
615         readlink "$@"
616     fi
617 }
618
619
620 pp_install_script_common () {
621         cat <<-.
622
623             # Automatically generated for
624             #    $name $version ($pp_platform)
625             # by PolyPackage $pp_version
626
627             usage () {
628               case "$1" in
629               "list-services")
630                 echo "usage: \$0 list-services" ;;
631               "list-components")
632                 echo "usage: \$0 list-components" ;;
633               "list-files")
634                 echo "usage: \$0 list-files {cpt...|all}" ;;
635               "install")
636                 echo "usage: \$0 install {cpt...|all}" ;;
637               "uninstall")
638                 echo "usage: \$0 uninstall {cpt...|all}" ;;
639               "start")
640                 echo "usage: \$0 start {svc...}" ;;
641               "stop")
642                 echo "usage: \$0 stop {svc...}" ;;
643               "print-platform")
644                 echo "usage: \$0 print-platform" ;;
645               *)
646                 echo "usage: \$0 [-q] command [args]"
647                 echo "   list-services"
648                 echo "   list-components"
649                 echo "   list-files {cpt...|all}"
650                 echo "   install {cpt...|all}"
651                 echo "   uninstall {cpt...|all}"
652                 echo "   start {svc...}"
653                 echo "   stop {svc...}"
654                 echo "   print-platform"
655                 ;;
656               esac >&2
657               exit 1
658             }
659
660             if test x"\$1" = x"-q"; then
661                 shift
662                 verbose () { "\$@"; }
663                 verbosemsg () { : ; }
664             else
665                 verbose () { echo "+ \$*"; "\$@"; }
666                 verbosemsg () { echo "\$*"; }
667             fi
668 .
669 }
670
671
672 pp_functions () {
673     typeset func deps allfuncs
674     allfuncs=
675     while test $# -gt 0; do
676         pp_add_to_list allfuncs "$1"
677         deps=`pp_backend_function "$1:depends"`
678         shift
679         set -- `pp_unique "$@" $deps`
680     done
681
682     for func in $allfuncs
683     do
684         pp_debug "generating function code for '$1'"
685         echo ""
686         echo "$func () {"
687         case "$func" in
688             pp_mkgroup|pp_mkuser|pp_havelib) echo <<.;;
689                 if test \$# -lt 1; then
690                     echo "$func: not enough arguments" >&2
691                     return 1
692                 fi
693 .
694         esac
695         pp_backend_function "$func" || cat <<.
696                 echo "$func: not implemented" >&2
697                 return 1
698 .
699         echo "}"
700     done
701 }
702
703 pp_function () {
704     pp_functions "$1"
705 }
706
707 pp_makevar () {
708     #-- convert all non alpha/digits to underscores
709     echo "$*" | tr -c '[a-z][A-Z][0-9]\012' '[_*]'
710 }
711
712 pp_getpwuid () {
713     awk -F: '$3 == uid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' uid="$1" \
714         < /etc/passwd || pp_error "no local username for uid $1"
715 }
716
717 pp_getgrgid () {
718     awk -F: '$3 == gid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' gid="$1" \
719         < /etc/group || pp_error "no local group for gid $1"
720 }
721
722 pp_backend_function_getopt () {
723     cat <<'..'
724 pp_getopt () {
725      _pp_optstring="$1"; shift; eval `_pp_getopt "$_pp_optstring"`
726 }
727 _pp_getopt_meta=s,[\\\\\"\'\`\$\&\;\(\)\{\}\#\%\ \      ],\\\\\&,g
728 _pp_protect () {
729     sed "$_pp_getopt_meta" <<. | tr '\012' ' '
730 $*
731 .
732 }
733 _pp_protect2 () {
734     sed "s,^..,,$pp_getopt_meta" <<. | tr '\012' ' '
735 $*
736 .
737 }
738 _pp_nonl () {
739     tr '\012' ' ' <<.
740 $*
741 .
742 }
743 _pp_getopt () {
744     _pp_nonl '_pp_nonl set --; while test $# -gt 0; do case "$1" in "--") shift; break;;'
745     sed 's/\([^:        ]:*\)/<@<\1>@>/g;
746          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' <<.
747 $1
748 .
749     _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'
750     echo
751 }
752 ..
753 }
754
755 pp_copy_unstripped () {
756     typeset filedir realdir
757     filedir="`dirname ${1#$pp_destdir}`"
758     realdir="$pp_wrkdir/unstripped/$filedir"
759
760     mkdir -p "$realdir"
761     # Can't use hardlinks because `strip` modifies the original file in-place
762     cp "$1" "$realdir"
763 }
764
765 pp_package_stripped_binaries () {
766     (cd "$pp_wrkdir/unstripped" && tar -c .) \
767      | gzip > "$name-dbg-$version.tar.gz"
768     rm -rf "$pp_wrkdir/unstripped"
769 }
770
771 pp_strip_binaries () {
772     if test x"$pp_opt_save_unstripped" = x"true"; then
773         rm  -rf "$pp_wrkdir/unstripped"
774         mkdir "$pp_wrkdir/unstripped"
775     fi
776
777     for f in `find "$pp_destdir" -type f`; do
778         if file "$f" | awk '{print $2}' | grep ^ELF >/dev/null 2>&1; then
779             if test x"$pp_opt_save_unstripped" = x"true"; then
780                 if file "$f" | LC_MESSAGES=C grep 'not stripped' >/dev/null 2>&1; then
781                     pp_debug "Saving unstripped binary $f"
782                     pp_copy_unstripped "$f"
783                 else
784                     pp_debug "$f is already stripped; not saving a copy"
785                 fi
786             fi
787             pp_debug "Stripping unnecessary symbols from $f"
788             strip "$f"
789         fi
790     done
791
792     if test x"$pp_opt_save_unstripped" = x"true"; then
793         pp_package_stripped_binaries
794     fi
795 }
796
797 pp_if_true=0
798 pp_if_false=0
799
800 pp_frontend_init () {
801     name=
802     version=
803     summary="no summary"
804     description="No description"
805     copyright="Copyright 2012 Quest Software, Inc. ALL RIGHTS RESERVED."
806
807     #-- if the user supplied extra arguments on the command line
808     #   then load them now.
809     pp_debug "pp_opt_init_vars=$pp_opt_init_vars"
810     test -n "$pp_opt_init_vars" && eval "$pp_opt_init_vars"
811 }
812
813 pp_is_qualifier () {
814     typeset ret
815
816     case "$1" in
817         "["*"]") ret=true;;
818         *)       ret=false;;
819     esac
820     pp_debug "is_qualifier: $* -> $ret"
821     test $ret = true
822 }
823
824 pp_eval_qualifier () {
825     typeset ret
826
827     case "$1" in
828         "[!$pp_platform]"| \
829          "[!"*",$pp_platform]"| \
830          "[!$pp_platform,"*"]"| \
831          "[!"*",$pp_platform,"*"]") ret=false;;
832         "[!"*"]") ret=true;;
833         "[$pp_platform]"| \
834          "["*",$pp_platform]"| \
835          "[$pp_platform,"*"]"| \
836          "["*",$pp_platform,"*"]") ret=true;;
837         "["*"]") ret=false;;
838         *) pp_die "pp_eval_qualifier: bad qualifier '$1'"
839     esac
840     pp_debug "eval: $* -> $ret"
841     test true = $ret
842 }
843
844 pp_frontend_if () {
845     typeset ifcmd ifret
846     ifcmd="$1";
847     shift
848     case "$ifcmd" in
849         %if) if test 0 = $pp_if_false; then
850                 case "$*" in
851                     true |1) pp_incr pp_if_true;;
852                     false|0) pp_incr pp_if_false;;
853                     *)
854                         ifret=true
855                         if pp_is_qualifier "$*"; then
856                             pp_eval_qualifier "$*" || ifret=false
857                         else
858                             eval test "$@" || ifret=false
859                             pp_debug "evaluating test $* -> $ifret"
860                         fi
861                         pp_incr pp_if_$ifret
862                         ;;
863                 esac
864              else
865                 pp_incr pp_if_false
866              fi;;
867         %else)  test $# = 0 || pp_warn "ignoring argument to %else"
868                 if test $pp_if_false -gt 1; then
869                   : no change
870                 elif test $pp_if_false = 1; then
871                   pp_incr pp_if_true
872                   pp_decr pp_if_false
873                 elif test $pp_if_true = 0; then
874                   pp_die "unmatched %else"
875                 else
876                   pp_incr pp_if_false
877                   pp_decr pp_if_true
878                 fi;;
879         %endif) test $# = 0 || pp_warn "ignoring argument to %endif"
880                 if test $pp_if_false -gt 0; then
881                   pp_decr pp_if_false
882                 elif test $pp_if_true -gt 0; then
883                   pp_decr pp_if_true
884                 else
885                   pp_die "unmatched %endif"
886                 fi;;
887         *) pp_die "frontend_if: unknown cmd $ifcmd";;
888     esac
889 }
890
891
892 pp_frontend () {
893   typeset section newsection sed_word sed_ws line cpt svc
894   typeset section_enabled newsection_enabled s sed sed_candidate
895
896   section='%_initial'
897   newsection='%_initial'
898   section_enabled=:
899   newsection_enabled=:
900   sed_word="[a-zA-Z_][a-zA-Z_0-9]*"
901   sed_ws="[     ]"
902
903   #-- not all seds are created equal
904   sed=
905   for sed_candidate in ${PP_SED:-sed} /usr/xpg4/bin/sed; do
906       if echo 'foo' | $sed_candidate -ne '/^\(x\)*foo/p' | grep foo > /dev/null
907       then
908         sed="$sed_candidate"
909         break
910       fi
911   done
912   test -z "$sed" &&
913         pp_die "sed is broken on this system"
914
915   pp_lineno=0
916
917   #-- Note: this sed script should perform similar to pp_eval_qualifier()
918   $sed -e "/^#/s/.*//" \
919        -e "/^\\[!\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]/s/.*//" \
920        -e "s/^\\[\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]$sed_ws*//" \
921        -e "s/^\\[!\\($sed_word,\\)*$sed_word\\]$sed_ws*//" \
922        -e "/^\\[\\($sed_word,\\)*$sed_word\\]/s/.*//" \
923        -e "s/^%$sed_ws*/%/" \
924        -e "s/^$sed_ws/%\\\\&/" \
925      > $pp_wrkdir/frontend.tmp
926
927   #-- add an ignore section at the end to force section completion
928   echo '%ignore' >> $pp_wrkdir/frontend.tmp
929   echo  >> $pp_wrkdir/frontend.tmp
930
931   exec 0<$pp_wrkdir/frontend.tmp
932   : > $pp_wrkdir/tmp
933   : > $pp_wrkdir/%fixup
934   while read -r line; do
935      #-- Convert leading double-% to single-%, or switch sections
936      pp_incr pp_lineno
937
938      pp_debug "line $pp_lineno: $line"
939      set -f
940      set -- $line
941      set +f
942      #pp_debug "line $pp_lineno: $*"
943
944      case "$line" in %*)
945         case "$1" in
946            %if|%else|%endif)
947                 pp_debug "processing if directive $1"
948                 pp_frontend_if "$@"
949                 continue;;
950         esac
951         test 0 -ne $pp_if_false && continue     # ignore lines %if'd out
952
953         case "$1" in
954           %set|%fixup|%ignore)
955              pp_debug "processing new section $1"
956              newsection="$1"; shift
957              newsection_enabled=:
958              if pp_is_qualifier "$1"; then
959                 pp_eval_qualifier "$1" || newsection_enabled=false
960                 shift
961              fi
962              test $# -eq 0 || pp_warn "ignoring extra arguments: $line"
963              continue;;
964           %pre|%post|%preun|%postup|%postun|%files|%depend|%check|%conflict)
965              pp_debug "processing new component section $*"
966              s="$1"; shift
967              if test $# -eq 0 || pp_is_qualifier "$1"; then
968                 cpt=run
969              else
970                 cpt="$1"
971                 shift
972              fi
973              newsection="$s.$cpt"
974              newsection_enabled=:
975              if test $# -gt 0 && pp_is_qualifier "$1"; then
976                 pp_eval_qualifier "$1" || newsection_enabled=false
977                 shift
978              fi
979              test $# -eq 0 ||
980                 pp_warn "ignoring extra arguments: $line"
981              case "$cpt" in
982                 run|dbg|doc|dev)
983                     $newsection_enabled && pp_add_component "$cpt";;
984                 x-*) :;;    # useful for discarding stuff
985                 *) pp_error "unknown component: $1 $cpt";;
986              esac
987              continue;;
988           %pp)
989             newsection="%ignore"; shift
990             if test $# -gt 0; then
991                 pp_set_api_version "$1"
992                 shift
993             else
994                 pp_error "%pp: missing version"
995             fi
996             test $# -gt 0 &&
997                 pp_error "%pp: too many arguments"
998             continue;;
999           %service)
1000              pp_debug "processing new service section $1 $2"
1001              s="$1"; shift
1002              if test $# -eq 0 || pp_is_qualifier "$1"; then
1003                 pp_error "$s: service name required"
1004                 svc=unknown
1005              else
1006                 svc="$1"; shift
1007              fi
1008
1009              newsection="$s.$svc"
1010              newsection_enabled=:
1011              if test $# -gt 0 && pp_is_qualifier "$1"; then
1012                 pp_eval_qualifier "$1" || newsection_enabled=false
1013                 shift
1014              fi
1015              test $# -eq 0 ||
1016                 pp_warn "ignoring extra arguments: $line"
1017              $newsection_enabled && pp_add_service "$svc"
1018              continue;;
1019           %\\*)
1020              pp_debug "removing leading %\\"
1021              line="${line#??}"
1022              pp_debug "  result is <$line>"
1023              set -f
1024              set -- $line
1025              set +f
1026              ;;
1027           %%*)
1028              pp_debug "removing leading %"
1029              line="${line#%}"
1030              set -f
1031              set -- $line
1032              set +f
1033              ;;
1034           %*)
1035              pp_error "unknown section $1"
1036              newsection='%ignore'
1037              newsection_enabled=:
1038              continue;;
1039         esac;;
1040      esac
1041
1042      test 0 != $pp_if_false && continue # ignore lines %if'd out
1043
1044      pp_debug "section=$section (enabled=$section_enabled) newsection=$newsection (enabled=$newsection_enabled)"
1045
1046      #-- finish processing a previous section
1047      if test x"$newsection" != x""; then
1048       $section_enabled && case "$section" in
1049         %ignore|%_initial)
1050                 pp_debug "leaving ignored section $section"
1051                 : ignore  # guaranteed to be the last section
1052                 ;;
1053         %set)
1054                 pp_debug "leaving $section: sourcing $pp_wrkdir/tmp"
1055                 $pp_opt_debug && cat $pp_wrkdir/tmp >&2
1056                 . $pp_wrkdir/tmp
1057                 : > $pp_wrkdir/tmp
1058                 ;;
1059         %pre.*|%preun.*|%post.*|%postup.*|%postun.*|%depend.*|%check.*|%conflict.*|%service.*|%fixup)
1060                 pp_debug "leaving $section: substituting $pp_wrkdir/tmp"
1061                 # cat $pp_wrkdir/tmp >&2    # debugging
1062                 $pp_opt_debug && pp_substitute < $pp_wrkdir/tmp >&2
1063                 pp_substitute < $pp_wrkdir/tmp > $pp_wrkdir/tmp.sh
1064                 . $pp_wrkdir/tmp.sh >> $pp_wrkdir/$section ||
1065                     pp_error "shell error in $section"
1066                 rm -f $pp_wrkdir/tmp.sh
1067                 : > $pp_wrkdir/tmp
1068                 ;;
1069       esac
1070       section="$newsection"
1071       section_enabled="$newsection_enabled"
1072       newsection=
1073      fi
1074
1075      #-- ignore section content that is disabled
1076      $section_enabled || continue
1077
1078      #-- process some lines in-place
1079      case "$section" in
1080         %_initial)
1081                 case "$line" in "") continue;; esac # ignore non-section blanks
1082                 pp_die "Ignoring text before % section introducer";;
1083         %set|%pre.*|%preun.*|%post.*|%postup.*|%postun.*|%check.*|%service.*|%fixup)
1084                 pp_debug "appending line to \$pp_wrkdir/tmp"
1085                 echo "$line" >> $pp_wrkdir/tmp
1086                 ;;
1087         %files.*)
1088                 test $# -eq 0 && continue;
1089                 pp_files_expand "$@" >> $pp_wrkdir/$section
1090                 ;;
1091         %depend.*)
1092                 pp_debug "Adding explicit dependency $@ to $cpt"
1093                 echo "$@" >> $pp_wrkdir/%depend.$cpt
1094                 ;;
1095         %conflict.*)
1096                 pp_debug "Adding explicit conflict $@ to $cpt"
1097                 echo "$@" >> $pp_wrkdir/%conflict.$cpt
1098                 ;;
1099      esac
1100   done
1101   exec <&-
1102
1103   if test $pp_if_true != 0 -o $pp_if_false != 0; then
1104         pp_die "missing %endif at end of file"
1105   fi
1106
1107   pp_lineno=
1108
1109   pp_debug " name        = $name"
1110   pp_debug " version     = $version"
1111   pp_debug " summary     = $summary"
1112   pp_debug " description = $description"
1113   pp_debug " copyright   = $copyright"
1114   pp_debug ""
1115   pp_debug "\$pp_components: $pp_components"
1116   pp_debug "\$pp_services:   $pp_services"
1117 }
1118
1119 pp_set_api_version() {
1120     case "$1" in
1121         1.0)    : ;;
1122         *)      pp_error "This version of polypackage is too old";;
1123     esac
1124 }
1125
1126 pp_platform=
1127
1128 pp_set_platform () {
1129     if test -n "$pp_opt_platform"; then
1130         pp_contains "$pp_platforms" "$pp_opt_platform" ||
1131                 pp_die "$pp_opt_platform: unknown platform"
1132         pp_platform="$pp_opt_platform"
1133     else
1134         uname_s=`uname -s 2>/dev/null`
1135         pp_platform=
1136         for p in $pp_platforms; do
1137             pp_debug "probing for platform $p"
1138             if eval pp_backend_${p}_detect "$uname_s"; then
1139                 pp_platform="$p"
1140                 break;
1141             fi
1142         done
1143         test -z "$pp_platform" &&
1144                 pp_die "cannot detect platform (supported: $pp_platforms)"
1145     fi
1146     pp_debug "pp_platform = $pp_platform"
1147 }
1148
1149 pp_expand_path=
1150
1151 pp_expand_test_usr_bin () {
1152         awk '$1 == "/usr" || $2 == "/usr" {usr++}
1153              $1 == "/bin" || $2 == "/bin" {bin++}
1154              END { if (usr == 1 && bin == 1) exit(0); else exit(1); }'
1155 }
1156
1157 pp_set_expand_converter_or_reexec () {
1158     test -d /usr -a -d /bin ||
1159         pp_die "missing /usr or /bin"
1160     echo /usr /bin | pp_expand_test_usr_bin || pp_die "pp_expand_test_usr_bin?"
1161     if (eval "echo /{usr,bin}" | pp_expand_test_usr_bin) 2>/dev/null; then
1162         pp_expand_path=pp_expand_path_brace
1163     elif (eval "echo /@(usr|bin)" | pp_expand_test_usr_bin) 2>/dev/null; then
1164         pp_expand_path=pp_expand_path_at
1165     else
1166         test x"$pp_expand_rexec" != x"true" ||
1167             pp_die "problem finding shell that can do brace expansion"
1168         for shell in ksh ksh93 bash; do
1169             if ($shell -c 'echo /{usr,bin}' |
1170                         pp_expand_test_usr_bin) 2>/dev/null ||
1171                ($shell -c 'echo /@(usr|bin)' |
1172                         pp_expand_test_usr_bin) 2>/dev/null
1173             then
1174                 pp_debug "switching to shell $shell"
1175                 pp_expand_rexec=true exec $shell "$0" "$@"
1176             fi
1177         done
1178         pp_die "cannot find a shell that does brace expansion"
1179     fi
1180 }
1181
1182 pp_expand_path_brace () {
1183         typeset f
1184         eval "for f in $1; do echo \"\$f\"; done|sort -u"
1185 }
1186
1187 pp_expand_path_at () {
1188         typeset f
1189         eval "for f in `
1190             echo "$1" | sed -e 's/{/@(/g' -e 's/}/)/g' -e 's/,/|/g'
1191                 `; do echo \"\$f\"; done|sort -u"
1192 }
1193
1194 pp_shlib_suffix='.so*'
1195
1196 pp_model_init () {
1197     #@ $pp_components: whitespace-delimited list of components seen in %files
1198     pp_components=
1199     #@ $pp_services: whitespace-delimited list of %service seen
1200     pp_services=
1201
1202     rm -f $pp_wrkdir/%files.* \
1203           $pp_wrkdir/%post.* \
1204           $pp_wrkdir/%pre.* \
1205           $pp_wrkdir/%preun.* \
1206           $pp_wrkdir/%postup.* \
1207           $pp_wrkdir/%postun.* \
1208           $pp_wrkdir/%service.* \
1209           $pp_wrkdir/%set \
1210           $pp_wrkdir/%fixup
1211 }
1212
1213
1214 pp_have_component () {
1215         pp_contains "$pp_components" "$1"
1216 }
1217
1218 pp_have_all_components () {
1219         pp_contains_all "$pp_components" "$@"
1220 }
1221
1222 pp_add_component () {
1223         pp_add_to_list 'pp_components' "$1"
1224 }
1225
1226 pp_add_service () {
1227         pp_add_to_list 'pp_services' "$1"
1228 }
1229
1230 pp_service_init_vars () {
1231         cmd=
1232         pidfile=
1233         stop_signal=15          # SIGTERM
1234         user=root
1235         group=
1236         enable=yes              # make it so the service starts on boot
1237         optional=no             # Whether installing this service is optional
1238         pp_backend_init_svc_vars
1239 }
1240
1241 pp_service_check_vars () {
1242         test -n "$cmd" ||
1243                 pp_error "%service $1: cmd not defined"
1244         case "$enable" in
1245             yes|no) : ;;
1246             *) pp_error "%service $1: \$enable must be set to yes or no";;
1247         esac
1248 }
1249
1250 pp_load_service_vars () {
1251         pp_service_init_vars
1252         . "$pp_wrkdir/%service.$1"
1253         pp_service_check_vars "$1"
1254 }
1255
1256 pp_files_expand () {
1257     typeset _p _mode _group _owner _flags _path _optional _has_target _tree
1258     typeset _path _file _tgt _m _o _g _f _type _lm _ll _lo _lg _ls _lx
1259     typeset _ignore _a
1260
1261     test $# -eq 0 && return
1262
1263     pp_debug "pp_files_expand: path is: $1"
1264
1265     case "$1" in "#"*) return;; esac
1266     _p="$1"; shift
1267
1268     pp_debug "pp_files_expand: other arguments: $*"
1269
1270     #-- the mode must be an octal number of at least three digits
1271     _mode="="
1272     _a=`eval echo \"$1\"`
1273     case "$_a" in
1274         *:*) :;;
1275         -|=|[01234567][01234567][01234567]*) _mode="$_a"; shift;;
1276     esac
1277
1278     #-- the owner:group field may have optional parts
1279     _a=`eval echo \"$1\"`
1280     case "$_a" in
1281         *:*) _group=${_a#*:}; _owner=${_a%:*}; shift;;
1282         =|-) _group=$_a;      _owner=$_a; shift;;
1283         *)   _group=;         _owner=;;
1284     esac
1285
1286     #-- process the flags argument
1287     _flags=
1288     _optional=false
1289     _has_target=false
1290     _ignore=false
1291     if test $# -gt 0; then
1292         _a=`eval echo \"$1\"`
1293         case ",$_a," in *,volatile,*) _flags="${_flags}v";; esac
1294         case ",$_a," in *,optional,*) _optional=true;; esac
1295         case ",$_a," in *,symlink,*) _has_target=true;; esac
1296         case ",$_a," in *,ignore-others,*) _flags="${_flags}i";; esac
1297         case ",$_a," in *,ignore,*) _ignore=true;; esac
1298         shift
1299     fi
1300
1301     #-- process the target argument
1302     if $_has_target; then
1303         test $# -ne 0 || pp_error "$_p: missing target"
1304         _a=`eval echo \"$1\"`
1305         _target="$_a"
1306         shift
1307     fi
1308
1309     pp_debug "pp_files_expand: $_mode|$_owner:$_group|$_flags|$_target|$*"
1310
1311     test $# -eq 0 || pp_error "$_p: too many arguments"
1312
1313     #-- process speciall suffixes
1314     tree=
1315     case "$_p" in
1316         *"/**")  _p="${_p%"/**"}"; tree="**";;
1317         *".%so") _p="${_p%".%so"}$pp_shlib_suffix";;
1318     esac
1319
1320     #-- expand the path using the shell glob
1321     pp_debug "expanding .$_p ... with $pp_expand_path"
1322     (cd ${pp_destdir} && $pp_expand_path ".$_p") > $pp_wrkdir/tmp.files.exp
1323
1324     #-- expand path/** by rewriting the glob output file
1325     case "$tree" in
1326         "") : ;;
1327         "**")
1328             pp_debug "expanding /** tree ..."
1329             while read _path; do
1330                 _path="${_path#.}"
1331                 pp_find_recurse "$pp_destdir${_path%/}"
1332             done < $pp_wrkdir/tmp.files.exp |
1333                  sort -u > $pp_wrkdir/tmp.files.exp2
1334             mv $pp_wrkdir/tmp.files.exp2 $pp_wrkdir/tmp.files.exp
1335             ;;
1336     esac
1337
1338     while read _path; do
1339         _path="${_path#.}"
1340         _file="${pp_destdir}${_path}"
1341         _tgt=
1342         _m="$_mode"
1343         _o="${_owner:--}"
1344         _g="${_group:--}"
1345         _f="$_flags"
1346
1347         case "$_path" in
1348             /*) :;;
1349             *)  pp_warn "$_path: inserting leading /"
1350                 _path="/$_path";;  # ensure leading /
1351         esac
1352
1353         #-- sanity checks
1354         case "$_path" in
1355             */../*|*/..) pp_error "$_path: invalid .. in path";;
1356             */./*|*/.)   pp_warn  "$_path: invalid component . in path";;
1357             *//*)        pp_warn  "$_path: redundant / in path";;
1358         esac
1359
1360         #-- set the type based on the real file's type
1361         if $_ignore; then
1362            _type=f _m=_ _o=_ _g=_
1363         elif test -h "$_file"; then
1364            case "$_path" in
1365                 */) pp_warn "$_path (symlink $_file): removing trailing /"
1366                     _path="${_path%/}"
1367                     ;;
1368            esac
1369            _type=s
1370            if test x"$_target" != x"=" -a -n "$_target"; then
1371                _tgt="$_target"
1372 pp_debug "symlink target is $_tgt"
1373            else
1374                _tgt=`pp_readlink "$_file"`;
1375                test -z "$_tgt" && pp_error "can't readlink $_file"
1376                case "$_tgt" in
1377                     ${pp_destdir}/*)
1378                        pp_warn "stripped \$destdir from symlink ($_path)"
1379                        _tgt="${_tgt#$pp_destdir}";;
1380                esac
1381            fi
1382            _m=777
1383         elif test -d "$_file"; then
1384            #-- display a warning if the user forgot the trailing /
1385            case "$_path" in
1386                 */) :;;
1387                 *) pp_warn "$_path (matching $_file): adding trailing /"
1388                    _path="$_path/";;
1389            esac
1390            _type=d
1391            $_has_target && pp_error "$_file: not a symlink"
1392         elif test -f "$_file"; then
1393            case "$_path" in
1394                 */) pp_warn "$_path (matching $_file): removing trailing /"
1395                     _path="${_path%/}"
1396                     ;;
1397            esac
1398            _type=f
1399            $_has_target && pp_error "$_file: not a symlink"
1400         else
1401            $_optional && continue
1402            pp_error "$_file: missing"
1403            _type=f
1404         fi
1405
1406         #-- convert '=' shortcuts into mode/owner/group from ls
1407         case ":$_m:$_o:$_g:" in *:=:*)
1408             if LS_OPTIONS=--color=never /bin/ls -ld "$_file" \
1409                     > $pp_wrkdir/ls.tmp
1410             then
1411                 read _lm _ll _lo _lg _ls _lx < $pp_wrkdir/ls.tmp
1412                 test x"$_m" = x"=" && _m=`pp_mode_from_ls "$_lm"`
1413                 test x"$_o" = x"=" && _o="$_lo"
1414                 test x"$_g" = x"=" && _g="$_lg"
1415             else
1416                 pp_error "cannot read $_file"
1417                 test x"$_m" = x"=" && _m=-
1418                 test x"$_o" = x"=" && _o=-
1419                 test x"$_g" = x"=" && _g=-
1420             fi
1421             ;;
1422         esac
1423
1424         test -n "$_f" || _f=-
1425
1426         #-- sanity checks
1427         test -n "$_type" || pp_die "_type empty"
1428         test -n "$_path" || pp_die "_path empty"
1429         test -n "$_m" || pp_die "_m empty"
1430         test -n "$_o" || pp_die "_o empty"
1431         test -n "$_g" || pp_die "_g empty"
1432
1433         #-- setuid/gid files must be given an explicit owner/group (or =)
1434         case "$_o:$_g:$_m" in
1435             -:*:[4657][1357]??|-:*:[4657]?[1357]?|-:*:[4657]??[1357])
1436                 pp_error "$_path: setuid file ($_m) missing explicit owner";;
1437             *:-:[2367][1357]??|*:-:[2367]?[1357]?|*:-:[2367]??[1357])
1438                 pp_error "$_path: setgid file ($_m) missing explicit group";;
1439         esac
1440
1441         # convert numeric uids into usernames; only works for /etc/passwd
1442         case "$_o" in [0-9]*) _o=`pp_getpwuid $_o`;; esac
1443         case "$_g" in [0-9]*) _g=`pp_getgrgid $_g`;; esac
1444
1445         pp_debug "$_type $_m $_o $_g $_f $_path" $_tgt
1446         $_ignore || echo "$_type $_m $_o $_g $_f $_path" $_tgt
1447         pp_note_file_used "$_path"
1448         case "$_f" in *i*) echo "$_path" >> $pp_wrkdir/ign.files;; esac
1449     done < $pp_wrkdir/tmp.files.exp
1450 }
1451
1452 pp_files_check_duplicates () {
1453     typeset _path
1454     if test -s $pp_wrkdir/all.files; then
1455         sort < $pp_wrkdir/all.files | uniq -d > $pp_wrkdir/duplicate.files
1456         if test -f $pp_wrkdir/ign.awk; then
1457             # Remove ignored files
1458             mv $pp_wrkdir/duplicate.files $pp_wrkdir/duplicate.files.ign
1459             sed -e 's/^/_ _ _ _ _ /' < $pp_wrkdir/duplicate.files.ign |
1460                 awk -f $pp_wrkdir/ign.awk |
1461                 sed -e 's/^_ _ _ _ _ //' > $pp_wrkdir/duplicate.files
1462         fi
1463         while read _path; do
1464             pp_warn "$_path: file declared more than once"
1465         done <$pp_wrkdir/duplicate.files
1466     fi
1467 }
1468
1469 pp_files_check_coverage () {
1470     pp_find_recurse "$pp_destdir" | sort > $pp_wrkdir/coverage.avail
1471     if test -s $pp_wrkdir/all.files; then
1472         sort -u < $pp_wrkdir/all.files
1473     else
1474         :
1475     fi > $pp_wrkdir/coverage.used
1476     join -v1 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
1477         > $pp_wrkdir/coverage.not-packaged
1478     if test -s $pp_wrkdir/coverage.not-packaged; then
1479         pp_warn "The following files/directories were found but not packaged:"
1480         sed -e 's,^,    ,' <  $pp_wrkdir/coverage.not-packaged >&2
1481     fi
1482     join -v2 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
1483         > $pp_wrkdir/coverage.not-avail
1484     if test -s $pp_wrkdir/coverage.not-avail; then
1485         pp_warn "The following files/directories were named but not found:"
1486         sed -e 's,^,    ,' <  $pp_wrkdir/coverage.not-avail >&2
1487     fi
1488 }
1489
1490 pp_files_ignore_others () {
1491     typeset p f
1492
1493     test -s $pp_wrkdir/ign.files || return
1494
1495     #-- for each file in ign.files, we remove it from all the
1496     #   other %files.* lists, except where it has an i flag.
1497     #   rather than scan each list multiple times, we build
1498     #   an awk script
1499
1500     pp_debug "stripping ignore files"
1501
1502     while read p; do
1503         echo '$6 == "'"$p"'" && $5 !~ /i/ { next }'
1504     done < $pp_wrkdir/ign.files > $pp_wrkdir/ign.awk
1505     echo '{ print }' >> $pp_wrkdir/ign.awk
1506
1507     $pp_opt_debug && cat $pp_wrkdir/ign.awk
1508
1509     for f in $pp_wrkdir/%files.*; do
1510         mv $f $f.ign
1511         awk -f $pp_wrkdir/ign.awk < $f.ign > $f || pp_error "awk"
1512     done
1513 }
1514
1515 pp_service_scan_groups () {
1516     typeset svc
1517
1518     #-- scan for "group" commands, and build a list of groups
1519     pp_service_groups=
1520     if test -n "$pp_services"; then
1521         for svc in $pp_services; do
1522             group=
1523             . $pp_wrkdir/%service.$svc
1524             if test -n "$group"; then
1525                 pp_contains "$pp_services" "$group" && pp_error \
1526                     "%service $svc: group name $group in use by a service"
1527                 pp_add_to_list 'pp_service_groups' "$group"
1528                 echo "$svc" >> $pp_wrkdir/%svcgrp.$group
1529             fi
1530         done
1531     fi
1532 }
1533
1534 pp_service_get_svc_group () {
1535     (tr '\012' ' ' < $pp_wrkdir/%svcgrp.$1 ; echo) | sed -e 's/ $//'
1536 }
1537
1538 for _sufx in _init '' _names _cleanup _install_script \
1539     _init_svc_vars _function _probe _vas_platforms
1540 do
1541  eval "pp_backend$_sufx () { pp_debug pp_backend$_sufx; pp_backend_\${pp_platform}$_sufx \"\$@\"; }"
1542 done
1543
1544
1545 pp_platforms="$pp_platforms aix"
1546
1547 pp_backend_aix_detect () {
1548         test x"$1" = x"AIX"
1549 }
1550
1551 pp_backend_aix_init () {
1552         pp_aix_detect_arch
1553         pp_aix_detect_os
1554
1555         pp_aix_bosboot=         # components that need bosboot
1556         pp_aix_lang=en_US
1557         pp_aix_copyright=
1558         pp_aix_start_services_after_install=false
1559         pp_aix_init_services_after_install=true
1560
1561         pp_aix_sudo=sudo        # AIX package tools must run as root
1562
1563         case "$pp_aix_os" in
1564             *) pp_readlink_fn=pp_ls_readlink;;  # XXX
1565         esac
1566
1567         pp_aix_abis_seen=
1568 }
1569
1570 pp_aix_detect_arch () {
1571         pp_aix_arch_p=`uname -p 2>/dev/null`
1572         case "$pp_aix_arch_p"  in
1573            "")      pp_debug "can't get processor type from uname -p"
1574                     pp_aix_arch_p=powerpc
1575                     pp_aix_arch=R;;  # guess (lsattr -l proc0 ??)
1576            powerpc) pp_aix_arch=R;;
1577            *)       pp_aix_arch_p=intel
1578                     pp_aix_arch=I;;  # XXX? verify
1579         esac
1580
1581         case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
1582             PowerPC_POWER*) pp_aix_arch_std=ppc64;;
1583             PowerPC*) pp_aix_arch_std=ppc;;
1584             *) pp_aix_arch_std=unknown;;
1585         esac
1586 }
1587
1588 pp_aix_detect_os () {
1589         typeset r v
1590
1591         r=`uname -r`
1592         v=`uname -v`
1593         pp_aix_os=aix$v$r
1594 }
1595
1596 pp_aix_version_fix () {
1597     typeset v
1598     v=`echo $1 | sed 's/[-+]/./' | tr -c -d '[0-9].\012' | awk -F"." '{ printf "%d.%d.%d.%.4s\n", $1, $2, $3, $4 }' | sed 's/[.]*$//g'`
1599     if test x"$v" != x"$1"; then
1600         pp_warn "stripped version '$1' to '$v'"
1601     fi
1602     case $v in
1603         ""|*..*|.*|*.) pp_error "malformed '$1'"
1604                  echo "0.0.0.0";;
1605         *.*.*.*.*)
1606                  # 5 components are only valid for fileset updates, not base
1607                  # filesets (full packages). We trim 5+ components down to 4.
1608                  pp_warn "version '$1' has too many dots for AIX, truncating"
1609                  echo "$v" | cut -d. -f1-4;;
1610         *.*.*.*) echo "$v";;
1611         *.*.*) echo "$v.0";;
1612         *.*) echo "$v.0.0";;
1613         *) echo "$v.0.0.0";;
1614     esac
1615 }
1616
1617 pp_aix_select () {
1618         case "$1" in
1619             -user) op="";;
1620             -root) op="!";;
1621             *) pp_die "pp_aix_select: bad argument";;
1622         esac
1623         #pp_debug awk '$5 '$op' /^\/(usr|opt)(\/|$)/ { print; }'
1624         #awk '$5 '$op' /^\/(usr|opt)(\/|$)/ { print; }'
1625         awk $op'($6 ~ /^\/usr\// || $6 ~ /^\/opt\//) { print; }'
1626 }
1627
1628 pp_aix_copy_root () {
1629     typeset t m o g f p st target
1630     while read t m o g f p st; do
1631         case "$t" in
1632            d) pp_create_dir_if_missing "$1${p%/}";;
1633            f) pp_add_transient_file "$1$p"
1634               pp_verbose ln "$pp_destdir$p" "$pp_destdir$1$p" ||
1635                 pp_error "can't link $p into $1";;
1636            *) pp_warn "pp_aix_copy_root: filetype $t not handled";;
1637         esac
1638     done
1639 }
1640
1641
1642 pp_aix_size () {
1643     typeset prefix t m o g f p st
1644
1645     prefix="$1"
1646     while read t m o g f p st; do
1647       case "$t" in f) du -a "$pp_destdir$p";; esac
1648     done | sed -e 's!/[^/]*$!!' | sort +1 |
1649     awk '{ if ($2 != d)
1650            { if (sz) print d,sz;
1651              d=$2; sz=0 }
1652            sz += $1; }
1653          END { if (sz) print d,sz }' |
1654     sed -n -e "s!^$pp_destdir!$prefix!p"
1655 }
1656
1657 pp_aix_list () {
1658     awk '{ print "." pfx $6; }' pfx="$1"
1659 }
1660
1661 pp_aix_make_liblpp () {
1662     typeset out dn fl f
1663
1664     out="$1"; shift
1665     dn=`dirname "$2"`
1666     fl=
1667     for f
1668     do
1669         case "$f" in "$dn/"*) fl="$fl `basename $f`" ;;
1670                      *) pp_die "liblpp name $f not in $dn/";; esac
1671     done
1672     (cd "$dn" && pp_verbose  ar -c -g -r "$out" $fl) || pp_error "ar error"
1673 }
1674
1675 pp_aix_make_script () {
1676     rm -f "$1"
1677     echo "#!/bin/sh" > "$1"
1678     cat >> "$1"
1679     echo "exit 0" >> "$1"
1680     chmod +x "$1"
1681 }
1682
1683 pp_aix_inventory () {
1684     typeset fileset t m o g f p st type
1685
1686     fileset="$1"
1687     while read t m o g f p st; do
1688       case "$p" in *:*) pp_error "path $p contains colon";; esac
1689       echo "$p:"
1690       case "$t" in
1691         f)   type=FILE;      defm=644 ;;
1692         s)   type=SYMLINK;   defm=777 ;;
1693         d)   type=DIRECTORY; defm=755 ;;
1694       esac
1695       echo " type = $type"
1696       echo " class = inventory,apply,$fileset"
1697       if test x"$m" = x"-"; then m="$defm"; fi
1698       if test x"$o" = x"-"; then o="root"; fi
1699       if test x"$g" = x"-"; then g="system"; fi
1700       echo " owner = $o"
1701       echo " group = $g"
1702
1703       case "$m" in ????)
1704         m=`echo $m|sed -e 's/^1/TCB,/' \
1705                        -e 's/^[23]/TCB,SGID,/' \
1706                        -e 's/^[45]/TCB,SUID,/' \
1707                        -e 's/^[67]/TCB,SUID,SGID,/'`;;  # vtx bit ignored
1708       esac
1709       echo " mode = $m"
1710       case "$t" in
1711         f) if test ! -f "$pp_destdir$p"; then
1712                 pp_error "$p: missing file"
1713            fi
1714            case "$flags" in
1715             *v*)
1716               echo " size = VOLATILE"
1717               echo " checksum = VOLATILE"
1718               ;;
1719             *)
1720               if test -r "$pp_destdir$p"; then
1721                 echo " size = $size"
1722                 pp_verbose  sum -r < "$pp_destdir$p" |
1723                   sed -e 's/.*/ checksum = "&"/'
1724               fi
1725               ;;
1726            esac;;
1727         s)
1728            echo " target = $st"
1729            ;;
1730       esac
1731
1732       #-- Record ABI types seen
1733       case "$t" in
1734         f) if test -r "$pp_destdir$p"; then
1735             case "`file "$pp_destdir$p"`" in
1736                 *"executable (RISC System/6000)"*) abi=ppc;;
1737                 *"64-bit XCOFF executable"*)       abi=ppc64;;
1738                 *) abi=;;
1739             esac
1740             if test -n "$abi"; then
1741                 pp_add_to_list pp_aix_abis_seen $abi
1742             fi
1743            fi;;
1744       esac
1745
1746     done
1747 }
1748
1749 pp_aix_depend ()
1750 {
1751     if test -s "$1"; then
1752        pp_warn "aix dependencies not implemented"
1753     fi
1754 }
1755
1756 pp_aix_add_service () {
1757         typeset svc cmd_cmd cmd_arg f
1758         svc="$1"
1759
1760         pp_load_service_vars $svc
1761
1762         set -- $cmd
1763         cmd_cmd="$1"; shift
1764         cmd_arg="${pp_aix_mkssys_cmd_args:-$*}";
1765
1766         case "$stop_signal" in
1767                 HUP) stop_signal=1;;
1768                 INT) stop_signal=2;;
1769                 QUIT) stop_signal=3;;
1770                 KILL) stop_signal=9;;
1771                 TERM) stop_signal=15;;
1772                 USR1) stop_signal=30;;
1773                 USR2) stop_signal=31;;
1774                 "")
1775                   pp_error "%service $svc: stop_signal not set";;
1776                 [a-zA-Z]*)
1777                   pp_error "%service $svc: bad stop_signal ($stop_signal)";;
1778         esac
1779
1780         test -z "$pidfile" || pp_error "aix requires empty pidfile (non daemon)"
1781
1782         pp_add_component run
1783         if test "$user" = "root"; then
1784             uid=0
1785         else
1786             uid="\"\`/usr/bin/id -u $user\`\""
1787         fi
1788
1789
1790         #-- add command text to create/remove the service
1791         cat <<-. >> $pp_wrkdir/%post.$svc
1792 svc=$svc
1793 uid=0
1794 cmd_cmd="$cmd_cmd"
1795 cmd_arg="$cmd_arg"
1796 stop_signal=$stop_signal
1797 force_signal=9
1798 srcgroup="$pp_aix_mkssys_group"
1799 instances_allowed=${pp_aix_mkssys_instances_allowed:--Q}
1800
1801 lssrc -s \$svc > /dev/null 2>&1
1802 if [ \$? -eq 0 ]; then
1803   lssrc -s \$svc | grep "active" > /dev/null 2>&1
1804   if [ \$? -eq 0 ]; then
1805     stopsrc -s \$svc > /dev/null 2>&1
1806   fi
1807   rmsys -s \$svc > /dev/null 2>&1
1808 fi
1809
1810 mkssys -s \$svc -u \$uid -p "\$cmd_cmd" \${cmd_arg:+-a "\$cmd_arg"} -S -n \$stop_signal -f 9 ${pp_aix_mkssys_args} \${srcgroup:+-G \$srcgroup} \$instances_allowed
1811 .
1812
1813         #-- add code to start the service on reboot
1814         ${pp_aix_init_services_after_install} &&
1815           cat <<-. >> $pp_wrkdir/%post.$svc
1816 id=\`echo "\$svc" | cut -c1-14\`
1817 mkitab "\$id:2:once:/usr/bin/startsrc -s \$svc" > /dev/null 2>&1
1818 .
1819
1820         ${pp_aix_start_services_after_install} &&
1821           cat <<-. >> $pp_wrkdir/%post.$svc
1822 startsrc -s \$svc
1823 .
1824
1825 if [ -f "$pp_wrkdir/%post.run" ];then
1826     cat $pp_wrkdir/%post.run >> $pp_wrkdir/%post.$svc
1827 fi
1828 mv $pp_wrkdir/%post.$svc $pp_wrkdir/%post.run
1829
1830
1831         ${pp_aix_init_services_after_install} &&
1832            pp_prepend $pp_wrkdir/%preun.$svc <<-.
1833 rmitab `echo "$svc" | cut -c1-14` > /dev/null 2>&1
1834 .
1835         pp_prepend $pp_wrkdir/%preun.$svc <<-.
1836 stopsrc -s $svc >/dev/null 2>&1
1837 rmssys -s $svc
1838 .
1839
1840 if [ -f "$pp_wrkdir/%preun.run" ];then
1841     cat $pp_wrkdir/%preun.run >> $pp_wrkdir/%preun.$svc
1842 fi
1843 mv $pp_wrkdir/%preun.$svc $pp_wrkdir/%preun.run
1844 }
1845
1846 pp_backend_aix () {
1847         typeset briefex instuser instroot svc cmp outbff
1848         typeset user_wrkdir root_wrkdir
1849         typeset user_files root_files
1850
1851         test -n "$pp_destdir" ||
1852            pp_error "AIX backend requires the '--destdir' option"
1853
1854         instuser="/usr/lpp/$name"
1855         instroot="$instuser/inst_root"
1856         pp_aix_bff_name=${pp_aix_bff_name:-$name}
1857
1858         # Here is the component mapping:
1859         #  run -> $pp_aix_bff_name.rte ('Run time environment')
1860         #  doc -> $pp_aix_bff_name.doc (non-standard)
1861         #  dev -> $pp_aix_bff_name.adt ('Application developer toolkit')
1862         #  dbg -> $pp_aix_bff_name.diag ('Diagnostics')
1863
1864         test `echo "$summary" | wc -c ` -gt 40 && pp_error "\$summary too long"
1865
1866         user_wrkdir=$pp_wrkdir/u
1867         root_wrkdir=$pp_wrkdir/r
1868         pp_verbose  rm -rf $user_wrkdir $root_wrkdir
1869         pp_verbose  mkdir -p $user_wrkdir $root_wrkdir
1870
1871         for svc in $pp_services .; do
1872             test . = "$svc" && continue
1873             pp_aix_add_service $svc
1874         done
1875
1876         {
1877           echo "4 $pp_aix_arch I $name {"
1878
1879           for cmp in $pp_components; do
1880             case "$cmp" in
1881                 run) ex=rte  briefex="runtime";;
1882                 doc) ex=doc  briefex="documentation";;
1883                 dev) ex=adt  briefex="developer toolkit";;
1884                 dbg) ex=diag briefex="diagnostics";;
1885             esac
1886
1887             user_files=$pp_wrkdir/%files.$cmp.u
1888             root_files=$pp_wrkdir/%files.$cmp.r
1889
1890             pp_aix_select -user < $pp_wrkdir/%files.$cmp > $user_files
1891             pp_aix_select -root < $pp_wrkdir/%files.$cmp > $root_files
1892
1893             # Default to USR only unless there are root files,
1894             # or a post/pre/check script associated
1895             content=U
1896             if test -s $root_files \
1897                     -o -s $pp_wrkdir/%pre.$cmp \
1898                     -o -s $pp_wrkdir/%post.$cmp \
1899                     -o -s $pp_wrkdir/%preun.$cmp \
1900                     -o -s $pp_wrkdir/%postun.$cmp \
1901                     -o -s $pp_wrkdir/%check.$cmp
1902             then
1903                 content=B
1904             fi
1905
1906             if $pp_opt_debug; then
1907                 echo "$cmp USER %files:"
1908                 cat $user_files
1909                 echo "$cmp ROOT %files:"
1910                 cat $root_files
1911             fi >&2
1912
1913             bosboot=N; pp_contains_any "$pp_aix_bosboot" $cmp && bosboot=b
1914
1915             echo $pp_aix_bff_name.$ex \
1916              `[ $pp_aix_version ] && pp_aix_version_fix $pp_aix_version || pp_aix_version_fix "$version"` \
1917                  1 $bosboot $content \
1918                  $pp_aix_lang "$summary $briefex"
1919             echo "["
1920
1921             pp_aix_depend $pp_wrkdir/%depend.$cmp
1922
1923             echo "%"
1924
1925             # generate per-directory size information
1926             pp_aix_size < $user_files
1927             pp_aix_size $instroot < $root_files
1928
1929             pp_aix_list            < $user_files  > $user_wrkdir/$pp_aix_bff_name.$ex.al
1930             pp_aix_list $instroot  < $root_files >> $user_wrkdir/$pp_aix_bff_name.$ex.al
1931             pp_aix_list            < $root_files  > $root_wrkdir/$pp_aix_bff_name.$ex.al
1932
1933             if $pp_opt_debug; then
1934                 echo "$cmp USER $pp_aix_bff_name.$ex.al:"
1935                 cat $user_wrkdir/$pp_aix_bff_name.$ex.al
1936                 echo "$cmp ROOT $pp_aix_bff_name.$ex.al:"
1937                 cat $root_wrkdir/$pp_aix_bff_name.$ex.al
1938             fi >&2
1939
1940             pp_aix_inventory $pp_aix_bff_name.$ex < $user_files \
1941                                        > $user_wrkdir/$pp_aix_bff_name.$ex.inventory
1942             pp_aix_inventory $pp_aix_bff_name.$ex < $root_files \
1943                                        > $root_wrkdir/$pp_aix_bff_name.$ex.inventory
1944
1945             if $pp_opt_debug; then
1946                 pp_debug "$cmp USER $pp_aix_bff_name.$ex.inventory:"
1947                 cat $user_wrkdir/$pp_aix_bff_name.$ex.inventory
1948                 pp_debug "$cmp ROOT $pp_aix_bff_name.$ex.inventory:"
1949                 cat $root_wrkdir/$pp_aix_bff_name.$ex.inventory
1950             fi >&2
1951
1952             if test x"" != x"${pp_aix_copyright:-$copyright}"; then
1953                 echo "${pp_aix_copyright:-$copyright}" > $user_wrkdir/$pp_aix_bff_name.$ex.copyright
1954                 echo "${pp_aix_copyright:-$copyright}" > $root_wrkdir/$pp_aix_bff_name.$ex.copyright
1955             fi
1956
1957             #-- assume that post/pre uninstall scripts only make
1958             #   sense when installed in a root context
1959
1960             if test -r $pp_wrkdir/%pre.$cmp; then
1961                         pp_aix_make_script $user_wrkdir/$pp_aix_bff_name.$ex.pre_i \
1962                 < $pp_wrkdir/%pre.$cmp
1963             fi
1964
1965             if test -r $pp_wrkdir/%post.$cmp; then
1966                 pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.post_i \
1967                         < $pp_wrkdir/%post.$cmp
1968             fi
1969
1970             if test -r $pp_wrkdir/%preun.$cmp; then
1971                 pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpost_i \
1972                         < $pp_wrkdir/%preun.$cmp
1973             fi
1974
1975             if test -r $pp_wrkdir/%postun.$cmp; then
1976                 pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpre_i \
1977                         < $pp_wrkdir/%postun.$cmp
1978             fi
1979
1980             # remove empty files
1981             for f in $user_wrkdir/$pp_aix_bff_name.$ex.* $root_wrkdir/$pp_aix_bff_name.$ex.*; do
1982               if test ! -s "$f"; then
1983                 pp_debug "removing empty $f"
1984                 rm -f "$f"
1985               fi
1986             done
1987
1988             # copy/link the root files so we can do an easy backup later
1989             pp_aix_copy_root $instroot < $root_files
1990
1991             echo "%"
1992             echo "]"
1993           done
1994           echo "}"
1995         } > $pp_wrkdir/lpp_name
1996
1997         if $pp_opt_debug; then
1998             echo "/lpp_name :"
1999             cat $pp_wrkdir/lpp_name
2000         fi >&2
2001
2002         #-- copy the /lpp_name file to the destdir
2003         pp_add_transient_file /lpp_name
2004         cp $pp_wrkdir/lpp_name $pp_destdir/lpp_name
2005
2006         #-- copy the liblpp.a files under destdir for packaging
2007         (cd $user_wrkdir && pp_verbose  ar -c -g -r liblpp.a $name.*) ||
2008                 pp_error "ar error"
2009         if test -s $user_wrkdir/liblpp.a; then
2010            pp_add_transient_file $instuser/liblpp.a
2011            pp_verbose cp $user_wrkdir/liblpp.a $pp_destdir$instuser/liblpp.a ||
2012                 pp_error "cannot create user liblpp.a"
2013         fi
2014         (cd $root_wrkdir && pp_verbose  ar -c -g -r liblpp.a $name.*) ||
2015                 pp_error "ar error"
2016         if test -s $root_wrkdir/liblpp.a; then
2017            pp_add_transient_file $instroot/liblpp.a
2018            pp_verbose cp $root_wrkdir/liblpp.a $pp_destdir$instroot/liblpp.a ||
2019                 pp_error "cannot create root liblpp.a"
2020         fi
2021
2022         { echo ./lpp_name
2023           test -s $user_wrkdir/liblpp.a && echo .$instuser/liblpp.a
2024           test -s $root_wrkdir/liblpp.a && echo .$instroot/liblpp.a
2025           cat $user_wrkdir/$name.*.al   # includes the relocated root files!
2026         } > $pp_wrkdir/bff.list
2027
2028         if test -n "$pp_aix_abis_seen" -a x"$pp_aix_arch_std" = x"auto"; then
2029             case "$pp_aix_abis_seen" in
2030                 "ppc ppc64"|"ppc64 ppc")
2031                     pp_aix_arch_std=ppc64
2032                     ;;
2033                 ppc|ppc64)
2034                     pp_aix_arch_std=$pp_aix_abis_seen
2035                     ;;
2036                 *" "*)
2037                     pp_warn "multiple architectures detected: $pp_aix_abis_seen"
2038                     pp_aix_arch_std=unknown
2039                     ;;
2040                 "")
2041                     pp_warn "no binary executables detected; using noarch"
2042                     pp_aix_arch_std=noarch
2043                     ;;
2044                 *)
2045                     pp_warn "unknown architecture detected $pp_aix_abis_seen"
2046                     pp_aix_arch_std=$pp_aix_abis_seen
2047                     ;;
2048             esac
2049         fi
2050
2051         . $pp_wrkdir/%fixup
2052
2053         outbff=`pp_backend_aix_names`
2054         pp_debug "creating: $pp_wrkdir/$outbff"
2055         (cd $pp_destdir && pp_verbose  /usr/sbin/backup -i -q -p -f -) \
2056           < $pp_wrkdir/bff.list \
2057           > $pp_wrkdir/$outbff || pp_error "backup failed"
2058         $pp_aix_sudo /usr/sbin/installp -l -d $pp_wrkdir/$outbff
2059 }
2060
2061 pp_backend_aix_cleanup () {
2062     :
2063 }
2064
2065 pp_backend_aix_names () {
2066     echo "$name.`[ $pp_aix_version ] && pp_aix_version_fix $pp_aix_version || pp_aix_version_fix "$version"`.bff"
2067 }
2068
2069 pp_backend_aix_install_script () {
2070         typeset pkgname platform
2071         #
2072         # The script should take a first argument being the
2073         # operation; further arguments refer to components or services
2074         #
2075         # list-components           -- lists components in the pkg
2076         # install component...      -- installs the components
2077         # uninstall component...    -- uninstalles the components
2078         # list-services             -- lists the services in the pkg
2079         # start service...          -- starts the name service
2080         # stop service...           -- stops the named services
2081         # print-platform            -- prints the platform group
2082         #
2083         pkgname="`pp_backend_aix_names`"
2084         platform="`pp_backend_aix_probe`"   # XXX should be derived from files
2085
2086         fsets=
2087         for cmp in $pp_components; do
2088             case "$cmp" in
2089                 run) ex=rte;;
2090                 doc) ex=doc;;
2091                 dev) ex=adt;;
2092                 dbg) ex=diag;;
2093             esac
2094             fsets="$fsets $name.$ex"
2095         done
2096
2097         echo '#!/bin/sh'
2098         pp_install_script_common
2099
2100         cat <<-.
2101
2102             cpt_to_fileset () {
2103                 test x"\$*" = x"all" &&
2104                     set -- $pp_components
2105                 for cpt
2106                 do
2107                     case "\$cpt" in
2108                         run) echo "$name.rte";;
2109                         doc) echo "$name.doc";;
2110                         dev) echo "$name.adt";;
2111                         dbg) echo "$name.diag";;
2112                         *) usage;;
2113                     esac
2114                 done
2115             }
2116
2117             test \$# -eq 0 && usage
2118             op="\$1"; shift
2119
2120             case "\$op" in
2121                 list-components)
2122                     test \$# -eq 0 || usage \$op
2123                     echo "$pp_components"
2124                     ;;
2125                 list-services)
2126                     test \$# -eq 0 || usage \$op
2127                     echo "$pp_services"
2128                     ;;
2129                 list-files)
2130                     test \$# -ge 1 || usage \$op
2131                     echo \${PP_PKGDESTDIR:-.}/$pkgname
2132                     ;;
2133                 install)
2134                     test \$# -ge 1 || usage \$op
2135                     verbose /usr/sbin/installp -acX -V0 -F \
2136                         -d \${PP_PKGDESTDIR:-.}/$pkgname \
2137                         \`cpt_to_fileset "\$@"\`
2138                     ;;
2139                 uninstall)
2140                     test \$# -ge 1 || usage \$op
2141                     verbose /usr/sbin/installp -u -e/dev/null \
2142                         -V0 \`cpt_to_fileset "\$@"\`
2143                     ;;
2144                 start|stop)
2145                     test \$# -ge 1 || usage \$op
2146                     ec=0
2147                     for svc
2148                     do
2149                         verbose \${op}src -s \$svc || ec=1
2150                     done
2151                     exit \$ec
2152                     ;;
2153                 print-platform)
2154                     echo "$platform"
2155                     ;;
2156                 *)
2157                     usage;;
2158             esac
2159 .
2160 }
2161
2162 pp_backend_aix_init_svc_vars () {
2163     :
2164 }
2165
2166 pp_backend_aix_probe () {
2167         echo "${pp_aix_os}-${pp_aix_arch_std}"
2168 }
2169
2170 pp_backend_aix_vas_platforms () {
2171     case "${pp_aix_arch_std}" in
2172         ppc*)   :;;
2173         *)      pp_die "unknown architecture ${pp_aix_arch_std}";;
2174     esac
2175     case "${pp_aix_os}" in
2176         aix43)  echo "aix-43";;
2177         aix51)  echo "aix-51 aix-43";;
2178         aix52)  echo "aix-51 aix-43";;
2179         aix53)  echo "aix-53 aix-51 aix-43";;
2180         aix61)  echo "aix-53 aix-51 aix-43";;
2181         *)      pp_die "unknown system ${pp_aix_os}";;
2182     esac
2183 }
2184 pp_backend_aix_function () {
2185     case "$1" in
2186     pp_mkgroup) cat <<'.';;
2187             /usr/sbin/lsgroup "$1" >/dev/null &&
2188                 return 0
2189             echo "Creating group $1"
2190             /usr/bin/mkgroup -A "$1"
2191 .
2192     pp_mkuser:depends) echo pp_mkgroup;;
2193     pp_mkuser) cat <<'.';;
2194             /usr/sbin/lsuser "$1" >/dev/null &&
2195                 return 0
2196             pp_mkgroup "${2:-$1}" || return 1
2197             echo "Creating user $1"
2198             /usr/bin/mkuser \
2199                 login=false \
2200                 rlogin=false \
2201                 account_locked=true \
2202                 home="${3:-/nohome.$1}" \
2203                 pgrp="${2:-$1}" \
2204                 "$1"
2205 .
2206     pp_havelib) cat <<'.';;
2207             case "$2" in
2208                 "")    pp_tmp_name="lib$1.so";;
2209                 *.*.*) pp_tmp_name="lib$1.so.$2";;
2210                 *.*)   pp_tmp_name="lib$1.so.$2.0";;
2211                 *)     pp_tmp_name="lib$1.so.$2";;
2212             esac
2213             for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
2214                 test -r "$pp_tmp_dir/$pp_tmp_name" -a \
2215                     -r "$pp_tmp_dir/lib$1.so" && return 0
2216             done
2217             return 1
2218 .
2219     *) false;;
2220     esac
2221 }
2222
2223 pp_platforms="$pp_platforms sd"
2224
2225 pp_backend_sd_detect () {
2226     test x"$1" = x"HP-UX"
2227 }
2228
2229 pp_backend_sd_init () {
2230     pp_sd_sudo=
2231     pp_sd_startlevels=2
2232     pp_sd_stoplevels=auto
2233     pp_sd_config_file=
2234     pp_sd_vendor=
2235     pp_sd_vendor_tag=Quest
2236     pp_sd_default_start=1           # config_file default start value
2237
2238     pp_readlink_fn=pp_ls_readlink   # HPUX has no readlink
2239     pp_shlib_suffix='.sl'           # .so on most other platforms
2240
2241     pp_sd_detect_os
2242 }
2243
2244 pp_sd_detect_os () {
2245     typeset revision
2246
2247     revision=`uname -r`
2248     pp_sd_os="${revision#?.}"
2249     test -z "$pp_sd_os" &&
2250         pp_warn "cannot detect OS version"
2251     pp_sd_os_std="hpux`echo $pp_sd_os | tr -d .`"
2252
2253     case "`uname -m`" in
2254         9000/[678]??) pp_sd_arch_std=hppa;;
2255         ia64) pp_sd_arch_std=ia64;;
2256         *) pp_sd_arch_std=unknown;;
2257     esac
2258 }
2259
2260 pp_sd_write_files () {
2261     typeset t m o g f p st line dm
2262     while read t m o g f p st; do
2263         line="                file"
2264         case "$f" in *v*) line="$line -v";; esac    # FIXME for uninstall
2265         case ${pp_sd_os} in
2266             10.*)
2267                 case $t in
2268                     f) dm=644;;
2269                     d) p=${p%/}; dm=755;;
2270                 esac
2271                 ;;
2272             *)
2273                 case $t in
2274                     f) dm=644;;
2275                     d) line="$line -t d"; p=${p%/}; dm=755;;
2276                     s) line="$line -t s";;
2277                 esac
2278                 ;;
2279         esac
2280
2281         test x"$o" = x"-" && o=root
2282         test x"$g" = x"-" && g=sys
2283         test x"$m" = x"-" && m=$dm
2284
2285         case $t in
2286             s)
2287                 # swpackage will make unqualified links relative to the
2288                 # current working (source) directory, not the destination;
2289                 # we need to qualify them to prevent this.
2290                 case "$st" in
2291                     [!/]*) st="`dirname \"$p\"`/$st";;
2292                 esac
2293                 echo "$line -o $o -g $g -m $m $st $p"
2294                 ;;
2295             *)
2296                 echo "$line -o $o -g $g -m $m $pp_destdir$p $p"
2297                 ;;
2298         esac
2299
2300     done
2301 }
2302
2303 pp_sd_service_group_script () {
2304     typeset grp svcs scriptpath out
2305     grp="$1"
2306     svcs="$2"
2307     scriptpath="/sbin/init.d/$grp"
2308     out="$pp_destdir$scriptpath"
2309
2310     pp_add_file_if_missing $scriptpath run 755 || return 0
2311
2312     cat <<-. > $out
2313         #!/sbin/sh
2314         # generated by pp $pp_version
2315         svcs="$svcs"
2316 .
2317
2318     cat <<-'.' >> $out
2319         #-- starts services in order.. stops them all if any break
2320         pp_start () {
2321             undo=
2322             for svc in \$svcs; do
2323                 /sbin/init.d/\$svc start
2324                 case \$? in
2325                   0|4)
2326                     undo="\$svc \$undo"
2327                     ;;
2328                   *)
2329                     if test -n "\$undo"; then
2330                         for svc in \$undo; do
2331                             /sbin/init.d/\$svc stop
2332                         done
2333                         return 1
2334                     fi
2335                     ;;
2336                 esac
2337             done
2338             return 0
2339         }
2340
2341         #-- stops services in reverse
2342         pp_stop () {
2343             reverse=
2344             for svc in \$svcs; do
2345                 reverse="\$svc \$reverse"
2346             done
2347             rc=0
2348             for svc in \$reverse; do
2349                 /sbin/init.d/\$svc stop || rc=\$?
2350             done
2351             return \$rc
2352         }
2353
2354         case \$1 in
2355             start_msg) echo "Starting \$svcs";;
2356             stop_msg)  echo "Stopping \$svcs";;
2357             start)     pp_start;;
2358             stop)      pp_stop;;
2359             *)         echo "usage: \$0 {start|stop|start_msg|stop_msg}"
2360                        exit 1;;
2361         esac
2362 .
2363 }
2364
2365 pp_sd_service_script () {
2366     typeset svc config_file config_value scriptpath out
2367
2368     svc="$1"
2369     scriptpath="/sbin/init.d/$svc"
2370
2371     config_file=${pp_sd_config_file:-/etc/rc.config.d/$svc}
2372     sd_config_var=`echo run-$svc | tr '[a-z]-' '[A-Z]_'`
2373     sd_config_value=${pp_sd_default_start:-0}
2374     pp_load_service_vars "$svc"
2375
2376     test -n "$user" -a x"$user" != x"root" &&
2377         cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
2378     if test -z "$pidfile"; then
2379         pidfile="/var/run/$svc.pid"
2380         cmd="$cmd & echo \$! > \$pidfile"
2381     fi
2382
2383     pp_debug "config file is $config_file"
2384
2385     pp_add_file_if_missing $scriptpath run 755
2386     pp_add_file_if_missing $config_file run 644 v
2387
2388     cat <<-. >> $pp_destdir$config_file
2389
2390         # Controls whether the $svc service is started
2391         $sd_config_var=$sd_config_value
2392 .
2393
2394     if test ! -f $pp_destdir$scriptpath; then
2395     cat <<-. > $pp_destdir$scriptpath
2396         #!/sbin/sh
2397         # generated by pp $pp_version
2398
2399         svc="$svc"
2400         pidfile="$pidfile"
2401         config_file="$config_file"
2402
2403         pp_start () {
2404             $cmd
2405         }
2406
2407         pp_disabled () {
2408             test \${$sd_config_var:-0} -eq 0
2409         }
2410
2411         pp_stop () {
2412             if test ! -s "\$pidfile"; then
2413                 echo "Unable to stop \$svc (no pid file)"
2414                 return 1
2415             else
2416                 read pid < "\$pidfile"
2417                 if kill -0 "\$pid" 2>/dev/null; then
2418                     if kill -${stop_signal:-TERM} "\$pid"; then
2419                         rm -f "\$pidfile"
2420                         return 0
2421                     else
2422                         echo "Unable to stop \$svc"
2423                         return 1
2424                     fi
2425                 else
2426                     rm -f "\$pidfile"
2427                     return 0
2428                 fi
2429             fi
2430         }
2431
2432         pp_running () {
2433             if test ! -s "\$pidfile"; then
2434                 return 1
2435             else
2436                 read pid < "\$pidfile"
2437                 kill -0 "\$pid" 2>/dev/null
2438             fi
2439         }
2440
2441         case \$1 in
2442             start_msg) echo "Starting the \$svc service";;
2443             stop_msg)  echo "Stopping the \$svc service";;
2444             start)
2445                     if test -f "\$config_file"; then
2446                         . \$config_file
2447                     fi
2448                     if pp_disabled; then
2449                         exit 2
2450                     elif pp_running; then
2451                         echo "\$svc already running";
2452                         exit 0
2453                     elif pp_start; then
2454                         echo "\$svc started";
2455                         # rc(1M) says we should exit 4, but nobody expects it!
2456                         exit 0
2457                     else
2458                         exit 1
2459                     fi;;
2460             stop)   if pp_stop; then
2461                         echo "\$svc stopped";
2462                         exit 0
2463                     else
2464                         exit 1
2465                     fi;;
2466             *) echo "usage: \$0 {start|stop|start_msg|stop_msg}"
2467                exit 1;;
2468         esac
2469 .
2470     fi
2471 }
2472
2473 pp_sd_make_service () {
2474         typeset level startpriority stoppriority startlevels stoplevels
2475         typeset svc svcvar symtype
2476
2477         svc="$1"
2478         svcvar=`pp_makevar $svc`
2479
2480         case ${pp_sd_os} in
2481             10.*) symtype="file";;
2482             *) symtype="file -t s";;
2483         esac
2484
2485         # TODO: Figure out why this check is here
2486         #-- don't do anything if the script exists
2487         #if test -s "$pp_destdir/sbin/init.d/$svc"; then
2488         #    pp_error "$pp_destdir/sbin/init.d/$svc exists"
2489         #    return
2490         #fi
2491
2492         # symlink the script, depending on the priorities chosen
2493         eval startpriority='${pp_sd_startpriority_'$svcvar'}'
2494         eval stoppriority='${pp_sd_stoppriority_'$svcvar'}'
2495         test -z "$startpriority" && startpriority="${pp_sd_startpriority:-50}"
2496         test -z "$stoppriority" && stoppriority="${pp_sd_stoppriority:-50}"
2497
2498         eval startlevels='${pp_sd_startlevels_'$svcvar'}'
2499         test -z "$startlevels" && startlevels="$pp_sd_startlevels"
2500
2501         eval stoplevels='${pp_sd_stoplevels_'$svcvar'}'
2502         test -z "$stoplevels" && stoplevels="$pp_sd_stoplevels"
2503
2504         # create the script and config file
2505         pp_sd_service_script $svc
2506
2507         # fix the priority up
2508         case "$startpriority" in
2509             ???) :;;
2510             ??) startpriority=0$startpriority;;
2511             ?) startpriority=00$startpriority;;
2512         esac
2513         case "$stoppriority" in
2514             ???) :;;
2515             ??) stoppriority=0$stoppriority;;
2516             ?) stoppriority=00$stoppriority;;
2517         esac
2518
2519         if test x"$stoplevels" = x"auto"; then
2520             stoplevels=
2521             test -z "$startlevels" || for level in $startlevels; do
2522                 stoplevels="$stoplevels `expr $level - 1`"
2523             done
2524         fi
2525
2526         # create the symlinks
2527         test -z "$startlevels" || for level in $startlevels; do
2528             echo "                ${symtype}" \
2529                     "/sbin/init.d/$svc" \
2530                     "/sbin/rc$level.d/S$startpriority$svc"
2531         done
2532         test -z "$stoplevels" || for level in $stoplevels; do
2533             echo "                ${symtype}" \
2534                     "/sbin/init.d/$svc" \
2535                     "/sbin/rc$level.d/K$stoppriority$svc"
2536         done
2537 }
2538
2539 pp_sd_control () {
2540     typeset ctrl script
2541     typeset cpt
2542
2543     ctrl="$1"; shift
2544     cpt="$1"; shift
2545     script="$pp_wrkdir/control.$ctrl.$cpt"
2546     cat <<. >$script
2547 .
2548     cat "$@" >> $script
2549     echo "exit 0" >> $script
2550     /usr/bin/chmod +x $script
2551     echo "                $ctrl $script"
2552 }
2553
2554 pp_sd_depend () {
2555     typeset _name _vers
2556     while read _name _vers; do
2557         case "$_name" in ""| "#"*) continue ;; esac
2558         echo "                prerequisites $_name ${_vers:+r>= $_vers}"
2559     done
2560 }
2561
2562 pp_sd_conflict () {
2563     typeset _name _vers
2564     while read _name _vers; do
2565         case "$_name" in ""| "#"*) continue ;; esac
2566         echo "                exrequisites $_name ${_vers:+r>= $_vers}"
2567     done
2568 }
2569
2570 pp_backend_sd () {
2571     typeset psf cpt svc outfile release swp_flags
2572
2573     psf=$pp_wrkdir/psf
2574     release="?.${pp_sd_os%.[0-9][0-9]}.*"
2575
2576     echo "depot" > $psf
2577     echo "layout_version 1.0" >>$psf
2578
2579     #-- vendor
2580     cat <<. >>$psf
2581         vendor
2582             tag             $pp_sd_vendor_tag
2583             title           "${pp_sd_vendor:-$vendor}"
2584         end
2585
2586         product
2587             tag             $name
2588             revision        $version
2589             vendor_tag      $pp_sd_vendor_tag
2590             is_patch        false
2591             title           "$summary"
2592             copyright       "$copyright"
2593             machine_type    *
2594             os_name         HP-UX
2595             os_release      $release
2596             os_version      ?
2597             directory       /
2598             is_locatable    false
2599 .
2600     test -n "$description" \
2601         && echo $description > $pp_wrkdir/description \
2602         && cat <<. >> $psf
2603             description     < $pp_wrkdir/description
2604 .
2605
2606     # make convenience service groups
2607     if test -n "$pp_service_groups"; then
2608         for grp in $pp_service_groups; do
2609             pp_sd_service_group_script \
2610                 $grp "`pp_service_get_svc_group $grp`"
2611         done
2612     fi
2613
2614     for cpt in $pp_components; do
2615         cat <<. >>$psf
2616             fileset
2617                 tag             ${pp_sd_fileset_tag:-$cpt}
2618                 title           "${summary:-cpt}"
2619                 revision        $version
2620 .
2621         test -s $pp_wrkdir/%depend.$cpt &&
2622               pp_sd_depend < $pp_wrkdir/%depend.$cpt >> $psf
2623         test -s $pp_wrkdir/%conflict.$cpt &&
2624               pp_sd_conflict < $pp_wrkdir/%conflict.$cpt >> $psf
2625
2626         #-- make sure services are shut down during uninstall
2627         if test $cpt = run -a -n "$pp_services"; then
2628             for svc in $pp_services; do
2629                 pp_prepend $pp_wrkdir/%preun.$cpt <<-.
2630                         /sbin/init.d/$svc stop
2631 .
2632             done
2633         fi
2634
2635         #-- we put the post/preun code into configure/unconfigure
2636         # and not postinstall/preremove, because configure/unconfigure
2637         # scripts are run on the hosts where the package is installed,
2638         # not loaded (a subtle difference).
2639         test -s $pp_wrkdir/%pre.$cpt &&
2640             pp_sd_control checkinstall $cpt $pp_wrkdir/%pre.$cpt >> $psf
2641         test -s $pp_wrkdir/%post.$cpt &&
2642             pp_sd_control configure $cpt $pp_wrkdir/%post.$cpt >> $psf
2643         test -s $pp_wrkdir/%preun.$cpt &&
2644             pp_sd_control unconfigure $cpt $pp_wrkdir/%preun.$cpt >> $psf
2645         test -s $pp_wrkdir/%postun.$cpt &&
2646             pp_sd_control postremove $cpt $pp_wrkdir/%postun.$cpt >> $psf
2647         test -s $pp_wrkdir/%check.$cpt &&
2648             pp_sd_control checkinstall $cpt $pp_wrkdir/%check.$cpt >> $psf
2649
2650         if test $cpt = run -a -n "$pp_services"; then
2651             for svc in $pp_services; do
2652                 #-- service names are 10 chars max on hpux
2653                 case "$svc" in ???????????*)
2654                     pp_warn "service name '$svc' is too long for hpux";;
2655                 esac
2656                 pp_sd_make_service $svc >> $psf
2657             done
2658             #pp_sd_make_service_config
2659         fi
2660
2661         pp_sd_write_files < $pp_wrkdir/%files.$cpt >> $psf
2662
2663         #-- end fileset clause
2664         cat <<. >>$psf
2665             end
2666 .
2667
2668     done
2669
2670     #-- end product clause
2671     cat <<. >>$psf
2672         end
2673 .
2674
2675     $pp_opt_debug && cat $psf >&2
2676
2677     test -s $pp_wrkdir/%fixup && . $pp_wrkdir/%fixup
2678
2679     outfile=`pp_backend_sd_names`
2680     case ${pp_sd_os} in
2681         10.*)
2682             swp_flags="-x target_type=tape"
2683             ;;
2684         *)
2685             swp_flags="-x media_type=tape"
2686             ;;
2687     esac
2688     if pp_verbose ${pp_sd_sudo} /usr/sbin/swpackage -s $psf $swp_flags \
2689         @ $pp_wrkdir/$outfile
2690     then
2691         pp_verbose ${pp_sd_sudo} /usr/sbin/swlist -l file -s $pp_wrkdir/$outfile
2692     else
2693         pp_error "swpackage failed"
2694     fi
2695 }
2696
2697 pp_backend_sd_cleanup () {
2698     :
2699 }
2700
2701 pp_backend_sd_names () {
2702     echo "$name-$version.$pp_sd_arch_std.depot"
2703 }
2704
2705 pp_backend_sd_install_script () {
2706     typeset pkgname platform
2707
2708     pkgname=`pp_backend_sd_names`
2709     platform="`pp_backend_sd_probe`"
2710
2711     echo "#!/bin/sh"
2712     pp_install_script_common
2713     cat <<.
2714
2715         cpt_to_tags () {
2716             test x"\$*" = x"all" && set -- $pp_components
2717             for cpt
2718             do
2719                 echo "$name.\$cpt"
2720             done
2721         }
2722
2723         test \$# -eq 0 && usage
2724         op="\$1"; shift
2725
2726         case "\$op" in
2727             list-components)
2728                 test \$# -eq 0 || usage \$op
2729                 echo "$pp_components"
2730                 ;;
2731             list-services)
2732                 test \$# -eq 0 || usage \$op
2733                 echo "$pp_services"
2734                 ;;
2735             list-files)
2736                 test \$# -ge 1 || usage \$op
2737                 echo \${PP_PKGDESTDIR:-.}/$pkgname
2738                 ;;
2739             install)
2740                 test \$# -ge 1 || usage \$op
2741                 verbose /usr/sbin/swinstall -x verbose=0 \
2742                     -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \
2743                     \`cpt_to_tags "\$@"\`
2744                 ;;
2745             uninstall)
2746                 test \$# -ge 1 || usage \$op
2747                 verbose /usr/sbin/swremove -x verbose=0 \
2748                     \`cpt_to_tags "\$@"\`
2749                 ;;
2750             start|stop)
2751                 test \$# -ge 1 || usage \$op
2752                 ec=0
2753                 for svc
2754                 do
2755                     verbose /sbin/init.d/\$svc \$op
2756                     [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
2757                 done
2758                 exit \$ec
2759                 ;;
2760             print-platform)
2761                 echo "$platform"
2762                 ;;
2763             *)
2764                 usage
2765                 ;;
2766         esac
2767 .
2768 }
2769
2770 pp_backend_sd_probe () {
2771     echo "${pp_sd_os_std}-${pp_sd_arch_std}"
2772 }
2773
2774 pp_backend_sd_vas_platforms () {
2775     case "`pp_backend_sd_probe`" in
2776         hpux*-hppa) echo hpux-pa;;
2777         hpux*-ia64) echo hpux-ia64 hpux-pa;;
2778         *)          pp_die "unknown system `pp_backend_sd_probe`";;
2779     esac
2780 }
2781
2782 pp_backend_sd_init_svc_vars () {
2783     :
2784 }
2785 pp_backend_sd_function () {
2786     case "$1" in
2787         pp_mkgroup) cat <<'.';;
2788             /usr/sbin/groupmod "$1" 2>/dev/null ||
2789                 /usr/sbin/groupadd "$1"
2790 .
2791         pp_mkuser:depends) echo pp_mkgroup;;
2792         pp_mkuser) cat <<'.';;
2793             pp_mkgroup "${2:-$1}" || return 1
2794             /usr/sbin/useradd \
2795                 -g "${2:-$1}" \
2796                 -d "${3:-/nonexistent}" \
2797                 -s "${4:-/bin/false}" \
2798                 "$1"
2799 .
2800         pp_havelib) cat <<'.';;
2801             for pp_tmp_dir in `echo /usr/lib${3:+:$3} | tr : ' '`; do
2802                 test -r "$pp_tmp_dir/lib$1${2:+.$2}.sl" && return 0
2803             done
2804             return 1
2805 .
2806         *) false;;
2807     esac
2808 }
2809
2810 pp_platforms="$pp_platforms solaris"
2811
2812 pp_backend_solaris_detect () {
2813         test x"$1" = x"SunOS"
2814 }
2815
2816 pp_backend_solaris_init () {
2817         pp_solaris_category=
2818         pp_solaris_istates="s S 1 2 3"  # run-states when install is ok
2819         pp_solaris_rstates="s S 1 2 3"  # run-states when remove is ok
2820         pp_solaris_maxinst=
2821         pp_solaris_vendor=
2822         pp_solaris_pstamp=
2823         pp_solaris_copyright=
2824         pp_solaris_name=
2825         pp_solaris_desc=
2826         pp_solaris_package_arch=auto
2827
2828         pp_solaris_detect_os
2829         pp_solaris_detect_arch
2830
2831         pp_solaris_init_svc
2832
2833         #-- readlink not reliably available on Solaris
2834         pp_readlink_fn=pp_ls_readlink
2835 }
2836
2837 pp_solaris_detect_os () {
2838         typeset osrel
2839
2840         osrel=`/usr/bin/uname -r`
2841         case "$osrel" in
2842             5.[0-6])    pp_solaris_os="sol2${osrel#5.}";;
2843             5.*)        pp_solaris_os="sol${osrel#5.}";;
2844         esac
2845         test -z "$pp_solaris_os" &&
2846              pp_warn "can't determine OS suffix from uname -r"
2847
2848 }
2849
2850 pp_solaris_detect_arch () {
2851         pp_solaris_arch=`/usr/bin/optisa amd64 sparcv9 i386 sparc`
2852         [ -z "$pp_solaris_arch" ] &&
2853             pp_error "can't determine processor architecture"
2854         case "$pp_solaris_arch" in
2855             amd64)   pp_solaris_arch_std=x86_64;;
2856             i386)    pp_solaris_arch_std=i386;;
2857             sparcv9) pp_solaris_arch_std=sparc64;;
2858             sparc)   pp_solaris_arch_std=sparc;;
2859             *)       pp_solaris_arch_std=unknown;;
2860         esac
2861 }
2862
2863 pp_solaris_is_request_script_necessary () {
2864     typeset has_optional_services
2865
2866     has_optional_services=no
2867     for _svc in $pp_services; do
2868         pp_load_service_vars $_svc
2869         if test "$optional" = "yes"; then
2870             has_optional_services=yes
2871         fi
2872     done
2873
2874     # If the package has no optional services and only one component, don't
2875     # create a request script at all.
2876     if test "$has_optional_services" = "no" &&
2877        test `echo $pp_components | wc -w` -eq 1; then
2878         return 1 # no
2879     fi
2880
2881     return 0 # yes
2882 }
2883
2884 pp_solaris_request () {
2885     typeset _cmp _svc
2886
2887     #-- The common part of the request script contains the ask() function
2888     #   and resets the CLASSES list to empty
2889     cat <<'.'
2890         trap 'exit 3' 15
2891         ask () {
2892            ans=`ckyorn -d "$1" \
2893                 -p "Do you want to $2"` \
2894             || exit $?
2895            case "$ans" in y*|Y*) return 0;; *) return 1;; esac
2896         }
2897         CLASSES=
2898 .
2899     #-- each of our components adds itself to the CLASSES list
2900     for _cmp in $pp_components; do
2901       case "$_cmp" in
2902             run) :;;
2903             doc) echo 'ask y "install the documentation files" &&';;
2904             dev) echo 'ask y "install the development files" &&';;
2905             dbg) echo 'ask n "install the diagnostic files" &&';;
2906       esac
2907       echo '    CLASSES="$CLASSES '$_cmp'"'
2908     done
2909
2910     #-- the request script writes the CLASSES var to its output
2911     cat <<'.'
2912         echo "CLASSES=$CLASSES" > $1
2913 .
2914
2915     if test -n "$pp_services"; then
2916         echo 'SERVICES='
2917         for _svc in $pp_services; do
2918             pp_load_service_vars $_svc
2919             if test "$enable" = "yes"; then
2920                 _default_prompt=y
2921             else
2922                 _default_prompt=n
2923             fi
2924             if test "$optional" = "yes"; then
2925                 echo 'ask '$_default_prompt' "install '$_svc' service" &&'
2926             fi
2927             echo '    SERVICES="$SERVICES '$_svc'"'
2928         done
2929         echo 'echo "SERVICES=$SERVICES" >> $1'
2930     fi
2931
2932 }
2933
2934 pp_solaris_procedure () {
2935     cat <<.
2936
2937         #-- $2 for $1 component of $name
2938         case " \$CLASSES " in *" $1 "*)
2939 .
2940     cat
2941     cat <<.
2942         ;; esac
2943 .
2944 }
2945
2946 pp_solaris_depend () {
2947     typeset _name _vers
2948     while read _name _vers; do
2949         if test -n "$_name"; then
2950             echo "P $_name $_name"
2951             test -n "$_vers" && echo " $_vers"
2952         fi
2953     done
2954 }
2955
2956 pp_solaris_conflict () {
2957     typeset _name _vers
2958     while read _name _vers; do
2959         if test -n "$_name"; then
2960             echo "I $_name $_name"
2961             test -n "$_vers" && echo " $_vers"
2962         fi
2963     done
2964 }
2965
2966 pp_solaris_space() {
2967     echo "$2:$3:$1" >> $pp_wrkdir/space.cumulative
2968 }
2969
2970 pp_solaris_sum_space () {
2971     if test -s $pp_wrkdir/space.cumulative; then
2972         sort -t: +2 < $pp_wrkdir/space.cumulative |
2973         awk -F: 'NR==1{n=$3}{if($3==n){b+=$1;i+=$2}else{print n" "b" "i;b=$1;i=$2;n=$3}}END{print n" "b" "i}' > $pp_wrkdir/space
2974     fi
2975 }
2976
2977 pp_solaris_proto () {
2978         typeset t m o g f p st
2979         typeset abi
2980
2981         while read t m o g f p st; do
2982           # Use Solaris default mode, owner and group if all unspecified
2983           if test x"$m$o$g" = x"---"; then
2984             m="?"; o="?"; g="?"
2985           fi
2986           test x"$o" = x"-" && o="root"
2987           case "$t" in
2988             f) test x"$g" = x"-" && g="bin"
2989                test x"$m" = x"-" && m=444
2990                case "$f" in
2991                 *v*) echo "v $1 $p=$pp_destdir$p $m $o $g";;
2992                 *)   echo "f $1 $p=$pp_destdir$p $m $o $g";;
2993                esac
2994                if test -r "$pp_destdir$p"; then
2995                   #-- Use file to record ABI types seen
2996                   case "`file "$pp_destdir$p"`" in
2997                     *"ELF 32"*80386*) abi=i386;;
2998                     *"ELF 64"*AMD*) abi=x86_64;;
2999                     *"ELF 32"*SPARC*) abi=sparc;;
3000                     *"ELF 64"*SPARC*) abi=sparc64;;
3001                     *) abi=;;
3002                   esac
3003                   if test -n "$abi"; then
3004                     pp_add_to_list pp_solaris_abis_seen $abi
3005                   fi
3006                fi
3007                ;;
3008             d) test x"$g" = x"-" && g="sys"
3009                test x"$m" = x"-" && m=555
3010                echo "d $1 $p $m $o $g"
3011                ;;
3012             s) test x"$g" = x"-" && g="bin"
3013                test x"$m" = x"-" && m=777
3014                if test x"$m" != x"777" -a x"$m" != x"?"; then
3015                   pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
3016                fi
3017                echo "s $1 $p=$st $m $o $g"
3018                ;;
3019           esac
3020         done
3021 }
3022
3023 pp_backend_solaris () {
3024         typeset _cmp _svc _grp
3025
3026         prototype=$pp_wrkdir/prototype
3027         : > $prototype
3028
3029         pkginfo=$pp_wrkdir/pkginfo
3030         : > $pkginfo
3031         echo "i pkginfo=$pkginfo" >> $prototype
3032
3033         case "${pp_solaris_name:-$name}" in
3034             [0-9]*)
3035                 pp_error "Package name '${pp_solaris_name:-$name}'" \
3036                         "cannot start with a number"
3037                 ;;
3038             ???????????????*)
3039                 pp_warn "Package name '${pp_solaris_name:-$name}'" \
3040                         "too long for Solaris 2.6 or 2.7 (max 9 characters)"
3041                 ;;
3042             ??????????*)
3043                 pp_warn "Package name '${pp_solaris_name:-$name}'" \
3044                         "too long for 2.7 Solaris (max 9 characters)"
3045                 ;;
3046         esac
3047
3048         #-- generate the package info file
3049         echo "VERSION=$version" >> $pkginfo
3050         echo "PKG=${pp_solaris_name:-$name}" >> $pkginfo
3051         echo "CLASSES=$pp_components" >> $pkginfo
3052         echo "BASEDIR=/" >> $pkginfo
3053         echo "NAME=$name $version" >> $pkginfo
3054         echo "CATEGORY=${pp_solaris_category:-application}" >> $pkginfo
3055
3056         desc="${pp_solaris_desc:-$description}"
3057         test -n "$desc" &&
3058           echo "DESC=$desc" >> $pkginfo
3059
3060         test -n "$pp_solaris_rstates" &&
3061           echo "RSTATES=$pp_solaris_rstates" >> $pkginfo
3062         test -n "$pp_solaris_istates" &&
3063           echo "ISTATES=$pp_solaris_istates" >> $pkginfo
3064         test -n "$pp_solaris_maxinst" &&
3065           echo "MAXINST=$pp_solaris_maxinst" >> $pkginfo
3066         test -n "${pp_solaris_vendor:-$vendor}" &&
3067           echo "VENDOR=${pp_solaris_vendor:-$vendor}" >> $pkginfo
3068         test -n "$pp_solaris_pstamp" &&
3069           echo "PSTAMP=$pp_solaris_pstamp" >> $pkginfo
3070
3071         if test -n "${pp_solaris_copyright:-$copyright}"; then
3072             echo "${pp_solaris_copyright:-$copyright}" > $pp_wrkdir/copyright
3073             echo "i copyright=$pp_wrkdir/copyright" >> $prototype
3074         fi
3075
3076         #-- scripts to run before and after install
3077         : > $pp_wrkdir/postinstall
3078         : > $pp_wrkdir/preremove
3079         : > $pp_wrkdir/postremove
3080         for _cmp in $pp_components; do
3081         #-- add the preinstall scripts in definition order
3082         if test -s $pp_wrkdir/%pre.$_cmp; then
3083             pp_solaris_procedure $_cmp preinst < $pp_wrkdir/%pre.$_cmp \
3084                 >> $pp_wrkdir/preinstall
3085         fi
3086         #-- add the postinstall scripts in definition order
3087         if test -s $pp_wrkdir/%post.$_cmp; then
3088             pp_solaris_procedure $_cmp postinst < $pp_wrkdir/%post.$_cmp \
3089                 >> $pp_wrkdir/postinstall
3090         fi
3091         #-- add the preremove rules in reverse definition order
3092         if test -s $pp_wrkdir/%preun.$_cmp; then
3093             pp_solaris_procedure $_cmp preremove < $pp_wrkdir/%preun.$_cmp |
3094                     pp_prepend $pp_wrkdir/preremove
3095         fi
3096         #-- add the postremove scripts in definition order
3097         if test -s $pp_wrkdir/%postun.$_cmp; then
3098             pp_solaris_procedure $_cmp postremove < $pp_wrkdir/%postun.$_cmp \
3099                 >> $pp_wrkdir/postremove
3100         fi
3101         #-- Add the check script in definition order
3102         if test -s $pp_wrkdir/%check.$_cmp; then
3103             pp_solaris_procedure $_cmp checkinstall \
3104                         < $pp_wrkdir/%check.$_cmp \
3105                         >> $pp_wrkdir/checkinstall
3106         fi
3107         #-- All dependencies and conflicts are merged together for Solaris pkgs
3108         test -s $pp_wrkdir/%depend.$_cmp &&
3109               pp_solaris_depend < $pp_wrkdir/%depend.$_cmp >> $pp_wrkdir/depend
3110         test -s $pp_wrkdir/%conflict.$_cmp &&
3111               pp_solaris_conflict < $pp_wrkdir/%conflict.$_cmp >> $pp_wrkdir/depend
3112         done
3113
3114
3115         if pp_solaris_is_request_script_necessary; then
3116             pp_solaris_request > $pp_wrkdir/request
3117         fi
3118
3119         test -n "$pp_services" &&
3120             for _svc in $pp_services; do
3121                 pp_load_service_vars $_svc
3122                 pp_solaris_smf $_svc
3123                 pp_solaris_make_service $_svc
3124                 pp_solaris_install_service $_svc | pp_prepend $pp_wrkdir/postinstall
3125                 pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/preremove
3126                 pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/postremove
3127                 unset pp_svc_xml_file
3128             done
3129
3130         test -n "$pp_service_groups" &&
3131             for _grp in $pp_service_groups; do
3132                 pp_solaris_make_service_group \
3133                     $_grp "`pp_service_get_svc_group $_grp`"
3134             done
3135
3136         #-- if installf was used; we need to indicate a termination
3137         grep installf $pp_wrkdir/postinstall >/dev/null &&
3138             echo 'installf -f $PKGINST' >> $pp_wrkdir/postinstall
3139
3140         pp_solaris_sum_space
3141
3142         # NB: pkginfo and copyright are added earlier
3143         for f in compver depend space checkinstall \
3144                  preinstall request postinstall \
3145                  preremove postremove; do
3146             if test -s $pp_wrkdir/$f; then
3147                 case $f in
3148                     *install|*remove|request)
3149                         # turn scripts into a proper shell scripts
3150                         mv $pp_wrkdir/$f $pp_wrkdir/$f.tmp
3151                         { echo "#!/bin/sh";
3152                           echo "# $f script for ${pp_solaris_name:-$name}-$version"
3153                           cat $pp_wrkdir/$f.tmp
3154                           echo "exit 0"; } > $pp_wrkdir/$f
3155                         chmod +x $pp_wrkdir/$f
3156                         rm -f $pp_wrkdir/$f.tmp
3157                         ;;
3158                 esac
3159                 if $pp_opt_debug; then
3160                     pp_debug "contents of $f:"
3161                     cat $pp_wrkdir/$f >&2
3162                 fi
3163                 echo "i $f=$pp_wrkdir/$f" >> $prototype
3164             fi
3165         done
3166
3167         #-- create the prototype file which lists the files to install
3168         # do this as late as possible because files could be added
3169         pp_solaris_abis_seen=
3170         for _cmp in $pp_components; do
3171           pp_solaris_proto $_cmp < $pp_wrkdir/%files.$_cmp
3172         done >> $prototype
3173
3174         if test x"$pp_solaris_package_arch" = x"auto"; then
3175             if pp_contains "$pp_solaris_abis_seen" sparc64; then
3176                 pp_solaris_package_arch_std="sparc64"
3177                 echo "ARCH=sparcv9" >> $pkginfo
3178             elif pp_contains "$pp_solaris_abis_seen" sparc; then
3179                 pp_solaris_package_arch_std="sparc"
3180                 echo "ARCH=sparc" >> $pkginfo
3181             elif pp_contains "$pp_solaris_abis_seen" x86_64; then
3182                 pp_solaris_package_arch_std="x86_64"
3183                 echo "ARCH=amd64" >> $pkginfo
3184             elif pp_contains "$pp_solaris_abis_seen" i386; then
3185                 pp_solaris_package_arch_std="i386"
3186                 echo "ARCH=i386" >> $pkginfo
3187             else
3188                 pp_warn "No ELF files found: not supplying an ARCH type"
3189                 pp_solaris_package_arch_std="noarch"
3190             fi
3191         else
3192             pp_solaris_package_arch_std="$pp_solaris_package_arch"
3193             echo "ARCH=$pp_solaris_package_arch" >> $pkginfo
3194         fi
3195
3196         mkdir $pp_wrkdir/pkg
3197
3198         . $pp_wrkdir/%fixup
3199
3200 if $pp_opt_debug; then
3201   echo "$pkginfo::"; cat $pkginfo
3202   echo "$prototype::"; cat $prototype
3203 fi >&2
3204
3205         pkgmk -d $pp_wrkdir/pkg -f $prototype \
3206                 || { error "pkgmk failed"; return; }
3207         pkgtrans -s $pp_wrkdir/pkg \
3208                 $pp_wrkdir/`pp_backend_solaris_names` \
3209                 ${pp_solaris_name:-$name} \
3210                 || { error "pkgtrans failed"; return; }
3211 }
3212
3213 pp_backend_solaris_cleanup () {
3214         :
3215 }
3216
3217 pp_backend_solaris_names () {
3218         echo ${pp_solaris_name:-$name}-$version-${pp_solaris_package_arch_std:-$pp_solaris_arch}.pkg
3219 }
3220
3221 pp_backend_solaris_install_script () {
3222         typeset pkgname platform
3223
3224         platform="${pp_solaris_os:-solaris}-${pp_solaris_package_arch_std:-$pp_solaris_arch}"
3225
3226         echo "#! /sbin/sh"
3227         pp_install_script_common
3228         pkgname=`pp_backend_solaris_names`
3229
3230         cat <<.
3231             tmpnocheck=/tmp/nocheck\$\$
3232             tmpresponse=/tmp/response\$\$
3233             trap 'rm -f \$tmpnocheck \$tmpresponse' 0
3234
3235             make_tmpfiles () {
3236                 cat <<-.. > \$tmpresponse
3237                         CLASSES=\$*
3238                         SERVICES=$pp_services
3239 ..
3240                 cat <<-.. > \$tmpnocheck
3241                         mail=
3242                         instance=overwrite
3243                         partial=nocheck
3244                         runlevel=nocheck
3245                         idepend=nocheck
3246                         rdepend=nocheck
3247                         space=nocheck
3248                         setuid=nocheck
3249                         conflict=nocheck
3250                         action=nocheck
3251                         basedir=default
3252 ..
3253             }
3254
3255             test \$# -eq 0 && usage
3256             op="\$1"; shift
3257
3258             case "\$op" in
3259                 list-components)
3260                     test \$# -eq 0 || usage \$op
3261                     echo "$pp_components"
3262                     ;;
3263                 list-services)
3264                     test \$# -eq 0 || usage \$op
3265                     echo "$pp_services"
3266                     ;;
3267                 list-files)
3268                     test \$# -ge 1 || usage \$op
3269                     echo \${PP_PKGDESTDIR:-.}/$pkgname
3270                     ;;
3271                 install)
3272                     test \$# -ge 1 || usage \$op
3273                     make_tmpfiles "\$@"
3274                     verbose /usr/sbin/pkgadd -n -d \${PP_PKGDESTDIR:-.}/$pkgname \
3275                         -r \$tmpresponse \
3276                         -a \$tmpnocheck \
3277                         ${pp_solaris_name:-$name}
3278                     ;;
3279                 uninstall)
3280                     test \$# -ge 1 || usage \$op
3281                     make_tmpfiles "\$@"
3282                     verbose /usr/sbin/pkgrm -n \
3283                         -a \$tmpnocheck \
3284                         ${pp_solaris_name:-$name}
3285                     ;;
3286                 start|stop)
3287                     test \$# -ge 1 || usage \$op
3288                     ec=0
3289                     for svc
3290                     do
3291                         verbose /etc/init.d/\$svc \$op || ec=1
3292                     done
3293                     exit \$ec
3294                     ;;
3295                 print-platform)
3296                     echo "$platform"
3297                     ;;
3298                 *)
3299                     usage
3300                     ;;
3301             esac
3302 .
3303 }
3304
3305 pp_solaris_dynlib_depend () {
3306         xargs ldd 2>/dev/null |
3307         sed -e '/^[^    ]*:$/d' -e 's,.*=>[      ]*,,' -e 's,^[         ]*,,' |
3308         sort -u |
3309         grep -v '^/usr/platform/' | (
3310           set -- ""; shift
3311           while read p; do
3312             set -- "$@" -p "$p"
3313             if [ $# -gt 32 ]; then
3314                 echo "$# is $#" >&2
3315                 pkgchk -l "$@"
3316                 set -- ""; shift
3317             fi
3318           done
3319           [ $# -gt 0 ] && pkgchk -l "$@"
3320         )|
3321         awk '/^Current status:/{p=0} p==1 {print $1} /^Referenced by/ {p=1}' |
3322         sort -u |
3323         xargs -l32 pkginfo -x |
3324         awk 'NR % 2 == 1 { name=$1; } NR%2 == 0 { print name, $2 }'
3325 }
3326
3327 pp_solaris_add_dynlib_depends () {
3328     typeset tmp
3329     tmp=$pp_wrkdir/tmp.dynlib
3330
3331     for _cmp in $pp_components; do
3332         awk '{print destdir $6}' destdir="$pp_destdir" \
3333                 < $pp_wrkdir/%files.$_cmp |
3334         pp_solaris_dynlib_depend > $tmp
3335         if test -s $tmp; then
3336             cat $tmp >> $pp_wrkdir/%depend.$_cmp
3337         fi
3338         rm -f $tmp
3339     done
3340 }
3341
3342 pp_backend_solaris_probe () {
3343     echo "${pp_solaris_os}-${pp_solaris_arch_std}"
3344 }
3345
3346 pp_backend_solaris_vas_platforms () {
3347     case `pp_backend_solaris_probe` in
3348         sol10-sparc* | sol9-sparc* | sol8-sparc*)
3349                         echo solaris8-sparc solaris7-sparc solaris26-sparc;;
3350         sol7-sparc*)    echo                solaris7-sparc solaris26-sparc;;
3351         sol26-sparc*)   echo                               solaris26-sparc;;
3352         sol8-*86)       echo solaris8-x86;;
3353         sol10-*86 | sol10-x86_64)
3354                         echo solaris10-x64 solaris8-x86;;
3355         *)              pp_die "unknown system `pp_backend_solaris_probe`";;
3356     esac
3357 }
3358 pp_backend_solaris_function() {
3359     case "$1" in
3360         pp_mkgroup) cat<<'.';;
3361             /usr/sbin/groupmod "$1" 2>/dev/null && return 0
3362             /usr/sbin/groupadd "$1"
3363 .
3364         pp_mkuser:depends) echo pp_mkgroup;;
3365         pp_mkuser) cat<<'.';;
3366             id "$1" >/dev/null 2>/dev/null && return 0
3367             pp_mkgroup "${2:-$1}" || return 1
3368             /usr/sbin/useradd \
3369                 -g "${2:-$1}" \
3370                 -d "${3:-/nonexistent}" \
3371                 -s "${4:-/bin/false}" \
3372                 "$1"
3373 .
3374     *) false;;
3375     esac
3376 }
3377
3378 pp_backend_solaris_init_svc_vars () {
3379     _smf_category=${pp_solaris_smf_category:-application}
3380     _smf_method_envvar_name=${smf_method_envvar_name:-"PP_SMF_SERVICE"}
3381     pp_solaris_service_shell=/sbin/sh
3382 }
3383
3384 pp_solaris_init_svc () {
3385     smf_version=1
3386     smf_type=service
3387     solaris_user=
3388     solaris_stop_signal=
3389     solaris_sysv_init_start=S70     # invocation order for start scripts
3390     solaris_sysv_init_kill=K30      # invocation order for kill scripts
3391     solaris_sysv_init_start_states="2" # states to install start link
3392     solaris_sysv_init_kill_states="S 0 1"  # states to install kill link
3393
3394     #
3395     # To have the service be installed to start automatically,
3396     #   %service foo
3397     #   solaris_sysv_init_start_states="S 0 1 2"
3398     #
3399 }
3400
3401 pp_solaris_smf () {
3402     typeset f _pp_solaris_service_script svc _pp_solaris_manpage
3403
3404     pp_solaris_name=${pp_solaris_name:-$name}
3405     pp_solaris_manpath=${pp_solaris_manpath:-"/usr/share/man"}
3406     pp_solaris_mansect=${pp_solaris_mansect:-1}
3407     smf_start_timeout=${smf_start_timeout:-60}
3408     smf_stop_timeout=${smf_stop_timeout:-60}
3409     smf_restart_timeout=${smf_restart_timeout:-60}
3410
3411     svc=${pp_solaris_smf_service_name:-$1}
3412     _pp_solaris_service_script=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3413     _pp_solaris_manpage=${pp_solaris_manpage:-$svc}
3414
3415     if [ -z $pp_svc_xml_file ]; then
3416         pp_svc_xml_file="/var/svc/manifest/$_smf_category/$svc.xml"
3417         echo "## Generating the smf service manifest file for $pp_svc_xml_file"
3418     else
3419         echo "## SMF service manifest file already defined at $pp_svc_xml_file"
3420         if [ -z $pp_solaris_smf_service_name ] || [ -z $pp_solaris_smf_category ] || [ -z $pp_solaris_service_script ] || [ -z $smf_method_envvar_name ]; then
3421           pp_error "All required variables are not set.\n"\
3422                    "When using a custom manifest file all of the following variables must be set:\n"\
3423                    "pp_solaris_smf_service_name, pp_solaris_smf_category, pp_solaris_service_script and smf_method_envvar_name.\n\n"\
3424                    "Example:\n"\
3425                    " \$pp_solaris_smf_category=application\n"\
3426                    " \$pp_solaris_smf_service_name=pp\n\n"\
3427                    "  <service name='application/pp' type='service' version='1'>\n\n"\
3428                    "Example:\n"\
3429                    " \$pp_solaris_service_script=/etc/init.d/pp\n\n"\
3430                    "  <exec_method type='method' name='start' exec='/etc/init.d/pp' />\n\n"\
3431                    "Example:\n"\
3432                    " \$smf_method_envvar_name=PP_SMF_SERVICE\n\n"\
3433                    "  <method_environment>\n"\
3434                    "    <envvar name='PP_SMF_SERVICE' value='1'/>\n"\
3435                    "  </method_environment>\n"
3436
3437           return 1
3438         fi
3439         return 0
3440     fi
3441
3442     f=$pp_svc_xml_file
3443     pp_add_file_if_missing $f ||
3444         return 0
3445     pp_solaris_add_parent_dirs "$f"
3446
3447     _pp_solaris_smf_dependencies="
3448           <dependency name='pp_local_filesystems'
3449                 grouping='require_all'
3450                 restart_on='none'
3451                 type='service'>
3452                 <service_fmri value='svc:/system/filesystem/local'/>
3453           </dependency>
3454
3455           <dependency name='pp_single-user'
3456                 grouping='require_all'
3457                 restart_on='none'
3458                 type='service'>
3459                 <service_fmri value='svc:/milestone/single-user' />
3460           </dependency>
3461 "
3462     _pp_solaris_smf_dependencies=${pp_solaris_smf_dependencies:-$_pp_solaris_smf_dependencies}
3463
3464     cat <<-. >$pp_destdir$f
3465 <?xml version="1.0"?>
3466 <!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
3467 <!--
3468         $copyright
3469         Generated by PolyPackage $pp_version
3470 -->
3471
3472     <service_bundle type='manifest' name='${pp_solaris_name}:${svc}' >
3473           <service name='$_smf_category/$svc'
3474                 type='$smf_type'
3475                 version='$smf_version'>
3476
3477           <create_default_instance enabled='false'/>
3478
3479           <single_instance />
3480
3481           $_pp_solaris_smf_dependencies
3482
3483           $pp_solaris_smf_additional_dependencies
3484
3485           <method_context>
3486                 <method_credential user='${solaris_user:-$user}' />
3487                 <method_environment>
3488                     <envvar name='$_smf_method_envvar_name' value='1'/>
3489                 </method_environment>
3490           </method_context>
3491
3492           <exec_method type='method' name='start'
3493                 exec='$_pp_solaris_service_script start'
3494                 timeout_seconds='$smf_start_timeout' />
3495
3496           <exec_method type='method' name='stop'
3497                 exec='$_pp_solaris_service_script stop'
3498                 timeout_seconds='$smf_stop_timeout' />
3499
3500           <exec_method type='method' name='restart'
3501                 exec='$_pp_solaris_service_script restart'
3502                 timeout_seconds='$smf_restart_timeout' />
3503
3504           <template>
3505               <common_name>
3506                   <loctext xml:lang='C'>$description</loctext>
3507               </common_name>
3508               <documentation>
3509                   <manpage title='$pp_solaris_manpage' section='$pp_solaris_mansect' manpath='$pp_solaris_manpath'/>
3510               </documentation>
3511           </template>
3512         </service>
3513     </service_bundle>
3514 .
3515 }
3516
3517 pp_solaris_make_service_group () {
3518     typeset group out file svcs svc
3519
3520     group="$1"
3521     svcs="$2"
3522     file="/etc/init.d/$group"
3523     out="$pp_destdir$file"
3524
3525     #-- return if the script is supplied already
3526     pp_add_file_if_missing "$file" run 755 || return 0
3527     pp_solaris_add_parent_dirs "$file"
3528
3529     echo "#! /sbin/sh" > $out
3530     echo "# polypkg service group script for these services:" >> $out
3531     echo "svcs=\"$svcs\"" >> $out
3532
3533     cat <<'.' >>$out
3534
3535         #-- starts services in order.. stops them all if any break
3536         pp_start () {
3537             undo=
3538             for svc in $svcs; do
3539                 if /etc/init.d/$svc start; then
3540                     undo="$svc $undo"
3541                 else
3542                     if test -n "$undo"; then
3543                         for svc in $undo; do
3544                            /etc/init.d/$svc stop
3545                         done
3546                         return 1
3547                     fi
3548                 fi
3549             done
3550             return 0
3551         }
3552
3553         #-- stops services in reverse
3554         pp_stop () {
3555             reverse=
3556             for svc in $svcs; do
3557                 reverse="$svc $reverse"
3558             done
3559             rc=0
3560             for svc in $reverse; do
3561                 /etc/init.d/$svc stop || rc=$?
3562             done
3563             return $rc
3564         }
3565
3566         #-- returns true only if all services return true status
3567         pp_status () {
3568             rc=0
3569             for svc in $svcs; do
3570                 /etc/init.d/$svc status || rc=$?
3571             done
3572             return $rc
3573         }
3574
3575         case "$1" in
3576             start)   pp_start;;
3577             stop)    pp_stop;;
3578             status)  pp_status;;
3579             restart) pp_stop && pp_start;;
3580             *)       echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
3581         esac
3582 .
3583 }
3584
3585 pp_solaris_make_service () {
3586     typeset file out _cmd svc
3587
3588     svc="${pp_solaris_smf_service_name:-$1}"
3589     file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3590     out="$pp_destdir$file"
3591
3592     #-- return if we don't need to create the init script
3593     pp_add_file_if_missing "$file" run 755 ||
3594         return 0
3595     pp_solaris_add_parent_dirs "$file"
3596
3597     echo "#! /sbin/sh" >$out
3598     echo "#-- This service init file generated by polypkg" >>$out
3599
3600     #-- Start SMF integration.
3601     if [ -n "$pp_svc_xml_file" ] ; then
3602         cat <<_EOF >>$out
3603 if [ -x /usr/sbin/svcadm ] && [ "x\$1" != "xstatus" ] && [ "t\$$_smf_method_envvar_name" = "t" ] ; then
3604     case "\$1" in
3605         start)
3606             echo "starting $svc"
3607             /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1
3608             /usr/sbin/svcadm enable -s $_smf_category/$svc
3609             RESULT=\$?
3610             if [ "\$RESULT" -ne 0 ] ; then
3611                 echo "Error \$RESULT starting $svc" >&2
3612             fi
3613             ;;
3614         stop)
3615             echo "stopping $svc"
3616             /usr/sbin/svcadm disable -ts $_smf_category/$svc
3617             RESULT=0
3618             ;;
3619         restart)
3620             echo "restarting $svc"
3621             /usr/sbin/svcadm disable -ts $_smf_category/$svc
3622             /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1
3623             /usr/sbin/svcadm enable -s $_smf_category/$svc
3624             RESULT=\$?
3625             if [ "\$RESULT" -ne 0 ] ; then
3626                 echo "Error \$RESULT starting $svc" >&2
3627             fi
3628             ;;
3629         *)
3630             echo "Usage: $file {start|stop|restart|status}" >&2
3631             RESULT=1
3632     esac
3633     exit $RESULT
3634 fi
3635 _EOF
3636     fi
3637
3638     #-- construct a start command that builds a pid file as needed
3639     #   and forks the daemon
3640     _cmd="$cmd";
3641     if test -z "$pidfile"; then
3642         # The service does not define a pidfile, so we have to make
3643         # our own up. On Solaris systems where there is no /var/run
3644         # we must use /tmp to guarantee the pid files are removed after
3645         # a system crash.
3646         cat <<. >>$out
3647             pp_piddir="/var/run"
3648             test -d "\$pp_piddir/." || pp_piddir="/tmp"
3649             pidfile="\$pp_piddir/$svc.pid"
3650 .
3651         _cmd="$cmd & echo \$! > \$pidfile"
3652     else
3653         # The service is able to write its own PID file
3654         cat <<. >>$out
3655             pidfile="$pidfile"
3656 .
3657     fi
3658
3659     if test "${user:-root}" != "root"; then
3660         _cmd="su $user -c exec $_cmd";
3661     fi
3662
3663     cat <<. >>$out
3664         stop_signal="${stop_signal:-TERM}"
3665         svc="${svc}"
3666
3667         # generated command to run $svc as a daemon process
3668         pp_exec () { $_cmd; }
3669 .
3670
3671     #-- write the invariant section of the init script
3672     cat <<'.' >>$out
3673
3674         # returns true if $svc is running
3675         pp_running () {
3676             test -s "$pidfile" || return 1
3677             read pid junk < "$pidfile" 2>/dev/null
3678             test ${pid:-0} -gt 1 &&
3679             kill -0 "$pid" 2>/dev/null
3680         }
3681
3682         # prints a message describing $svc's running state
3683         pp_status () {
3684             if pp_running; then
3685                 echo "service $svc is running (pid $pid)"
3686                 return 0
3687             elif test -f "$pidfile"; then
3688                 echo "service $svc is not running, but pid file exists"
3689                 return 2
3690             else
3691                 echo "service $svc is not running"
3692                 return 1
3693             fi
3694         }
3695
3696         # starts $svc
3697         pp_start () {
3698             if pp_running; then
3699                 echo "service $svc already running" >&2
3700                 return 0
3701             fi
3702             echo "starting $svc... \c"
3703             if pp_exec; then
3704                 echo "done."
3705             else
3706                 echo "ERROR."
3707                 exit 1
3708             fi
3709         }
3710
3711         # stops $svc
3712         pp_stop () {
3713             if pp_running; then
3714                 echo "stopping $svc... \c"
3715                 if kill -$stop_signal $pid; then
3716                     rm -f "$pidfile"
3717                     echo "done."
3718                 else
3719                     echo "ERROR."
3720                     return 1
3721                 fi
3722             else
3723                 echo "service $svc already stopped" >&2
3724                 return 0
3725             fi
3726         }
3727
3728         umask 022
3729         case "$1" in
3730             start)   pp_start;;
3731             stop)    pp_stop;;
3732             status)  pp_status;;
3733             restart) pp_stop && pp_start;;
3734             *)       echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
3735         esac
3736 .
3737 }
3738
3739 pp_solaris_remove_service () {
3740     typeset file svc
3741
3742     svc="${pp_solaris_smf_service_name:-$1}"
3743     file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3744
3745     echo '
3746 '$file' stop >/dev/null 2>/dev/null
3747 if [ "x${PKG_INSTALL_ROOT}" = 'x' ]; then
3748     if [ -x /usr/sbin/svcadm ] ; then
3749         # Likely un-needed, but just in case.
3750         /usr/sbin/svcadm disable -s '$svc' 2>/dev/null
3751         /usr/sbin/svccfg delete '$svc' 2>/dev/null
3752     fi
3753 fi
3754     '
3755 }
3756
3757 pp_solaris_install_service () {
3758     typeset s k l file svc
3759
3760     svc="${pp_solaris_smf_service_name:-$1}"
3761     file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3762
3763     s="${solaris_sysv_init_start}$svc"
3764     k="${solaris_sysv_init_kill}$svc"
3765
3766     echo '
3767 if [ "x${PKG_INSTALL_ROOT}" != "x" ]; then
3768   if [ -x ${PKG_INSTALL_ROOT}/usr/sbin/svcadm ]; then
3769     echo "/usr/sbin/svccfg import '$pp_svc_xml_file' 2>/dev/null" >> ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade
3770   else'
3771     test -n "${solaris_sysv_init_start_states}" &&
3772         for state in ${solaris_sysv_init_start_states}; do
3773             l="/etc/rc$state.d/$s"
3774             echo "echo '$l'"
3775             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3776             pp_solaris_space /etc/rc$state.d 0 1
3777         done
3778     test -n "${solaris_sysv_init_kill_states}" &&
3779         for state in ${solaris_sysv_init_kill_states}; do
3780             l="/etc/rc$state.d/$k"
3781             echo "echo '$l'"
3782             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3783             pp_solaris_space /etc/rc$state.d 0 1
3784         done
3785     echo '
3786   fi
3787 else
3788     if [ -x /usr/sbin/svcadm ]; then
3789         echo "Registering '$svc' with SMF"
3790         /usr/sbin/svcadm disable -s '$svc' 2>/dev/null
3791         /usr/sbin/svccfg delete '$svc' 2>/dev/null
3792         /usr/sbin/svccfg import '$pp_svc_xml_file'
3793     else'
3794     test -n "${solaris_sysv_init_start_states}" &&
3795         for state in ${solaris_sysv_init_start_states}; do
3796             l="/etc/rc$state.d/$s"
3797             echo "echo '$l'"
3798             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3799             pp_solaris_space /etc/rc$state.d 0 1
3800         done
3801     test -n "${solaris_sysv_init_kill_states}" &&
3802         for state in ${solaris_sysv_init_kill_states}; do
3803             l="/etc/rc$state.d/$k"
3804             echo "echo '$l'"
3805             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3806             pp_solaris_space /etc/rc$state.d 0 1
3807         done
3808     echo '
3809     fi
3810 fi'
3811 }
3812
3813 pp_solaris_add_parent_dirs () {
3814     typeset dir
3815
3816     dir=${1%/*}
3817     while test -n "$dir"; do
3818         if awk "\$6 == \"$dir/\" {exit 1}" < $pp_wrkdir/%files.run; then
3819             echo "d - - - - $dir/" >> $pp_wrkdir/%files.run
3820         fi
3821         dir=${dir%/*}
3822     done
3823 }
3824
3825 pp_platforms="$pp_platforms deb"
3826
3827 pp_backend_deb_detect () {
3828     test -f /etc/debian_version
3829 }
3830
3831 pp_deb_cmp_full_name () {
3832     local prefix
3833     prefix="${pp_deb_name:-$name}"
3834     case "$1" in
3835         run) echo "${prefix}" ;;
3836         dbg) echo "${prefix}-${pp_deb_dbg_pkgname}";;
3837         dev) echo "${prefix}-${pp_deb_dev_pkgname}";;
3838         doc) echo "${prefix}-${pp_deb_doc_pkgname}";;
3839         *)   pp_error "unknown component '$1'";
3840     esac
3841 }
3842
3843 pp_backend_deb_init () {
3844     pp_deb_dpkg_version="2.0"
3845     pp_deb_name=
3846     pp_deb_version=
3847     pp_deb_release=
3848     pp_deb_arch=
3849     pp_deb_arch_std=
3850     pp_deb_maintainer="Quest Software, Inc <support@quest.com>"
3851     pp_deb_copyright=
3852     pp_deb_distro=
3853     pp_deb_control_description=
3854     pp_deb_summary=
3855     pp_deb_description=
3856     pp_deb_dbg_pkgname="dbg"
3857     pp_deb_dev_pkgname="dev"
3858     pp_deb_doc_pkgname="doc"
3859     pp_deb_section=contrib # Free software that depends on non-free software
3860
3861     # Detect the host architecture
3862     pp_deb_detect_arch
3863
3864     # Make sure any programs we require are installed
3865     pp_deb_check_required_programs
3866 }
3867
3868 pp_deb_check_required_programs () {
3869     local p needed notfound ok
3870     needed= notfound=
3871     for prog in dpkg dpkg-deb install md5sum fakeroot
3872     do
3873         if which $prog 2>/dev/null >/dev/null; then
3874             pp_debug "$prog: found"
3875         else
3876             pp_debug "$prog: not found"
3877             case "$prog" in
3878                 dpkg|dpkg-deb)  p=dpkg;;
3879                 install|md5sum) p=coreutils;;
3880                 fakeroot)       p=fakeroot;;
3881                 *)              pp_die "unexpected dpkg tool $prog";;
3882             esac
3883             notfound="$notfound $prog"
3884             pp_contains "$needed" "$p" || needed="$needed $p"
3885         fi
3886     done
3887     if [ -n "$notfound" ]; then
3888         pp_error "cannot find these programs: $notfound"
3889         pp_error "please install these packages: $needed"
3890     fi
3891 }
3892
3893 pp_deb_munge_description () {
3894     # Insert a leading space on each line, replace blank lines with a
3895     #space followed by a full-stop.
3896     pp_deb_control_description="`echo ${pp_deb_description:-$description} | \
3897         sed 's,^\(.*\)$, \1, ' | sed 's,^[ \t]*$, .,g' | fmt -w 80`"
3898 }
3899
3900 pp_deb_detect_arch () {
3901    pp_deb_arch=`dpkg --print-architecture`
3902    pp_deb_arch_std=`uname -m`
3903 }
3904
3905 pp_deb_sanitize_version() {
3906     echo "$@" | tr -d -c '[:alnum:].+-:~'
3907 }
3908
3909 pp_deb_version_final() {
3910     if test -n "$pp_deb_version"; then
3911         # Don't sanitize; assume the user is sane (hah!)
3912         echo "$pp_deb_version"
3913     else
3914         pp_deb_sanitize_version "$version"
3915     fi
3916 }
3917
3918 pp_deb_conflict () {
3919     local _name _vers _conflicts
3920
3921     _conflicts="Conflicts:"
3922     while read _name _vers; do
3923         case "$_name" in ""| "#"*) continue ;; esac
3924         _conflicts="$_conflicts $_name"
3925         test -n "$_vers" && _conflicts="$_conflicts $_name (>= $vers)"
3926         _conflicts="${_conflicts},"
3927     done
3928     echo "${_conflicts%,}"
3929 }
3930
3931 pp_deb_make_control() {
3932     local cmp="$1"
3933     local installed_size
3934
3935     # compute the installed size
3936     installed_size=`pp_deb_files_size < $pp_wrkdir/%files.$cmp`
3937
3938     package_name=`pp_deb_cmp_full_name "$cmp"`
3939     cat <<-.
3940         Package: ${package_name}
3941         Version: `pp_deb_version_final`-${pp_deb_release:-1}
3942         Section: ${pp_deb_section:-contrib}
3943         Priority: optional
3944         Architecture: ${pp_deb_arch}
3945         Maintainer: ${pp_deb_maintainer:-$maintainer}
3946         Description: ${pp_deb_summary:-$summary}
3947         ${pp_deb_control_description}
3948         Installed-Size: ${installed_size}
3949 .
3950     if test -s $pp_wrkdir/%depend."$cmp"; then
3951         sed -ne '/^[    ]*$/!s/^[       ]*/Depends: /p' \
3952             < $pp_wrkdir/%depend."$cmp"
3953     fi
3954     if test -s $pp_wrkdir/%conflict."$cmp"; then
3955         pp_deb_conflict < $pp_wrkdir/%conflict."$cmp"
3956     fi
3957 }
3958
3959 pp_deb_make_md5sums() {
3960     local cmp="$1"; shift
3961     local pkg_dir
3962
3963     pkg_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
3964     (cd $pkg_dir && md5sum "$@") > $pkg_dir/DEBIAN/md5sums ||
3965         pp_error "cannot make md5sums"
3966 }
3967
3968 pp_deb_make_package_maintainer_script() {
3969     local output="$1"
3970     local source="$2"
3971     local desc="$3"
3972
3973     # See if we need to create this script at all
3974     if [ -s "$source" ]
3975     then
3976
3977         # Create header
3978         cat <<-. >$output || pp_error "Cannot create $output"
3979         #!/bin/sh
3980         # $desc
3981         # Generated by PolyPackage $pp_version
3982
3983 .
3984
3985         cat $source >> "$output" || pp_error "Cannot append to $output"
3986
3987         # Set perms
3988         chmod 755 "$output" || pp_error "Cannot chmod $output"
3989     fi
3990 }
3991
3992 pp_deb_handle_services() {
3993     local svc
3994
3995     #-- add service start/stop code
3996     if test -n "$pp_services"; then
3997         #-- record the uninstall commands in reverse order
3998         for svc in $pp_services; do
3999             pp_load_service_vars $svc
4000
4001             # Create init script (unless one exists)
4002             pp_deb_service_make_init_script $svc
4003
4004             #-- append %post code to install the svc
4005             test x"yes" = x"$enable" &&
4006             cat<<-. >> $pp_wrkdir/%post.run
4007                 case "\$1" in
4008                     configure)
4009                         # Install the service links
4010                         update-rc.d $svc defaults
4011                         ;;
4012                 esac
4013 .
4014
4015             #-- prepend %preun code to stop svc
4016             cat<<-. | pp_prepend $pp_wrkdir/%preun.run
4017                 case "\$1" in
4018                     remove|deconfigure|upgrade)
4019                         # Stop the $svc service
4020                         invoke-rc.d $svc stop
4021                         ;;
4022                 esac
4023 .
4024
4025             #-- prepend %postun code to remove service
4026             cat<<-. | pp_prepend $pp_wrkdir/%postun.run
4027                 case "\$1" in
4028                     purge)
4029                         # Remove the service links
4030                         update-rc.d $svc remove
4031                         ;;
4032                 esac
4033 .
4034         done
4035         #pp_deb_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
4036     fi
4037
4038 }
4039 pp_deb_fakeroot () {
4040     if test -s $pp_wrkdir/fakeroot.save; then
4041         fakeroot -i $pp_wrkdir/fakeroot.save -s $pp_wrkdir/fakeroot.save "$@"
4042     else
4043         fakeroot -s $pp_wrkdir/fakeroot.save "$@"
4044     fi
4045 }
4046
4047 pp_deb_files_size () {
4048     local t m o g f p st
4049     while read t m o g f p st; do
4050         case $t in
4051             f|s) du -k "${pp_destdir}$p";;
4052             d)   echo 4;;
4053         esac
4054     done | awk '{n+=$1} END {print n}'
4055 }
4056
4057 pp_deb_make_DEBIAN() {
4058     local cmp="${1:-run}"
4059     local data cmp_full_name
4060     local old_umask
4061
4062     old_umask=`umask`
4063     umask 0022
4064     cmp_full_name=`pp_deb_cmp_full_name $cmp`
4065     data=$pp_wrkdir/$cmp_full_name
4066
4067     # Create DEBIAN dir $data/DEBIAN
4068     mkdir -p $data/DEBIAN
4069
4070     # Create control file
4071     pp_deb_make_control $cmp > $data/DEBIAN/control
4072
4073     # Copy in conffiles
4074     if test -f $pp_wrkdir/%conffiles.$cmp; then
4075         cp $pp_wrkdir/%conffiles.$cmp $data/DEBIAN/conffiles
4076     fi
4077
4078     # Create preinst
4079     pp_deb_make_package_maintainer_script "$data/DEBIAN/preinst" \
4080         "$pp_wrkdir/%pre.$cmp" "Pre-install script for $cmp_full_name"\
4081         || exit $?
4082
4083     # Create postinst
4084     pp_deb_make_package_maintainer_script "$data/DEBIAN/postinst" \
4085         "$pp_wrkdir/%post.$cmp" "Post-install script for $cmp_full_name"\
4086         || exit $?
4087
4088     # Create prerm
4089     pp_deb_make_package_maintainer_script "$data/DEBIAN/prerm" \
4090         "$pp_wrkdir/%preun.$cmp" "Pre-uninstall script for $cmp_full_name"\
4091         || exit $?
4092
4093     # Create postrm
4094     pp_deb_make_package_maintainer_script "$data/DEBIAN/postrm" \
4095         "$pp_wrkdir/%postun.$cmp" "Post-uninstall script for $cmp_full_name"\
4096         || exit $?
4097
4098     umask $old_umask
4099 }
4100
4101 pp_deb_make_data() {
4102     local _l t m o g f p st data
4103     local data share_doc owner group
4104     cmp=$1
4105     data=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
4106     cat $pp_wrkdir/%files.${cmp} | while read t m o g f p st; do
4107         if test x"$m" = x"-"; then
4108             case "$t" in
4109                 d) m=755;;
4110                 f) m=644;;
4111             esac
4112         fi
4113         test x"$o" = x"-" && o=root
4114         test x"$g" = x"-" && g=root
4115         case "$t" in
4116         f) # Files
4117            pp_deb_fakeroot install -D -o $o -g $g -m ${m} $pp_destdir/$p $data/$p;
4118            if [ x"$f" = x"v" ]
4119            then
4120                # File marked as "volatile". Assume this means it's a conffile
4121                # TODO: check this as admins like modified conffiles to be left
4122                #       behind
4123                echo "$p" >> $pp_wrkdir/%conffiles.$cmp
4124            fi;;
4125
4126         d) # Directories
4127            pp_deb_fakeroot install -m ${m} -o $o -g $g -d $data/$p;;
4128
4129         s) # Symlinks
4130            # Remove leading / from vars
4131            rel_p=`echo $p | sed s,^/,,`
4132            rel_st=`echo $st | sed s,^/,,`
4133            # TODO: we are always doing absolute links here. We should follow
4134            # the debian policy of relative links when in the same top-level
4135            # directory
4136            (cd $data; ln -sf $st $rel_p);;
4137             *) pp_error "Unsupported data file type: $t";;
4138         esac
4139     done
4140
4141     # If no copyright file is present add one. This is a debian requirement.
4142     share_doc="/usr/share/doc/`pp_deb_cmp_full_name $cmp`"
4143     if [ ! -f "$data/$share_doc/copyright" ]
4144     then
4145         echo "${pp_deb_copyright:-$copyright}" > "$pp_wrkdir/copyright"
4146         install -D -m 644 "$pp_wrkdir/copyright" "$data/$share_doc/copyright"
4147     fi
4148
4149 }
4150
4151 pp_deb_makedeb () {
4152     local cmp
4153     local package_build_dir
4154
4155     cmp="$1"
4156
4157     package_build_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
4158
4159     # Create package dir
4160     mkdir -p $package_build_dir
4161
4162     # Copy in data
4163     pp_deb_make_data $cmp ||
4164         pp_die "Could not make DEBIAN data files for $cmp"
4165
4166     # Make control files
4167     # must be done after copying data so conffiles are found
4168     pp_deb_make_DEBIAN $cmp ||
4169         pp_die "Could not make DEBIAN control files for $cmp"
4170
4171     # Create md5sums
4172     pp_deb_make_md5sums $cmp `(cd $package_build_dir;
4173         find . -name DEBIAN -prune -o -type f -print | sed "s,^\./,,")` ||
4174             pp_die "Could not make DEBIAN md5sums for $cmp"
4175 }
4176
4177 pp_backend_deb () {
4178     local debname
4179
4180     # Munge description for control file inclusion
4181     pp_deb_munge_description
4182
4183     # Handle services
4184     pp_deb_handle_services $cmp
4185
4186     for cmp in $pp_components
4187     do
4188         debname=`pp_deb_name $cmp`
4189         pp_deb_makedeb $cmp
4190     done
4191
4192     . $pp_wrkdir/%fixup
4193
4194     for cmp in $pp_components
4195     do
4196         debname=`pp_deb_name $cmp`
4197         # Create debian package
4198         pp_debug "Building `pp_deb_cmp_full_name $cmp` -> $output"
4199         pp_deb_fakeroot dpkg-deb \
4200             --build $pp_wrkdir/`pp_deb_cmp_full_name $cmp` \
4201             $pp_wrkdir/$debname ||
4202                 pp_error "failed to create $cmp package"
4203     done
4204 }
4205
4206 pp_backend_deb_cleanup () {
4207     # rm -rf $pp_wrkdir
4208     :
4209 }
4210
4211 pp_deb_name () {
4212     local cmp="${1:-run}"
4213     echo `pp_deb_cmp_full_name $cmp`"_"`pp_deb_version_final`"-${pp_deb_release:-1}_${pp_deb_arch}.deb"
4214 }
4215 pp_backend_deb_names () {
4216     for cmp in $pp_components
4217     do
4218         pp_deb_name $cmp
4219     done
4220 }
4221
4222 pp_backend_deb_install_script () {
4223     local cmp _cmp_full_name
4224
4225     echo "#!/bin/sh"
4226     pp_install_script_common
4227
4228     cat <<.
4229
4230         cmp_to_pkgname () {
4231             test x"\$*" = x"all" &&
4232                 set -- $pp_components
4233             for cmp
4234             do
4235                 case \$cmp in
4236 .
4237     for cmp in $pp_components; do
4238          echo "$cmp) echo '`pp_deb_cmp_full_name $cmp`';;"
4239     done
4240     cat <<.
4241                 *) usage;;
4242                 esac
4243             done
4244         }
4245
4246
4247         cmp_to_pathname () {
4248             test x"\$*" = x"all" &&
4249                 set -- $pp_components
4250             for cmp
4251             do
4252                 case \$cmp in
4253 .
4254     for cmp in $pp_components; do
4255          echo "$cmp) echo \${PP_PKGDESTDIR:-.}/'`pp_deb_name $cmp`';;"
4256     done
4257     cat <<.
4258                 *) usage;;
4259                 esac
4260             done
4261         }
4262
4263         test \$# -eq 0 && usage
4264         op="\$1"; shift
4265         case "\$op" in
4266             list-components)
4267                 test \$# -eq 0 || usage \$op
4268                 echo $pp_components
4269                 ;;
4270             list-services)
4271                 test \$# -eq 0 || usage \$op
4272                 echo $pp_services
4273                 ;;
4274             list-files)
4275                 test \$# -ge 1 || usage \$op
4276                 cmp_to_pathname "\$@"
4277                 ;;
4278             install)
4279                 test \$# -ge 1 || usage \$op
4280                 dpkg --install \`cmp_to_pathname "\$@"\`
4281                 ;;
4282             uninstall)
4283                 test \$# -ge 1 || usage \$op
4284                 dpkg --remove \`cmp_to_pkgname "\$@"\`; :
4285                 ;;
4286             start|stop)
4287                 test \$# -ge 1 || usage \$op
4288                 ec=0
4289                 for svc
4290                 do
4291                     /etc/init.d/\$svc \$op || ec=1
4292                 done
4293                 exit \$ec
4294                 ;;
4295             print-platform)
4296                 test \$# -eq 0 || usage \$op
4297                 echo "linux-${pp_deb_arch}"
4298                 ;;
4299             *)
4300                 usage
4301                 ;;
4302         esac
4303 .
4304 }
4305
4306 pp_backend_deb_probe() {
4307     local arch distro release
4308
4309     pp_deb_detect_arch
4310
4311     # /etc/debian_version exists on Debian & Ubuntu, so it's no use
4312     # to us. Use lsb_release instead.
4313
4314     case `(lsb_release -is || echo no-lsb) 2>/dev/null` in
4315         Debian)
4316             distro=deb
4317             ;;
4318         Ubuntu)
4319             distro=ubu
4320             ;;
4321         no-lsb)
4322             echo unknown-$pp_deb_arch_std
4323             return 0
4324             ;;
4325         *)
4326             distro=unknown
4327             ;;
4328     esac
4329
4330     release=`lsb_release -rs`
4331
4332     # If release is not numeric, use the codename
4333     case $release in
4334         *[!.0-9r]*)
4335             release=`lsb_release -cs`
4336             case $release in
4337                 buzz)
4338                     release="11"
4339                     ;;
4340                 rex)
4341                     release="12"
4342                     ;;
4343                 bo)
4344                     release="13"
4345                     ;;
4346                 hamm)
4347                     release="20"
4348                     ;;
4349                 slink)
4350                     release="21"
4351                     ;;
4352                 potato)
4353                     release="22"
4354                     ;;
4355                 woody)
4356                     release="30"
4357                     ;;
4358                 sarge)
4359                     release="31"
4360                     ;;
4361                 etch)
4362                     release="40"
4363                     ;;
4364                 lenny)
4365                     release="50"
4366                     ;;
4367                 squeeze)
4368                     release="60"
4369                     ;;
4370             esac
4371             ;;
4372         *)
4373             # Remove trailing revision number and any dots
4374             release=`echo $release | cut -dr -f1 | tr -d .`
4375             ;;
4376     esac
4377
4378     echo $distro$release-$pp_deb_arch_std
4379 }
4380
4381 pp_backend_deb_vas_platforms () {
4382     case "$pp_deb_arch_std" in
4383         x86_64) echo "linux-x86_64.deb";; # DO NOT add linux-x86.deb here!!
4384         *86)    echo "linux-x86.deb";;
4385         *)      pp_die "unknown architecture ${pp_deb_arch_std}";;
4386     esac
4387 }
4388 pp_backend_deb_init_svc_vars () {
4389
4390     reload_signal=
4391     start_runlevels=${pp_deb_default_start_runlevels-"2 3 4 5"} # == lsb default-start
4392     stop_runlevels=${pp_deb_default_stop_runlevels-"0 1 6"}     # == lsb default-stop
4393     svc_description="${pp_deb_default_svc_description}" # == lsb short descr
4394     svc_process=
4395
4396     lsb_required_start='$local_fs $network'
4397     lsb_should_start=
4398     lsb_required_stop='$local_fs'
4399     lsb_description=
4400
4401     start_priority=50
4402     stop_priority=50            #-- stop_priority = 100 - start_priority
4403 }
4404
4405 pp_deb_service_make_init_script () {
4406     local svc=$1
4407     local script=/etc/init.d/$svc
4408     local out=$pp_destdir$script
4409     local _process _cmd
4410
4411     pp_add_file_if_missing $script run 755 v || return 0
4412
4413     #-- start out as an empty shell script
4414     cat <<-'.' >$out
4415         #!/bin/sh
4416 .
4417
4418     #-- determine the process name from $cmd unless $svc_process is given
4419     set -- $cmd
4420     #_process=${svc_process:-"$1"} --? WTF
4421
4422     #-- construct a start command that builds a pid file if needed
4423     #-- the command name in /proc/[pid]/stat is limited to 15 characters 
4424     _cmd="$cmd";
4425     _cmd_path=`echo $cmd | cut -d" " -f1`
4426     _cmd_name=`basename $_cmd_path | cut -c1-15`
4427     _cmd_args=`echo $cmd | cut -d" " -f2-`
4428     test x"$_cmd_path" != x"$_cmd_args" || _cmd_args=
4429
4430     #-- generate the LSB init info
4431     cat <<-. >>$out
4432         ### BEGIN INIT INFO
4433         # Provides: ${svc}
4434         # Required-Start: ${lsb_required_start}
4435         # Should-Start: ${lsb_should_start}
4436         # Required-Stop: ${lsb_required_stop}
4437         # Default-Start: ${start_runlevels}
4438         # Default-Stop: ${stop_runlevels}
4439         # Short-Description: ${svc_description:-no description}
4440         ### END INIT INFO
4441         # Generated by PolyPackage ${pp_version}
4442         # ${copyright}
4443
4444 .
4445
4446     if test x"${svc_description}" = x"${pp_deb_default_svc_description}"; then
4447         svc_description=
4448     fi
4449
4450     #-- write service-specific definitions
4451     cat <<. >>$out
4452 NAME="${_cmd_name}"
4453 DESC="${svc_description:-$svc service}"
4454 USER="${user}"
4455 GROUP="${group}"
4456 PIDFILE="${pidfile}"
4457 STOP_SIGNAL="${stop_signal}"
4458 RELOAD_SIGNAL="${reload_signal}"
4459 CMD="${_cmd}"
4460 DAEMON="${_cmd_path}"
4461 DAEMON_ARGS="${_cmd_args}"
4462 SCRIPTNAME=${script}
4463 .
4464
4465     #-- write the generic part of the init script
4466     cat <<'.' >>$out
4467
4468 [ -x "$DAEMON" ] || exit 0
4469
4470 [ -r /etc/default/$NAME ] && . /etc/default/$NAME
4471
4472 [ -f /etc/default/rcS ] && . /etc/default/rcS
4473
4474 . /lib/lsb/init-functions
4475
4476 do_start()
4477 {
4478         # Return
4479         #   0 if daemon has been started
4480         #   1 if daemon was already running
4481         #   2 if daemon could not be started
4482     if [ -n "$PIDFILE" ]
4483     then
4484         pidfile_opt="--pidfile $PIDFILE"
4485     else
4486         pidfile_opt="--make-pidfile --background --pidfile /var/run/$NAME.pid"
4487     fi
4488     if [ -n "$USER" ]
4489     then
4490         user_opt="--user $USER"
4491     fi
4492     if [ -n "$GROUP" ]
4493     then
4494         group_opt="--group $GROUP"
4495     fi
4496
4497         start-stop-daemon --start --quiet $pidfile_opt $user_opt --exec $DAEMON --test > /dev/null \
4498             || return 1
4499
4500     # Note: there seems to be no way to tell whether the daemon will fork itself or not, so pass
4501     # --background for now
4502     start-stop-daemon --start --quiet $pidfile_opt $user_opt --exec $DAEMON -- \
4503         $DAEMON_ARGS \
4504         || return 2
4505 }
4506
4507 do_stop()
4508 {
4509         # Return
4510         #   0 if daemon has been stopped
4511         #   1 if daemon was already stopped
4512         #   2 if daemon could not be stopped
4513         #   other if a failure occurred
4514     if [ -n "$PIDFILE" ]
4515     then
4516         pidfile_opt="--pidfile $PIDFILE"
4517     else
4518         pidfile_opt="--pidfile /var/run/$NAME.pid"
4519     fi
4520     if [ -n "$USER" ]
4521     then
4522         user_opt="--user $USER"
4523     fi
4524     if [ -n $STOP_SIGNAL ]
4525     then
4526         signal_opt="--signal $STOP_SIGNAL"
4527     fi
4528         start-stop-daemon --stop --quiet $signal_opt --retry=TERM/30/KILL/5 $pidfile_opt --name $NAME
4529         RETVAL="$?"
4530         [ "$RETVAL" = 2 ] && return 2
4531         # Wait for children to finish too if this is a daemon that forks
4532         # and if the daemon is only ever run from this initscript.
4533         # If the above conditions are not satisfied then add some other code
4534         # that waits for the process to drop all resources that could be
4535         # needed by services started subsequently.  A last resort is to
4536         # sleep for some time.
4537         start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
4538         [ "$?" = 2 ] && return 2
4539         # Many daemons don't delete their pidfiles when they exit.
4540         test -z $PIDFILE || rm -f $PIDFILE
4541         return "$RETVAL"
4542 }
4543
4544 do_reload() {
4545         #
4546         # If the daemon can reload its configuration without
4547         # restarting (for example, when it is sent a SIGHUP),
4548         # then implement that here.
4549         #
4550     if [ -n "$PIDFILE" ]
4551     then
4552         pidfile_opt="--pidfile $PIDFILE"
4553     else
4554         pidfile_opt="--pidfile /var/run/$NAME.pid"
4555     fi
4556     if [ -n "$RELOAD_SIGNAL" ]
4557     then
4558             start-stop-daemon --stop --signal $RELOAD_SIGNAL --quiet $pidfile_opt --name $NAME
4559     fi
4560         return 0
4561 }
4562
4563 case "$1" in
4564   start)
4565         [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
4566         do_start
4567         case "$?" in
4568                 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
4569                 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
4570         esac
4571         ;;
4572   stop)
4573         [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
4574         do_stop
4575         case "$?" in
4576                 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
4577                 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
4578         esac
4579         ;;
4580   reload|force-reload)
4581     if [ -n "$RELOAD_SIGNAL" ]
4582     then
4583             log_daemon_msg "Reloading $DESC" "$NAME"
4584             do_reload
4585             log_end_msg $?
4586     else
4587         # Do a restart instead
4588         "$0" restart
4589     fi
4590         ;;
4591   restart)
4592         #
4593         # If the "reload" option is implemented then remove the
4594         # 'force-reload' alias
4595         #
4596         log_daemon_msg "Restarting $DESC" "$NAME"
4597         do_stop
4598         case "$?" in
4599           0|1)
4600                 do_start
4601                 case "$?" in
4602                         0) log_end_msg 0 ;;
4603                         1) log_end_msg 1 ;; # Old process is still running
4604                         *) log_end_msg 1 ;; # Failed to start
4605                 esac
4606                 ;;
4607           *)
4608                 # Failed to stop
4609                 log_end_msg 1
4610                 ;;
4611         esac
4612         ;;
4613   *)
4614         #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
4615         echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
4616         exit 3
4617         ;;
4618 esac
4619
4620 :
4621 .
4622     chmod 755 $out
4623 }
4624 pp_backend_deb_function() {
4625     case "$1" in
4626         pp_mkgroup) cat<<'.';;
4627             /usr/sbin/groupmod "$1" 2>/dev/null && return 0
4628             /usr/sbin/groupadd "$1"
4629 .
4630         pp_mkuser:depends) echo pp_mkgroup;;
4631         pp_mkuser) cat<<'.';;
4632             pp_tmp_system=
4633             id -u "$1" >/dev/null 2>/dev/null && return 0
4634             # deb 3.1's useradd changed API in 4.0. Gah!
4635             /usr/sbin/useradd --help 2>&1 | /bin/grep -q .--system &&
4636                 pp_tmp_system=--system
4637             pp_mkgroup "${2:-$1}" || return 1
4638             /usr/sbin/useradd \
4639                 -g "${2:-$1}" \
4640                 -d "${3:-/nonexistent}" \
4641                 -s "${4:-/bin/false}" \
4642                 $pp_tmp_system \
4643                 "$1"
4644 .
4645         pp_havelib) cat<<'.';;
4646             for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
4647                 test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
4648             done
4649             return 1
4650 .
4651     *) false;;
4652     esac
4653 }
4654
4655 pp_platforms="$pp_platforms kit"
4656
4657 pp_backend_kit_detect () {
4658     test x"$1" = x"OSF1"
4659 }
4660
4661 pp_backend_kit_init () {
4662         pp_kit_name=
4663         pp_kit_package=
4664         pp_kit_desc=
4665         pp_kit_version=
4666         pp_kit_subset=
4667         pp_readlink_fn=pp_ls_readlink
4668         pp_kit_startlevels="2 3"
4669         pp_kit_stoplevels="0 2 3"
4670 }
4671
4672 pp_backend_kit () {
4673     typeset mi_file k_file svc outfile
4674     typeset desc
4675
4676     pp_backend_kit_names > /dev/null
4677
4678     if test -z "$pp_kit_desc"; then
4679         pp_kit_desc="$description"
4680     fi
4681
4682     mi_file="$pp_wrkdir/$pp_kit_subset.mi"
4683     k_file="$pp_wrkdir/$pp_kit_subset.k"
4684     scp_file="$pp_wrkdir/$pp_kit_subset.scp"
4685
4686     desc="${pp_kit_desc:-$description}"
4687
4688     cat <<-. >> $k_file
4689         NAME='$name'
4690         CODE=$pp_kit_name
4691         VERS=$pp_kit_version
4692         MI=$mi_file
4693         COMPRESS=0
4694         %%
4695         $pp_kit_subset  .       0       '$desc'
4696 .
4697
4698     if test -n "$pp_services"; then
4699         for svc in $pp_services; do
4700             pp_kit_make_service $svc
4701             pp_prepend $pp_wrkdir/%preun.run <<-.
4702                 /sbin/init.d/$svc stop
4703 .
4704          done
4705     fi
4706
4707     pp_backend_kit_make_mi "$mi_file"
4708     pp_backend_kit_make_scp
4709     #rm -rf  $pp_wrkdir/kit_dest
4710     mkdir -p $pp_wrkdir/kit_dest
4711     pp_backend_kit_kits $k_file $pp_opt_destdir $pp_wrkdir/kit_dest
4712     tar cvf $pp_wrkdir/$pp_kit_subset.tar -C $pp_wrkdir/kit_dest .
4713     gzip -c $pp_wrkdir/$pp_kit_subset.tar > $pp_wrkdir/$pp_kit_subset.tar.gz
4714     #rm -rf $pp_wrkdir/$pp_kit_subset.tar $pp_wrkdir/scps
4715 }
4716
4717 pp_backend_kit_make_mi () {
4718     # XXX this information should go into the .inv files
4719     typeset t m o g f p st line dm
4720     while read t m o g f p st; do
4721         case $t in
4722             f|d)
4723                 echo "0 .$p     $pp_kit_subset"
4724                 echo "        chmod $m $p" >> $pp_wrkdir/%post.run
4725                 if [ x"$o" = x"-" ] ; then
4726                     echo "        chown root $p" >> $pp_wrkdir/%post.run
4727                 else
4728                     echo "        chown $o $p" >> $pp_wrkdir/%post.run
4729                 fi
4730                 if [ x"$g" = x"-" ] ; then
4731                     echo "        chgrp 0 $p" >> $pp_wrkdir/%post.run
4732                 else
4733                     echo "        chgrp $g $p" >> $pp_wrkdir/%post.run
4734                 fi
4735                 ;;
4736             s)
4737                 echo "        ln -s $st $p" >> $pp_wrkdir/%post.run
4738                 echo "        rm -f $p" >> $pp_wrkdir/%preun.run
4739                 ;;
4740          esac
4741     done < $pp_wrkdir/%files.run | sort -k3  |uniq > $1
4742 }
4743
4744
4745 pp_backend_kit_make_scp () {
4746     scpdir="$pp_wrkdir/scps"
4747     mkdir "$scpdir" && touch "$scpdir"/$pp_kit_subset.scp
4748     cat <<EOF >"$scpdir"/$pp_kit_subset.scp
4749
4750     . /usr/share/lib/shell/libscp
4751
4752     case "\$ACT" in
4753     PRE_L)
4754     STL_ScpInit
4755
4756
4757
4758     ;;
4759     POST_L)
4760         STL_ScpInit
4761         STL_LinkCreate
4762 EOF
4763
4764     cat $pp_wrkdir/%post.run >>"$scpdir"/$pp_kit_subset.scp
4765     cat >>"$scpdir"/$pp_kit_subset.scp <<EOF
4766     ;;
4767     PRE_D)
4768         STL_ScpInit
4769         STL_LinkRemove
4770 EOF
4771     cat $pp_wrkdir/%preun.run >>"$scpdir"/$pp_kit_subset.scp
4772     cat >>"$scpdir"/$pp_kit_subset.scp <<EOF
4773         ;;
4774     POST_D)
4775
4776         ;;
4777     C)
4778         STL_ScpInit
4779
4780         case "\$1" in
4781         INSTALL)
4782         echo "Installation of the \$_DESC (\$_SUB) subset is complete."
4783         ;;
4784     DELETE)
4785         ;;
4786     esac
4787
4788         ;;
4789     V)
4790
4791         ;;
4792     esac
4793
4794     exit 0
4795 EOF
4796     chmod 744 "$scpdir"/$pp_kit_subset.scp
4797 }
4798
4799
4800 pp_backend_kit_cleanup () {
4801     :
4802 }
4803
4804 pp_backend_kit_names () {
4805     if test -z "$pp_kit_name"; then
4806         pp_warn "pp_kit_name not specified, using XXX"
4807         pp_kit_name=XXX
4808     fi
4809     case "$pp_kit_name" in
4810         ???) : ok;;
4811         *) pp_error "\$pp_kit_name $pp_kit_name must be three characters";;
4812     esac
4813     if test -z "$pp_kit_package"; then
4814         pp_warn "pp_kit_package not specified, using YYYY"
4815         pp_kit_package=YYYY
4816     fi
4817     if test -z "$pp_kit_version"; then
4818         pp_kit_version=`echo $version|tr -d '.a-zA-Z'`
4819     fi
4820     case "$pp_kit_version" in
4821         [0-9]) pp_kit_version="${pp_kit_version}00";;
4822         [0-9][0-9]) pp_kit_version="${pp_kit_version}0";;
4823         [0-9][0-9][0-9]) : ok;;
4824         *) pp_error "\$pp_kit_version $pp_kit_version must be three digits, ";;
4825     esac
4826     if test -z "$pp_kit_subset"; then
4827         pp_kit_subset="$pp_kit_name$pp_kit_package$pp_kit_version"
4828     fi
4829     echo "$pp_kit_subset.tar.gz"
4830 }
4831
4832 pp_backend_kit_install_script () {
4833     typeset pkgname platform
4834
4835     pkgname=`pp_backend_kit_names`
4836     platform="`pp_backend_kit_probe`"
4837
4838     echo "#!/bin/sh"
4839     pp_install_script_common
4840     cat <<.
4841
4842         cpt_to_tags () {
4843             test x"\$*" = x"all" && set -- $pp_components
4844             for cpt
4845             do
4846                 echo "$name.\$cpt"
4847             done
4848         }
4849
4850         test \$# -eq 0 && usage
4851         op="\$1"; shift
4852
4853         case "\$op" in
4854             list-components)
4855                 test \$# -eq 0 || usage \$op
4856                 echo "$pp_components"
4857                 ;;
4858             list-services)
4859                 test \$# -eq 0 || usage \$op
4860                 echo "$pp_services"
4861                 ;;
4862             list-files)
4863                 test \$# -ge 1 || usage \$op
4864                 echo \${PP_PKGDESTDIR:-.}/$pkgname
4865                 ;;
4866             install)
4867                 test \$# -ge 1 || usage \$op
4868                 verbose echo \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\`
4869                 #verbose swinstall -x verbose=0 -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\`
4870                 ;;
4871             uninstall)
4872                 test \$# -ge 1 || usage \$op
4873                 verbose echo \`cpt_to_tags "\$@"\`
4874                 #verbose swremove -x verbose=0 \`cpt_to_tags "\$@"\`
4875                 ;;
4876             start|stop)
4877                 test \$# -ge 1 || usage \$op
4878                 ec=0
4879                 for svc
4880                 do
4881                     verbose /sbin/init.d/\$svc \$op
4882                     [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
4883                 done
4884                 exit \$ec
4885                 ;;
4886             print-platform)
4887                 echo "$platform"
4888                 ;;
4889             *)
4890                 usage
4891                 ;;
4892         esac
4893 .
4894 }
4895
4896 pp_backend_kit_function () {
4897     case "$1" in
4898         pp_mkgroup) cat <<'.';;
4899             grep "^$1:" /etc/group >/dev/null ||
4900                 /usr/sbin/groupadd $1
4901 .
4902         pp_mkuser) cat <<'.';;
4903             eval user=\$$#
4904             grep "^$user:" /etc/passwd >/dev/null ||
4905                 /usr/sbin/useradd -s /usr/bin/false "$@"
4906 .
4907         pp_havelib) cat <<'.';;
4908             for dir in `echo /usr/lib${3+:$3} | tr : ' '`; do
4909                 test -r "$dir/lib$1.${2-sl}" && return 0
4910             done
4911             return 1
4912 .
4913         *) pp_error "unknown function request: $1";;
4914     esac
4915 }
4916
4917 pp_backend_kit_init_svc_vars () {
4918     :
4919 }
4920
4921 pp_backend_kit_probe () {
4922     echo tru64-`uname -r | sed 's/V\([0-9]*\)\.\([0-9]*\)/\1\2/'`
4923 }
4924
4925 pp_kit_service_group_script () {
4926     typeset grp svcs scriptpath out
4927     grp="$1"
4928     svcs="$2"
4929     scriptpath="/sbin/init.d/$grp"
4930     out="$pp_destdir$scriptpath"
4931
4932     pp_add_file_if_missing $scriptpath run 755 || return 0
4933
4934     cat <<-. > $out
4935         #!/sbin/sh
4936         # generated by pp $pp_version
4937         svcs="$svcs"
4938 .
4939
4940 cat <<-'.' >> $out
4941         #-- starts services in order.. stops them all if any break
4942         pp_start () {
4943             undo=
4944             for svc in $svcs; do
4945                 /sbin/init.d/$svc start
4946                 case $? in
4947                     0|4)
4948                         undo="$svc $undo"
4949                         ;;
4950                     *)
4951                         if test -n "$undo"; then
4952                         for svc in $undo; do
4953                             /sbin/init.d/$svc stop
4954                         done
4955                         return 1
4956                         fi
4957                         ;;
4958                 esac
4959             done
4960             return 0
4961         }
4962
4963         #-- stops services in reverse
4964         pp_stop () {
4965             reverse=
4966                 for svc in $svcs; do
4967                     reverse="$svc $reverse"
4968                 done
4969                 rc=0
4970                 for svc in $reverse; do
4971                     /sbin/init.d/$svc stop || rc=$?
4972                 done
4973                 return $rc
4974         }
4975
4976         case "$1" in
4977             start_msg) echo "Starting $svcs";;
4978         stop_msg)  echo "Stopping $svcs";;
4979         start)     pp_start;;
4980         stop)      pp_stop;;
4981         *)         echo "usage: $0 {start|stop|start_msg|stop_msg}"
4982             exit 1;;
4983         esac
4984 .
4985 }
4986
4987 pp_kit_service_script () {
4988     typeset svc scriptpath out
4989
4990     svc="$1"
4991     scriptpath="/sbin/init.d/$svc"
4992
4993     pp_load_service_vars "$svc"
4994
4995     test -n "$user" -a x"$user" != x"root" &&
4996     cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
4997     if test -z "$pidfile"; then
4998         pidfile="/var/run/$svc.pid"
4999         cmd="$cmd & echo \$! > \$pidfile"
5000     fi
5001
5002     pp_add_file_if_missing $scriptpath run 755
5003
5004     cat <<-. > $pp_destdir$scriptpath
5005         svc="$svc"
5006         pidfile="$pidfile"
5007
5008         pp_start () {
5009             $cmd
5010         }
5011 .
5012     cat <<-'.' >>$pp_destdir$scriptpath
5013             pp_stop () {
5014                 if test ! -s "$pidfile"; then
5015                     echo "Unable to stop $svc (no pid file)"
5016                         return 1
5017                 else
5018                     read pid < "$pidfile"
5019                     if kill -0 "$pid" 2>/dev/null; then
5020                         if kill -${stop_signal:-TERM} "$pid"; then
5021                             rm -f "$pidfile"
5022                             return 0
5023                         else
5024                             echo "Unable to stop $svc"
5025                             return 1
5026                         fi
5027                     else
5028                         rm -f "$pidfile"
5029                         return 0
5030                     fi
5031                 fi
5032             }
5033
5034             pp_running () {
5035                 if test ! -s "$pidfile"; then
5036                     return 1
5037                 else
5038                     read pid < "$pidfile"
5039                     kill -0 "$pid" 2>/dev/null
5040                 fi
5041             }
5042             case "$1" in
5043                 start_msg) echo "Starting the $svc service";;
5044                 stop_msg)  echo "Stopping the $svc service";;
5045                 start)
5046                     if pp_running; then
5047                         echo "$svc already running";
5048                         exit 0
5049                     elif pp_start; then
5050                         echo "$svc started";
5051         # rc(1M) says we should exit 4, but nobody expects it!
5052                         exit 0
5053                     else
5054                         exit 1
5055                     fi
5056                     ;;
5057                 stop)
5058                     if pp_stop; then
5059                         echo "$svc stopped";
5060                         exit 0
5061                     else
5062                         exit 1
5063                     fi
5064                     ;;
5065                 *) echo "usage: $0 {start|stop|start_msg|stop_msg}"
5066                    exit 1
5067                    ;;
5068             esac
5069 .
5070 }
5071
5072 pp_kit_make_service () {
5073     typeset level priority startlevels stoplevels
5074     typeset svc svcvar
5075
5076     svc="$1"
5077     svcvar=`pp_makevar $svc`
5078
5079     #-- don't do anything if the script exists
5080     if test -s "$pp_destdir/sbin/init.d/$svc"; then
5081         pp_error "$pp_destdir/sbin/init.d/$svc exists"
5082         return
5083     fi
5084
5085     # symlink the script, depending on the priorities chosen
5086     eval priority='${pp_kit_priority_'$svcvar'}'
5087     test -z "$priority" && priority="${pp_kit_priority:-50}"
5088
5089     eval startlevels='${pp_kit_startlevels_'$svcvar'}'
5090     test -z "$startlevels" && startlevels="$pp_kit_startlevels"
5091
5092     eval stoplevels='${pp_kit_stoplevels_'$svcvar'}'
5093     test -z "$stoplevels" && stoplevels="$pp_kit_stoplevels"
5094
5095     # create the script and config file
5096     pp_kit_service_script $svc
5097
5098     # fix the priority up
5099     case "$priority" in
5100         ???) :;;
5101         ??) priority=0$priority;;
5102         ?) priority=00$priority;;
5103     esac
5104
5105     if test x"$stoplevels" = x"auto"; then
5106         stoplevels=
5107         test -z "$startlevels" || for level in $startlevels; do
5108             stoplevels="$stoplevels `expr $level - 1`"
5109         done
5110     fi
5111
5112     # create the symlinks
5113     test -z "$startlevels" || for level in $startlevels; do
5114         echo "        ln -s /sbin/init.d/$svc /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%post.run
5115         echo "        rm /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%preun.run
5116     done
5117     test -z "$stoplevels" || for level in $stoplevels; do
5118         echo "        ln -s /sbin/init.d/$svc /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%post.run
5119         echo "        rm -f /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%preun.run
5120     done
5121 }
5122
5123
5124
5125
5126 pp_backend_kit_sizes () {
5127     awk '
5128     BEGIN { root = usr = var = 0; }
5129     {
5130         if (substr($9, 1, 1) != "l")
5131             if (substr($10, 1, 6) == "./var/")
5132                 var += $2;
5133             else if (substr($10, 1, 10) == "./usr/var/")
5134                 var += $2
5135             else if (substr($10, 1, 6) == "./usr/")
5136                 usr += $2
5137             else
5138                 root += $2
5139     }
5140     END { printf "%d\t%d\t%d", root, usr, var }
5141     ' "$@"
5142 }
5143
5144 pp_kit_kits_global () {
5145     line=`sed -n '/^%%/q;/^'$2'=/{s/^'$2'=//p;q;}' <"$1"`
5146     test -z "$line" && return 1
5147     eval "echo $line"
5148     :
5149 }
5150
5151 pp_backend_kit_kits () {
5152     typeset KITFILE FROMDIR TODIR
5153     typeset SCPDIR
5154
5155     SCPDIR="$pp_wrkdir/scps"
5156
5157     PATH="/usr/lbin:/usr/bin:/etc:/usr/ucb:$PATH"; export PATH # XXX
5158     #umask 2 # XXX
5159
5160     test $# -ge 3 || pp_die "pp_backend_kit_kits: too few arguments"
5161     KITFILE="$1"; shift
5162     FROMDIR="$1"; shift
5163     TODIR="$1"; shift
5164
5165     test -f "$KITFILE" || pp_die "$KITFILE not found"
5166     test -d "$FROMDIR" || pp_die "$FROMDIR not found"
5167     test -d "$TODIR"   || pp_die "$TODIR not found"
5168
5169     INSTCTRL="$TODIR/instctrl"
5170     mkdir -p "$INSTCTRL" || pp_die "cannot create instctrl directory"
5171     chmod 775 "$INSTCTRL"
5172
5173     grep "%%" $KITFILE > /dev/null || pp_die "no %% in $KITFILE"
5174
5175     typeset NAME CODE VERS MI ROOT COMPRESS
5176     typeset S_LIST ALLSUBS
5177
5178     NAME=`pp_kit_kits_global "$KITFILE" NAME` || pp_die "no NAME in $KITFILE"
5179     CODE=`pp_kit_kits_global "$KITFILE" CODE` || pp_die "no CODE in $KITFILE"
5180     VERS=`pp_kit_kits_global "$KITFILE" VERS` || pp_die "no VERS in $KITFILE"
5181     MI=`pp_kit_kits_global "$KITFILE" MI` || pp_die "no MI in $KITFILE"
5182     ROOT=`pp_kit_kits_global "$KITFILE" ROOT`
5183     COMPRESS=`pp_kit_kits_global "$KITFILE" COMPRESS`
5184
5185     test -f "$MI" || pp_die "Inventory file $MI not found"
5186
5187     case "$ROOT" in
5188     *ROOT)
5189         test -f "$TODIR/$ROOT" ||
5190             pp_die "Root image $ROOT not found in $TODIR" ;;
5191     esac
5192
5193     ALLSUBS=`awk 'insub==1 {print $1} /^%%/ {insub=1}' <"$KITFILE"`
5194     test $# -eq 0 && set -- $ALLSUBS
5195
5196     pp_debug "Creating $# $NAME subsets."
5197     pp_debug "ALLSUBS=<$ALLSUBS>"
5198
5199     if test x"$COMPRESS" = x"1"; then
5200         COMPRESS=:
5201     else
5202         COMPRESS=false
5203     fi
5204
5205     #rm -f *.ctrl Volume*
5206
5207     for SUB
5208     do
5209         test -z "$SUB" && pp_die "SUB is empty"
5210
5211         typeset INV CTRL ROOTSIZE USRSIZE VARSIZE TSSUB
5212         #rm -f Volume*
5213         case $SUB in
5214             .*) :;;
5215             *)  pp_verbose rm -f "$TODIR/$SUB"* "$INSTCTRL/$SUB"*;;
5216         esac
5217
5218         TSSUB="$pp_wrkdir/ts.$SUB"
5219
5220         pp_debug "kits: Subset $SUB"
5221
5222         INV="$SUB.inv"
5223         CTRL="$SUB.ctrl"
5224         pp_debug "kits: Generating media creation information..."
5225
5226         # Invcutter takes as input
5227         #   SUB dir/path
5228         # and generates stl_inv(4) files, like this
5229         #   f 0 00000 0 0 100644 2/11/09 010 f dir/path none SUB
5230         grep "  $SUB\$" "$MI" |
5231             pp_verbose /usr/lbin/invcutter \
5232                 -v "$VERS" -f "$FROMDIR" > "$INSTCTRL/$INV" ||
5233             pp_die "failed to create $INSTCTRL/$INV"
5234         chmod 664 "$INSTCTRL/$INV"
5235
5236         pp_backend_kit_sizes "$INSTCTRL/$INV" > "$pp_wrkdir/kit.sizes"
5237         read ROOTSIZE USRSIZE VARSIZE < "$pp_wrkdir/kit.sizes"
5238
5239         # Prefix each line with $FROMDIR. This will be stripped
5240         awk '$1 != "d" {print from $10}' from="$FROMDIR/" \
5241             > "$TSSUB" < "$INSTCTRL/$INV" ||
5242             pp_die "failed"
5243
5244         NVOLS=0
5245
5246         pp_debug "kits: Creating $SUB control file..."
5247
5248         sed '1,/^%%/d;/^'"$SUB"'/{p;q;}' < "$KITFILE" > "$pp_wrkdir/kit.line"
5249         read _SUB _IGNOR DEPS FLAGS DESC < "$pp_wrkdir/kit.line"
5250         if test -z "$_SUB"; then
5251             pp_warn "No such subset $SUB in $KITFILE"
5252             continue
5253         fi
5254         DEPS=`echo $DEPS | tr '|' ' '`
5255         case $FLAGS in
5256             FLGEXP*) pp_verbose FLAGS='"${'"$FLAGS"'}"' ;;
5257         esac
5258         case $DESC in
5259             *%*) DESC=`echo $DESC|awk -F% '{printf "%-36s%%%s\n", $1, $2}'`;;
5260         esac
5261
5262         cat > "$INSTCTRL/$CTRL" <<-.
5263                 NAME='$NAME $SUB'
5264                 DESC=$DESC
5265                 ROOTSIZE=$ROOTSIZE
5266                 USRSIZE=$USRSIZE
5267                 VARSIZE=$VARSIZE
5268                 NVOLS=1:$NVOLS
5269                 MTLOC=1:$TLOC
5270                 DEPS="$DEPS"
5271                 FLAGS=$FLAGS
5272 .
5273         chmod 664 "$INSTCTRL/$CTRL"
5274
5275         pp_debug "kits: Making tar image"
5276
5277         pp_verbose tar cfPR "$TODIR/$SUB" "$FROMDIR/" "$TSSUB" ||
5278              pp_error "problem creating kit file"
5279
5280         if $COMPRESS; then
5281             pp_debug "kits: Compressing"
5282             (cd "$TODIR" && compress -f -v "$SUB") ||
5283                 pp_die "problem compressing $TODIR/$SUB"
5284             SPC=`expr $SUB : '\(...\).*'`    # first three characters
5285             SVC=`expr $SUB : '.*\(...\)'`    # last three characters
5286             : > "$INSTCTRL/$SPC$SVC.comp"
5287             chmod 664 "$INSTCTRL/$SPC$SVC.comp"
5288             pp_debug "kits: Padding compressed file to 10kB" # wtf?
5289             rm -f "$TODIR/$SUB"
5290             pp_verbose \
5291             dd if="$TODIR/$SUB.Z" of="$TODIR/$SUB" bs=10k conv=sync ||
5292                 pp_die "problem moving compressed file"
5293             rm -f "$TODIR/$SUB.Z"
5294         fi
5295         chmod 664 "$TODIR/$SUB"
5296
5297         if test -f "$SCPDIR/$SUB.scp"; then
5298                 cp "$SCPDIR/$SUB.scp" "$INSTCTRL/$SUB.scp"
5299                 chmod 755 "$INSTCTRL/$SUB.scp"
5300         else
5301                 pp_debug "kits: null subset control program for $SUB"
5302                 : > "$INSTCTRL/$SUB.scp"
5303                 chmod 744 "$INSTCTRL/$SUB.scp"
5304         fi
5305
5306         pp_debug "kits: Finished creating media image for $SUB"
5307     done
5308
5309     pp_debug "kits: Creating $CODE.image"
5310
5311     case "$ROOT" in
5312     *ROOT)      ALLSUBS="$ROOT $ALLSUBS"
5313                 ;;
5314     esac
5315
5316     (cd "$TODIR" && sum $ALLSUBS) > "$INSTCTRL/$CODE.image"
5317     chmod 664 "$INSTTRL/$CODE.image"
5318     pp_debug "kits: Creating INSTCTRL"
5319     (cd "$INSTCTRL" && tar cpvf - *) > "$TODIR/INSTCTRL"
5320     chmod 664 "$TODIR/INSTCTRL"
5321     cp "$INSTCTRL/$CODE.image" "$TODIR/$CODE.image"
5322     chmod 664 "$TODIR/$CODE.image"
5323
5324     pp_debug "kits: Media image production complete"
5325 }
5326
5327 pp_platforms="$pp_platforms rpm"
5328
5329 pp_backend_rpm_detect () {
5330     test x"$1" = x"Linux" -a ! -f /etc/debian_version
5331 }
5332
5333 pp_backend_rpm_init () {
5334
5335     pp_rpm_version=
5336     pp_rpm_summary=
5337     pp_rpm_description=
5338     pp_rpm_group="Applications/Internet"
5339     pp_rpm_license="Unspecified"
5340     pp_rpm_vendor=
5341     pp_rpm_url=
5342     pp_rpm_packager=
5343     pp_rpm_provides=
5344     pp_rpm_requires=
5345     pp_rpm_release=
5346     pp_rpm_epoch=
5347     pp_rpm_dev_group="Development/Libraries"
5348     pp_rpm_dbg_group="Development/Tools"
5349     pp_rpm_doc_group="Documentation"
5350     pp_rpm_dev_description=
5351     pp_rpm_dbg_description=
5352     pp_rpm_doc_description=
5353     pp_rpm_dev_requires=
5354     pp_rpm_dbg_requires=
5355     pp_rpm_doc_requires=
5356     pp_rpm_dev_provides=
5357     pp_rpm_dbg_provides=
5358     pp_rpm_doc_provides=
5359
5360     pp_rpm_dbg_pkgname=debug
5361     pp_rpm_dev_pkgname=devel
5362     pp_rpm_doc_pkgname=doc
5363
5364     pp_rpm_defattr_uid=root
5365     pp_rpm_defattr_gid=root
5366
5367     pp_rpm_detect_arch
5368     pp_rpm_detect_distro
5369     pp_rpm_rpmbuild=`pp_rpm_detect_rpmbuild`
5370
5371     # SLES8 doesn't always come with readlink
5372     test -x /usr/bin/readlink -o -x /bin/readlink ||
5373         pp_readlink_fn=pp_ls_readlink
5374 }
5375
5376 pp_rpm_detect_arch () {
5377     pp_rpm_arch=auto
5378
5379     #-- Find the default native architecture that RPM is configured to use
5380     cat <<-. >$pp_wrkdir/dummy.spec
5381         Name: dummy
5382         Version: 1
5383         Release: 1
5384         Summary: dummy
5385         Group: ${pp_rpm_group}
5386         License: ${pp_rpm_license}
5387         %description
5388         dummy
5389 .
5390     $pp_opt_debug && cat $pp_wrkdir/dummy.spec
5391     pp_rpm_arch_local=`rpm -q --qf '%{arch}\n' --specfile $pp_wrkdir/dummy.spec`
5392     rm $pp_wrkdir/dummy.spec
5393
5394     #-- Ask the kernel what machine architecture is in use
5395     local arch
5396     for arch in "`uname -m`" "`uname -p`"; do
5397         case "$arch" in
5398             i?86)
5399                 pp_rpm_arch_std=i386
5400                 break
5401                 ;;
5402             x86_64|ppc|ppc64|ia64|s390|s390x)
5403                 pp_rpm_arch_std="$arch"
5404                 break
5405                 ;;
5406             powerpc)
5407                 # Probably AIX
5408                 case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
5409                     PowerPC_POWER*)     pp_rpm_arch_std=ppc64;;
5410                     *)                  pp_rpm_arch_std=ppc;;
5411                 esac
5412                 break
5413                 ;;
5414             *)  pp_rpm_arch_std=unknown
5415                 ;;
5416         esac
5417     done
5418
5419     #-- Later on, when files are processed, we use 'file' to determine
5420     #   what platform ABIs are used. This is used when pp_rpm_arch == auto
5421     pp_rpm_arch_seen=
5422 }
5423
5424 pp_rpm_detect_distro () {
5425     pp_rpm_distro=
5426     if test -f /etc/whitebox-release; then
5427        pp_rpm_distro=`awk '
5428           /^White Box Enterprise Linux release/ { print "wbel" $6; exit; }
5429        ' /etc/whitebox-release`
5430     elif test -f /etc/mandrakelinux-release; then
5431        pp_rpm_distro=`awk '
5432           /^Mandrakelinux release/ { print "mand" $3; exit; }
5433        ' /etc/mandrake-release`
5434     elif test -f /etc/mandrake-release; then
5435        pp_rpm_distro=`awk '
5436           /^Linux Mandrake release/ { print "mand" $4; exit; }
5437           /^Mandrake Linux release/ { print "mand" $4; exit; }
5438        ' /etc/mandrake-release`
5439     elif test -f /etc/fedora-release; then
5440        pp_rpm_distro=`awk '
5441           /^Fedora Core release/ { print "fc" $4; exit; }
5442           /^Fedora release/ { print "f" $3; exit; }
5443        ' /etc/fedora-release`
5444     elif test -f /etc/redhat-release; then
5445        pp_rpm_distro=`awk '
5446           /^Red Hat Enterprise Linux/ { print "rhel" $7; exit; }
5447           /^CentOS release/           { print "centos" $3; exit; }
5448           /^CentOS Linux release/     { print "centos" $4; exit; }
5449           /^Red Hat Linux release/    { print "rh" $5; exit; }
5450        ' /etc/redhat-release`
5451     elif test -f /etc/SuSE-release; then
5452        pp_rpm_distro=`awk '
5453           /^SuSE Linux [0-9]/ { print "suse" $3; exit; }
5454           /^SUSE LINUX [0-9]/ { print "suse" $3; exit; }
5455           /^openSUSE [0-9]/   { print "suse" $2; exit; }
5456           /^S[uU]SE Linux Enterprise Server [0-9]/ { print "sles" $5; exit; }
5457           /^S[uU]SE LINUX Enterprise Server [0-9]/ { print "sles" $5; exit; }
5458           /^SuSE SLES-[0-9]/  { print "sles" substr($2,6); exit; }
5459        ' /etc/SuSE-release`
5460     elif test -f /etc/pld-release; then
5461        pp_rpm_distro=`awk '
5462           /^[^ ]* PLD Linux/ { print "pld" $1; exit; }
5463        ' /etc/pld-release`
5464     elif test X"`uname -s 2>/dev/null`" = X"AIX"; then
5465         local r v
5466         r=`uname -r`
5467         v=`uname -v`
5468         pp_rpm_distro="aix$v$r"
5469     fi
5470     pp_rpm_distro=`echo $pp_rpm_distro | tr -d .`
5471     test -z "$pp_rpm_distro" &&
5472        pp_warn "unknown distro"
5473 }
5474
5475 pp_rpm_detect_rpmbuild () {
5476     local cmd
5477     for cmd in rpmbuild rpm; do
5478         if `which $cmd > /dev/null 2>&1`; then
5479             echo $cmd
5480             return 0
5481         fi
5482     done
5483
5484     pp_error "Could not find rpmbuild"
5485     # Default to `rpmbuild` in case it magically appears
5486     echo rpmbuild
5487     return 1
5488 }
5489
5490 pp_rpm_label () {
5491     local label arg
5492     label="$1"; shift
5493     for arg
5494     do
5495         test -z "$arg" || echo "$label: $arg"
5496     done
5497 }
5498
5499 pp_rpm_writefiles () {
5500     local _l t m o g f p st fo farch
5501     while read t m o g f p st; do
5502         _l="$p"
5503         test $t = d && _l="%dir ${_l%/}/"
5504         if test x"$m" = x"-"; then
5505             case "$t" in
5506                 d) m=755;;
5507                 f) m=644;;
5508             esac
5509         fi
5510         test x"$o" = x"-" && o="${pp_rpm_defattr_uid:-root}"
5511         test x"$g" = x"-" && g="${pp_rpm_defattr_gid:-root}"
5512         _l="%attr($m,$o,$g) $_l"
5513
5514         if test "$t" = "f" -a x"$pp_rpm_arch" = x"auto"; then
5515             fo=`file "${pp_destdir}$p" 2>/dev/null`
5516             #NB: The following should match executables and shared objects,
5517             #relocatable objects. It will not match .a files however.
5518             case "$fo" in
5519                 *": ELF 32-bit LSB "*", Intel 80386"*)
5520                     farch=i386;;
5521                 *": ELF 64-bit LSB "*", AMD x86-64"*|\
5522                 *": ELF 64-bit LSB "*", x86-64"*)
5523                     farch=x86_64;;
5524                 *": ELF 32-bit MSB "*", PowerPC"*)
5525                     farch=ppc;;
5526                 *": ELF 64-bit MSB "*", 64-bit PowerPC"*)
5527                     farch=ppc64;;
5528                 *": ELF 64-bit LSB "*", IA-64"*)
5529                     farch=ia64;;
5530                 *": ELF 32-bit MSB "*", IBM S/390"*)
5531                     farch=s390;;
5532                 *": ELF 64-bit MSB "*", IBM S/390"*)
5533                     farch=s390x;;
5534                 *"executable (RISC System/6000)"*)
5535                     farch=ppc;;
5536                 *"64-bit XCOFF executable"*)
5537                     farch=ppc64;;
5538                 *" ELF "*)
5539                     farch=ELF;;
5540                 *)
5541                     farch=noarch;;
5542             esac
5543             # If file(1) doesn't provide enough info, try readelf(1)
5544             if test "$farch" = "ELF"; then
5545                 fo=`readelf -h "${pp_destdir}$p" | awk '{if ($1 == "Class:") {class=$2} else if ($1 == "Machine:") {machine=$0; sub(/^ *Machine: */, "", machine)}} END {print class " " machine}' 2>/dev/null`
5546                 case "$fo" in
5547                     "ELF32 Intel 80386")
5548                         farch=i386;;
5549                     "ELF64 "*[xX]"86-64")
5550                         farch=x86_64;;
5551                     "ELF32 PowerPC")
5552                         farch=ppc;;
5553                     "ELF64 PowerPC"*)
5554                         farch=ppc64;;
5555                     "ELF64 IA-64")
5556                         farch=ia64;;
5557                     "ELF32 IBM S/390")
5558                         farch=s390;;
5559                     "ELF64 IBM S/390")
5560                         farch=s390x;;
5561                     *)
5562                         farch=noarch;;
5563                 esac
5564             fi
5565             pp_debug "file: $fo -> $farch"
5566             test x"$farch" = x"noarch" || pp_add_to_list pp_rpm_arch_seen $farch
5567         fi
5568
5569         case $f in *v*) _l="%config(noreplace) $_l";; esac
5570         echo "$_l"
5571     done
5572     echo
5573 }
5574
5575 pp_rpm_subname () {
5576     case "$1" in
5577         run) : ;;
5578         dbg) echo "${2}${pp_rpm_dbg_pkgname}";;
5579         dev) echo "${2}${pp_rpm_dev_pkgname}";;
5580         doc) echo "${2}${pp_rpm_doc_pkgname}";;
5581         *)   pp_error "unknown component '$1'";
5582     esac
5583 }
5584
5585 pp_rpm_depend () {
5586     local _name _vers
5587     while read _name _vers; do
5588         case "$_name" in ""| "#"*) continue ;; esac
5589         echo "Requires: $_name ${_vers:+>= $_vers}"
5590     done
5591 }
5592
5593 pp_rpm_conflict () {
5594     local _name _vers
5595     while read _name _vers; do
5596         case "$_name" in ""| "#"*) continue ;; esac
5597         echo "Conflicts: $_name ${_vers:+>= $_vers}"
5598     done
5599 }
5600
5601 pp_rpm_override_requires () {
5602     local orig_find_requires
5603
5604     if test -z "$pp_rpm_depend_filter_cmd"; then
5605         return 0
5606     fi
5607
5608     orig_find_requires=`rpm --eval '%{__find_requires}'`
5609     cat << EOF > "$pp_wrkdir/filtered-find-requires"
5610 $orig_find_requires \$@ | $pp_rpm_depend_filter_cmd
5611 EOF
5612     chmod +x "$pp_wrkdir/filtered-find-requires"
5613     echo "%define __find_requires $pp_wrkdir/filtered-find-requires"
5614     # Might be necessary for old versions of RPM? Not for 4.4.2.
5615     #echo "%define _use_internal_dependency_generator 0"
5616 }
5617
5618 pp_backend_rpm () {
5619     local cmp specfile _summary _group _desc _pkg _subname svc
5620
5621         specfile=$pp_wrkdir/$name.spec
5622         : > $specfile
5623
5624         #-- force existence of a 'run' component
5625         pp_add_component run
5626         : >> $pp_wrkdir/%files.run
5627
5628         if test -z "$pp_rpm_arch"; then
5629             pp_error "Unknown RPM architecture"
5630             return 1
5631         fi
5632
5633         #-- Write the header components of the RPM spec file
5634         cat <<-. >>$specfile
5635                 Name: ${pp_rpm_name:-$name}
5636                 Version: ${pp_rpm_version:-$version}
5637                 Release: ${pp_rpm_release:-1}
5638                 Summary: ${pp_rpm_summary:-$summary}
5639                 Group:   ${pp_rpm_group}
5640                 License: ${pp_rpm_license}
5641 .
5642         if test -n "$pp_rpm_url"; then
5643             pp_rpm_label "URL"  "$pp_rpm_url"               >>$specfile
5644         fi
5645         pp_rpm_label "Vendor"   "${pp_rpm_vendor:-$vendor}" >>$specfile
5646         pp_rpm_label "Packager" "$pp_rpm_packager"          >>$specfile
5647         pp_rpm_label "Provides" "$pp_rpm_provides"          >>$specfile
5648         pp_rpm_label "Requires" "$pp_rpm_requires"          >>$specfile
5649
5650         test -n "$pp_rpm_serial" && pp_warn "pp_rpm_serial deprecated"
5651         if test -n "$pp_rpm_epoch"; then
5652             #-- Epoch was introduced in RPM 2.5.6
5653             case `$pp_rpm_rpmbuild --version 2>/dev/null` in
5654                 1.*|2.[0-5].*|2.5.[0-5])
5655                     pp_rpm_label "Serial" $pp_rpm_epoch >>$specfile;;
5656                 *)
5657                     pp_rpm_label "Epoch" $pp_rpm_epoch >>$specfile;;
5658             esac
5659         fi
5660
5661         if test -n "$pp_rpm_requires"; then
5662             pp_rpm_label "Requires" "$pp_rpm_requires" >>$specfile
5663         elif test -s $pp_wrkdir/%depend.run; then
5664             pp_rpm_depend < $pp_wrkdir/%depend.run >> $specfile
5665         fi
5666         if test -s $pp_wrkdir/%conflict.run; then
5667             pp_rpm_conflict < $pp_wrkdir/%conflict.run >> $specfile
5668         fi
5669
5670         pp_rpm_override_requires >> $specfile
5671
5672         cat <<-. >>$specfile
5673
5674                 %description
5675                 ${pp_rpm_description:-$description}
5676 .
5677
5678         for cmp in $pp_components; do
5679                 case $cmp in
5680                    run) continue;;
5681                    dev) _summary="development tools for $pp_rpm_summary"
5682                         _group="$pp_rpm_dev_group"
5683                         _desc="${pp_rpm_dev_description:-Development libraries for $name. $pp_rpm_description.}"
5684                         ;;
5685                    doc) _summary="documentation for $pp_rpm_summary"
5686                         _group="$pp_rpm_doc_group"
5687                         _desc="${pp_rpm_doc_description:-Documentation for $name. $pp_rpm_description.}"
5688                         ;;
5689                    dbg) _summary="diagnostic tools for $pp_rpm_summary"
5690                         _group="$pp_rpm_dbg_group"
5691                         _desc="${pp_rpm_dbg_description:-Diagnostic tools for $name.}"
5692                         ;;
5693                 esac
5694
5695                 _subname=`pp_rpm_subname $cmp`
5696                 cat <<-.
5697
5698                         %package $_subname
5699                         Summary: $name $_summary
5700                         Group: $_group
5701 .
5702                 eval '_pkg="$pp_rpm_'$cmp'_requires"'
5703                 if test -n "$_pkg"; then
5704                     eval pp_rpm_label Requires ${pp_rpm_name:-$name} $_pkg
5705                 elif test -s $pp_wrkdir/%depend.$cmp; then
5706                     pp_rpm_depend < $pp_wrkdir/%depend.$cmp >> $specfile
5707                 fi
5708                 if test -s $pp_wrkdir/%conflict.$cmp; then
5709                     pp_rpm_conflict < $pp_wrkdir/%conflict.$cmp >> $specfile
5710                 fi
5711
5712                 eval '_pkg="$pp_rpm_'$cmp'_provides"'
5713                 eval pp_rpm_label Provides $_pkg
5714
5715                 cat <<-.
5716
5717                         %description $_subname
5718                         $_desc
5719 .
5720         done >>$specfile
5721
5722         #-- NB: we don't put any %prep, %build or %install RPM sections
5723         #   into the spec file.
5724
5725         #-- add service start/stop code
5726         if test -n "$pp_services"; then
5727             pp_rpm_service_install_common >> $pp_wrkdir/%post.run
5728
5729             #-- record the uninstall commands in reverse order
5730             for svc in $pp_services; do
5731                 pp_load_service_vars $svc
5732
5733                 pp_rpm_service_make_init_script $svc
5734
5735                 #-- append %post code to install the svc
5736                 pp_rpm_service_install $svc >> $pp_wrkdir/%post.run
5737
5738                 #-- prepend %preun code to uninstall svc
5739                 # (use files in case vars are modified)
5740                 pp_rpm_service_remove $svc | pp_prepend $pp_wrkdir/%preun.run
5741             done
5742             pp_rpm_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
5743         fi
5744
5745         # make convenience service groups
5746         if test -n "$pp_service_groups"; then
5747             for grp in $pp_service_groups; do
5748                 pp_rpm_service_group_make_init_script \
5749                     $grp "`pp_service_get_svc_group $grp`"
5750             done
5751         fi
5752
5753         #-- Write the RPM %file sections
5754         #   (do this after services, since services adds to %files.run)
5755         for cmp in $pp_components; do
5756             _subname=`pp_rpm_subname $cmp`
5757
5758             if test -s $pp_wrkdir/%check.$cmp; then
5759                 echo ""
5760                 echo "%pre $_subname"
5761                 cat $pp_wrkdir/%check.$cmp
5762                 echo :   # causes script to exit true by default
5763             fi
5764
5765             if test -s $pp_wrkdir/%files.$cmp; then
5766                 echo ""
5767                 echo "%files $_subname"
5768                 pp_rpm_writefiles < $pp_wrkdir/%files.$cmp
5769             fi
5770
5771             if test -n "$pp_rpm_ghost"; then
5772                 for ghost in $pp_rpm_ghost; do
5773                     echo "%ghost $ghost"
5774                 done
5775             fi
5776
5777             if test -s $pp_wrkdir/%pre.$cmp; then
5778                 echo ""
5779                 echo "%pre $_subname"
5780                 cat $pp_wrkdir/%pre.$cmp
5781                 echo :   # causes script to exit true
5782             fi
5783
5784             if test -s $pp_wrkdir/%post.$cmp; then
5785                 echo ""
5786                 echo "%post $_subname"
5787                 cat $pp_wrkdir/%post.$cmp
5788                 echo :   # causes script to exit true
5789             fi
5790
5791             if test -s $pp_wrkdir/%preun.$cmp; then
5792                 echo ""
5793                 echo "%preun $_subname"
5794                 cat $pp_wrkdir/%preun.$cmp
5795                 echo :   # causes script to exit true
5796             fi
5797
5798             if test -s $pp_wrkdir/%postun.$cmp; then
5799                 echo ""
5800                 echo "%postun $_subname"
5801                 cat $pp_wrkdir/%postun.$cmp
5802                 echo :   # causes script to exit true
5803             fi
5804         done >>$specfile
5805
5806         #-- create a suitable work area for rpmbuild
5807         cat <<-. >$pp_wrkdir/.rpmmacros
5808                 %_topdir $pp_wrkdir
5809                 # XXX Note escaped %% for use in headerSprintf
5810                 %_rpmfilename   %%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
5811         .
5812         mkdir $pp_wrkdir/RPMS
5813         mkdir $pp_wrkdir/BUILD
5814
5815         if test x"$pp_rpm_arch" = x"auto"; then
5816             #-- Reduce the arch_seen list to exactly one item
5817             case "$pp_rpm_arch_seen" in
5818                 "i386 x86_64"|"x86_64 i386")
5819                     pp_rpm_arch_seen=x86_64;;
5820                 *"s390 s390x"* | *"s390x s390"* )
5821                     pp_rpm_arch_seen=s390x;;
5822                 *" "*)
5823                     pp_error "detected multiple targets: $pp_rpm_arch_seen"
5824                     pp_rpm_arch_seen=unknown;;      # not detected
5825                 "")
5826                     pp_warn "detected no binaries: using target noarch"
5827                     pp_rpm_arch_seen=noarch;;
5828                 *)
5829                     pp_debug "detected architecture $pp_rpm_arch_seen"
5830             esac
5831             pp_rpm_arch="$pp_rpm_arch_seen"
5832         fi
5833
5834         . $pp_wrkdir/%fixup
5835
5836 $pp_opt_debug && cat $specfile
5837
5838         pp_debug "creating: `pp_backend_rpm_names`"
5839
5840 pp_debug "pp_rpm_arch_seen = <${pp_rpm_arch_seen}>"
5841 pp_debug "pp_rpm_arch = <${pp_rpm_arch}>"
5842
5843         HOME=$pp_wrkdir \
5844         pp_verbose \
5845         $pp_rpm_rpmbuild -bb \
5846                 --buildroot="$pp_destdir/" \
5847                 --target="${pp_rpm_arch}" \
5848                 --define='_unpackaged_files_terminate_build 0' \
5849                 --define='_use_internal_dependency_generator 0' \
5850                 `$pp_opt_debug && echo --verbose || echo --quiet` \
5851                 $pp_rpm_rpmbuild_extra_flags \
5852                 $specfile ||
5853             pp_error "Problem creating RPM packages"
5854
5855         for f in `pp_backend_rpm_names`; do
5856             # The package might be in an arch-specific subdir
5857             pkgfile=not-found
5858             for dir in $pp_wrkdir/RPMS/${pp_rpm_arch} $pp_wrkdir/RPMS; do
5859                 if test -f $dir/$f; then
5860                     pkgfile=$dir/$f
5861                 fi
5862             done
5863             if test x"$pkgfile" = x"not-found"; then
5864                 pp_error "Problem predicting RPM filename: $f"
5865             else
5866                 ln $pkgfile $pp_wrkdir/$f
5867             fi
5868         done
5869 }
5870
5871 pp_rpm_output_name () {
5872     echo "${pp_rpm_name:-$name}`pp_rpm_subname "$1" -`-${pp_rpm_version:-$version}-${pp_rpm_release:-1}.${pp_rpm_arch}.rpm"
5873 }
5874
5875 pp_backend_rpm_names () {
5876     local cmp _subname
5877     for cmp in $pp_components; do
5878         pp_rpm_output_name $cmp
5879     done
5880 }
5881
5882 pp_backend_rpm_cleanup () {
5883     :
5884 }
5885
5886 pp_rpm_print_requires () {
5887     local _subname _name
5888
5889     echo "CPU:$pp_rpm_arch"
5890     ## XXX should be lines of the form (from file/ldd/objdump)
5891     #    EXEC:/bin/sh
5892     #    RTLD:libc.so.4:open
5893     rpm -q --requires -p $pp_wrkdir/`pp_rpm_output_name $1` |sed -e '/^rpmlib(/d;s/ //g;s/^/RPM:/' | sort -u
5894 }
5895
5896 pp_backend_rpm_install_script () {
5897     local cmp _subname
5898
5899     echo "#!/bin/sh"
5900     pp_install_script_common
5901
5902     cat <<.
5903
5904         cmp_to_pkgname () {
5905             local oi name
5906             if test x"\$1" = x"--only-installed"; then
5907                 #-- only print if installation detected
5908                 oi=false
5909                 shift
5910             else
5911                 oi=true
5912             fi
5913             test x"\$*" = x"all" &&
5914                 set -- $pp_components
5915             for cmp
5916             do
5917                 case \$cmp in
5918 .
5919     for cmp in $pp_components; do
5920         _subname=`pp_rpm_subname $cmp -`
5921          echo "$cmp) name=${pp_rpm_name:-$name}${_subname};;"
5922     done
5923     cat <<.
5924                 *) usage;;
5925                 esac
5926                 if \$oi || rpm -q "\$name" >/dev/null 2>/dev/null; then
5927                     echo "\$name"
5928                 fi
5929             done
5930         }
5931
5932
5933         cmp_to_pathname () {
5934             test x"\$*" = x"all" &&
5935                 set -- $pp_components
5936             for cmp
5937             do
5938                 case \$cmp in
5939 .
5940     for cmp in $pp_components; do
5941         echo "$cmp) echo \${PP_PKGDESTDIR:-.}/`pp_rpm_output_name $cmp` ;;"
5942     done
5943     cat <<.
5944                 *) usage;;
5945                 esac
5946             done
5947         }
5948
5949         print_requires () {
5950             test x"\$*" = x"all" &&
5951                 set -- $pp_components
5952             for cmp
5953             do
5954                 case \$cmp in
5955 .
5956     for cmp in $pp_components; do
5957         echo "$cmp) cat <<'._end'"
5958         pp_rpm_print_requires $cmp
5959         echo "._end"; echo ';;'
5960     done
5961     cat <<.
5962                 *) usage;;
5963                 esac
5964             done
5965         }
5966
5967         test \$# -eq 0 && usage
5968         op="\$1"; shift
5969         case "\$op" in
5970             list-components)
5971                 test \$# -eq 0 || usage \$op
5972                 echo $pp_components
5973                 ;;
5974             list-services)
5975                 test \$# -eq 0 || usage \$op
5976                 echo $pp_services
5977                 ;;
5978             list-files)
5979                 test \$# -ge 1 || usage \$op
5980                 cmp_to_pathname "\$@"
5981                 ;;
5982             install)
5983                 test \$# -ge 1 || usage \$op
5984                 verbose rpm -U --replacepkgs --oldpackage \
5985                     \`cmp_to_pathname "\$@"\`
5986                 ;;
5987             uninstall)
5988                 test \$# -ge 1 || usage \$op
5989                 pkgs=\`cmp_to_pkgname --only-installed "\$@"\`
5990                 if test -z "\$pkgs"; then
5991                     verbosemsg "nothing to uninstall"
5992                 else
5993                     verbose rpm -e \$pkgs
5994                 fi
5995                 ;;
5996             start|stop)
5997                 test \$# -ge 1 || usage \$op
5998                 ec=0
5999                 for svc
6000                 do
6001                     verbose /etc/init.d/\$svc \$op || ec=1
6002                 done
6003                 exit \$ec
6004                 ;;
6005             print-platform)
6006                 test \$# -eq 0 || usage \$op
6007                 echo "linux-${pp_rpm_arch}"
6008                 ;;
6009             print-requires)
6010                 test \$# -ge 1 || usage \$op
6011                 print_requires "\$@"
6012                 ;;
6013             *)
6014                 usage
6015                 ;;
6016         esac
6017 .
6018
6019 }
6020
6021 pp_backend_rpm_probe () {
6022         echo "${pp_rpm_distro}-${pp_rpm_arch_std}"
6023 }
6024
6025 pp_backend_rpm_vas_platforms () {
6026     case "$pp_rpm_arch_std" in
6027         x86_64) echo "linux-x86_64.rpm linux-x86.rpm";;
6028         *86)    echo "linux-x86.rpm";;
6029         s390)   echo "linux-s390";;
6030         s390x)  echo "linux-s390x";;
6031         ppc*)   echo "linux-glibc23-ppc64 linux-glibc22-ppc64";;
6032         ia64)   echo "linux-ia64";;
6033         *)      pp_die "unknown architecture $pp_rpm_arch_std";;
6034     esac
6035 }
6036
6037 pp_rpm_service_install_common () {
6038     cat <<-'.'
6039
6040         _pp_install_service () {
6041             local svc level
6042             svc="$1"
6043             if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
6044             then
6045                 # LSB-style install
6046                 /usr/lib/lsb/install_initd /etc/init.d/$svc &> /dev/null
6047             elif [ -x /sbin/chkconfig ]; then
6048                 # Red Hat/chkconfig-style install
6049                 /sbin/chkconfig --add $svc &> /dev/null
6050                 /sbin/chkconfig $svc off &> /dev/null
6051             else
6052                 : # manual links under /etc/init.d
6053             fi
6054         }
6055
6056         _pp_enable_service () {
6057             local svc level
6058             svc="$1"
6059             if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
6060             then
6061                 # LSB-style install
6062                 : # not sure how to enable
6063             elif [ -x /sbin/chkconfig ]; then
6064                 # Red Hat/chkconfig-style install
6065                 /sbin/chkconfig $svc on &> /dev/null
6066             else
6067                 # manual install
6068                 set -- `sed -n -e 's/^# Default-Start://p' /etc/init.d/$svc`
6069                 start_priority=`sed -n -e 's/^# X-Quest-Start-Priority:[[:space:]]*//p' /etc/init.d/$svc`
6070                 stop_priority=`sed -n -e 's/^# X-Quest-Stop-Priority:[[:space:]]*//p' /etc/init.d/$svc`
6071
6072                 # Provide default start & stop priorities of 20 & 80 in
6073                 # accordance with Debian update-rc.d defaults
6074                 if [ -z "$start_priority" ]; then
6075                     start_priority=20
6076                 fi
6077                 if [ -z "$stop_priority" ]; then
6078                     stop_priority=80
6079                 fi
6080                     
6081                 if [ -d "/etc/rc.d" ];then
6082                     rcdir=/etc/rc.d
6083                 else
6084                     rcdir=/etc
6085                 fi
6086
6087                 for level
6088                 do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/S$start_priority$svc; done
6089                 set -- `sed -n -e 's/^# Default-Stop://p' /etc/init.d/$svc`
6090                 for level
6091                 do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/K$stop_priority$svc; done
6092             fi
6093         }
6094 .
6095 }
6096
6097 pp_rpm_service_remove_common () {
6098     cat <<-'.'
6099
6100         _pp_remove_service () {
6101             local svc
6102             svc="$1"
6103             /etc/init.d/$svc stop >/dev/null 2>&1
6104             if [ -x /usr/lib/lsb/remove_initd -a ! -r /etc/redhat-release ]
6105             then
6106                 /usr/lib/lsb/remove_initd /etc/init.d/$svc &> /dev/null
6107             elif [ -x /sbin/chkconfig ]; then
6108                 /sbin/chkconfig --del $svc &> /dev/null
6109             else
6110                 if [ -d "/etc/rc.d" ];then
6111                     rcdir=/etc/rc.d
6112                 else
6113                     rcdir=/etc
6114                 fi
6115
6116                 rm -f $rcdir/rc?.d/[SK]??$svc
6117             fi
6118         }
6119 .
6120 }
6121
6122
6123 pp_rpm_service_install () {
6124     pp_rpm_service_make_init_script $1 >/dev/null ||
6125         pp_error "could not create init script for service $1"
6126     echo "_pp_install_service $1"
6127     test $enable = yes && echo "_pp_enable_service $1"
6128 }
6129
6130 pp_rpm_service_remove () {
6131     cat <<-.
6132         if [ "\$1" = "remove" -o "\$1" = "0" ]; then
6133             # only remove the service if not upgrade
6134             _pp_remove_service $1
6135         fi
6136 .
6137 }
6138
6139
6140 pp_backend_rpm_init_svc_vars () {
6141
6142     reload_signal=
6143     start_runlevels=${pp_rpm_default_start_runlevels-"2 3 4 5"} # == lsb default-start
6144     stop_runlevels=${pp_rpm_default_stop_runlevels-"0 1 6"} # == lsb default-stop
6145     svc_description="${pp_rpm_default_svc_description}" # == lsb short descr
6146     svc_process=
6147
6148     lsb_required_start='$local_fs $network'
6149     lsb_should_start=
6150     lsb_required_stop=
6151     lsb_description=
6152
6153     start_priority=50
6154     stop_priority=50            #-- stop_priority = 100 - start_priority
6155 }
6156
6157 pp_rpm_service_group_make_init_script () {
6158     local grp=$1
6159     local svcs="$2"
6160     local script=/etc/init.d/$grp
6161     local out=$pp_destdir$script
6162
6163     pp_add_file_if_missing $script run 755 || return 0
6164
6165     cat <<-. >>$out
6166         #!/bin/sh
6167         svcs="$svcs"
6168 .
6169
6170     cat <<-'.' >>$out
6171
6172         #-- prints usage message
6173         pp_usage () {
6174             echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
6175             return 2
6176         }
6177
6178         #-- starts services in order.. stops them all if any break
6179         pp_start () {
6180             undo=
6181             for svc in $svcs; do
6182                 if /etc/init.d/$svc start; then
6183                     undo="$svc $undo"
6184                 else
6185                     if test -n "$undo"; then
6186                         for svc in $undo; do
6187                            /etc/init.d/$svc stop
6188                         done
6189                         return 1
6190                     fi
6191                 fi
6192             done
6193             return 0
6194         }
6195
6196         #-- stops services in reverse
6197         pp_stop () {
6198             reverse=
6199             for svc in $svcs; do
6200                 reverse="$svc $reverse"
6201             done
6202             rc=0
6203             for svc in $reverse; do
6204                 /etc/init.d/$svc stop || rc=$?
6205             done
6206             return $rc
6207         }
6208
6209         #-- returns true only if all services return true status
6210         pp_status () {
6211             rc=0
6212             for svc in $svcs; do
6213                 /etc/init.d/$svc status || rc=$?
6214             done
6215             return $rc
6216         }
6217
6218         pp_reload () {
6219             rc=0
6220             for svc in $svcs; do
6221                 /etc/init.d/$svc reload || rc=$?
6222             done
6223             return $rc
6224         }
6225
6226         case "$1" in
6227             start)          pp_start;;
6228             stop)           pp_stop;;
6229             restart)        pp_stop; pp_start;;
6230             status)         pp_status;;
6231             try-restart|condrestart)
6232                             if pp_status >/dev/null; then
6233                                     pp_restart
6234                             fi;;
6235             reload)         pp_reload;;
6236             force-reload)   if pp_status >/dev/null; then
6237                                     pp_reload
6238                             else
6239                                     pp_restart
6240                             fi;;
6241             *)              pp_usage;;
6242         esac
6243 .
6244     chmod 755 $out
6245 }
6246
6247 pp_rpm_service_make_init_script () {
6248     local svc=$1
6249     local script=/etc/init.d/$svc
6250     local out=$pp_destdir$script
6251     local _process _cmd _rpmlevels
6252
6253     pp_add_file_if_missing $script run 755 || return 0
6254
6255     #-- start out as an empty shell script
6256     cat <<-'.' >$out
6257         #!/bin/sh
6258 .
6259
6260     #-- determine the process name from $cmd unless $svc_process is given
6261     set -- $cmd
6262     _process=${svc_process:-"$1"}
6263
6264     #-- construct a start command that builds a pid file if needed
6265     _cmd="$cmd";
6266     if test -z "$pidfile"; then
6267         pidfile=/var/run/$svc.pid
6268         _cmd="$cmd & echo \$! > \$pidfile"
6269     fi
6270     if test "$user" != "root"; then
6271         _cmd="su $user -c exec $_cmd";
6272     fi
6273
6274     #-- generate the Red Hat chkconfig headers
6275     _rpmlevels=`echo $start_runlevels | tr -d ' '`
6276     cat <<-. >>$out
6277         # chkconfig: ${_rpmlevels:--} ${start_priority:-50} ${stop_priority:-50}
6278         # description: ${svc_description:-no description}
6279         # processname: ${_process}
6280         # pidfile: ${pidfile}
6281 .
6282
6283     #-- generate the LSB init info
6284     cat <<-. >>$out
6285         ### BEGIN INIT INFO
6286         # Provides: ${svc}
6287         # Required-Start: ${lsb_required_start}
6288         # Should-Start: ${lsb_should_start}
6289         # Required-Stop: ${lsb_required_stop}
6290         # Default-Start: ${start_runlevels}
6291         # Default-Stop: ${stop_runlevels}
6292         # Short-Description: ${svc_description}
6293         ### END INIT INFO
6294         # Generated by PolyPackage ${pp_version}
6295         # ${copyright}
6296
6297 .
6298
6299     if test x"${svc_description}" = x"${pp_rpm_default_svc_description}"; then
6300         svc_description=
6301     fi
6302
6303     #-- write service-specific definitions
6304     cat <<. >>$out
6305         #-- definitions specific to service ${svc}
6306         svc_name="${svc_description:-$svc service}"
6307         user="${user}"
6308         pidfile="${pidfile}"
6309         stop_signal="${stop_signal}"
6310         reload_signal="${reload_signal}"
6311         pp_exec_cmd () { $_cmd; }
6312 .
6313
6314     #-- write the generic part of the init script
6315     cat <<'.' >>$out
6316
6317         #-- use system message logging, if available
6318         if [ -f /lib/lsb/init-functions -a ! -r /etc/redhat-release ]; then
6319             . /lib/lsb/init-functions
6320             pp_success_msg () { log_success_msg "$@"; }
6321             pp_failure_msg () { log_failure_msg "$@"; }
6322             pp_warning_msg () { log_warning_msg "$@"; }
6323         elif [ -f /etc/init.d/functions ]; then
6324             . /etc/init.d/functions
6325             pp_success_msg () { echo -n "$*"; success "$@"; echo; }
6326             pp_failure_msg () { echo -n "$*"; failure "$@"; echo; }
6327             pp_warning_msg () { echo -n "$*"; warning "$@"; echo; }
6328         else
6329             pp_success_msg () { echo ${1:+"$*:"} OK; }
6330             pp_failure_msg () { echo ${1:+"$*:"} FAIL; }
6331             pp_warning_msg () { echo ${1:+"$*:"} WARNING; }
6332         fi
6333
6334         #-- prints a status message
6335         pp_msg () { echo -n "$*: "; }
6336
6337         #-- prints usage message
6338         pp_usage () {
6339             echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
6340             return 2
6341         }
6342
6343         #-- reloads the service, if possible
6344         #   returns 0=success 1=failure 3=unimplemented
6345         pp_reload () {
6346             test -n "$reload_signal" || return 3 # unimplemented
6347             pp_msg "Reloading ${svc_name}"
6348             if pp_signal -${reload_signal}; then
6349                 pp_success_msg
6350                 return 0
6351             else
6352                 pp_failure_msg "not running"
6353                 return 1
6354             fi
6355         }
6356
6357         #-- delivers signal $1 to the pidfile
6358         #   returns 0=success 1=failure
6359         pp_signal () {
6360             if test -r "$pidfile"; then
6361                 read pid < $pidfile
6362                 kill "$@" "$pid" 2>/dev/null
6363             else
6364                 return 1
6365             fi
6366         }
6367
6368         #-- prints information about the service status
6369         #   returns 0=running 1=crashed 3=stopped
6370         pp_status () {
6371             pp_msg "Checking for ${svc_name}"
6372             if pp_signal -0; then
6373                 pp_success_msg "running"
6374                 return 0
6375             elif test -r "$pidfile"; then
6376                 pp_failure_msg "not running (crashed)"
6377                 return 1
6378             else
6379                 pp_failure_msg "not running"
6380                 return 3
6381             fi
6382         }
6383
6384         #-- starts the service
6385         #   returns 0=success 1=failure
6386         pp_start () {
6387             pp_msg "Starting ${svc_name}"
6388             if pp_status >/dev/null; then
6389                 pp_warning_msg "already started"
6390                 return 0
6391             elif pp_exec_cmd; then
6392                 pp_success_msg
6393                 return 0
6394             else
6395                 pp_failure_msg "cannot start"
6396                 return 1
6397             fi
6398         }
6399
6400         #-- stops the service
6401         #   returns 0=success (always)
6402         pp_stop () {
6403             pp_msg "Stopping ${svc_name}"
6404             if pp_signal -${stop_signal}; then
6405                 pp_success_msg
6406             else
6407                 pp_success_msg "already stopped"
6408             fi
6409             rm -f "$pidfile"
6410             return 0
6411         }
6412
6413         #-- stops and starts the service
6414         pp_restart () {
6415             pp_stop
6416             pp_start
6417         }
6418
6419         case "$1" in
6420             start)          pp_start;;
6421             stop)           pp_stop;;
6422             restart)        pp_restart;;
6423             status)         pp_status;;
6424             try-restart|condrestart)
6425                             if pp_status >/dev/null; then
6426                                     pp_restart
6427                             fi;;
6428             reload)         pp_reload;;
6429             force-reload)   if pp_status >/dev/null; then
6430                                     pp_reload
6431                             else
6432                                     pp_restart
6433                             fi;;
6434             *)              pp_usage;;
6435         esac
6436
6437 .
6438     chmod 755 $out
6439 }
6440 pp_backend_rpm_function () {
6441     case "$1" in
6442         pp_mkgroup) cat<<'.';;
6443             /usr/sbin/groupadd -f -r "$1"
6444 .
6445         pp_mkuser:depends) echo pp_mkgroup;;
6446         pp_mkuser) cat<<'.';;
6447             pp_mkgroup "${2:-$1}" || return 1
6448             /usr/sbin/useradd \
6449                 -g "${2:-$1}" \
6450                 -M -d "${3:-/nonexistent}" \
6451                 -s "${4:-/bin/false}" \
6452                 -r "$1"
6453 .
6454         pp_havelib) cat<<'.';;
6455             for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
6456                 test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
6457             done
6458             return 1
6459 .
6460         *) false;;
6461     esac
6462 }
6463
6464 : NOTES <<.
6465
6466  # creating a dmg file for publishing on the web
6467     hdiutil create -srcfolder /path/foo foo.dmg
6468     hdiutil internet-enable -yes /path/foo.dmg
6469  # Layout for packages
6470     <name>-<cpy>/component/<file>
6471     <name>-<cpt>/extras/postinstall
6472     <name>-<cpt>/extras/postupgrade
6473  # /Developer/usr/bin/packagemaker (man packagemaker)
6474
6475     Make a bunch of packages, and then build a 'distribution'
6476     which is only understood by macos>10.4
6477
6478  # Message files in the resource path used are
6479     Welcome.{rtf,html,rtfd,txt} - limited text shown in Intro
6480     ReadMe.{rtf,html,rtfd,txt} - scrollable/printable, after Intro
6481     License.{rtf,html,rtfd,txt} - ditto, user must click 'Accept'
6482     background.{jpg,tif,gif,pict,eps,pdf} 620x418 background image
6483
6484  # These scripts looked for in the resource path
6485     InstallationCheck $pkgpath $defaultloc $targetvol
6486         0:ok 32:warn 32+x:warn[1] 64:stop 96+x:stop[2]
6487     VolumeCheck $volpath
6488         0:ok 32:failure 32+x:failure[3]
6489     preflight   $pkgpath $targetloc $targetvol    [priv]
6490     preinstall  $pkgpath $targetloc $targetvol    [priv]
6491     preupgrade  $pkgpath $targetloc $targetvol    [priv]
6492     postinstall $pkgpath $targetloc $targetvol    [priv]
6493     postupgrade $pkgpath $targetloc $targetvol    [priv]
6494     postflight  $pkgpath $targetloc $targetvol    [priv]
6495         0:ok else fail (for all scripts)
6496
6497     A detailed reason is deduced by finding an index x (16..31)
6498     in the file InstallationCheck.strings or VolumeCheck.strings.
6499
6500     Scripts marked [priv] are executed with root privileges.
6501     None of the [priv] scripts are used by metapackages.
6502
6503  # Default permissions
6504     Permissions of existing directories should match those
6505     of a clean install of the OS; typically root:admin 0775
6506     New directories or files should be 0775 or 0664 with the
6507     appropriate user:group.
6508     Exceptions:
6509         /etc    root:admin 0755
6510         /var    root:admin 0755
6511
6512     <http://developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution4/Concepts/sd_pkg_flags.html>
6513     Info.plist = {
6514      CFBundleGetInfoString: "1.2.3, Quest Software, Inc.",
6515      CFBundleIdentifier: "com.quest.rc.openssh",
6516      CFBundleShortVersionString: "1.2.3",
6517      IFMajorVersion: 1,
6518      IFMinorVersion: 2,
6519      IFPkgFlagAllowBackRev: false,
6520      IFPkgFlagAuthorizationAction: "AdminAuthorization",
6521      IFPkgFlagDefaultLocation: "/",
6522      IFPkgFlagFollowLinks: true,
6523      IFPkgFlagInstallFat: false,
6524      IFPkgFlagInstalledSize: <integer>,     # this is added by packagemaker
6525      IFPkgFlagIsRequired: false,
6526      IFPkgFlagOverwritePermissions: false,
6527      IFPkgFlagRelocatable: false,
6528      IFPkgFlagRestartAction: "NoRestart",
6529      IFPkgFlagRootVolumeOnly: false,
6530      IFPkgFlagUpdateInstalledLanguages: false,
6531      IFPkgFormatVersion= 0.10000000149011612,
6532      IFRequirementDicts: [ {
6533        Level = "requires",
6534        SpecArgument = "/opt/quest/lib/libvas.4.2.0.dylib",
6535        SpecType = "file",
6536        TestObject = true,
6537        TestOperator = "eq", } ]
6538     }
6539
6540     Description.plist = {
6541      IFPkgDescriptionDescription = "this is the description text",
6542      IFPkgDescriptionTitle = "quest-openssh"
6543     }
6544
6545  # Startup scripts
6546     'launchd' is a kind of combined inetd and rc/init.d system.
6547     <http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/DesigningDaemons.html>
6548     Create a /Library/LaunchDaemons/$daemonname.plist file
6549     Examples found in /System/Library/LaunchDaemons/
6550     See manual page launchd.plist(5) for details:
6551
6552     { Label: "com.quest.rc.foo",                        # required
6553       Program: "/sbin/program",
6554       ProgramArguments: [ "/sbin/program", "arg1", "arg2" ], # required
6555       RunAtLoad: true,
6556       WatchPaths: [ "/etc/crontab" ],
6557       QueueDirectories: [ "/var/cron/tabs" ],
6558       inetdCompatibility: { Wait: false },                   # inetd-only
6559       OnDemand: false,                                       # recommended
6560       SessionCreate: true,
6561       UserName: "nobody",
6562       InitGroups: true,
6563       Sockets: {                                             # inetd only
6564         Listeners: {
6565            SockServiceName: "ssh",
6566            Bonjour: ["ssh", "sftp-ssh"], } },
6567       Disabled: false,
6568       StandardErrorPath: "/dev/null",
6569     }
6570
6571
6572     How to add a new user
6573         dscl . -create /Users/$user
6574         dscl . -create /Users/$user UserShell /bin/bash
6575         dscl . -create /Users/$user RealName "$user"
6576         dscl . -create /Users/$user UniqueID $uid
6577         dscl . -create /Users/$user PrimaryGroupID $gid
6578         dscl . -create /Users/$user NFSHomeDirectory /Users/$user
6579         dscl . -passwd /Users/$user "$passwd"
6580         mkdir /Users/$user
6581         chown $uid.$gid /Users/$user
6582
6583 .
6584
6585
6586 pp_platforms="$pp_platforms macos"
6587
6588 pp_backend_macos_detect () {
6589     [ x"$1" = x"Darwin" ]
6590 }
6591
6592 pp_backend_macos_init () {
6593     pp_macos_default_bundle_id_prefix="com.quest.rc."
6594     pp_macos_bundle_id=
6595     pp_macos_bundle_vendor=
6596     pp_macos_bundle_version=
6597     pp_macos_bundle_info_string=
6598     pp_macos_pkg_type=bundle
6599     pp_macos_pkg_license=
6600     pp_macos_pkg_readme=
6601     pp_macos_pkg_welcome=
6602     pp_macos_sudo=sudo
6603     pp_macos_installer_plugin=
6604     # OS X puts the library version *before* the .dylib extension
6605     pp_shlib_suffix='*.dylib'
6606 }
6607
6608 pp_macos_plist () {
6609     typeset in
6610     in=""
6611     while test $# -gt 0; do
6612      case "$1" in
6613
6614       start-plist) cat <<-.; in="  "; shift ;;
6615         <?xml version="1.0" encoding="UTF-8"?>
6616         <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
6617         <plist version="1.0">
6618 .
6619       end-plist) echo "</plist>"; in=; shift;;
6620
6621       '[')   echo "$in<array>"; in="$in  "; shift;;
6622       ']')   echo "$in</array>"; in="${in#  }"; shift;;
6623       '{')   echo "<dict>"; in="$in      "; shift;;
6624       '}')   echo "</dict>"; in="${in#      }"; shift;;
6625       key)         shift; echo "$in<key>$1</key>"; shift;;
6626       string)      shift;
6627                    echo "$1" | sed -e 's/&/&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;' \
6628                                    -e 's/^/'"$in"'<string>/;s/$/<\/string>/';
6629                    shift;;
6630       true)        echo "$in<true/>"; shift;;
6631       false)       echo "$in<false/>"; shift;;
6632       real)        shift; echo "$in<real>$1</real>"; shift;;
6633       integer)     shift; echo "$in<integer>$1</integer>"; shift;;
6634       date)        shift; echo "$in<date>$1</date>"; shift;; # ISO 8601 format
6635       data)        shift; echo "$in<data>$1</data>"; shift;; # base64 encoded
6636       *)           pp_error "pp_macos_plist: bad argument '$1'"; shift;;
6637      esac
6638     done
6639 }
6640
6641 pp_macos_rewrite_cpio () {
6642     typeset script
6643     script=$pp_wrkdir/cpio-rewrite.pl
6644     cat <<-'.' >$script
6645         #!/usr/bin/perl
6646         #
6647         # Filter a cpio file, applying the user/group/mode specified in %files
6648         #
6649         # A CPIO header block has octal fields at the following offset/lengths:
6650         #   0  6 magic
6651         #   6  6 dev
6652         #  12  6 ino
6653         #  18  6 mode
6654         #  24  6 uid
6655         #  30  6 gid
6656         #  36  6 nlink
6657         #  42  6 rdev
6658         #  48 11 mtime
6659         #  59  6 namesize (including NUL terminator)
6660         #  65 11 filesize
6661         #  76    --
6662         #
6663         use strict;
6664         use warnings;
6665         no strict 'subs';
6666
6667         # set %uid, %gid, %mode based on %files
6668         my (%uid, %gid, %mode, %users, %groups);
6669         my %type_map = ( d => 0040000, f => 0100000, s => 0120000 );
6670         while (<DATA>) {
6671             my ($type,$mode,$uid,$gid,$flags,$name) =
6672                 m/^(.) (\S+) (\S+) (\S+) (\S+) (\S+)/;
6673             $mode = $type eq "f" ? "0644" : "0755" if $mode eq "-";
6674             $uid = 0 if $uid eq "-";
6675             $gid = 0 if $gid eq "-";
6676             if ($uid ne "=" and $uid =~ m/\D/) {
6677                 unless (exists $users{$uid}) {
6678                     my @pw = getpwnam($uid) or die "bad username '$uid'";
6679                     $users{$uid} = $pw[2];
6680                 }
6681                 $uid = $users{$uid};
6682             }
6683             if ($gid ne "=" and $gid =~ m/\D/) {
6684                 unless (exists $groups{$gid}) {
6685                     my @gr = getgrnam($gid) or die "bad group'$gid'";
6686                     $groups{$gid} = $gr[2];
6687                 }
6688                 $gid = $groups{$gid};
6689             }
6690             $name =~ s:/$:: if $type eq "d";
6691             $name = ".".$name."\0";
6692             $uid{$name} = sprintf("%06o",int($uid)) unless $uid eq "=";
6693             $gid{$name} = sprintf("%06o",int($gid)) unless $gid eq "=";
6694             $mode{$name} = sprintf("%06o",oct($mode)|$type_map{$type}) unless $mode eq "=";
6695         }
6696         undef %users;
6697         undef %groups;
6698         # parse the cpio file
6699         my $hdrlen = 76;
6700         while (read(STDIN, my $header, $hdrlen)) {
6701             my ($name, $namesize, $filesize);
6702             my $filepad = 0;
6703             if ($header =~ m/^07070[12]/) {
6704                 # SVR4 ASCII format, convert to ODC
6705                 if ($hdrlen == 76) {
6706                     # Read in rest of header and update header len for SVR4
6707                     read(STDIN, $header, 110 - 76, 76);
6708                     $hdrlen = 110;
6709                 }
6710                 my $ino = hex(substr($header, 6, 8)) & 0x3ffff;
6711                 my $mode = hex(substr($header, 14, 8)) & 0x3ffff;
6712                 my $uid = hex(substr($header, 22, 8)) & 0x3ffff;
6713                 my $gid = hex(substr($header, 30, 8)) & 0x3ffff;
6714                 my $nlink = hex(substr($header, 38, 8)) & 0x3ffff;
6715                 my $mtime = hex(substr($header, 46, 8)) & 0xffffffff;
6716                 $filesize = hex(substr($header, 54, 8)) & 0xffffffff;
6717                 my $dev_maj = hex(substr($header, 62, 8));
6718                 my $dev_min = hex(substr($header, 70, 8));
6719                 my $dev = &makedev($dev_maj, $dev_min) & 0x3ffff;
6720                 my $rdev_maj = hex(substr($header, 78, 8));
6721                 my $rdev_min = hex(substr($header, 86, 8));
6722                 my $rdev = &makedev($rdev_maj, $rdev_min) & 0x3ffff;
6723                 $namesize = hex(substr($header, 94, 8)) & 0x3ffff;
6724                 read(STDIN, $name, $namesize);
6725                 # Header + name is padded to a multiple of 4 bytes
6726                 my $namepad = (($hdrlen + $namesize + 3) & 0xfffffffc) - ($hdrlen + $namesize);
6727                 read(STDIN, my $padding, $namepad) if ($namepad);
6728                 # File data is padded to be a multiple of 4 bytes
6729                 $filepad = (($filesize + 3) & 0xfffffffc) - $filesize;
6730
6731                 my $new_header = sprintf("070707%06o%06o%06o%06o%06o%06o%06o%011o%06o%011o", $dev, $ino, $mode, $uid, $gid, $nlink, $rdev, $mtime, $namesize, $filesize);
6732                 $header = $new_header;
6733             } elsif ($header =~ m/^070707/) {
6734                 # POSIX Portable ASCII Format
6735                 $namesize = oct(substr($header, 59, 6));
6736                 $filesize = oct(substr($header, 65, 11));
6737                 read(STDIN, $name, $namesize);
6738             } else {
6739                 die "bad magic";
6740             }
6741             # update uid, gid and mode (already in octal)
6742             substr($header, 24, 6) = $uid{$name} if exists $uid{$name};
6743             substr($header, 30, 6) = $gid{$name} if exists $gid{$name};
6744             substr($header, 18, 6) = $mode{$name} if exists $mode{$name};
6745             print($header, $name);
6746             # check for trailer at EOF
6747             last if $filesize == 0 && $name =~ /^TRAILER!!!\0/;
6748             # copy-through the file data
6749             while ($filesize > 0) {
6750                 my $seg = 8192;
6751                 $seg = $filesize if $filesize < $seg;
6752                 read(STDIN, my $data, $seg);
6753                 print $data;
6754                 $filesize -= $seg;
6755             }
6756             # If file data is padded, skip it
6757             read(STDIN, my $padding, $filepad) if ($filepad);
6758         }
6759         # pass through any padding at the end (blocksize-dependent)
6760         for (;;) {
6761             my $numread = read(STDIN, my $data, 8192);
6762             last unless $numread;
6763             print $data;
6764         }
6765         exit(0);
6766
6767         sub makedev {
6768             (((($_[0] & 0xff)) << 24) | ($_[1] & 0xffffff));
6769         }
6770         __DATA__
6771 .
6772     # Append to the script the %files data
6773     cat "$@" </dev/null >> $script
6774     /usr/bin/perl $script || pp_error "pp_macos_rewrite_cpio error";
6775 }
6776
6777 pp_macos_files_bom () {
6778     typeset _l t m o g f p st owner
6779     while read t m o g f p st; do
6780         # make sure that $m is padded up to 4 digits long
6781         case "$m" in
6782             ?) m="000$m";;
6783             ??) m="00$m";;
6784             ???) m="0$m";;
6785             ?????*) pp_error "pp_macos_writebom: mode '$m' too long";;
6786         esac
6787
6788         # convert owner,group into owner/group in octal
6789         case $o in -)   o=0;; esac
6790         case $g in -)   g=0;; esac
6791         owner=`pp_d2o $o`/`pp_d2o $g`
6792
6793         case $t in
6794             f)
6795                 test x"$m" = x"000-" && m=0644
6796                 echo ".$p       10$m    $owner  `
6797                     /usr/bin/cksum < "${pp_destdir}$p" |
6798                     awk '{print $2 "    " $1}'`"
6799                 ;;
6800             d)
6801                 test x"$m" = x"000-" && m=0755
6802                 echo ".${p%/}   4$m     $owner"
6803                 ;;
6804             s)
6805                 test x"$m" = x"000-" && m=0755
6806                 rl=`/usr/bin/readlink "${pp_destdir}$p"`
6807                 #test x"$rl" = x"$st" ||
6808                 #    pp_error "symlink mismatch $rl != $st"
6809                 echo ".$p       12$m    $owner  `
6810                     /usr/bin/readlink -n "${pp_destdir}$p" |
6811                     /usr/bin/cksum |
6812                     awk '{print $2 "    " $1}'` $st"
6813                 ;;
6814         esac
6815     done
6816 }
6817
6818 pp_macos_bom_fix_parents () {
6819     perl -pe '
6820         sub dirname { my $d=shift; $d=~s,/[^/]*$,,; $d; }
6821         sub chk { my $d=shift;
6822                   &chk(&dirname($d)) if $d =~ m,/,;
6823                   unless ($seen{$d}++) {
6824                     # Make sure we do not override system directories
6825                     if ($d =~ m:^\./(etc|var)$:) {
6826                       my $tgt = "private/$1";
6827                       my ($sum, $len) = split(/\s+/, `/usr/bin/printf "$tgt" | /usr/bin/cksum /dev/stdin`);
6828                       print "$d\t120755\t0/0\t$len\t$sum\t$tgt\n";
6829                     } elsif ($d eq "." || $d eq "./Library") {
6830                       print "$d\t41775\t0/80\n";
6831                     } elsif ($d eq "./Applications" || $d eq "./Developer") {
6832                       print "$d\t40775\t0/80\n";
6833                     } else {
6834                       print "$d\t40755\t0/0\n";
6835                     }
6836                   }
6837                 }
6838         m/^(\S+)\s+(\d+)/;
6839         if (oct($2) & 040000) {
6840             $seen{$1}++; # directory
6841         }
6842         &chk(&dirname($1));'
6843 }
6844
6845 pp_macos_files_size () {
6846     typeset _l t m o g f p st owner
6847     while read t m o g f p st; do
6848         case $t in
6849             f)  wc -c < "${pp_destdir}$p";;
6850             s)  echo 4095;;
6851             d)  ;; # always seems to be zero
6852         esac
6853     done | awk '{n+=1+int($1/4096)} END {print n*4}'
6854 }
6855
6856 pp_o2d () {
6857     awk 'BEGIN { x=0; '`echo "$1" |
6858         sed -e 's/./x=x*8+&;/g'`'print x;}' </dev/null
6859 }
6860 pp_d2o () {
6861     case "$1" in
6862         [0-7]) echo $1;;
6863         *) awk 'BEGIN { printf("%o\n", 0+('"$1"'));}' < /dev/null;;
6864     esac
6865 }
6866
6867 pp_macos_mkbom () {
6868     #/usr/bin/mkbom -i $1 $2
6869     typeset path mode ugid size cksum linkpath
6870     typeset bomstage
6871
6872     # Use mkbom if it understands -i (avoids a copy)
6873     if /usr/bin/mkbom -i /dev/null "$2" 2>/dev/null; then
6874         rm -f "$2"
6875         /usr/bin/mkbom -i "$1" "$2"
6876         return
6877     fi
6878
6879     # On 10.4 we have this nonsense.
6880     pp_warn "mkbom workaround: copying source files to staging area"
6881
6882     bomstage=$pp_wrkdir/bom_stage
6883     $pp_macos_sudo /bin/mkdir "$bomstage"
6884     while IFS=' ' read path mode ugid size cksumi linkpath; do
6885         if test -h "$pp_destdir/$path"; then
6886             $pp_macos_sudo /bin/ln -s "$linkpath" "$bomstage/$path"
6887         else
6888             if test -d "$pp_destdir/$path"; then
6889                 $pp_macos_sudo /bin/mkdir -p "$bomstage/$path"
6890             else
6891                 $pp_macos_sudo /bin/cp "$pp_destdir/$path" "$bomstage/$path"
6892             fi
6893             $pp_macos_sudo /bin/chmod $mode "$bomstage/$path"
6894             $pp_macos_sudo /usr/sbin/chown `echo $ugid| tr / :` "$bomstage/$path"
6895         fi
6896     done <"$1"
6897     (cd $bomstage && $pp_macos_sudo mkbom . $pp_wrkdir/bom_stage.bom) ||
6898         pp_error "mkbom failed"
6899     $pp_macos_sudo mv $pp_wrkdir/bom_stage.bom "$2"
6900 }
6901
6902 pp_backend_macos () {
6903     : ${pp_macos_bundle_id:=$pp_macos_default_bundle_id_prefix$name}
6904     case "$pp_macos_pkg_type" in
6905         bundle) pp_backend_macos_bundle;;
6906         flat) pp_backend_macos_flat;;
6907         *) pp_error "unsupported package type $pp_macos_pkg_type";;
6908     esac
6909 }
6910
6911 pp_backend_macos_bundle () {
6912     typeset pkgdir Contents Resources lprojdir svc
6913     typeset Info_plist Description_plist
6914     typeset bundle_vendor bundle_version size cmp filelists
6915
6916     mac_version=`sw_vers -productVersion`
6917     bundle_vendor=${pp_macos_bundle_vendor:-$vendor}
6918
6919     if test -z "$pp_macos_bundle_version"; then
6920         bundle_version=`echo "$version.0.0.0" | sed -n -e 's/[^0-9.]//g' \
6921             -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'`
6922     else
6923         bundle_version="$pp_macos_bundle_version"
6924     fi
6925     source_version=`echo $version | sed 's/.*\.//'`
6926
6927     # build the package layout
6928     pkgdir=$pp_wrkdir/$name.pkg
6929     Contents=$pkgdir/Contents
6930     Resources=$Contents/Resources
6931     lprojdir=$Resources/en.lproj
6932     mkdir $pkgdir $Contents $Resources $lprojdir ||
6933         pp_error "Can't make package temporary directories"
6934
6935     echo "major: 1" > $Resources/package_version
6936     echo "minor: 0" >> $Resources/package_version
6937     echo "pmkrpkg1" > $Contents/PkgInfo
6938     case $mac_version in
6939         "10.6"*)
6940             xattr -w "com.apple.TextEncoding" "macintosh;0" "$Resources/package_version"
6941             xattr -w "com.apple.TextEncoding" "macintosh;0" "$Contents/PkgInfo"
6942             ;;
6943     esac
6944
6945     # Copy welcome file/dir for display at package install time.
6946     if test -n "$pp_macos_pkg_welcome"; then
6947         typeset sfx
6948         sfx=`echo "$pp_macos_pkg_welcome"|sed 's/^.*\.\([^\.]*\)$/\1/'`
6949         case "$sfx" in
6950             rtf|html|rtfd|txt) ;;
6951             *) sfx=txt;;
6952         esac
6953         cp -R ${pp_macos_pkg_welcome} $Resources/Welcome.$sfx
6954     fi
6955
6956     # Copy readme file/dir for display at package install time.
6957     if test -n "$pp_macos_pkg_readme"; then
6958         typeset sfx
6959         sfx=`echo "$pp_macos_pkg_readme"|sed 's/^.*\.\([^\.]*\)$/\1/'`
6960         case "$sfx" in
6961             rtf|html|rtfd|txt) ;;
6962             *) sfx=txt;;
6963         esac
6964         cp -R ${pp_macos_pkg_readme} $Resources/ReadMe.$sfx
6965     fi
6966
6967     # Copy license file/dir for display at package install time.
6968     if test -n "$pp_macos_pkg_license"; then
6969         typeset sfx
6970         sfx=`echo "$pp_macos_pkg_license"|sed 's/^.*\.\([^\.]*\)$/\1/'`
6971         case "$sfx" in
6972             rtf|html|rtfd|txt) ;;
6973             *) sfx=txt;;
6974         esac
6975         cp -R ${pp_macos_pkg_license} $Resources/License.$sfx
6976     fi
6977
6978     # Add services (may modify %files)
6979     for svc in $pp_services .; do
6980         test . = "$svc" && continue
6981         pp_macos_add_service $svc
6982     done
6983
6984     # Find file lists (%files.* includes ignore files)
6985     for cmp in $pp_components; do
6986         test -f $pp_wrkdir/%files.$cmp && filelists="$filelists${filelists:+ }$pp_wrkdir/%files.$cmp"
6987     done
6988
6989     # compute the installed size
6990     size=`cat $filelists | pp_macos_files_size`
6991
6992     #-- Create Info.plist
6993     Info_plist=$Contents/Info.plist
6994     pp_macos_plist \
6995         start-plist \{ \
6996         key CFBundleGetInfoString string \
6997             "${pp_macos_bundle_info_string:-$version $bundle_vendor}" \
6998         key CFBundleIdentifier string \
6999             "${pp_macos_bundle_id}" \
7000     key CFBundleName string "$name" \
7001         key CFBundleShortVersionString string "$bundle_version" \
7002         key IFMajorVersion integer 1 \
7003         key IFMinorVersion integer 0 \
7004         key IFPkgFlagAllowBackRev false \
7005         key IFPkgFlagAuthorizationAction string "RootAuthorization" \
7006         key IFPkgFlagDefaultLocation string "/" \
7007         key IFPkgFlagFollowLinks true \
7008         key IFPkgFlagInstallFat true \
7009         key IFPkgFlagInstalledSize integer $size \
7010         key IFPkgFlagIsRequired false \
7011         key IFPkgFlagOverwritePermissions true \
7012         key IFPkgFlagRelocatable false \
7013         key IFPkgFlagRestartAction string "NoRestart" \
7014         key IFPkgFlagRootVolumeOnly true \
7015         key IFPkgFlagUpdateInstalledLanguages false \
7016         key IFPkgFlagUseUserMask false \
7017         key IFPkgFormatVersion real 0.10000000149011612 \
7018         key SourceVersion string $source_version \
7019         \} end-plist> $Info_plist
7020
7021     # write en.lproj/Description.plist
7022     Description_plist=$lprojdir/Description.plist
7023     pp_macos_plist \
7024         start-plist \{ \
7025         key IFPkgDescriptionDeleteWarning string "" \
7026             key IFPkgDescriptionDescription string "$pp_macos_bundle_info_string" \
7027             key IFPkgDescriptionTitle       string "$name" \
7028             key IFPkgDescriptionVersion string "$version" \
7029         \} end-plist > $Description_plist
7030
7031     # write Resources/files
7032     awk '{print $6}' $filelists > $Resources/files
7033
7034     # write package size file
7035     printf \
7036 "NumFiles 0
7037 InstalledSize $size
7038 CompressedSize 0
7039 " > $Resources/$name.sizes
7040
7041     # write Resources/preinstall
7042     for cmp in $pp_components; do
7043         if test -s $pp_wrkdir/%pre.$cmp; then
7044             if test ! -s $Resources/preinstall; then
7045                 echo "#!/bin/sh" > $Resources/preinstall
7046                 chmod +x $Resources/preinstall
7047             fi
7048             cat $pp_wrkdir/%pre.$cmp >> $Resources/preinstall
7049             echo : >> $Resources/preinstall
7050         fi
7051     done
7052
7053     # write Resources/postinstall
7054     for cmp in $pp_components; do
7055         if test -s $pp_wrkdir/%post.$cmp; then
7056             if test ! -s $Resources/postinstall; then
7057                 echo "#!/bin/sh" > $Resources/postinstall
7058                 chmod +x $Resources/postinstall
7059             fi
7060             cat $pp_wrkdir/%post.$cmp >> $Resources/postinstall
7061             echo : >> $Resources/postinstall
7062         fi
7063     done
7064
7065     # write Resources/postupgrade
7066     for cmp in $pp_components; do
7067         if test -s $pp_wrkdir/%postup.$cmp; then
7068             if test ! -s $Resources/postupgrade; then
7069                 echo "#!/bin/sh" > $Resources/postupgrade
7070                 chmod +x $Resources/postupgrade
7071             fi
7072             cat $pp_wrkdir/%postup.$cmp >> $Resources/postupgrade
7073             echo : >> $Resources/postupgrade
7074         fi
7075     done
7076
7077     # write Resources/preremove
7078     for cmp in $pp_components; do
7079         if test -s $pp_wrkdir/%preun.$cmp; then
7080             if test ! -s $Resources/preremove; then
7081                 echo "#!/bin/sh" > $Resources/preremove
7082                 chmod +x $Resources/preremove
7083             fi
7084             cat $pp_wrkdir/%preun.$cmp >> $Resources/preremove
7085             echo : >> $Resources/preremove
7086         fi
7087     done
7088
7089     # write Resources/postremove
7090     for cmp in $pp_components; do
7091         if test -s $pp_wrkdir/%postun.$cmp; then
7092             if test ! -s $Resources/postremove; then
7093                 echo "#!/bin/sh" > $Resources/postremove
7094                 chmod +x $Resources/postremove
7095             fi
7096             cat $pp_wrkdir/%postun.$cmp >> $Resources/postremove
7097             echo : >> $Resources/postremove
7098         fi
7099     done
7100
7101     # write uninstall info
7102     echo "version=$version" > $Resources/uninstall
7103     if [ -n "$pp_macos_requires" ];then
7104         echo "requires=$pp_macos_requires" >> $Resources/uninstall
7105     fi
7106
7107     . $pp_wrkdir/%fixup
7108
7109     # Create the bill-of-materials (Archive.bom)
7110     cat $filelists | pp_macos_files_bom | sort |
7111         pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls
7112
7113     pp_macos_mkbom $pp_wrkdir/tmp.bomls $Contents/Archive.bom
7114
7115     # Create the cpio archive (Archive.pax.gz)
7116     (
7117     cd $pp_destdir &&
7118     awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $Contents/Archive.pax.gz
7119     )
7120
7121     # Copy installer plugins if any
7122     if test -n "$pp_macos_installer_plugin"; then
7123         if test ! -f "$pp_macos_installer_plugin/InstallerSections.plist"; then
7124             pp_error "Missing InstallerSections.plist file in $pp_macos_installer_plugin"
7125         fi
7126         mkdir -p $pkgdir/Plugins
7127         cp -R "$pp_macos_installer_plugin"/* $pkgdir/Plugins
7128     fi
7129
7130     test -d $pp_wrkdir/bom_stage && $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage
7131
7132     rm -f ${name}-${version}.dmg
7133     hdiutil create -fs HFS+ -srcfolder $pkgdir -volname $name ${name}-${version}.dmg
7134 }
7135
7136 pp_backend_macos_flat () {
7137     typeset pkgdir bundledir Resources lprojdir svc
7138     typeset Info_plist Description_plist
7139     typeset bundle_vendor bundle_version size numfiles cmp filelists
7140
7141     mac_version=`sw_vers -productVersion`
7142     bundle_vendor=${pp_macos_bundle_vendor:-$vendor}
7143
7144     if test -z "$pp_macos_bundle_version"; then
7145         bundle_version=`echo "$version.0.0.0" | sed -n -e 's/[^0-9.]//g' \
7146             -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'`
7147     else
7148         bundle_version="$pp_macos_bundle_version"
7149     fi
7150     source_version=`echo $version | sed 's/.*\.//'`
7151
7152     # build the flat package layout
7153     pkgdir=$pp_wrkdir/pkg
7154     bundledir=$pp_wrkdir/pkg/$name.pkg
7155     Resources=$pkgdir/Resources
7156     lprojdir=$Resources/en.lproj
7157     mkdir $pkgdir $bundledir $Resources $lprojdir ||
7158         pp_error "Can't make package temporary directories"
7159
7160     # Add services (may modify %files)
7161     for svc in $pp_services .; do
7162         test . = "$svc" && continue
7163         pp_macos_add_service $svc
7164     done
7165
7166     # Find file lists (%files.* includes ignore files)
7167     for cmp in $pp_components; do
7168         test -f $pp_wrkdir/%files.$cmp && filelists="$filelists${filelists:+ }$pp_wrkdir/%files.$cmp"
7169     done
7170
7171     # compute the installed size and number of files/dirs
7172     size=`cat $filelists | pp_macos_files_size`
7173     numfiles=`cat $filelists | wc -l`
7174     numfiles="${numfiles##* }"
7175
7176     # Write Distribution file
7177     cat <<-. >$pkgdir/Distribution
7178         <?xml version="1.0" encoding="UTF-8"?>
7179         <installer-script minSpecVersion="1.000000" authoringTool="com.quest.rc.PolyPkg" authoringToolVersion="$pp_version" authoringToolBuild="$pp_revision">
7180             <title>$name $version</title>
7181             <options customize="never" allow-external-scripts="no"/>
7182             <domains enable_localSystem="true"/>
7183 .
7184     if test -n "$pp_macos_pkg_welcome"; then
7185         cp -R "${pp_macos_pkg_welcome}" $Resources
7186         echo "    <welcome file=\"${pp_macos_pkg_welcome##*/}\"/>" >>$pkgdir/Distribution
7187     fi
7188     if test -n "$pp_macos_pkg_readme"; then
7189         cp -R "${pp_macos_pkg_readme}" $Resources
7190         echo "    <readme file=\"${pp_macos_pkg_readme##*/}\"/>" >>$pkgdir/Distribution
7191     fi
7192     if test -n "$pp_macos_pkg_license"; then
7193         cp -R "${pp_macos_pkg_license}" $Resources
7194         echo "    <license file=\"${pp_macos_pkg_license##*/}\"/>" >>$pkgdir/Distribution
7195     fi
7196     cat <<-. >>$pkgdir/Distribution
7197             <choices-outline>
7198                 <line choice="choice0"/>
7199             </choices-outline>
7200             <choice id="choice0" title="$name $version">
7201                 <pkg-ref id="${pp_macos_bundle_id}"/>
7202             </choice>
7203             <pkg-ref id="${pp_macos_bundle_id}" installKBytes="$size" version="$version" auth="Root">#$name.pkg</pkg-ref>
7204         </installer-script>
7205 .
7206
7207     # write scripts archive
7208     # XXX - missing preupgrade, preflight, postflight
7209     mkdir $pp_wrkdir/scripts
7210     for cmp in $pp_components; do
7211         if test -s $pp_wrkdir/%pre.$cmp; then
7212             if test ! -s $pp_wrkdir/scripts/preinstall; then
7213                 echo "#!/bin/sh" > $pp_wrkdir/scripts/preinstall
7214                 chmod +x $pp_wrkdir/scripts/preinstall
7215             fi
7216             cat $pp_wrkdir/%pre.$cmp >> $pp_wrkdir/scripts/preinstall
7217             echo : >> $pp_wrkdir/scripts/preinstall
7218         fi
7219         if test -s $pp_wrkdir/%post.$cmp; then
7220             if test ! -s $pp_wrkdir/scripts/postinstall; then
7221                 echo "#!/bin/sh" > $pp_wrkdir/scripts/postinstall
7222                 chmod +x $pp_wrkdir/scripts/postinstall
7223             fi
7224             cat $pp_wrkdir/%post.$cmp >> $pp_wrkdir/scripts/postinstall
7225             echo : >> $pp_wrkdir/scripts/postinstall
7226         fi
7227         if test -s $pp_wrkdir/%postup.$cmp; then
7228             if test ! -s $pp_wrkdir/scripts/postupgrade; then
7229                 echo "#!/bin/sh" > $pp_wrkdir/scripts/postupgrade
7230                 chmod +x $pp_wrkdir/scripts/postupgrade
7231             fi
7232             cat $pp_wrkdir/%postup.$cmp >> $pp_wrkdir/scripts/postupgrade
7233             echo : >> $pp_wrkdir/scripts/postupgrade
7234         fi
7235         # XXX - not supported
7236         if test -s $pp_wrkdir/%preun.$cmp; then
7237             if test ! -s $pp_wrkdir/scripts/preremove; then
7238                 echo "#!/bin/sh" > $pp_wrkdir/scripts/preremove
7239                 chmod +x $pp_wrkdir/scripts/preremove
7240             fi
7241             cat $pp_wrkdir/%preun.$cmp >> $pp_wrkdir/scripts/preremove
7242             echo : >> $pp_wrkdir/scripts/preremove
7243         fi
7244         # XXX - not supported
7245         if test -s $pp_wrkdir/%postun.$cmp; then
7246             if test ! -s $pp_wrkdir/scripts/postremove; then
7247                 echo "#!/bin/sh" > $pp_wrkdir/scripts/postremove
7248                 chmod +x $pp_wrkdir/scripts/postremove
7249             fi
7250             cat $pp_wrkdir/%postun.$cmp >> $pp_wrkdir/scripts/postremove
7251             echo : >> $pp_wrkdir/scripts/postremove
7252         fi
7253     done
7254     if test "`echo $pp_wrkdir/scripts/*`" != "$pp_wrkdir/scripts/*"; then
7255         # write scripts archive, scripts are mode 0755 uid/gid 0/0
7256         # resetting the owner and mode is not strictly required
7257         (
7258         cd $pp_wrkdir/scripts || pp_error "Can't cd to $pp_wrkdir/scripts"
7259         rm -f $pp_wrkdir/tmp.files.scripts
7260         for s in *; do
7261             echo "f 0755 0 0 - ./$s" >>$pp_wrkdir/tmp.files.scripts
7262         done
7263         find . -type f | /usr/bin/cpio -o | pp_macos_rewrite_cpio $pp_wrkdir/tmp.files.scripts | gzip -9f -c > $bundledir/Scripts
7264         )
7265     fi
7266
7267     # Write PackageInfo file
7268     cat <<-. >$bundledir/PackageInfo
7269         <?xml version="1.0" encoding="UTF-8"?>
7270         <pkg-info format-version="2" identifier="${pp_macos_bundle_id}" version="$version" install-location="/" relocatable="false" overwrite-permissions="true" followSymLinks="true" auth="root">
7271             <payload installKBytes="$size" numberOfFiles="$numfiles"/>
7272 .
7273     if test -s $bundledir/Scripts; then
7274         echo "    <scripts>" >>$bundledir/PackageInfo
7275         for s in preflight postflight preinstall postinstall preupgrade postupgrade; do
7276             if test -s "$pp_wrkdir/scripts/$s"; then
7277                 echo "  <$s file=\"$s\"/>" >>$bundledir/PackageInfo
7278             fi
7279         done
7280         echo "    </scripts>" >>$bundledir/PackageInfo
7281     fi
7282     cat <<-. >>$bundledir/PackageInfo
7283         </pkg-info>
7284 .
7285
7286     . $pp_wrkdir/%fixup
7287
7288     # Create the bill-of-materials (Bom)
7289     cat $filelists | pp_macos_files_bom | sort |
7290         pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls
7291     pp_macos_mkbom $pp_wrkdir/tmp.bomls $bundledir/Bom
7292
7293     # Create the cpio payload
7294     (
7295     cd $pp_destdir || pp_error "Can't cd to $pp_destdir"
7296     awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $bundledir/Payload
7297     )
7298
7299     # Copy installer plugins if any
7300     if test -n "$pp_macos_installer_plugin"; then
7301         if test ! -f "$pp_macos_installer_plugin/InstallerSections.plist"; then
7302             pp_error "Missing InstallerSections.plist file in $pp_macos_installer_plugin"
7303         fi
7304         mkdir -p $pkgdir/Plugins
7305         cp -R "$pp_macos_installer_plugin"/* $pkgdir/Plugins
7306     fi
7307
7308     test -d $pp_wrkdir/bom_stage && $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage
7309
7310     # Create the flat package with xar (like pkgutil --flatten does)
7311     # Note that --distribution is only supported by Mac OS X 10.6 and above
7312     xar_flags="--compression=bzip2 --no-compress Scripts --no-compress Payload"
7313     case $mac_version in
7314         "10.5"*) ;;
7315         *)       xar_flags="$xar_flags --distribution";;
7316     esac
7317     (cd $pkgdir && /usr/bin/xar $xar_flags -cf "../$name-$version.pkg" *)
7318 }
7319
7320 pp_backend_macos_cleanup () {
7321     :
7322 }
7323
7324 pp_backend_macos_names () {
7325     case "$pp_macos_pkg_type" in
7326         bundle) echo ${name}.pkg;;
7327         flat) echo ${name}-${version}.pkg;;
7328         *) pp_error "unsupported package type $pp_macos_pkg_type";;
7329     esac
7330 }
7331
7332 pp_backend_macos_install_script () {
7333     echo '#!/bin/sh'
7334     typeset pkgname platform
7335
7336     pkgname="`pp_backend_macos_names`"
7337     platform="`pp_backend_macos_probe`"
7338     pp_install_script_common
7339
7340     cat <<.
7341         test \$# -eq 0 && usage
7342         op="\$1"; shift
7343
7344         case "\$op" in
7345         list-components)
7346             test \$# -eq 0 || usage \$op
7347             echo "$pp_components"
7348             ;;
7349         list-services)
7350             test \$# -eq 0 || usage \$op
7351             echo "$pp_services"
7352             ;;
7353         list-files)
7354             test \$# -ge 1 || usage \$op
7355             echo \${PP_PKGDESTDIR:-.}/"$pkgname"
7356             ;;
7357         install)
7358             test \$# -ge 1 || usage \$op
7359             vol=/Volumes/pp\$\$
7360             pkg=\$vol/${name}-${version}.pkg
7361             hdiutil attach -readonly -mountpoint \$vol \
7362                 \${PP_PKGDESTDIR:-.}/"$pkgname"
7363             trap "hdiutil detach \$vol" 0
7364             installer -pkginfo -pkg \$pkg
7365             installer -verbose -pkg \$pkg -target /
7366             ;;
7367         uninstall)
7368             test \$# -ge 1 || usage \$op
7369             # XXX
7370             echo "Uninstall not implemented" >&2
7371             exit 1;;
7372         start|stop)
7373             test \$# -ge 1 || usage \$op
7374             ec=0
7375             for svc
7376             do
7377                 # XXX
7378                 echo "\${op} not implemented" >&2
7379                 ec=1
7380             done
7381             exit \$ec
7382             ;;
7383         print-platform)
7384             echo "$platform"
7385             ;;
7386         *)
7387             usage;;
7388         esac
7389 .
7390 }
7391
7392 pp_backend_macos_init_svc_vars () {
7393     pp_macos_start_services_after_install=false
7394     pp_macos_service_name=
7395     pp_macos_default_service_id_prefix="com.quest.rc."
7396     pp_macos_service_id=
7397     pp_macos_service_user=
7398     pp_macos_service_group=
7399     pp_macos_service_initgroups=
7400     pp_macos_service_umask=
7401     pp_macos_service_cwd=
7402     pp_macos_service_nice=
7403     pp_macos_svc_plist_file=
7404 }
7405
7406 pp_macos_launchd_plist () {
7407     typeset svc svc_id
7408
7409     svc="$1"
7410     svc_id="$2"
7411
7412     set -- $cmd
7413
7414     if [ -n "$pp_macos_svc_plist_file" ]; then
7415         echo "## Launchd plist file already defined at $pp_macos_svc_plist_file"
7416         return
7417     fi
7418
7419     echo "## Generating the launchd plist file for $svc"
7420     pp_macos_svc_plist_file="$pp_wrkdir/$svc.plist"
7421     cat <<-. > $pp_macos_svc_plist_file
7422         <?xml version="1.0" encoding="UTF-8"?>
7423         <!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
7424         http://www.apple.com/DTDs/PropertyList-1.0.dtd >
7425         <plist version="1.0">
7426         <dict>
7427             <key>Label</key>
7428             <string>$svc_id</string>
7429             <key>ProgramArguments</key>
7430             <array>
7431 .
7432     while test $# != 0; do
7433         printf "        <string>$1</string>\n" >> $pp_macos_svc_plist_file
7434         shift
7435     done
7436     cat <<-. >> $pp_macos_svc_plist_file
7437             </array>
7438             <key>KeepAlive</key>
7439             <true/>
7440 .
7441     if test -n "$pp_macos_service_user"; then
7442         printf "    <key>UserName</key>\n" >> $pp_macos_svc_plist_file
7443         printf "    <string>$pp_macos_service_user</string>\n" >> $pp_macos_svc_plist_file
7444     fi
7445     if test -n "$pp_macos_service_group"; then
7446         printf "    <key>GroupName</key>\n" >> $pp_macos_svc_plist_file
7447         printf "    <string>$pp_macos_service_group</string>\n" >> $pp_macos_svc_plist_file
7448     fi
7449     if test -n "$pp_macos_service_initgroups"; then
7450         printf "    <key>InitGroups</key>\n" >> $pp_macos_svc_plist_file
7451         printf "    <string>$pp_macos_service_initgroups</string>\n" >> $pp_macos_svc_plist_file
7452     fi
7453     if test -n "$pp_macos_service_umask"; then
7454         printf "    <key>Umask</key>\n" >> $pp_macos_svc_plist_file
7455         printf "    <string>$pp_macos_service_umask</string>\n" >> $pp_macos_svc_plist_file
7456     fi
7457     if test -n "$pp_macos_service_cwd"; then
7458         printf "    <key>WorkingDirectory</key>\n" >> $pp_macos_svc_plist_file
7459         printf "    <string>$pp_macos_service_cwd</string>\n" >> $pp_macos_svc_plist_file
7460     fi
7461     if test -n "$pp_macos_service_nice"; then
7462         printf "    <key>Nice</key>\n" >> $pp_macos_svc_plist_file
7463         printf "    <string>$pp_macos_service_nice</string>\n" >> $pp_macos_svc_plist_file
7464     fi
7465     cat <<-. >> $pp_macos_svc_plist_file
7466         </dict>
7467         </plist>
7468 .
7469 }
7470
7471 pp_macos_add_service () {
7472     typeset svc svc_id plist_file plist_dir
7473
7474     pp_load_service_vars "$1"
7475     svc=${pp_macos_service_name:-$1}
7476     svc_id=${pp_macos_service_id:-$pp_macos_default_service_id_prefix$svc}
7477
7478     #-- create a plist file for svc
7479     pp_macos_launchd_plist "$svc" "$svc_id"
7480
7481     #-- copy the plist file into place and add to %files
7482     plist_dir="/Library/LaunchDaemons"
7483     plist_file="$plist_dir/$svc_id.plist"
7484     mkdir -p "$pp_destdir/$plist_dir"
7485     cp "$pp_macos_svc_plist_file" "$pp_destdir/$plist_file"
7486     pp_add_file_if_missing "$plist_file"
7487
7488     #-- add code to start the service on install
7489     ${pp_macos_start_services_after_install} && <<-. >> $pp_wrkdir/%post.$svc
7490         # start service '$svc' automatically after install
7491         launchctl load "$plist_file"
7492 .
7493 }
7494
7495 pp_backend_macos_probe () {
7496     typeset name vers arch
7497     case `sw_vers -productName` in
7498          "Mac OS X") name="macos";;
7499          *)          name="unknown";;
7500     esac
7501     vers=`sw_vers -productVersion | sed -e 's/^\([^.]*\)\.\([^.]*\).*/\1\2/'`
7502     arch=`arch`
7503     echo "$name$vers-$arch"
7504 }
7505
7506 pp_backend_macos_vas_platforms () {
7507     echo "osx"    # XXX non-really sure what they do.. it should be "macos"
7508 }
7509 pp_backend_macos_function () {
7510     case "$1" in
7511         _pp_macos_search_unused) cat<<'.';;
7512             # Find an unused value in the given path
7513             # args: path attribute minid [maxid]
7514                 pp_tmp_val=$3
7515                 while :; do
7516                     test $pp_tmp_val -ge ${4:-999999} && return 1
7517                     /usr/bin/dscl . -search "$1" "$2" $pp_tmp_val |
7518                         grep . > /dev/null || break
7519                     pp_tmp_val=`expr $pp_tmp_val + 1`
7520                 done
7521                 echo $pp_tmp_val
7522 .
7523         pp_mkgroup:depends) echo _pp_macos_search_unused;;
7524         pp_mkgroup) cat<<'.';;
7525             set -e
7526             /usr/bin/dscl . -read /Groups/"$1" >/dev/null 2>&1 && return
7527             pp_tmp_gid=`_pp_macos_search_unused /Groups PrimaryGroupID 100`
7528             /usr/bin/dscl . -create /Groups/"$1"
7529             /usr/bin/dscl . -create /Groups/"$1" PrimaryGroupID $pp_tmp_gid
7530             /usr/bin/dscl . -create /Groups/"$1" RealName "Group $1"
7531             /usr/bin/dscl . -create /Groups/"$1" GroupMembership ""
7532             /usr/bin/dscl . -create /Groups/"$1" Password '*'
7533 .
7534         pp_mkuser:depends) echo pp_mkgroup _pp_macos_search_unused;;
7535         pp_mkuser) cat<<'.';;
7536             set -e
7537             /usr/bin/dscl . -read /Users/"$1" >/dev/null 2>&1 && return
7538             pp_tmp_uid=`_pp_macos_search_unused /Users UniqueID 100`
7539             pp_mkgroup "${2:-$1}"
7540             pp_tmp_gid=`/usr/bin/dscl . -read /Groups/"${2:-$1}" \
7541                 PrimaryGroupID | awk '{print $2}'`
7542             /usr/bin/dscl . -create /Users/"$1"
7543             /usr/bin/dscl . -create /Users/"$1" PrimaryGroupID $pp_tmp_gid
7544             /usr/bin/dscl . -create /Users/"$1" NFSHomeDirectory \
7545                                     "${3:-/var/empty}"
7546             /usr/bin/dscl . -create /Users/"$1" UserShell \
7547                                     "${4:-/usr/bin/false}"
7548             /usr/bin/dscl . -create /Users/"$1" RealName "$1"
7549             /usr/bin/dscl . -create /Users/"$1" UniqueID $pp_tmp_uid
7550             /usr/bin/dscl . -create /Users/"$1" Password '*'
7551 .
7552         pp_havelib) cat<<'.';;
7553             # (use otool -L to find dependent libraries)
7554             for pp_tmp_dir in `echo "${3:+$3:}/usr/local/lib:/lib:/usr/lib" |
7555                     tr : ' '`; do
7556                 test -r "$pp_tmp_dir/lib$1{$2:+.$2}.dylib" && return 0
7557             done
7558             return 1
7559 .
7560         *) false;;
7561     esac
7562 }
7563
7564 pp_platforms="$pp_platforms inst"
7565
7566 pp_backend_inst_detect () {
7567     case "$1" in
7568         IRIX*)  return 0;;
7569         *)      return 1;;
7570     esac
7571 }
7572
7573 pp_backend_inst_init () {
7574     pp_readlink_fn=pp_ls_readlink
7575 }
7576
7577 pp_backend_inst_create_idb()
7578 {
7579     typeset t m o g f p st
7580
7581     while read t m o g f p st; do
7582         if test x"$o" = x"-"; then
7583             o="root"
7584         fi
7585         if test x"$g" = x"-"; then
7586             g="sys"
7587         fi
7588         case "$t" in
7589             f)  test x"$m" = x"-" && m=444
7590                 echo "f 0$m $o $g $p $p $name.sw.base"
7591                 ;;
7592             d)  test x"$m" = x"-" && m=555
7593                 echo "d 0$m $o $g $p $p $name.sw.base"
7594                 ;;
7595             s)  test x"$m" = x"-" && m=777
7596                 test x"$m" = x"777" ||
7597                     pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
7598                 echo "l 0$m $o $g $p $p $name.sw.base symval($st)"
7599                 ;;
7600         esac
7601     done
7602 }
7603
7604 pp_backend_inst_create_spec()
7605 {
7606     echo "product $name"
7607     echo "    id \"${summary}. Version: ${version}\""
7608     echo "    image sw"
7609     echo "        id \"Software\""
7610     echo "        version $version"
7611     echo "        order 9999"
7612     echo "        subsys base"
7613     echo "            id \"Base Software\""
7614     echo "            replaces self"
7615     echo "            exp $name.sw.base"
7616     echo "        endsubsys"
7617     echo "    endimage"
7618     echo "endproduct"
7619 }
7620
7621 pp_backend_inst () {
7622     curdir=`pwd`
7623
7624     cd "$pp_opt_wrkdir"
7625
7626     # initialize
7627     pp_inst_tardist=tardist
7628     pp_inst_spec=${name}.spec
7629     pp_inst_idb=${name}.idb
7630  
7631     rm -rf $pp_inst_tardist $pp_inst_spec $pp_inst_idb
7632     mkdir -p $pp_inst_tardist
7633
7634     # Create idb file
7635     (for _cmp in $pp_components; do
7636         cat  %files.$_cmp | sort +4u -6 | pp_backend_inst_create_idb
7637     done) >> $pp_inst_idb
7638
7639     pp_backend_inst_create_spec >> $pp_inst_spec
7640
7641     # Generate tardist
7642     gendist -verbose -all -root / -source $pp_opt_destdir -idb $pp_inst_idb -spec $pp_inst_spec -dist $pp_inst_tardist $name
7643     tar -cvf `pp_backend_inst_names` $pp_inst_tardist
7644
7645     cd "$curdir"
7646 }
7647
7648 pp_backend_inst_cleanup () {
7649     :
7650 }
7651
7652 pp_backend_inst_names () {
7653     echo ${name}-${version}.tardist
7654 }
7655
7656 pp_backend_inst_install_script () {
7657     :
7658 }
7659
7660 pp_backend_inst_function () {
7661     echo false
7662 }
7663
7664 pp_backend_inst_init_svc_vars () {
7665     :
7666 }
7667
7668 pp_backend_inst_probe () {
7669     cpu=`hinv|sed -n '/^CPU/{s/000 /k /;s/^CPU: //;s/ Process.*//;s/^MIPS //;p;q;}'|tr A-Z a-z`
7670     echo irix`uname -r`-$cpu
7671 }
7672
7673 pp_backend_inst_vas_platforms () {
7674     echo "irix-65"
7675 }
7676
7677 pp_platforms="$pp_platforms null"
7678
7679 pp_backend_null_detect () {
7680     ! :
7681 }
7682
7683 pp_backend_null_init () {
7684     :
7685 }
7686
7687
7688 pp_backend_null () {
7689     :
7690 }
7691
7692 pp_backend_null_cleanup () {
7693     :
7694 }
7695
7696 pp_backend_null_names () {
7697     :
7698 }
7699
7700 pp_backend_null_install_script () {
7701     :
7702 }
7703
7704 pp_backend_null_function () {
7705     echo false
7706 }
7707
7708 pp_backend_null_init_svc_vars () {
7709     :
7710 }
7711
7712 pp_backend_null_probe () {
7713     echo unknown-unknown
7714 }
7715
7716 pp_backend_null_vas_platforms () {
7717 :
7718 }
7719
7720
7721 quest_require_vas () {
7722     typeset v d
7723
7724     if test $# -ne 1; then
7725         return
7726     fi
7727     set -- `echo "$1" | tr . ' '` 0 0 0
7728
7729     for d
7730     do
7731         echo $d | grep '^[0-9][0-9]*$' > /dev/null ||
7732             pp_error "quest_require_vas: Bad version component $d"
7733     done
7734
7735     test $# -lt 4 &&
7736             pp_error "quest_require_vas: missing version number"
7737
7738     case "$1.$2.$3.$4" in
7739         *.0.0.0) v=$1;;
7740         *.*.0.0) v=$1.$2;;
7741         *.*.*.0) v=$1.$2.$3;;
7742         *)       v=$1.$2.$3.$4;;
7743     esac
7744
7745     cat <<.
7746         if test -x /opt/quest/bin/vastool &&
7747            /opt/quest/bin/vastool -v |
7748             awk 'NR == 1 {print \$4}' |
7749             awk -F. '{ if (\$1<$1 || \$1==$1 && ( \
7750                            \$2<$2 || \$2==$2 && ( \
7751                            \$3<$3 || \$2==$3 && ( \
7752                            \$4<$4 )))) exit(1); }'
7753         then
7754             exit 0
7755         else
7756             echo "Requires VAS $v or later"
7757             exit 1
7758         fi
7759 .
7760 }
7761 pp_main ${1+"$@"}