fix for postinst syntax error
[debian/sudo] / pp
1 #!/bin/sh
2 # (c) 2011 Quest Software, Inc. All rights reserved
3 pp_revision="305"
4  # Copyright 2010 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 2010, 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 2010 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)
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.*|%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      esac
1096   done
1097   exec <&-
1098
1099   if test $pp_if_true != 0 -o $pp_if_false != 0; then
1100         pp_die "missing %endif at end of file"
1101   fi
1102
1103   pp_lineno=
1104
1105   pp_debug " name        = $name"
1106   pp_debug " version     = $version"
1107   pp_debug " summary     = $summary"
1108   pp_debug " description = $description"
1109   pp_debug " copyright   = $copyright"
1110   pp_debug ""
1111   pp_debug "\$pp_components: $pp_components"
1112   pp_debug "\$pp_services:   $pp_services"
1113 }
1114
1115 pp_set_api_version() {
1116     case "$1" in
1117         1.0)    : ;;
1118         *)      pp_error "This version of polypackage is too old";;
1119     esac
1120 }
1121
1122 pp_platform=
1123
1124 pp_set_platform () {
1125     if test -n "$pp_opt_platform"; then
1126         pp_contains "$pp_platforms" "$pp_opt_platform" ||
1127                 pp_die "$pp_opt_platform: unknown platform"
1128         pp_platform="$pp_opt_platform"
1129     else
1130         uname_s=`uname -s 2>/dev/null`
1131         pp_platform=
1132         for p in $pp_platforms; do
1133             pp_debug "probing for platform $p"
1134             if eval pp_backend_${p}_detect "$uname_s"; then
1135                 pp_platform="$p"
1136                 break;
1137             fi
1138         done
1139         test -z "$pp_platform" &&
1140                 pp_die "cannot detect platform (supported: $pp_platforms)"
1141     fi
1142     pp_debug "pp_platform = $pp_platform"
1143 }
1144
1145 pp_expand_path=
1146
1147 pp_expand_test_usr_bin () {
1148         awk '$1 == "/usr" || $2 == "/usr" {usr++}
1149              $1 == "/bin" || $2 == "/bin" {bin++}
1150              END { if (usr == 1 && bin == 1) exit(0); else exit(1); }'
1151 }
1152
1153 pp_set_expand_converter_or_reexec () {
1154     test -d /usr -a -d /bin ||
1155         pp_die "missing /usr or /bin"
1156     echo /usr /bin | pp_expand_test_usr_bin || pp_die "pp_expand_test_usr_bin?"
1157     if (eval "echo /{usr,bin}" | pp_expand_test_usr_bin) 2>/dev/null; then
1158         pp_expand_path=pp_expand_path_brace
1159     elif (eval "echo /@(usr|bin)" | pp_expand_test_usr_bin) 2>/dev/null; then
1160         pp_expand_path=pp_expand_path_at
1161     else
1162         test x"$pp_expand_rexec" != x"true" ||
1163             pp_die "problem finding shell that can do brace expansion"
1164         for shell in ksh ksh93 bash; do
1165             if ($shell -c 'echo /{usr,bin}' |
1166                         pp_expand_test_usr_bin) 2>/dev/null ||
1167                ($shell -c 'echo /@(usr|bin)' |
1168                         pp_expand_test_usr_bin) 2>/dev/null
1169             then
1170                 pp_debug "switching to shell $shell"
1171                 pp_expand_rexec=true exec $shell "$0" "$@"
1172             fi
1173         done
1174         pp_die "cannot find a shell that does brace expansion"
1175     fi
1176 }
1177
1178 pp_expand_path_brace () {
1179         typeset f
1180         eval "for f in $1; do echo \"\$f\"; done|sort -u"
1181 }
1182
1183 pp_expand_path_at () {
1184         typeset f
1185         eval "for f in `
1186             echo "$1" | sed -e 's/{/@(/g' -e 's/}/)/g' -e 's/,/|/g'
1187                 `; do echo \"\$f\"; done|sort -u"
1188 }
1189
1190 pp_shlib_suffix='.so*'
1191
1192 pp_model_init () {
1193     #@ $pp_components: whitespace-delimited list of components seen in %files
1194     pp_components=
1195     #@ $pp_services: whitespace-delimited list of %service seen
1196     pp_services=
1197
1198     rm -f $pp_wrkdir/%files.* \
1199           $pp_wrkdir/%post.* \
1200           $pp_wrkdir/%pre.* \
1201           $pp_wrkdir/%preun.* \
1202           $pp_wrkdir/%postup.* \
1203           $pp_wrkdir/%postun.* \
1204           $pp_wrkdir/%service.* \
1205           $pp_wrkdir/%set \
1206           $pp_wrkdir/%fixup
1207 }
1208
1209
1210 pp_have_component () {
1211         pp_contains "$pp_components" "$1"
1212 }
1213
1214 pp_have_all_components () {
1215         pp_contains_all "$pp_components" "$@"
1216 }
1217
1218 pp_add_component () {
1219         pp_add_to_list 'pp_components' "$1"
1220 }
1221
1222 pp_add_service () {
1223         pp_add_to_list 'pp_services' "$1"
1224 }
1225
1226 pp_service_init_vars () {
1227         cmd=
1228         pidfile=
1229         stop_signal=15          # SIGTERM
1230         user=root
1231         group=
1232         enable=yes              # make it so the service starts on boot
1233         optional=no             # Whether installing this service is optional
1234         pp_backend_init_svc_vars
1235 }
1236
1237 pp_service_check_vars () {
1238         test -n "$cmd" ||
1239                 pp_error "%service $1: cmd not defined"
1240         case "$enable" in
1241             yes|no) : ;;
1242             *) pp_error "%service $1: \$enable must be set to yes or no";;
1243         esac
1244 }
1245
1246 pp_load_service_vars () {
1247         pp_service_init_vars
1248         . "$pp_wrkdir/%service.$1"
1249         pp_service_check_vars "$1"
1250 }
1251
1252 pp_files_expand () {
1253     typeset _p _mode _group _owner _flags _path _optional _has_target _tree
1254     typeset _path _file _tgt _m _o _g _f _type _lm _ll _lo _lg _ls _lx
1255     typeset _ignore _a
1256
1257     test $# -eq 0 && return
1258
1259     pp_debug "pp_files_expand: path is: $1"
1260
1261     case "$1" in "#"*) return;; esac
1262     _p="$1"; shift
1263
1264     pp_debug "pp_files_expand: other arguments: $*"
1265
1266     #-- the mode must be an octal number of at least three digits
1267     _mode="="
1268     _a=`eval echo \"$1\"`
1269     case "$_a" in
1270         *:*) :;;
1271         -|=|[01234567][01234567][01234567]*) _mode="$_a"; shift;;
1272     esac
1273
1274     #-- the owner:group field may have optional parts
1275     _a=`eval echo \"$1\"`
1276     case "$_a" in
1277         *:*) _group=${_a#*:}; _owner=${_a%:*}; shift;;
1278         =|-) _group=$_a;      _owner=$_a; shift;;
1279         *)   _group=;         _owner=;;
1280     esac
1281
1282     #-- process the flags argument
1283     _flags=
1284     _optional=false
1285     _has_target=false
1286     _ignore=false
1287     if test $# -gt 0; then
1288         _a=`eval echo \"$1\"`
1289         case ",$_a," in *,volatile,*) _flags="${_flags}v";; esac
1290         case ",$_a," in *,optional,*) _optional=true;; esac
1291         case ",$_a," in *,symlink,*) _has_target=true;; esac
1292         case ",$_a," in *,ignore-others,*) _flags="${_flags}i";; esac
1293         case ",$_a," in *,ignore,*) _ignore=true;; esac
1294         shift
1295     fi
1296
1297     #-- process the target argument
1298     if $_has_target; then
1299         test $# -ne 0 || pp_error "$_p: missing target"
1300         _a=`eval echo \"$1\"`
1301         _target="$_a"
1302         shift
1303     fi
1304
1305     pp_debug "pp_files_expand: $_mode|$_owner:$_group|$_flags|$_target|$*"
1306
1307     test $# -eq 0 || pp_error "$_p: too many arguments"
1308
1309     #-- process speciall suffixes
1310     tree=
1311     case "$_p" in
1312         *"/**")  _p="${_p%"/**"}"; tree="**";;
1313         *".%so") _p="${_p%".%so"}$pp_shlib_suffix";;
1314     esac
1315
1316     #-- expand the path using the shell glob
1317     pp_debug "expanding .$_p ... with $pp_expand_path"
1318     (cd ${pp_destdir} && $pp_expand_path ".$_p") > $pp_wrkdir/tmp.files.exp
1319
1320     #-- expand path/** by rewriting the glob output file
1321     case "$tree" in
1322         "") : ;;
1323         "**")
1324             pp_debug "expanding /** tree ..."
1325             while read _path; do
1326                 _path="${_path#.}"
1327                 pp_find_recurse "$pp_destdir${_path%/}"
1328             done < $pp_wrkdir/tmp.files.exp |
1329                  sort -u > $pp_wrkdir/tmp.files.exp2
1330             mv $pp_wrkdir/tmp.files.exp2 $pp_wrkdir/tmp.files.exp
1331             ;;
1332     esac
1333
1334     while read _path; do
1335         _path="${_path#.}"
1336         _file="${pp_destdir}${_path}"
1337         _tgt=
1338         _m="$_mode"
1339         _o="${_owner:--}"
1340         _g="${_group:--}"
1341         _f="$_flags"
1342
1343         case "$_path" in
1344             /*) :;;
1345             *)  pp_warn "$_path: inserting leading /"
1346                 _path="/$_path";;  # ensure leading /
1347         esac
1348
1349         #-- sanity checks
1350         case "$_path" in
1351             */../*|*/..) pp_error "$_path: invalid .. in path";;
1352             */./*|*/.)   pp_warn  "$_path: invalid component . in path";;
1353             *//*)        pp_warn  "$_path: redundant / in path";;
1354         esac
1355
1356         #-- set the type based on the real file's type
1357         if $_ignore; then
1358            _type=f _m=_ _o=_ _g=_
1359         elif test -h "$_file"; then
1360            case "$_path" in
1361                 */) pp_warn "$_path (symlink $_file): removing trailing /"
1362                     _path="${_path%/}"
1363                     ;;
1364            esac
1365            _type=s
1366            if test x"$_target" != x"=" -a -n "$_target"; then
1367                _tgt="$_target"
1368 pp_debug "symlink target is $_tgt"
1369            else
1370                _tgt=`pp_readlink "$_file"`;
1371                test -z "$_tgt" && pp_error "can't readlink $_file"
1372                case "$_tgt" in
1373                     ${pp_destdir}/*)
1374                        pp_warn "stripped \$destdir from symlink ($_path)"
1375                        _tgt="${_tgt#$pp_destdir}";;
1376                esac
1377            fi
1378            _m=777
1379         elif test -d "$_file"; then
1380            #-- display a warning if the user forgot the trailing /
1381            case "$_path" in
1382                 */) :;;
1383                 *) pp_warn "$_path (matching $_file): adding trailing /"
1384                    _path="$_path/";;
1385            esac
1386            _type=d
1387            $_has_target && pp_error "$_file: not a symlink"
1388         elif test -f "$_file"; then
1389            case "$_path" in
1390                 */) pp_warn "$_path (matching $_file): removing trailing /"
1391                     _path="${_path%/}"
1392                     ;;
1393            esac
1394            _type=f
1395            $_has_target && pp_error "$_file: not a symlink"
1396         else
1397            $_optional && continue
1398            pp_error "$_file: missing"
1399            _type=f
1400         fi
1401
1402         #-- convert '=' shortcuts into mode/owner/group from ls
1403         case ":$_m:$_o:$_g:" in *:=:*)
1404             if LS_OPTIONS=--color=never /bin/ls -ld "$_file" \
1405                     > $pp_wrkdir/ls.tmp
1406             then
1407                 read _lm _ll _lo _lg _ls _lx < $pp_wrkdir/ls.tmp
1408                 test x"$_m" = x"=" && _m=`pp_mode_from_ls "$_lm"`
1409                 test x"$_o" = x"=" && _o="$_lo"
1410                 test x"$_g" = x"=" && _g="$_lg"
1411             else
1412                 pp_error "cannot read $_file"
1413                 test x"$_m" = x"=" && _m=-
1414                 test x"$_o" = x"=" && _o=-
1415                 test x"$_g" = x"=" && _g=-
1416             fi
1417             ;;
1418         esac
1419
1420         test -n "$_f" || _f=-
1421
1422         #-- sanity checks
1423         test -n "$_type" || pp_die "_type empty"
1424         test -n "$_path" || pp_die "_path empty"
1425         test -n "$_m" || pp_die "_m empty"
1426         test -n "$_o" || pp_die "_o empty"
1427         test -n "$_g" || pp_die "_g empty"
1428
1429         #-- setuid/gid files must be given an explicit owner/group (or =)
1430         case "$_o:$_g:$_m" in
1431             -:*:[4657][1357]??|-:*:[4657]?[1357]?|-:*:[4657]??[1357])
1432                 pp_error "$_path: setuid file ($_m) missing explicit owner";;
1433             *:-:[2367][1357]??|*:-:[2367]?[1357]?|*:-:[2367]??[1357])
1434                 pp_error "$_path: setgid file ($_m) missing explicit group";;
1435         esac
1436
1437         # convert numeric uids into usernames; only works for /etc/passwd
1438         case "$_o" in [0-9]*) _o=`pp_getpwuid $_o`;; esac
1439         case "$_g" in [0-9]*) _g=`pp_getgrgid $_g`;; esac
1440
1441         pp_debug "$_type $_m $_o $_g $_f $_path" $_tgt
1442         $_ignore || echo "$_type $_m $_o $_g $_f $_path" $_tgt
1443         pp_note_file_used "$_path"
1444         case "$_f" in *i*) echo "$_path" >> $pp_wrkdir/ign.files;; esac
1445     done < $pp_wrkdir/tmp.files.exp
1446 }
1447
1448 pp_files_check_duplicates () {
1449     typeset _path
1450     if test -s $pp_wrkdir/all.files; then
1451         sort < $pp_wrkdir/all.files | uniq -d > $pp_wrkdir/duplicate.files
1452         if test -f $pp_wrkdir/ign.awk; then
1453             # Remove ignored files
1454             mv $pp_wrkdir/duplicate.files $pp_wrkdir/duplicate.files.ign
1455             sed -e 's/^/_ _ _ _ _ /' < $pp_wrkdir/duplicate.files.ign |
1456                 awk -f $pp_wrkdir/ign.awk |
1457                 sed -e 's/^_ _ _ _ _ //' > $pp_wrkdir/duplicate.files
1458         fi
1459         while read _path; do
1460             pp_warn "$_path: file declared more than once"
1461         done <$pp_wrkdir/duplicate.files
1462     fi
1463 }
1464
1465 pp_files_check_coverage () {
1466     pp_find_recurse "$pp_destdir" | sort > $pp_wrkdir/coverage.avail
1467     if test -s $pp_wrkdir/all.files; then
1468         sort -u < $pp_wrkdir/all.files
1469     else
1470         :
1471     fi > $pp_wrkdir/coverage.used
1472     join -v1 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
1473         > $pp_wrkdir/coverage.not-packaged
1474     if test -s $pp_wrkdir/coverage.not-packaged; then
1475         pp_warn "The following files/directories were found but not packaged:"
1476         sed -e 's,^,    ,' <  $pp_wrkdir/coverage.not-packaged >&2
1477     fi
1478     join -v2 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
1479         > $pp_wrkdir/coverage.not-avail
1480     if test -s $pp_wrkdir/coverage.not-avail; then
1481         pp_warn "The following files/directories were named but not found:"
1482         sed -e 's,^,    ,' <  $pp_wrkdir/coverage.not-avail >&2
1483     fi
1484 }
1485
1486 pp_files_ignore_others () {
1487     typeset p f
1488
1489     test -s $pp_wrkdir/ign.files || return
1490
1491     #-- for each file in ign.files, we remove it from all the
1492     #   other %files.* lists, except where it has an i flag.
1493     #   rather than scan each list multiple times, we build
1494     #   an awk script
1495
1496     pp_debug "stripping ignore files"
1497
1498     while read p; do
1499         echo '$6 == "'"$p"'" && $5 !~ /i/ { next }'
1500     done < $pp_wrkdir/ign.files > $pp_wrkdir/ign.awk
1501     echo '{ print }' >> $pp_wrkdir/ign.awk
1502
1503     $pp_opt_debug && cat $pp_wrkdir/ign.awk
1504
1505     for f in $pp_wrkdir/%files.*; do
1506         mv $f $f.ign
1507         awk -f $pp_wrkdir/ign.awk < $f.ign > $f || pp_error "awk"
1508     done
1509 }
1510
1511 pp_service_scan_groups () {
1512     typeset svc
1513
1514     #-- scan for "group" commands, and build a list of groups
1515     pp_service_groups=
1516     if test -n "$pp_services"; then
1517         for svc in $pp_services; do
1518             group=
1519             . $pp_wrkdir/%service.$svc
1520             if test -n "$group"; then
1521                 pp_contains "$pp_services" "$group" && pp_error \
1522                     "%service $svc: group name $group in use by a service"
1523                 pp_add_to_list 'pp_service_groups' "$group"
1524                 echo "$svc" >> $pp_wrkdir/%svcgrp.$group
1525             fi
1526         done
1527     fi
1528 }
1529
1530 pp_service_get_svc_group () {
1531     (tr '\012' ' ' < $pp_wrkdir/%svcgrp.$1 ; echo) | sed -e 's/ $//'
1532 }
1533
1534 for _sufx in _init '' _names _cleanup _install_script \
1535     _init_svc_vars _function _probe _vas_platforms
1536 do
1537  eval "pp_backend$_sufx () { pp_debug pp_backend$_sufx; pp_backend_\${pp_platform}$_sufx \"\$@\"; }"
1538 done
1539
1540
1541 pp_platforms="$pp_platforms aix"
1542
1543 pp_backend_aix_detect () {
1544         test x"$1" = x"AIX"
1545 }
1546
1547 pp_backend_aix_init () {
1548         pp_aix_detect_arch
1549         pp_aix_detect_os
1550
1551         pp_aix_bosboot=         # components that need bosboot
1552         pp_aix_lang=en_US
1553         pp_aix_copyright=
1554         pp_aix_start_services_after_install=false
1555         pp_aix_init_services_after_install=true
1556
1557         pp_aix_sudo=sudo        # AIX package tools must run as root
1558
1559         case "$pp_aix_os" in
1560             *) pp_readlink_fn=pp_ls_readlink;;  # XXX
1561         esac
1562
1563         pp_aix_abis_seen=
1564 }
1565
1566 pp_aix_detect_arch () {
1567         pp_aix_arch_p=`uname -p 2>/dev/null`
1568         case "$pp_aix_arch_p"  in
1569            "")      pp_debug "can't get processor type from uname -p"
1570                     pp_aix_arch_p=powerpc
1571                     pp_aix_arch=R;;  # guess (lsattr -l proc0 ??)
1572            powerpc) pp_aix_arch=R;;
1573            *)       pp_aix_arch_p=intel
1574                     pp_aix_arch=I;;  # XXX? verify
1575         esac
1576
1577         case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
1578             PowerPC_POWER*) pp_aix_arch_std=ppc64;;
1579             PowerPC*) pp_aix_arch_std=ppc;;
1580             *) pp_aix_arch_std=unknown;;
1581         esac
1582 }
1583
1584 pp_aix_detect_os () {
1585         typeset r v
1586
1587         r=`uname -r`
1588         v=`uname -v`
1589         pp_aix_os=aix$v$r
1590 }
1591
1592 pp_aix_version_fix () {
1593     typeset v
1594     v=`echo $1 | tr -c -d '[0-9].\012'`
1595     if test x"$v" != x"$1"; then
1596         pp_warn "stripped version '$1' to '$v'"
1597     fi
1598     case $v in
1599         ""|*..*|.*|*.) pp_error "malformed '$1'"
1600                  echo "0.0.0.0";;
1601         *.*.*.*.*)
1602                  # 5 components are only valid for fileset updates, not base
1603                  # filesets (full packages). We trim 5+ components down to 4.
1604                  pp_warn "version '$1' has too many dots for AIX, truncating"
1605                  echo "$v" | cut -d. -f1-4;;
1606         *.*.*.*) echo "$v";;
1607         *.*.*) echo "$v.0";;
1608         *.*) echo "$v.0.0";;
1609         *) echo "$v.0.0.0";;
1610     esac
1611 }
1612
1613 pp_aix_select () {
1614         case "$1" in
1615             -user) op="";;
1616             -root) op="!";;
1617             *) pp_die "pp_aix_select: bad argument";;
1618         esac
1619         #pp_debug awk '$5 '$op' /^\/(usr|opt)(\/|$)/ { print; }'
1620         #awk '$5 '$op' /^\/(usr|opt)(\/|$)/ { print; }'
1621         awk $op'($6 ~ /^\/usr\// || $6 ~ /^\/opt\//) { print; }'
1622 }
1623
1624 pp_aix_copy_root () {
1625     typeset t m o g f p st target
1626     while read t m o g f p st; do
1627         case "$t" in
1628            d) pp_create_dir_if_missing "$1${p%/}";;
1629            f) pp_add_transient_file "$1$p"
1630               pp_verbose ln "$pp_destdir$p" "$pp_destdir$1$p" ||
1631                 pp_error "can't link $p into $1";;
1632            *) pp_warn "pp_aix_copy_root: filetype $t not handled";;
1633         esac
1634     done
1635 }
1636
1637
1638 pp_aix_size () {
1639     typeset prefix t m o g f p st
1640
1641     prefix="$1"
1642     while read t m o g f p st; do
1643       case "$t" in f) du -a "$pp_destdir$p";; esac
1644     done | sed -e 's!/[^/]*$!!' | sort +1 |
1645     awk '{ if ($2 != d)
1646            { if (sz) print d,sz;
1647              d=$2; sz=0 }
1648            sz += $1; }
1649          END { if (sz) print d,sz }' |
1650     sed -n -e "s!^$pp_destdir!$prefix!p"
1651 }
1652
1653 pp_aix_list () {
1654     awk '{ print "." pfx $6; }' pfx="$1"
1655 }
1656
1657 pp_aix_make_liblpp () {
1658     typeset out dn fl f
1659
1660     out="$1"; shift
1661     dn=`dirname "$2"`
1662     fl=
1663     for f
1664     do
1665         case "$f" in "$dn/"*) fl="$fl `basename $f`" ;;
1666                      *) pp_die "liblpp name $f not in $dn/";; esac
1667     done
1668     (cd "$dn" && pp_verbose  ar -c -g -r "$out" $fl) || pp_error "ar error"
1669 }
1670
1671 pp_aix_make_script () {
1672     rm -f "$1"
1673     echo "#!/bin/sh" > "$1"
1674     cat >> "$1"
1675     echo "exit 0" >> "$1"
1676     chmod +x "$1"
1677 }
1678
1679 pp_aix_inventory () {
1680     typeset fileset t m o g f p st type
1681
1682     fileset="$1"
1683     while read t m o g f p st; do
1684       case "$p" in *:*) pp_error "path $p contains colon";; esac
1685       echo "$p:"
1686       case "$t" in
1687         f)   type=FILE;      defm=644 ;;
1688         s)   type=SYMLINK;   defm=777 ;;
1689         d)   type=DIRECTORY; defm=755 ;;
1690       esac
1691       echo " type = $type"
1692       echo " class = inventory,apply,$fileset"
1693       if test x"$m" = x"-"; then m="$defm"; fi
1694       if test x"$o" = x"-"; then o="root"; fi
1695       if test x"$g" = x"-"; then g="system"; fi
1696       echo " owner = $o"
1697       echo " group = $g"
1698
1699       case "$m" in ????)
1700         m=`echo $m|sed -e 's/^1/TCB,/' \
1701                        -e 's/^[23]/TCB,SGID,/' \
1702                        -e 's/^[45]/TCB,SUID,/' \
1703                        -e 's/^[67]/TCB,SUID,SGID,/'`;;  # vtx bit ignored
1704       esac
1705       echo " mode = $m"
1706       case "$t" in
1707         f) if test ! -f "$pp_destdir$p"; then
1708                 pp_error "$p: missing file"
1709            fi
1710            case "$flags" in
1711             *v*)
1712               echo " size = VOLATILE"
1713               echo " checksum = VOLATILE"
1714               ;;
1715             *)
1716               if test -r "$pp_destdir$p"; then
1717                 echo " size = $size"
1718                 pp_verbose  sum -r < "$pp_destdir$p" |
1719                   sed -e 's/.*/ checksum = "&"/'
1720               fi
1721               ;;
1722            esac;;
1723         s)
1724            echo " target = $st"
1725            ;;
1726       esac
1727
1728       #-- Record ABI types seen
1729       case "$t" in
1730         f) if test -r "$pp_destdir$p"; then
1731             case "`file "$pp_destdir$p"`" in
1732                 *"executable (RISC System/6000)"*) abi=ppc;;
1733                 *"64-bit XCOFF executable"*)       abi=ppc64;;
1734                 *) abi=;;
1735             esac
1736             if test -n "$abi"; then
1737                 pp_add_to_list pp_aix_abis_seen $abi
1738             fi
1739            fi;;
1740       esac
1741
1742     done
1743 }
1744
1745 pp_aix_depend ()
1746 {
1747     if test -s "$1"; then
1748        pp_warn "aix dependencies not implemented"
1749     fi
1750 }
1751
1752 pp_aix_add_service () {
1753         typeset svc cmd_cmd cmd_arg f
1754         svc="$1"
1755
1756         pp_load_service_vars $svc
1757
1758         set -- $cmd
1759         cmd_cmd="$1"; shift
1760         cmd_arg="$pp_aix_mkssys_cmd_args";
1761
1762         case "$stop_signal" in
1763                 HUP) stop_signal=1;;
1764                 INT) stop_signal=2;;
1765                 QUIT) stop_signal=3;;
1766                 KILL) stop_signal=9;;
1767                 TERM) stop_signal=15;;
1768                 USR1) stop_signal=30;;
1769                 USR2) stop_signal=31;;
1770                 "")
1771                   pp_error "%service $svc: stop_signal not set";;
1772                 [a-zA-Z]*)
1773                   pp_error "%service $svc: bad stop_signal ($stop_signal)";;
1774         esac
1775
1776         test -z "$pidfile" || pp_error "aix requires empty pidfile (non daemon)"
1777
1778         pp_add_component run
1779         if test "$user" = "root"; then
1780             uid=0
1781         else
1782             uid="\"\`/usr/bin/id -u $user\`\""
1783         fi
1784
1785
1786         #-- add command text to create/remove the service
1787         cat <<-. >> $pp_wrkdir/%post.$svc
1788 svc=$svc
1789 uid=0
1790 cmd_cmd=$daemon
1791 cmd_arg="$cmd_arg"
1792 stop_signal=$stop_signal
1793 force_signal=9
1794 srcgroup="$pp_aix_mkssys_group"
1795
1796 lssrc -s \$svc > /dev/null 2>&1
1797 if [ \$? -eq 0 ]; then
1798   lssrc -s \$svc | grep "active" > /dev/null 2>&1
1799   if [ \$? -eq 0 ]; then
1800     stopsrc -s \$svc > /dev/null 2>&1
1801   fi
1802   rmsys -s \$svc > /dev/null 2>&1
1803 fi
1804
1805 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}
1806 .
1807
1808         #-- add code to start the service on reboot
1809         ${pp_aix_init_services_after_install} &&
1810           cat <<-. >> $pp_wrkdir/%post.$svc
1811 mkitab "\$svc:2:once:/usr/bin/startsrc -s \$svc" > /dev/null 2>&1
1812 .
1813
1814         ${pp_aix_start_services_after_install} &&
1815           cat <<-. >> $pp_wrkdir/%post.$svc
1816 startsrc -s \$svc
1817 .
1818
1819 if [ -f "$pp_wrkdir/%post.run" ];then
1820     cat $pp_wrkdir/%post.run >> $pp_wrkdir/%post.$svc
1821 fi
1822 mv $pp_wrkdir/%post.$svc $pp_wrkdir/%post.run
1823
1824
1825         ${pp_aix_init_services_after_install} &&
1826            pp_prepend $pp_wrkdir/%preun.$svc <<-.
1827 rmitab $svc
1828 .
1829         pp_prepend $pp_wrkdir/%preun.$svc <<-.
1830 stopsrc -s $svc >/dev/null 2>&1
1831 rmssys -s $svc
1832 .
1833
1834 if [ -f "$pp_wrkdir/%preun.run" ];then
1835     cat $pp_wrkdir/%preun.run >> $pp_wrkdir/%preun.$svc
1836 fi
1837 mv $pp_wrkdir/%preun.$svc $pp_wrkdir/%preun.run
1838 }
1839
1840 pp_backend_aix () {
1841         typeset briefex instuser instroot svc cmp outbff
1842         typeset user_wrkdir root_wrkdir
1843         typeset user_files root_files
1844
1845         test -n "$pp_destdir" ||
1846            pp_error "AIX backend requires the '--destdir' option"
1847
1848         instuser="/usr/lpp/$name"
1849         instroot="$instuser/inst_root"
1850         pp_aix_bff_name=${pp_aix_bff_name:-$name}
1851
1852         # Here is the component mapping:
1853         #  run -> $pp_aix_bff_name.rte ('Run time environment')
1854         #  doc -> $pp_aix_bff_name.doc (non-standard)
1855         #  dev -> $pp_aix_bff_name.adt ('Application developer toolkit')
1856         #  dbg -> $pp_aix_bff_name.diag ('Diagnostics')
1857
1858         test `echo "$summary" | wc -c ` -gt 40 && pp_error "\$summary too long"
1859
1860         user_wrkdir=$pp_wrkdir/u
1861         root_wrkdir=$pp_wrkdir/r
1862         pp_verbose  rm -rf $user_wrkdir $root_wrkdir
1863         pp_verbose  mkdir -p $user_wrkdir $root_wrkdir
1864
1865         for svc in $pp_services .; do
1866             test . = "$svc" && continue
1867             pp_aix_add_service $svc
1868         done
1869
1870         {
1871           echo "4 $pp_aix_arch I $name {"
1872
1873           for cmp in $pp_components; do
1874             case "$cmp" in
1875                 run) ex=rte  briefex="runtime";;
1876                 doc) ex=doc  briefex="documentation";;
1877                 dev) ex=adt  briefex="developer toolkit";;
1878                 dbg) ex=diag briefex="diagnostics";;
1879             esac
1880
1881             user_files=$pp_wrkdir/%files.$cmp.u
1882             root_files=$pp_wrkdir/%files.$cmp.r
1883
1884             pp_aix_select -user < $pp_wrkdir/%files.$cmp > $user_files
1885             pp_aix_select -root < $pp_wrkdir/%files.$cmp > $root_files
1886
1887             # Default to USR only unless there are root files,
1888             # or a post/pre/check script associated
1889             content=U
1890             if test -s $root_files \
1891                     -o -s $pp_wrkdir/%pre.$cmp \
1892                     -o -s $pp_wrkdir/%post.$cmp \
1893                     -o -s $pp_wrkdir/%preun.$cmp \
1894                     -o -s $pp_wrkdir/%check.$cmp
1895             then
1896                 content=B
1897             fi
1898
1899             if $pp_opt_debug; then
1900                 echo "$cmp USER %files:"
1901                 cat $user_files
1902                 echo "$cmp ROOT %files:"
1903                 cat $root_files
1904             fi >&2
1905
1906             bosboot=N; pp_contains_any "$pp_aix_bosboot" $cmp && bosboot=b
1907
1908             echo $pp_aix_bff_name.$ex \
1909                  ${pp_aix_version:-`pp_aix_version_fix "$version"`} \
1910                  1 $bosboot $content \
1911                  $pp_aix_lang "$summary $briefex"
1912             echo "["
1913
1914             pp_aix_depend $pp_wrkdir/%depend.$cmp
1915
1916             echo "%"
1917
1918             # generate per-directory size information
1919             pp_aix_size < $user_files
1920             pp_aix_size $instroot < $root_files
1921
1922             pp_aix_list            < $user_files  > $user_wrkdir/$pp_aix_bff_name.$ex.al
1923             pp_aix_list $instroot  < $root_files >> $user_wrkdir/$pp_aix_bff_name.$ex.al
1924             pp_aix_list            < $root_files  > $root_wrkdir/$pp_aix_bff_name.$ex.al
1925
1926             if $pp_opt_debug; then
1927                 echo "$cmp USER $pp_aix_bff_name.$ex.al:"
1928                 cat $user_wrkdir/$pp_aix_bff_name.$ex.al
1929                 echo "$cmp ROOT $pp_aix_bff_name.$ex.al:"
1930                 cat $root_wrkdir/$pp_aix_bff_name.$ex.al
1931             fi >&2
1932
1933             pp_aix_inventory $pp_aix_bff_name.$ex < $user_files \
1934                                        > $user_wrkdir/$pp_aix_bff_name.$ex.inventory
1935             pp_aix_inventory $pp_aix_bff_name.$ex < $root_files \
1936                                        > $root_wrkdir/$pp_aix_bff_name.$ex.inventory
1937
1938             if $pp_opt_debug; then
1939                 pp_debug "$cmp USER $pp_aix_bff_name.$ex.inventory:"
1940                 cat $user_wrkdir/$pp_aix_bff_name.$ex.inventory
1941                 pp_debug "$cmp ROOT $pp_aix_bff_name.$ex.inventory:"
1942                 cat $root_wrkdir/$pp_aix_bff_name.$ex.inventory
1943             fi >&2
1944
1945             if test x"" != x"${pp_aix_copyright:-$copyright}"; then
1946                 echo "${pp_aix_copyright:-$copyright}" > $user_wrkdir/$pp_aix_bff_name.$ex.copyright
1947                 echo "${pp_aix_copyright:-$copyright}" > $root_wrkdir/$pp_aix_bff_name.$ex.copyright
1948             fi
1949
1950             #-- assume that post/pre uninstall scripts only make
1951             #   sense when installed in a root context
1952
1953             if test -r $pp_wrkdir/%pre.$cmp; then
1954                         pp_aix_make_script $user_wrkdir/$pp_aix_bff_name.$ex.pre_i \
1955                 < $pp_wrkdir/%pre.$cmp
1956             fi
1957
1958             if test -r $pp_wrkdir/%post.$cmp; then
1959                 pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.post_i \
1960                         < $pp_wrkdir/%post.$cmp
1961             fi
1962
1963             if test -r $pp_wrkdir/%preun.$cmp; then
1964                 pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpost_i \
1965                         < $pp_wrkdir/%preun.$cmp
1966             fi
1967
1968             # remove empty files
1969             for f in $user_wrkdir/$pp_aix_bff_name.$ex.* $root_wrkdir/$pp_aix_bff_name.$ex.*; do
1970               if test ! -s "$f"; then
1971                 pp_debug "removing empty $f"
1972                 rm -f "$f"
1973               fi
1974             done
1975
1976             # copy/link the root files so we can do an easy backup later
1977             pp_aix_copy_root $instroot < $root_files
1978
1979             echo "%"
1980             echo "]"
1981           done
1982           echo "}"
1983         } > $pp_wrkdir/lpp_name
1984
1985         if $pp_opt_debug; then
1986             echo "/lpp_name :"
1987             cat $pp_wrkdir/lpp_name
1988         fi >&2
1989
1990         #-- copy the /lpp_name file to the destdir
1991         pp_add_transient_file /lpp_name
1992         cp $pp_wrkdir/lpp_name $pp_destdir/lpp_name
1993
1994         #-- copy the liblpp.a files under destdir for packaging
1995         (cd $user_wrkdir && pp_verbose  ar -c -g -r liblpp.a $name.*) ||
1996                 pp_error "ar error"
1997         if test -s $user_wrkdir/liblpp.a; then
1998            pp_add_transient_file $instuser/liblpp.a
1999            pp_verbose cp $user_wrkdir/liblpp.a $pp_destdir$instuser/liblpp.a ||
2000                 pp_error "cannot create user liblpp.a"
2001         fi
2002         (cd $root_wrkdir && pp_verbose  ar -c -g -r liblpp.a $name.*) ||
2003                 pp_error "ar error"
2004         if test -s $root_wrkdir/liblpp.a; then
2005            pp_add_transient_file $instroot/liblpp.a
2006            pp_verbose cp $root_wrkdir/liblpp.a $pp_destdir$instroot/liblpp.a ||
2007                 pp_error "cannot create root liblpp.a"
2008         fi
2009
2010         { echo ./lpp_name
2011           test -s $user_wrkdir/liblpp.a && echo .$instuser/liblpp.a
2012           test -s $root_wrkdir/liblpp.a && echo .$instroot/liblpp.a
2013           cat $user_wrkdir/$name.*.al   # includes the relocated root files!
2014         } > $pp_wrkdir/bff.list
2015
2016         if test -n "$pp_aix_abis_seen" -a x"$pp_aix_arch_std" = x"auto"; then
2017             case "$pp_aix_abis_seen" in
2018                 "ppc ppc64"|"ppc64 ppc")
2019                     pp_aix_arch_std=ppc64
2020                     ;;
2021                 ppc|ppc64)
2022                     pp_aix_arch_std=$pp_aix_abis_seen
2023                     ;;
2024                 *" "*)
2025                     pp_warn "multiple architectures detected: $pp_aix_abis_seen"
2026                     pp_aix_arch_std=unknown
2027                     ;;
2028                 "")
2029                     pp_warn "no binary executables detected; using noarch"
2030                     pp_aix_arch_std=noarch
2031                     ;;
2032                 *)
2033                     pp_warn "unknown architecture detected $pp_aix_abis_seen"
2034                     pp_aix_arch_std=$pp_aix_abis_seen
2035                     ;;
2036             esac
2037         fi
2038
2039         . $pp_wrkdir/%fixup
2040
2041         outbff=`pp_backend_aix_names`
2042         pp_debug "creating: $pp_wrkdir/$outbff"
2043         (cd $pp_destdir && pp_verbose  /usr/sbin/backup -i -q -p -f -) \
2044           < $pp_wrkdir/bff.list \
2045           > $pp_wrkdir/$outbff || pp_error "backup failed"
2046         $pp_aix_sudo /usr/sbin/installp -l -d $pp_wrkdir/$outbff
2047 }
2048
2049 pp_backend_aix_cleanup () {
2050     :
2051 }
2052
2053 pp_backend_aix_names () {
2054         echo "$name.${pp_aix_version:-`pp_aix_version_fix "$version"`}.bff"
2055 }
2056
2057 pp_backend_aix_install_script () {
2058         typeset pkgname platform
2059         #
2060         # The script should take a first argument being the
2061         # operation; further arguments refer to components or services
2062         #
2063         # list-components           -- lists components in the pkg
2064         # install component...      -- installs the components
2065         # uninstall component...    -- uninstalles the components
2066         # list-services             -- lists the services in the pkg
2067         # start service...          -- starts the name service
2068         # stop service...           -- stops the named services
2069         # print-platform            -- prints the platform group
2070         #
2071         pkgname="`pp_backend_aix_names`"
2072         platform="`pp_backend_aix_probe`"   # XXX should be derived from files
2073
2074         fsets=
2075         for cmp in $pp_components; do
2076             case "$cmp" in
2077                 run) ex=rte;;
2078                 doc) ex=doc;;
2079                 dev) ex=adt;;
2080                 dbg) ex=diag;;
2081             esac
2082             fsets="$fsets $name.$ex"
2083         done
2084
2085         echo '#!/bin/sh'
2086         pp_install_script_common
2087
2088         cat <<-.
2089
2090             cpt_to_fileset () {
2091                 test x"\$*" = x"all" &&
2092                     set -- $pp_components
2093                 for cpt
2094                 do
2095                     case "\$cpt" in
2096                         run) echo "$name.rte";;
2097                         doc) echo "$name.doc";;
2098                         dev) echo "$name.adt";;
2099                         dbg) echo "$name.diag";;
2100                         *) usage;;
2101                     esac
2102                 done
2103             }
2104
2105             test \$# -eq 0 && usage
2106             op="\$1"; shift
2107
2108             case "\$op" in
2109                 list-components)
2110                     test \$# -eq 0 || usage \$op
2111                     echo "$pp_components"
2112                     ;;
2113                 list-services)
2114                     test \$# -eq 0 || usage \$op
2115                     echo "$pp_services"
2116                     ;;
2117                 list-files)
2118                     test \$# -ge 1 || usage \$op
2119                     echo \${PP_PKGDESTDIR:-.}/$pkgname
2120                     ;;
2121                 install)
2122                     test \$# -ge 1 || usage \$op
2123                     verbose /usr/sbin/installp -acX -V0 -F \
2124                         -d \${PP_PKGDESTDIR:-.}/$pkgname \
2125                         \`cpt_to_fileset "\$@"\`
2126                     ;;
2127                 uninstall)
2128                     test \$# -ge 1 || usage \$op
2129                     verbose /usr/sbin/installp -u -e/dev/null \
2130                         -V0 \`cpt_to_fileset "\$@"\`
2131                     ;;
2132                 start|stop)
2133                     test \$# -ge 1 || usage \$op
2134                     ec=0
2135                     for svc
2136                     do
2137                         verbose \${op}src -s \$svc || ec=1
2138                     done
2139                     exit \$ec
2140                     ;;
2141                 print-platform)
2142                     echo "$platform"
2143                     ;;
2144                 *)
2145                     usage;;
2146             esac
2147 .
2148 }
2149
2150 pp_backend_aix_init_svc_vars () {
2151     :
2152 }
2153
2154 pp_backend_aix_probe () {
2155         echo "${pp_aix_os}-${pp_aix_arch_std}"
2156 }
2157
2158 pp_backend_aix_vas_platforms () {
2159     case "${pp_aix_arch_std}" in
2160         ppc*)   :;;
2161         *)      pp_die "unknown architecture ${pp_aix_arch_std}";;
2162     esac
2163     case "${pp_aix_os}" in
2164         aix43)  echo "aix-43";;
2165         aix51)  echo "aix-51 aix-43";;
2166         aix52)  echo "aix-51 aix-43";;
2167         aix53)  echo "aix-53 aix-51 aix-43";;
2168         aix61)  echo "aix-53 aix-51 aix-43";;
2169         *)      pp_die "unknown system ${pp_aix_os}";;
2170     esac
2171 }
2172 pp_backend_aix_function () {
2173     case $1 in
2174     pp_mkgroup) cat <<'.';;
2175             /usr/sbin/lsgroup "$1" >/dev/null &&
2176                 return 0
2177             echo "Creating group $1"
2178             /usr/bin/mkgroup -A "$1"
2179 .
2180     pp_mkuser:depends) echo pp_mkgroup;;
2181     pp_mkuser) cat <<'.';;
2182             /usr/sbin/lsuser "$1" >/dev/null &&
2183                 return 0
2184             pp_mkgroup "${2:-$1}" || return 1
2185             echo "Creating user $1"
2186             /usr/bin/mkuser \
2187                 login=false \
2188                 rlogin=false \
2189                 account_locked=true \
2190                 home="${3:-/nohome.$1}" \
2191                 pgrp="${2:-$1}" \
2192                 "$1"
2193 .
2194     pp_havelib) cat <<'.';;
2195             case "$2" in
2196                 "")    pp_tmp_name="lib$1.so";;
2197                 *.*.*) pp_tmp_name="lib$1.so.$2";;
2198                 *.*)   pp_tmp_name="lib$1.so.$2.0";;
2199                 *)     pp_tmp_name="lib$1.so.$2";;
2200             esac
2201             for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
2202                 test -r "$pp_tmp_dir/$pp_tmp_name" -a \
2203                     -r "$pp_tmp_dir/lib$1.so" && return 0
2204             done
2205             return 1
2206 .
2207     *) false;;
2208     esac
2209 }
2210
2211 pp_platforms="$pp_platforms sd"
2212
2213 pp_backend_sd_detect () {
2214     test x"$1" = x"HP-UX"
2215 }
2216
2217 pp_backend_sd_init () {
2218     pp_sd_sudo=
2219     pp_sd_startlevels=2
2220     pp_sd_stoplevels=auto
2221     pp_sd_config_file=
2222     pp_sd_vendor=
2223     pp_sd_vendor_tag=Quest
2224     pp_sd_default_start=1           # config_file default start value
2225
2226     pp_readlink_fn=pp_ls_readlink   # HPUX has no readlink
2227     pp_shlib_suffix='.sl'           # .so on most other platforms
2228
2229     pp_sd_detect_os
2230 }
2231
2232 pp_sd_detect_os () {
2233     typeset revision
2234
2235     revision=`uname -r`
2236     pp_sd_os="${revision#?.}"
2237     test -z "$pp_sd_os" &&
2238         pp_warn "cannot detect OS version"
2239     pp_sd_os_std="hpux`echo $pp_sd_os | tr -d .`"
2240
2241     case "`uname -m`" in
2242         9000/[678]??) pp_sd_arch_std=hppa;;
2243         ia64) pp_sd_arch_std=ia64;;
2244         *) pp_sd_arch_std=unknown;;
2245     esac
2246 }
2247
2248 pp_sd_write_files () {
2249     typeset t m o g f p st line dm
2250     while read t m o g f p st; do
2251         line="                file"
2252         case "$f" in *v*) line="$line -v";; esac    # FIXME for uninstall
2253         case ${pp_sd_os} in
2254             10.*)
2255                 case $t in
2256                     f) dm=644;;
2257                     d) p=${p%/}; dm=755;;
2258                 esac
2259                 ;;
2260             *)
2261                 case $t in
2262                     f) dm=644;;
2263                     d) line="$line -t d"; p=${p%/}; dm=755;;
2264                     s) line="$line -t s";;
2265                 esac
2266                 ;;
2267         esac
2268
2269         test x"$o" = x"-" && o=root
2270         test x"$g" = x"-" && g=sys
2271         test x"$m" = x"-" && m=$dm
2272
2273         case $t in
2274             s) echo "$line $st $p";;
2275             *) echo "$line -o $o -g $g -m $m $pp_destdir$p $p";;
2276         esac
2277
2278     done
2279 }
2280
2281 pp_sd_service_group_script () {
2282     typeset grp svcs scriptpath out
2283     grp="$1"
2284     svcs="$2"
2285     scriptpath="/sbin/init.d/$grp"
2286     out="$pp_destdir$scriptpath"
2287
2288     pp_add_file_if_missing $scriptpath run 755 || return 0
2289
2290     cat <<-. > $out
2291         #!/sbin/sh
2292         # generated by pp $pp_version
2293         svcs="$svcs"
2294 .
2295
2296     cat <<-'.' >> $out
2297         #-- starts services in order.. stops them all if any break
2298         pp_start () {
2299             undo=
2300             for svc in $svcs; do
2301                 /sbin/init.d/$svc start
2302                 case $? in
2303                   0|4)
2304                     undo="$svc $undo"
2305                     ;;
2306                   *)
2307                     if test -n "$undo"; then
2308                         for svc in $undo; do
2309                            /sbin/init.d/$svc stop
2310                         done
2311                         return 1
2312                     fi
2313                     ;;
2314                 esac
2315             done
2316             return 0
2317         }
2318
2319         #-- stops services in reverse
2320         pp_stop () {
2321             reverse=
2322             for svc in $svcs; do
2323                 reverse="$svc $reverse"
2324             done
2325             rc=0
2326             for svc in $reverse; do
2327                 /sbin/init.d/$svc stop || rc=$?
2328             done
2329             return $rc
2330         }
2331
2332         case $1 in
2333             start_msg) echo "Starting $svcs";;
2334             stop_msg)  echo "Stopping $svcs";;
2335             start)     pp_start;;
2336             stop)      pp_stop;;
2337             *)         echo "usage: $0 {start|stop|start_msg|stop_msg}"
2338                        exit 1;;
2339         esac
2340 .
2341 }
2342
2343 pp_sd_service_script () {
2344     typeset svc config_file config_value scriptpath out
2345
2346     svc="$1"
2347     scriptpath="/sbin/init.d/$svc"
2348
2349     config_file=${pp_sd_config_file:-/etc/rc.config.d/$svc}
2350     sd_config_var=`echo run-$svc | tr '[a-z]-' '[A-Z]_'`
2351     sd_config_value=${pp_sd_default_start:-0}
2352     pp_load_service_vars "$svc"
2353
2354     test -n "$user" -a x"$user" != x"root" &&
2355         cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
2356     if test -z "$pidfile"; then
2357         pidfile="/var/run/$svc.pid"
2358         cmd="$cmd & echo \$! > \$pidfile"
2359     fi
2360
2361     pp_debug "config file is $config_file"
2362
2363     pp_add_file_if_missing $scriptpath run 755
2364     pp_add_file_if_missing $config_file run 644 v
2365
2366     cat <<-. >> $pp_destdir$config_file
2367
2368         # Controls whether the $svc service is started
2369         $sd_config_var=$sd_config_value
2370 .
2371
2372     if test ! -f $pp_destdir$scriptpath; then
2373     cat <<-. > $pp_destdir$scriptpath
2374         #!/sbin/sh
2375         # generated by pp $pp_version
2376
2377         svc="$svc"
2378         pidfile="$pidfile"
2379         config_file="$config_file"
2380
2381         pp_start () {
2382             $cmd
2383         }
2384
2385         pp_disabled () {
2386             test \${$sd_config_var:-0} -eq 0
2387         }
2388
2389         pp_stop () {
2390             if test ! -s "$pidfile"; then
2391                 echo "Unable to stop $svc (no pid file)"
2392                 return 1
2393             else
2394                 read pid < "$pidfile"
2395                 if kill -0 "$pid" 2>/dev/null; then
2396                     if kill -${stop_signal:-TERM} "$pid"; then
2397                         rm -f "$pidfile"
2398                         return 0
2399                     else
2400                         echo "Unable to stop $svc"
2401                         return 1
2402                     fi
2403                 else
2404                     rm -f "$pidfile"
2405                     return 0
2406                 fi
2407             fi
2408         }
2409
2410         pp_running () {
2411             if test ! -s "$pidfile"; then
2412                 return 1
2413             else
2414                 read pid < "$pidfile"
2415                 kill -0 "$pid" 2>/dev/null
2416             fi
2417         }
2418
2419         case $1 in
2420             start_msg) echo "Starting the $svc service";;
2421             stop_msg)  echo "Stopping the $svc service";;
2422             start)
2423                     if test -f "$config_file"; then
2424                         . $config_file
2425                     fi
2426                     if pp_disabled; then
2427                         exit 2
2428                     elif pp_running; then
2429                         echo "$svc already running";
2430                         exit 0
2431                     elif pp_start; then
2432                         echo "$svc started";
2433                         # rc(1M) says we should exit 4, but nobody expects it!
2434                         exit 0
2435                     else
2436                         exit 1
2437                     fi;;
2438             stop)   if pp_stop; then
2439                         echo "$svc stopped";
2440                         exit 0
2441                     else
2442                         exit 1
2443                     fi;;
2444             *) echo "usage: $0 {start|stop|start_msg|stop_msg}"
2445                exit 1;;
2446         esac
2447 .
2448     fi
2449 }
2450
2451 pp_sd_make_service () {
2452         typeset level startpriority stoppriority startlevels stoplevels
2453         typeset svc svcvar symtype
2454
2455         svc="$1"
2456         svcvar=`pp_makevar $svc`
2457
2458         case ${pp_sd_os} in
2459             10.*) symtype="file";;
2460             *) symtype="file -t s";;
2461         esac
2462
2463         # TODO: Figure out why this check is here
2464         #-- don't do anything if the script exists
2465         #if test -s "$pp_destdir/sbin/init.d/$svc"; then
2466         #    pp_error "$pp_destdir/sbin/init.d/$svc exists"
2467         #    return
2468         #fi
2469
2470         # symlink the script, depending on the priorities chosen
2471         eval startpriority='${pp_sd_startpriority_'$svcvar'}'
2472         eval stoppriority='${pp_sd_stoppriority_'$svcvar'}'
2473         test -z "$startpriority" && startpriority="${pp_sd_startpriority:-50}"
2474         test -z "$stoppriority" && stoppriority="${pp_sd_stoppriority:-50}"
2475
2476         eval startlevels='${pp_sd_startlevels_'$svcvar'}'
2477         test -z "$startlevels" && startlevels="$pp_sd_startlevels"
2478
2479         eval stoplevels='${pp_sd_stoplevels_'$svcvar'}'
2480         test -z "$stoplevels" && stoplevels="$pp_sd_stoplevels"
2481
2482         # create the script and config file
2483         pp_sd_service_script $svc
2484
2485         # fix the priority up
2486         case "$startpriority" in
2487             ???) :;;
2488             ??) startpriority=0$startpriority;;
2489             ?) startpriority=00$startpriority;;
2490         esac
2491         case "$stoppriority" in
2492             ???) :;;
2493             ??) stoppriority=0$stoppriority;;
2494             ?) stoppriority=00$stoppriority;;
2495         esac
2496
2497         if test x"$stoplevels" = x"auto"; then
2498             stoplevels=
2499             test -z "$startlevels" || for level in $startlevels; do
2500                 stoplevels="$stoplevels `expr $level - 1`"
2501             done
2502         fi
2503
2504         # create the symlinks
2505         test -z "$startlevels" || for level in $startlevels; do
2506             echo "                ${symtype}" \
2507                     "/sbin/init.d/$svc" \
2508                     "/sbin/rc$level.d/S$startpriority$svc"
2509         done
2510         test -z "$stoplevels" || for level in $stoplevels; do
2511             echo "                ${symtype}" \
2512                     "/sbin/init.d/$svc" \
2513                     "/sbin/rc$level.d/K$stoppriority$svc"
2514         done
2515 }
2516
2517 pp_sd_control () {
2518     typeset ctrl script
2519     typeset cpt
2520
2521     ctrl="$1"; shift
2522     cpt="$1"; shift
2523     script="$pp_wrkdir/control.$ctrl.$cpt"
2524     cat <<. >$script
2525 .
2526     cat "$@" >> $script
2527     echo "exit 0" >> $script
2528     /usr/bin/chmod +x $script
2529     echo "                $ctrl $script"
2530 }
2531
2532 pp_backend_sd () {
2533     typeset psf cpt svc outfile release swp_flags
2534
2535     psf=$pp_wrkdir/psf
2536     release="?.${pp_sd_os%.[0-9][0-9]}.*"
2537
2538     echo "depot" > $psf
2539     echo "layout_version 1.0" >>$psf
2540
2541     #-- vendor
2542     cat <<. >>$psf
2543         vendor
2544             tag             $pp_sd_vendor_tag
2545             title           "${pp_sd_vendor:-$vendor}"
2546         end
2547
2548         product
2549             tag             $name
2550             revision        $version
2551             vendor_tag      $pp_sd_vendor_tag
2552             is_patch        false
2553             title           "$summary"
2554             copyright       "$copyright"
2555             machine_type    *
2556             os_name         HP-UX
2557             os_release      $release
2558             os_version      ?
2559             directory       /
2560             is_locatable    false
2561 .
2562     test -n "$description" \
2563         && echo $description > $pp_wrkdir/description \
2564         && cat <<. >> $psf
2565             description     < $pp_wrkdir/description
2566 .
2567
2568     # make convenience service groups
2569     if test -n "$pp_service_groups"; then
2570         for grp in $pp_service_groups; do
2571             pp_sd_service_group_script \
2572                 $grp "`pp_service_get_svc_group $grp`"
2573         done
2574     fi
2575
2576     for cpt in $pp_components; do
2577         cat <<. >>$psf
2578             fileset
2579                 tag             ${pp_sd_fileset_tag:-$cpt}
2580                 title           "${summary:-cpt}"
2581                 revision        $version
2582 .
2583
2584         #-- make sure services are shut down during uninstall
2585         if test $cpt = run -a -n "$pp_services"; then
2586             for svc in $pp_services; do
2587                 pp_prepend $pp_wrkdir/%preun.$cpt <<-.
2588                         /sbin/init.d/$svc stop
2589 .
2590             done
2591         fi
2592
2593         #-- we put the post/preun code into configure/unconfigure
2594         # and not postinstall/preremove, because configure/unconfigure
2595         # scripts are run on the hosts where the package is installed,
2596         # not loaded (a subtle difference).
2597         test -s $pp_wrkdir/%pre.$cpt &&
2598             pp_sd_control checkinstall $cpt $pp_wrkdir/%pre.$cpt >> $psf
2599         test -s $pp_wrkdir/%post.$cpt &&
2600             pp_sd_control configure $cpt $pp_wrkdir/%post.$cpt >> $psf
2601         test -s $pp_wrkdir/%preun.$cpt &&
2602             pp_sd_control unconfigure $cpt $pp_wrkdir/%preun.$cpt >> $psf
2603         test -s $pp_wrkdir/%postun.$cpt &&
2604             pp_sd_control postremove $cpt $pp_wrkdir/%postun.$cpt >> $psf
2605         test -s $pp_wrkdir/%check.$cpt &&
2606             pp_sd_control checkinstall $cpt $pp_wrkdir/%check.$cpt >> $psf
2607
2608         if test $cpt = run -a -n "$pp_services"; then
2609             for svc in $pp_services; do
2610                 #-- service names are 10 chars max on hpux
2611                 case "$svc" in ???????????*)
2612                     pp_warn "service name '$svc' is too long for hpux";;
2613                 esac
2614                 pp_sd_make_service $svc >> $psf
2615             done
2616             #pp_sd_make_service_config
2617         fi
2618
2619         pp_sd_write_files < $pp_wrkdir/%files.$cpt >> $psf
2620
2621         #-- end fileset clause
2622         cat <<. >>$psf
2623             end
2624 .
2625
2626     done
2627
2628     #-- end product clause
2629     cat <<. >>$psf
2630         end
2631 .
2632
2633     $pp_opt_debug && cat $psf >&2
2634
2635     test -s $pp_wrkdir/%fixup && . $pp_wrkdir/%fixup
2636
2637     outfile=`pp_backend_sd_names`
2638     case ${pp_sd_os} in
2639         10.*)
2640             swp_flags="-x target_type=tape"
2641             ;;
2642         *)
2643             swp_flags="-x media_type=tape"
2644             ;;
2645     esac
2646     if pp_verbose ${pp_sd_sudo} /usr/sbin/swpackage -s $psf $swp_flags \
2647         @ $pp_wrkdir/$outfile
2648     then
2649         pp_verbose ${pp_sd_sudo} /usr/sbin/swlist -l file -s $pp_wrkdir/$outfile
2650     else
2651         pp_error "swpackage failed"
2652     fi
2653 }
2654
2655 pp_backend_sd_cleanup () {
2656     :
2657 }
2658
2659 pp_backend_sd_names () {
2660     echo "$name-$version.$pp_sd_arch_std.depot"
2661 }
2662
2663 pp_backend_sd_install_script () {
2664     typeset pkgname platform
2665
2666     pkgname=`pp_backend_sd_names`
2667     platform="`pp_backend_sd_probe`"
2668
2669     echo "#!/bin/sh"
2670     pp_install_script_common
2671     cat <<.
2672
2673         cpt_to_tags () {
2674             test x"\$*" = x"all" && set -- $pp_components
2675             for cpt
2676             do
2677                 echo "$name.\$cpt"
2678             done
2679         }
2680
2681         test \$# -eq 0 && usage
2682         op="\$1"; shift
2683
2684         case "\$op" in
2685             list-components)
2686                 test \$# -eq 0 || usage \$op
2687                 echo "$pp_components"
2688                 ;;
2689             list-services)
2690                 test \$# -eq 0 || usage \$op
2691                 echo "$pp_services"
2692                 ;;
2693             list-files)
2694                 test \$# -ge 1 || usage \$op
2695                 echo \${PP_PKGDESTDIR:-.}/$pkgname
2696                 ;;
2697             install)
2698                 test \$# -ge 1 || usage \$op
2699                 verbose /usr/sbin/swinstall -x verbose=0 \
2700                     -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \
2701                     \`cpt_to_tags "\$@"\`
2702                 ;;
2703             uninstall)
2704                 test \$# -ge 1 || usage \$op
2705                 verbose /usr/sbin/swremove -x verbose=0 \
2706                     \`cpt_to_tags "\$@"\`
2707                 ;;
2708             start|stop)
2709                 test \$# -ge 1 || usage \$op
2710                 ec=0
2711                 for svc
2712                 do
2713                     verbose /sbin/init.d/\$svc \$op
2714                     [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
2715                 done
2716                 exit \$ec
2717                 ;;
2718             print-platform)
2719                 echo "$platform"
2720                 ;;
2721             *)
2722                 usage
2723                 ;;
2724         esac
2725 .
2726 }
2727
2728 pp_backend_sd_probe () {
2729     echo "${pp_sd_os_std}-${pp_sd_arch_std}"
2730 }
2731
2732 pp_backend_sd_vas_platforms () {
2733     case "`pp_backend_sd_probe`" in
2734         hpux*-hppa) echo hpux-pa;;
2735         hpux*-ia64) echo hpux-ia64 hpux-pa;;
2736         *)          pp_die "unknown system `pp_backend_sd_probe`";;
2737     esac
2738 }
2739
2740 pp_backend_sd_init_svc_vars () {
2741     :
2742 }
2743 pp_backend_sd_function () {
2744     case $1 in
2745         pp_mkgroup) cat <<'.';;
2746             /usr/sbin/groupmod "$1" 2>/dev/null ||
2747                 /usr/sbin/groupadd "$1"
2748 .
2749         pp_mkuser:depends) echo pp_mkgroup;;
2750         pp_mkuser) cat <<'.';;
2751             pp_mkgroup "${2:-$1}" || return 1
2752             /usr/sbin/useradd \
2753                 -g "${2:-$1}" \
2754                 -d "${3:-/nonexistent}" \
2755                 -s "${4:-/bin/false}" \
2756                 "$1"
2757 .
2758         pp_havelib) cat <<'.';;
2759             for pp_tmp_dir in `echo /usr/lib${3:+:$3} | tr : ' '`; do
2760                 test -r "$pp_tmp_dir/lib$1${2:+.$2}.sl" && return 0
2761             done
2762             return 1
2763 .
2764         *) false;;
2765     esac
2766 }
2767
2768 pp_platforms="$pp_platforms solaris"
2769
2770 pp_backend_solaris_detect () {
2771         test x"$1" = x"SunOS"
2772 }
2773
2774 pp_backend_solaris_init () {
2775         pp_solaris_category=
2776         pp_solaris_istates="s S 1 2 3"  # run-states when install is ok
2777         pp_solaris_rstates="s S 1 2 3"  # run-states when remove is ok
2778         pp_solaris_maxinst=
2779         pp_solaris_vendor=
2780         pp_solaris_pstamp=
2781         pp_solaris_copyright=
2782         pp_solaris_name=
2783         pp_solaris_desc=
2784         pp_solaris_package_arch=auto
2785
2786         pp_solaris_detect_os
2787         pp_solaris_detect_arch
2788
2789         pp_solaris_init_svc
2790
2791         #-- readlink not reliably available on Solaris
2792         pp_readlink_fn=pp_ls_readlink
2793 }
2794
2795 pp_solaris_detect_os () {
2796         typeset osrel
2797
2798         osrel=`/usr/bin/uname -r`
2799         case "$osrel" in
2800             5.[0-6])    pp_solaris_os="sol2${osrel#5.}";;
2801             5.*)        pp_solaris_os="sol${osrel#5.}";;
2802         esac
2803         test -z "$pp_solaris_os" &&
2804              pp_warn "can't determine OS suffix from uname -r"
2805
2806 }
2807
2808 pp_solaris_detect_arch () {
2809         pp_solaris_arch=`/usr/bin/optisa amd64 sparcv9 i386 sparc`
2810         [ -z "$pp_solaris_arch" ] &&
2811             pp_error "can't determine processor architecture"
2812         case "$pp_solaris_arch" in
2813             amd64)   pp_solaris_arch_std=x86_64;;
2814             i386)    pp_solaris_arch_std=i386;;
2815             sparcv9) pp_solaris_arch_std=sparc64;;
2816             sparc)   pp_solaris_arch_std=sparc;;
2817             *)       pp_solaris_arch_std=unknown;;
2818         esac
2819 }
2820
2821 pp_solaris_is_request_script_necessary () {
2822     typeset has_optional_services
2823
2824     has_optional_services=no
2825     for _svc in $pp_services; do
2826         pp_load_service_vars $_svc
2827         if test "$optional" = "yes"; then
2828             has_optional_services=yes
2829         fi
2830     done
2831
2832     # If the package has no optional services and only one component, don't
2833     # create a request script at all.
2834     if test "$has_optional_services" = "no" &&
2835        test `echo $pp_components | wc -w` -eq 1; then
2836         return 1 # no
2837     fi
2838
2839     return 0 # yes
2840 }
2841
2842 pp_solaris_request () {
2843     typeset _cmp _svc
2844
2845     #-- The common part of the request script contains the ask() function
2846     #   and resets the CLASSES list to empty
2847     cat <<'.'
2848         trap 'exit 3' 15
2849         ask () {
2850            ans=`ckyorn -d "$1" \
2851                 -p "Do you want to $2"` \
2852             || exit $?
2853            case "$ans" in y*|Y*) return 0;; *) return 1;; esac
2854         }
2855         CLASSES=
2856 .
2857     #-- each of our components adds itself to the CLASSES list
2858     for _cmp in $pp_components; do
2859       case "$_cmp" in
2860             run) :;;
2861             doc) echo 'ask y "install the documentation files" &&';;
2862             dev) echo 'ask y "install the development files" &&';;
2863             dbg) echo 'ask n "install the diagnostic files" &&';;
2864       esac
2865       echo '    CLASSES="$CLASSES '$_cmp'"'
2866     done
2867
2868     #-- the request script writes the CLASSES var to its output
2869     cat <<'.'
2870         echo "CLASSES=$CLASSES" > $1
2871 .
2872
2873     if test -n "$pp_services"; then
2874         echo 'SERVICES='
2875         for _svc in $pp_services; do
2876             pp_load_service_vars $_svc
2877             if test "$enable" = "yes"; then
2878                 _default_prompt=y
2879             else
2880                 _default_prompt=n
2881             fi
2882             if test "$optional" = "yes"; then
2883                 echo 'ask '$_default_prompt' "install '$_svc' service" &&'
2884             fi
2885             echo '    SERVICES="$SERVICES '$_svc'"'
2886         done
2887         echo 'echo "SERVICES=$SERVICES" >> $1'
2888     fi
2889
2890 }
2891
2892 pp_solaris_procedure () {
2893     cat <<.
2894
2895         #-- $2 for $1 component of $name
2896         case " \$CLASSES " in *" $1 "*)
2897 .
2898     cat
2899     cat <<.
2900         ;; esac
2901 .
2902 }
2903
2904 pp_solaris_depend () {
2905     typeset _name _vers
2906     while read _name _vers; do
2907         if test -n "$_name"; then
2908             echo "P $_name $_name"
2909             test -n "$_vers" && echo " $_vers"
2910         fi
2911     done
2912 }
2913
2914 pp_solaris_space() {
2915     echo "$2:$3:$1" >> $pp_wrkdir/space.cumulative
2916 }
2917
2918 pp_solaris_sum_space () {
2919     if test -s $pp_wrkdir/space.cumulative; then
2920         sort -t: +2 < $pp_wrkdir/space.cumulative |
2921         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
2922     fi
2923 }
2924
2925 pp_solaris_proto () {
2926         typeset t m o g f p st
2927         typeset abi
2928
2929         while read t m o g f p st; do
2930           if test x"$o" = x"-"; then
2931             o="root"
2932           fi
2933           if test x"$g" = x"-"; then
2934             g="bin"
2935           fi
2936           case "$t" in
2937             f) test x"$m" = x"-" && m=444
2938                case "$f" in
2939                 *v*) echo "v $1 $p=$pp_destdir$p $m $o $g";;
2940                 *)   echo "f $1 $p=$pp_destdir$p $m $o $g";;
2941                esac
2942                if test -r "$pp_destdir$p"; then
2943                   #-- Use file to record ABI types seen
2944                   case "`file "$pp_destdir$p"`" in
2945                     *"ELF 32"*80386*) abi=i386;;
2946                     *"ELF 64"*AMD*) abi=x86_64;;
2947                     *"ELF 32"*SPARC*) abi=sparc;;
2948                     *"ELF 64"*SPARC*) abi=sparc64;;
2949                     *) abi=;;
2950                   esac
2951                   if test -n "$abi"; then
2952                     pp_add_to_list pp_solaris_abis_seen $abi
2953                   fi
2954                fi
2955                ;;
2956             d) test x"$m" = x"-" && m=555
2957                echo "d $1 $p $m $o $g"
2958                ;;
2959             s) test x"$m" = x"-" && m=777
2960                test x"$m" = x"777" ||
2961                   pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
2962                echo "s $1 $p=$st $m $o $g"
2963                ;;
2964           esac
2965         done
2966 }
2967
2968 pp_backend_solaris () {
2969         typeset _cmp _svc _grp
2970
2971         prototype=$pp_wrkdir/prototype
2972         : > $prototype
2973
2974         pkginfo=$pp_wrkdir/pkginfo
2975         : > $pkginfo
2976         echo "i pkginfo=$pkginfo" >> $prototype
2977
2978         case "${pp_solaris_name:-$name}" in
2979             [0-9]*)
2980                 pp_error "Package name '${pp_solaris_name:-$name}'" \
2981                         "cannot start with a number"
2982                 ;;
2983             ???????????????*)
2984                 pp_warn "Package name '${pp_solaris_name:-$name}'" \
2985                         "too long for Solaris 2.6 or 2.7 (max 9 characters)"
2986                 ;;
2987             ??????????*)
2988                 pp_warn "Package name '${pp_solaris_name:-$name}'" \
2989                         "too long for 2.7 Solaris (max 9 characters)"
2990                 ;;
2991         esac
2992
2993         #-- generate the package info file
2994         echo "VERSION=$version" >> $pkginfo
2995         echo "PKG=${pp_solaris_name:-$name}" >> $pkginfo
2996         echo "CLASSES=$pp_components" >> $pkginfo
2997         echo "BASEDIR=/" >> $pkginfo
2998         echo "NAME=$name $version" >> $pkginfo
2999         echo "CATEGORY=${pp_solaris_category:-application}" >> $pkginfo
3000
3001         desc="${pp_solaris_desc:-$description}"
3002         test -n "$desc" &&
3003           echo "DESC=$desc" >> $pkginfo
3004
3005         test -n "$pp_solaris_rstates" &&
3006           echo "RSTATES=$pp_solaris_rstates" >> $pkginfo
3007         test -n "$pp_solaris_istates" &&
3008           echo "ISTATES=$pp_solaris_istates" >> $pkginfo
3009         test -n "$pp_solaris_maxinst" &&
3010           echo "MAXINST=$pp_solaris_maxinst" >> $pkginfo
3011         test -n "${pp_solaris_vendor:-$vendor}" &&
3012           echo "VENDOR=${pp_solaris_vendor:-$vendor}" >> $pkginfo
3013         test -n "$pp_solaris_pstamp" &&
3014           echo "PSTAMP=$pp_solaris_pstamp" >> $pkginfo
3015
3016         if test -n "${pp_solaris_copyright:-$copyright}"; then
3017             echo "${pp_solaris_copyright:-$copyright}" > $pp_wrkdir/copyright
3018             echo "i copyright=$pp_wrkdir/copyright" >> $prototype
3019         fi
3020
3021         #-- scripts to run before and after install
3022         : > $pp_wrkdir/postinstall
3023         : > $pp_wrkdir/preremove
3024         for _cmp in $pp_components; do
3025         #-- add the preinstall scripts in definition order
3026         if test -s $pp_wrkdir/%pre.$_cmp; then
3027             pp_solaris_procedure $_cmp preinst < $pp_wrkdir/%pre.$_cmp \
3028                 >> $pp_wrkdir/preinstall
3029         fi
3030         #-- add the postinstall scripts in definition order
3031         if test -s $pp_wrkdir/%post.$_cmp; then
3032             pp_solaris_procedure $_cmp postinst < $pp_wrkdir/%post.$_cmp \
3033                 >> $pp_wrkdir/postinstall
3034         fi
3035         #-- add the preremove rules in reverse definition order
3036         if test -s $pp_wrkdir/%preun.$_cmp; then
3037             pp_solaris_procedure $_cmp preremove < $pp_wrkdir/%preun.$_cmp |
3038                     pp_prepend $pp_wrkdir/preremove
3039         fi
3040         #-- Add the check script in definition order
3041         if test -s $pp_wrkdir/%check.$_cmp; then
3042             pp_solaris_procedure $_cmp checkinstall \
3043                         < $pp_wrkdir/%check.$_cmp \
3044                         >> $pp_wrkdir/checkinstall
3045         fi
3046         #-- All dependencies are merged together for Solaris pkgs
3047         test -s $pp_wrkdir/%depend.$_cmp &&
3048               pp_solaris_depend < $pp_wrkdir/%depend.$_cmp > $pp_wrkdir/depend
3049         done
3050
3051
3052         if pp_solaris_is_request_script_necessary; then
3053             pp_solaris_request > $pp_wrkdir/request
3054         fi
3055
3056         test -n "$pp_services" &&
3057             for _svc in $pp_services; do
3058                 pp_load_service_vars $_svc
3059                 pp_solaris_smf $_svc
3060                 pp_solaris_make_service $_svc
3061                 pp_solaris_install_service $_svc | pp_prepend $pp_wrkdir/postinstall
3062                 pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/preremove
3063                 unset pp_svc_xml_file
3064             done
3065
3066         test -n "$pp_service_groups" &&
3067             for _grp in $pp_service_groups; do
3068                 pp_solaris_make_service_group \
3069                     $_grp "`pp_service_get_svc_group $_grp`"
3070             done
3071
3072         #-- if installf was used; we need to indicate a termination
3073         grep installf $pp_wrkdir/postinstall >/dev/null &&
3074             echo 'installf -f $PKGINST' >> $pp_wrkdir/postinstall
3075
3076         pp_solaris_sum_space
3077
3078         # NB: pkginfo and copyright are added earlier
3079         for f in compver depend space checkinstall \
3080                  preinstall request postinstall \
3081                  preremove postremove; do
3082             if test -s $pp_wrkdir/$f; then
3083                 case $f in
3084                     *install|*remove|request)
3085                         # turn scripts into a proper shell scripts
3086                         mv $pp_wrkdir/$f $pp_wrkdir/$f.tmp
3087                         { echo "#!/bin/sh";
3088                           echo "# $f script for ${pp_solaris_name:-$name}-$version"
3089                           cat $pp_wrkdir/$f.tmp
3090                           echo "exit 0"; } > $pp_wrkdir/$f
3091                         chmod +x $pp_wrkdir/$f
3092                         rm -f $pp_wrkdir/$f.tmp
3093                         ;;
3094                 esac
3095                 if $pp_opt_debug; then
3096                     pp_debug "contents of $f:"
3097                     cat $pp_wrkdir/$f >&2
3098                 fi
3099                 echo "i $f=$pp_wrkdir/$f" >> $prototype
3100             fi
3101         done
3102
3103         #-- create the prototype file which lists the files to install
3104         # do this as late as possible because files could be added
3105         pp_solaris_abis_seen=
3106         for _cmp in $pp_components; do
3107           pp_solaris_proto $_cmp < $pp_wrkdir/%files.$_cmp
3108         done >> $prototype
3109
3110         if test x"$pp_solaris_package_arch" = x"auto"; then
3111             if pp_contains "$pp_solaris_abis_seen" sparc64; then
3112                 pp_solaris_package_arch_std="sparc64"
3113                 echo "ARCH=sparcv9" >> $pkginfo
3114             elif pp_contains "$pp_solaris_abis_seen" sparc; then
3115                 pp_solaris_package_arch_std="sparc"
3116                 echo "ARCH=sparc" >> $pkginfo
3117             elif pp_contains "$pp_solaris_abis_seen" x86_64; then
3118                 pp_solaris_package_arch_std="x86_64"
3119                 echo "ARCH=amd64" >> $pkginfo
3120             elif pp_contains "$pp_solaris_abis_seen" i386; then
3121                 pp_solaris_package_arch_std="i386"
3122                 echo "ARCH=i386" >> $pkginfo
3123             else
3124                 pp_warn "No ELF files found: not supplying an ARCH type"
3125                 pp_solaris_package_arch_std="noarch"
3126             fi
3127         else
3128             pp_solaris_package_arch_std="$pp_solaris_package_arch"
3129             echo "ARCH=$pp_solaris_package_arch" >> $pkginfo
3130         fi
3131
3132         mkdir $pp_wrkdir/pkg
3133
3134         . $pp_wrkdir/%fixup
3135
3136 if $pp_opt_debug; then
3137   echo "$pkginfo::"; cat $pkginfo
3138   echo "$prototype::"; cat $prototype
3139 fi >&2
3140
3141         pkgmk -d $pp_wrkdir/pkg -f $prototype \
3142                 || { error "pkgmk failed"; return; }
3143         pkgtrans -s $pp_wrkdir/pkg \
3144                 $pp_wrkdir/`pp_backend_solaris_names` \
3145                 ${pp_solaris_name:-$name} \
3146                 || { error "pkgtrans failed"; return; }
3147 }
3148
3149 pp_backend_solaris_cleanup () {
3150         :
3151 }
3152
3153 pp_backend_solaris_names () {
3154         echo ${pp_solaris_name:-$name}-$version-${pp_solaris_package_arch_std:-$pp_solaris_arch}.pkg
3155 }
3156
3157 pp_backend_solaris_install_script () {
3158         typeset pkgname platform
3159
3160         platform="${pp_solaris_os:-solaris}-${pp_solaris_package_arch_std:-$pp_solaris_arch}"
3161
3162         echo "#! /sbin/sh"
3163         pp_install_script_common
3164         pkgname=`pp_backend_solaris_names`
3165
3166         cat <<.
3167             tmpnocheck=/tmp/nocheck\$\$
3168             tmpresponse=/tmp/response\$\$
3169             trap 'rm -f \$tmpnocheck \$tmpresponse' 0
3170
3171             make_tmpfiles () {
3172                 cat <<-.. > \$tmpresponse
3173                         CLASSES=\$*
3174                         SERVICES=$pp_services
3175 ..
3176                 cat <<-.. > \$tmpnocheck
3177                         mail=
3178                         instance=overwrite
3179                         partial=nocheck
3180                         runlevel=nocheck
3181                         idepend=nocheck
3182                         rdepend=nocheck
3183                         space=nocheck
3184                         setuid=nocheck
3185                         conflict=nocheck
3186                         action=nocheck
3187                         basedir=default
3188 ..
3189             }
3190
3191             test \$# -eq 0 && usage
3192             op="\$1"; shift
3193
3194             case "\$op" in
3195                 list-components)
3196                     test \$# -eq 0 || usage \$op
3197                     echo "$pp_components"
3198                     ;;
3199                 list-services)
3200                     test \$# -eq 0 || usage \$op
3201                     echo "$pp_services"
3202                     ;;
3203                 list-files)
3204                     test \$# -ge 1 || usage \$op
3205                     echo \${PP_PKGDESTDIR:-.}/$pkgname
3206                     ;;
3207                 install)
3208                     test \$# -ge 1 || usage \$op
3209                     make_tmpfiles "\$@"
3210                     verbose /usr/sbin/pkgadd -n -d \${PP_PKGDESTDIR:-.}/$pkgname \
3211                         -r \$tmpresponse \
3212                         -a \$tmpnocheck \
3213                         ${pp_solaris_name:-$name}
3214                     ;;
3215                 uninstall)
3216                     test \$# -ge 1 || usage \$op
3217                     make_tmpfiles "\$@"
3218                     verbose /usr/sbin/pkgrm -n \
3219                         -a \$tmpnocheck \
3220                         ${pp_solaris_name:-$name}
3221                     ;;
3222                 start|stop)
3223                     test \$# -ge 1 || usage \$op
3224                     ec=0
3225                     for svc
3226                     do
3227                         verbose /etc/init.d/\$svc \$op || ec=1
3228                     done
3229                     exit \$ec
3230                     ;;
3231                 print-platform)
3232                     echo "$platform"
3233                     ;;
3234                 *)
3235                     usage
3236                     ;;
3237             esac
3238 .
3239 }
3240
3241 pp_solaris_dynlib_depend () {
3242         xargs ldd 2>/dev/null |
3243         sed -e '/^[^    ]*:$/d' -e 's,.*=>[      ]*,,' -e 's,^[         ]*,,' |
3244         sort -u |
3245         grep -v '^/usr/platform/' | (
3246           set -- ""; shift
3247           while read p; do
3248             set -- "$@" -p "$p"
3249             if [ $# -gt 32 ]; then
3250                 echo "$# is $#" >&2
3251                 pkgchk -l "$@"
3252                 set -- ""; shift
3253             fi
3254           done
3255           [ $# -gt 0 ] && pkgchk -l "$@"
3256         )|
3257         awk '/^Current status:/{p=0} p==1 {print $1} /^Referenced by/ {p=1}' |
3258         sort -u |
3259         xargs -l32 pkginfo -x |
3260         awk 'NR % 2 == 1 { name=$1; } NR%2 == 0 { print name, $2 }'
3261 }
3262
3263 pp_solaris_add_dynlib_depends () {
3264     typeset tmp
3265     tmp=$pp_wrkdir/tmp.dynlib
3266
3267     for _cmp in $pp_components; do
3268         awk '{print destdir $6}' destdir="$pp_destdir" \
3269                 < $pp_wrkdir/%files.$_cmp |
3270         pp_solaris_dynlib_depend > $tmp
3271         if test -s $tmp; then
3272             cat $tmp >> $pp_wrkdir/%depend.$_cmp
3273         fi
3274         rm -f $tmp
3275     done
3276 }
3277
3278 pp_backend_solaris_probe () {
3279     echo "${pp_solaris_os}-${pp_solaris_arch_std}"
3280 }
3281
3282 pp_backend_solaris_vas_platforms () {
3283     case `pp_backend_solaris_probe` in
3284         sol10-sparc* | sol9-sparc* | sol8-sparc*)
3285                         echo solaris8-sparc solaris7-sparc solaris26-sparc;;
3286         sol7-sparc*)    echo                solaris7-sparc solaris26-sparc;;
3287         sol26-sparc*)   echo                               solaris26-sparc;;
3288         sol8-*86)       echo solaris8-x86;;
3289         sol10-*86 | sol10-x86_64)
3290                         echo solaris10-x64 solaris8-x86;;
3291         *)              pp_die "unknown system `pp_backend_solaris_probe`";;
3292     esac
3293 }
3294 pp_backend_solaris_function() {
3295     case $1 in
3296         pp_mkgroup) cat<<'.';;
3297             /usr/sbin/groupmod "$1" 2>/dev/null && return 0
3298             /usr/sbin/groupadd "$1"
3299 .
3300         pp_mkuser:depends) echo pp_mkgroup;;
3301         pp_mkuser) cat<<'.';;
3302             id "$1" >/dev/null 2>/dev/null && return 0
3303             pp_mkgroup "${2:-$1}" || return 1
3304             /usr/sbin/useradd \
3305                 -g "${2:-$1}" \
3306                 -d "${3:-/nonexistent}" \
3307                 -s "${4:-/bin/false}" \
3308                 "$1"
3309 .
3310     *) false;;
3311     esac
3312 }
3313
3314 pp_backend_solaris_init_svc_vars () {
3315     _smf_category=${pp_solaris_smf_category:-application}
3316     _smf_method_envvar_name=${smf_method_envvar_name:-"PP_SMF_SERVICE"}
3317     pp_solaris_service_shell=/sbin/sh
3318 }
3319
3320 pp_solaris_init_svc () {
3321     smf_version=1
3322     smf_type=service
3323     solaris_user=
3324     solaris_stop_signal=
3325     solaris_sysv_init_start=S70     # invocation order for start scripts
3326     solaris_sysv_init_kill=K30      # invocation order for kill scripts
3327     solaris_sysv_init_start_states="2" # states to install start link
3328     solaris_sysv_init_kill_states="S 0 1"  # states to install kill link
3329
3330     #
3331     # To have the service be installed to start automatically,
3332     #   %service foo
3333     #   solaris_sysv_init_start_states="S 0 1 2"
3334     #
3335 }
3336
3337 pp_solaris_smf () {
3338     typeset f _pp_solaris_service_script svc _pp_solaris_manpage
3339
3340     pp_solaris_name=${pp_solaris_name:-$name}
3341     pp_solaris_manpath=${pp_solaris_manpath:-"/usr/share/man"}
3342     smf_start_timeout=${smf_start_timeout:-60}
3343     smf_stop_timeout=${smf_stop_timeout:-60}
3344     smf_restart_timeout=${smf_restart_timeout:-60}
3345
3346     svc=${pp_solaris_smf_service_name:-$1}
3347     _pp_solaris_service_script=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3348     _pp_solaris_manpage=${pp_solaris_manpage:-$pp_solaris_smf_service_name}
3349
3350     if [ -z $pp_svc_xml_file ]; then
3351         pp_svc_xml_file="/var/svc/manifest/$_smf_category/$svc.xml"
3352         echo "## Generating the smf service manifest file for $pp_svc_xml_file"
3353     else
3354         echo "## SMF service manifest file already defined at $pp_svc_xml_file"
3355         if [ -z $pp_solaris_smf_service_name ] || [ -z $pp_solaris_smf_category ] || [ -z $pp_solaris_service_script ] || [ -z $smf_method_envvar_name ]; then
3356           pp_error "All required variables are not set.\n"\
3357                    "When using a custom manifest file all of the following variables must be set:\n"\
3358                    "pp_solaris_smf_service_name, pp_solaris_smf_category, pp_solaris_service_script and smf_method_envvar_name.\n\n"\
3359                    "Example:\n"\
3360                    " \$pp_solaris_smf_category=application\n"\
3361                    " \$pp_solaris_smf_service_name=pp\n\n"\
3362                    "  <service name='application/pp' type='service' version='1'>\n\n"\
3363                    "Example:\n"\
3364                    " \$pp_solaris_service_script=/etc/init.d/pp\n\n"\
3365                    "  <exec_method type='method' name='start' exec='/etc/init.d/pp' />\n\n"\
3366                    "Example:\n"\
3367                    " \$smf_method_envvar_name=PP_SMF_SERVICE\n\n"\
3368                    "  <method_environment>\n"\
3369                    "    <envvar name='PP_SMF_SERVICE' value='1'/>\n"\
3370                    "  </method_environment>\n"
3371
3372           return 1
3373         fi
3374         return 0
3375     fi
3376
3377     f=$pp_svc_xml_file
3378     pp_add_file_if_missing $f ||
3379         return 0
3380
3381     _pp_solaris_smf_dependencies="
3382           <dependency name='pp_local_filesystems'
3383                 grouping='require_all'
3384                 restart_on='none'
3385                 type='service'>
3386                 <service_fmri value='svc:/system/filesystem/local'/>
3387           </dependency>
3388
3389           <dependency name='pp_single-user'
3390                 grouping='require_all'
3391                 restart_on='none'
3392                 type='service'>
3393                 <service_fmri value='svc:/milestone/single-user' />
3394           </dependency>
3395 "
3396     _pp_solaris_smf_dependencies=${pp_solaris_smf_dependencies:-$_pp_solaris_smf_dependencies}
3397
3398     cat <<-. >$pp_destdir$f
3399 <?xml version="1.0"?>
3400 <!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
3401 <!--
3402         $copyright
3403         Generated by PolyPackage $pp_version
3404 -->
3405
3406     <service_bundle type='manifest' name='${pp_solaris_name}:${svc}' >
3407           <service name='$_smf_category/$svc'
3408                 type='$smf_type'
3409                 version='$smf_version'>
3410
3411           <create_default_instance enabled='false'/>
3412
3413           <single_instance />
3414
3415           $_pp_solaris_smf_dependencies
3416
3417           $pp_solaris_smf_additional_dependencies
3418
3419           <method_context>
3420                 <method_credential user='${solaris_user:-$user}' />
3421                 <method_environment>
3422                     <envvar name='$_smf_method_envvar_name' value='1'/>
3423                 </method_environment>
3424           </method_context>
3425
3426           <exec_method type='method' name='start'
3427                 exec='$_pp_solaris_service_script start'
3428                 timeout_seconds='$smf_start_timeout' />
3429
3430           <exec_method type='method' name='stop'
3431                 exec='$_pp_solaris_service_script stop'
3432                 timeout_seconds='$smf_stop_timeout' />
3433
3434           <exec_method type='method' name='restart'
3435                 exec='$_pp_solaris_service_script restart'
3436                 timeout_seconds='$smf_restart_timeout' />
3437
3438           <template>
3439               <common_name>
3440                   <loctext xml:lang='C'>$description</loctext>
3441               </common_name>
3442               <documentation>
3443                   <manpage title='$pp_solaris_manpage' section='1' manpath='$pp_solaris_manpath'/>
3444               </documentation>
3445           </template>
3446         </service>
3447     </service_bundle>
3448 .
3449 }
3450
3451 pp_solaris_make_service_group () {
3452     typeset group out file svcs svc
3453
3454     group="$1"
3455     svcs="$2"
3456     file="/etc/init.d/$group"
3457     out="$pp_destdir$file"
3458
3459     #-- return if the script is supplued already
3460     pp_add_file_if_missing "$file" run 755 || return 0
3461
3462     echo "#! /sbin/sh" > $out
3463     echo "# polypkg service group script for these services:" >> $out
3464     echo "svcs=\"$svcs\"" >> $out
3465
3466     cat <<'.' >>$out
3467
3468         #-- starts services in order.. stops them all if any break
3469         pp_start () {
3470             undo=
3471             for svc in $svcs; do
3472                 if /etc/init.d/$svc start; then
3473                     undo="$svc $undo"
3474                 else
3475                     if test -n "$undo"; then
3476                         for svc in $undo; do
3477                            /etc/init.d/$svc stop
3478                         done
3479                         return 1
3480                     fi
3481                 fi
3482             done
3483             return 0
3484         }
3485
3486         #-- stops services in reverse
3487         pp_stop () {
3488             reverse=
3489             for svc in $svcs; do
3490                 reverse="$svc $reverse"
3491             done
3492             rc=0
3493             for svc in $reverse; do
3494                 /etc/init.d/$svc stop || rc=$?
3495             done
3496             return $rc
3497         }
3498
3499         #-- returns true only if all services return true status
3500         pp_status () {
3501             rc=0
3502             for svc in $svcs; do
3503                 /etc/init.d/$svc status || rc=$?
3504             done
3505             return $rc
3506         }
3507
3508         case "$1" in
3509             start)   pp_start;;
3510             stop)    pp_stop;;
3511             status)  pp_status;;
3512             restart) pp_stop && pp_start;;
3513             *)       echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
3514         esac
3515 .
3516 }
3517
3518 pp_solaris_make_service () {
3519     typeset file out _cmd svc
3520
3521     svc="${pp_solaris_smf_service_name:-$1}"
3522     file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3523     out="$pp_destdir$file"
3524
3525     #-- return if we don't need to create the init script
3526     pp_add_file_if_missing "$file" run 755 ||
3527         return 0
3528
3529     echo "#! /sbin/sh" >$out
3530     echo "#-- This service init file generated by polypkg" >>$out
3531
3532     #-- Start SMF integration.
3533     if [ -n "$pp_svc_xml_file" ] ; then
3534         cat <<_EOF >>$out
3535 if [ -x /usr/sbin/svcadm ] && [ "x\$1" != "xstatus" ] && [ "t\$$_smf_method_envvar_name" = "t" ] ; then
3536     case "\$1" in
3537         start)
3538             echo "starting $svc"
3539             /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1
3540             /usr/sbin/svcadm enable -s $_smf_category/$svc
3541             RESULT=\$?
3542             if [ "\$RESULT" -ne 0 ] ; then
3543                 echo "Error \$RESULT starting $svc"
3544                 fi
3545             ;;
3546         stop)
3547             echo "stopping $svc"
3548             /usr/sbin/svcadm disable -ts $_smf_category/$svc
3549             ;;
3550         restart)
3551             echo "restarting $svc"
3552             /usr/sbin/svcadm disable -ts $_smf_category/$svc
3553             /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1
3554             /usr/sbin/svcadm enable -s $_smf_category/$svc
3555             RESULT=\$?
3556             if [ "\$RESULT" -ne 0 ] ; then
3557                 echo "Error \$RESULT starting $svc"
3558                     fi
3559                     ;;
3560         *)
3561             echo "Usage: $file {start|stop|restart|status}"
3562             exit 1
3563     esac
3564     exit 0
3565 fi
3566 _EOF
3567     fi
3568
3569     #-- construct a start command that builds a pid file as needed
3570     #   and forks the daemon
3571     _cmd="$cmd";
3572     if test -z "$pidfile"; then
3573         # The service does not define a pidfile, so we have to make
3574         # our own up. On Solaris systems where there is no /var/run
3575         # we must use /tmp to guarantee the pid files are removed after
3576         # a system crash.
3577         cat <<. >>$out
3578             pp_piddir="/var/run"
3579             test -d "\$pp_piddir/." || pp_piddir="/tmp"
3580             pidfile="\$pp_piddir/$svc.pid"
3581 .
3582         _cmd="$cmd & echo \$! > \$pidfile"
3583     else
3584         # The service is able to write its own PID file
3585         cat <<. >>$out
3586             pidfile="$pidfile"
3587 .
3588     fi
3589
3590     if test "${user:-root}" != "root"; then
3591         _cmd="su $user -c exec $_cmd";
3592     fi
3593
3594     cat <<. >>$out
3595         stop_signal="${stop_signal:-TERM}"
3596         svc="${svc}"
3597
3598         # generated command to run $svc as a daemon process
3599         pp_exec () { $_cmd; }
3600 .
3601
3602     #-- write the invariant section of the init script
3603     cat <<'.' >>$out
3604
3605         # returns true if $svc is running
3606         pp_running () {
3607             test -r "$pidfile" &&
3608             read pid junk < "$pidfile" &&
3609             test ${pid:-0} -gt 1 &&
3610             kill -0 "$pid" 2>/dev/null
3611         }
3612
3613         # prints a message describing $svc's running state
3614         pp_status () {
3615             if pp_running; then
3616                 echo "service $svc is running (pid $pid)"
3617                 return 0
3618             elif test -f "$pidfile"; then
3619                 echo "service $svc is not running, but pid file exists"
3620                 return 2
3621             else
3622                 echo "service $svc is not running"
3623                 return 1
3624             fi
3625         }
3626
3627         # starts $svc
3628         pp_start () {
3629             if pp_running; then
3630                 echo "service $svc already running" >&2
3631                 return 0
3632             fi
3633             echo "starting $svc... \c"
3634             if pp_exec; then
3635                 echo "done."
3636             else
3637                 echo "ERROR."
3638                 exit 1
3639             fi
3640         }
3641
3642         # stops $svc
3643         pp_stop () {
3644             if pp_running; then
3645                 echo "stopping $svc... \c"
3646                 if kill -$stop_signal $pid; then
3647                     rm -f "$pidfile"
3648                     echo "done."
3649                 else
3650                     echo "ERROR."
3651                     return 1
3652                 fi
3653             else
3654                 echo "service $svc already stopped" >&2
3655                 return 0
3656             fi
3657         }
3658
3659         umask 022
3660         case "$1" in
3661             start)   pp_start;;
3662             stop)    pp_stop;;
3663             status)  pp_status;;
3664             restart) pp_stop && pp_start;;
3665             *)       echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
3666         esac
3667 .
3668 }
3669
3670 pp_solaris_remove_service () {
3671     typeset file svc
3672
3673     svc="${pp_solaris_smf_service_name:-$1}"
3674     file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3675
3676     echo '
3677 '$file' stop >/dev/null 2>/dev/null
3678 if [ "x${PKG_INSTALL_ROOT}" = 'x' ]; then
3679     if [ -x /usr/sbin/svcadm ] ; then
3680         # Likely un-needed, but just in case.
3681         /usr/sbin/svcadm disable -s '$svc' 2>/dev/null
3682         /usr/sbin/svccfg delete '$svc' 2>/dev/null
3683     fi
3684 fi
3685     '
3686 }
3687
3688 pp_solaris_install_service () {
3689     typeset s k l file svc
3690
3691     svc="${pp_solaris_smf_service_name:-$1}"
3692     file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"}
3693
3694     s="${solaris_sysv_init_start}$svc"
3695     k="${solaris_sysv_init_kill}$svc"
3696
3697     echo '
3698 if [ "x${PKG_INSTALL_ROOT}" != "x" ]; then
3699   if [ -x ${PKG_INSTALL_ROOT}/usr/sbin/svcadm ]; then
3700     echo "/usr/sbin/svccfg import '$pp_svc_xml_file' 2>/dev/null" >> ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade
3701   else'
3702     test -n "${solaris_sysv_init_start_states}" &&
3703         for state in ${solaris_sysv_init_start_states}; do
3704             l="/etc/rc$state.d/$s"
3705             echo "echo '$l'"
3706             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3707             pp_solaris_space /etc/rc$state.d 0 1
3708         done
3709     test -n "${solaris_sysv_init_kill_states}" &&
3710         for state in ${solaris_sysv_init_kill_states}; do
3711             l="/etc/rc$state.d/$k"
3712             echo "echo '$l'"
3713             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3714             pp_solaris_space /etc/rc$state.d 0 1
3715         done
3716     echo '
3717   fi
3718 else
3719     if [ -x /usr/sbin/svcadm ]; then
3720         echo "Registering '$svc' with SMF"
3721         /usr/sbin/svcadm disable -s '$svc' 2>/dev/null
3722         /usr/sbin/svccfg delete '$svc' 2>/dev/null
3723         /usr/sbin/svccfg import '$pp_svc_xml_file'
3724     else'
3725     test -n "${solaris_sysv_init_start_states}" &&
3726         for state in ${solaris_sysv_init_start_states}; do
3727             l="/etc/rc$state.d/$s"
3728             echo "echo '$l'"
3729             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3730             pp_solaris_space /etc/rc$state.d 0 1
3731         done
3732     test -n "${solaris_sysv_init_kill_states}" &&
3733         for state in ${solaris_sysv_init_kill_states}; do
3734             l="/etc/rc$state.d/$k"
3735             echo "echo '$l'"
3736             echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=$file s"
3737             pp_solaris_space /etc/rc$state.d 0 1
3738         done
3739     echo '
3740     fi
3741 fi'
3742 }
3743
3744 pp_platforms="$pp_platforms deb"
3745
3746 pp_backend_deb_detect () {
3747     test -f /etc/debian_version
3748 }
3749
3750 pp_deb_cmp_full_name () {
3751     local prefix
3752     prefix="${pp_deb_name:-$name}"
3753     case "$1" in
3754         run) echo "${prefix}" ;;
3755         dbg) echo "${prefix}-${pp_deb_dbg_pkgname}";;
3756         dev) echo "${prefix}-${pp_deb_dev_pkgname}";;
3757         doc) echo "${prefix}-${pp_deb_doc_pkgname}";;
3758         *)   pp_error "unknown component '$1'";
3759     esac
3760 }
3761
3762 pp_backend_deb_init () {
3763     pp_deb_dpkg_version="2.0"
3764     pp_deb_name=
3765     pp_deb_version=
3766     pp_deb_release=
3767     pp_deb_arch=
3768     pp_deb_arch_std=
3769     pp_deb_maintainer=support@quest.com
3770     pp_deb_copyright=
3771     pp_deb_distro=
3772     pp_deb_control_description=
3773     pp_deb_summary=
3774     pp_deb_description=
3775     pp_deb_dbg_pkgname="dbg"
3776     pp_deb_dev_pkgname="dev"
3777     pp_deb_doc_pkgname="doc"
3778     pp_deb_section=contrib # Free software that depends on non-free software
3779
3780     # Detect the host architecture
3781     pp_deb_detect_arch
3782
3783     # Make sure any programs we require are installed
3784     pp_deb_check_required_programs
3785
3786     # Set generated/interrogated platforms variables
3787     pp_deb_munge_description
3788 }
3789
3790 pp_deb_check_required_programs () {
3791     local p needed notfound ok
3792     needed= notfound=
3793     for prog in dpkg dpkg-deb install md5sum fakeroot
3794     do
3795         if which $prog 2>/dev/null >/dev/null; then
3796             pp_debug "$prog: found"
3797         else
3798             pp_debug "$prog: not found"
3799             case "$prog" in
3800                 dpkg|dpkg-deb)  p=dpkg;;
3801                 install|md5sum) p=coreutils;;
3802                 fakeroot)       p=fakeroot;;
3803                 *)              pp_die "unexpected dpkg tool $prog";;
3804             esac
3805             notfound="$notfound $prog"
3806             pp_contains "$needed" "$p" || needed="$needed $p"
3807         fi
3808     done
3809     if [ -n "$notfound" ]; then
3810         pp_error "cannot find these programs: $notfound"
3811         pp_error "please install these packages: $needed"
3812     fi
3813 }
3814
3815 pp_deb_munge_description () {
3816     # Insert a leading space on each line, replace blank lines with a
3817     #space followed by a full-stop.
3818     pp_deb_control_description=`echo ${pp_deb_description:-$description} | \
3819         sed "s,^\(.*\)$, \1, " \
3820         | sed "s,^[ \t]*$, .,g"`
3821
3822 }
3823
3824 pp_deb_detect_arch () {
3825    pp_deb_arch=`dpkg --print-architecture`
3826    pp_deb_arch_std=`uname -m`
3827 }
3828
3829 pp_deb_sanitize_version() {
3830     echo "$@" | tr -d -c '[:alnum:].+-:~'
3831 }
3832
3833 pp_deb_version_final() {
3834     if test -n "$pp_deb_version"; then
3835         # Don't sanitize; assume the user is sane (hah!)
3836         echo "$pp_deb_version"
3837     else
3838         pp_deb_sanitize_version "$version"
3839     fi
3840 }
3841
3842 pp_deb_make_control() {
3843     package_name=`pp_deb_cmp_full_name "$1"`
3844     cat <<-.
3845         Package: ${package_name}
3846         Version: `pp_deb_version_final`-${pp_deb_release:-1}
3847         Section: ${pp_deb_section:-contrib}
3848         Priority: optional
3849         Architecture: ${pp_deb_arch}
3850         Maintainer: ${pp_deb_maintainer:-$maintainer}
3851         Description: ${pp_deb_summary:-$summary}
3852         ${pp_deb_control_description}
3853 .
3854     if test -s $pp_wrkdir/%depend."$1"; then
3855         sed -ne '/^[    ]*$/!s/^[       ]*/Depends: /p' \
3856             < $pp_wrkdir/%depend."$1"
3857     fi
3858 }
3859
3860 pp_deb_make_md5sums() {
3861     local cmp="$1"; shift
3862     local pkg_dir
3863
3864     pkg_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
3865     (cd $pkg_dir && md5sum "$@") > $pkg_dir/DEBIAN/md5sums ||
3866         pp_error "cannot make md5sums"
3867 }
3868
3869 pp_deb_make_package_maintainer_script() {
3870     local output="$1"
3871     local source="$2"
3872     local desc="$3"
3873
3874     # See if we need to create this script at all
3875     if [ -s "$source" ]
3876     then
3877
3878         # Create header
3879         cat <<-. >$output || pp_error "Cannot create $output"
3880         #!/bin/sh
3881         # $desc
3882         # Generated by PolyPackage $pp_version
3883
3884 .
3885
3886         cat $source >> "$output" || pp_error "Cannot append to $output"
3887
3888         # Set perms
3889         chmod 755 "$output" || pp_error "Cannot chmod $output"
3890     fi
3891 }
3892
3893 pp_deb_handle_services() {
3894     local svc
3895
3896     #-- add service start/stop code
3897     if test -n "$pp_services"; then
3898         #-- record the uninstall commands in reverse order
3899         for svc in $pp_services; do
3900             pp_load_service_vars $svc
3901
3902             # Create init script (unless one exists)
3903             pp_deb_service_make_init_script $svc
3904
3905             #-- append %post code to install the svc
3906             test x"yes" = x"$enable" &&
3907             cat<<-. >> $pp_wrkdir/%post.run
3908                 # Install the service links
3909                 /usr/sbin/update-rc.d $svc defaults
3910 .
3911
3912             #-- prepend %preun code to stop svc
3913             cat<<-. | pp_prepend $pp_wrkdir/%preun.run
3914                 # Stop the $svc service
3915                 if test -x /usr/sbin/invoke-rc.d; then
3916                     /usr/sbin/invoke-rc.d $svc stop
3917                 else
3918                     /etc/init.d/$svc stop
3919                 fi
3920                 # Remove the service links
3921                 /usr/sbin/update-rc.d -f $svc remove
3922 .
3923         done
3924         #pp_deb_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
3925     fi
3926
3927 }
3928 pp_deb_fakeroot () {
3929     if test -s $pp_wrkdir/fakeroot.save; then
3930         fakeroot -i $pp_wrkdir/fakeroot.save -s $pp_wrkdir/fakeroot.save "$@"
3931     else
3932         fakeroot -s $pp_wrkdir/fakeroot.save "$@"
3933     fi
3934 }
3935
3936 pp_deb_make_DEBIAN() {
3937     local cmp="${1:-run}"
3938     local data cmp_full_name
3939     local old_umask
3940
3941     old_umask=`umask`
3942     umask 0022
3943     cmp_full_name=`pp_deb_cmp_full_name $cmp`
3944     data=$pp_wrkdir/$cmp_full_name
3945
3946     # Create DEBIAN dir $data/DEBIAN
3947     mkdir -p $data/DEBIAN
3948
3949     # Create control file
3950     pp_deb_make_control $cmp > $data/DEBIAN/control
3951
3952     # Copy in conffiles
3953     if test -f $pp_wrkdir/%conffiles.$cmp; then
3954         cp $pp_wrkdir/%conffiles.$cmp $data/DEBIAN/conffiles
3955     fi
3956
3957     # Create postinst
3958     pp_deb_make_package_maintainer_script "$data/DEBIAN/postinst" \
3959         "$pp_wrkdir/%post.$cmp" "Post install script for $cmp_full_name"\
3960         || exit $?
3961
3962     # Create prerm
3963     pp_deb_make_package_maintainer_script "$data/DEBIAN/prerm" \
3964         "$pp_wrkdir/%preun.$cmp" "Pre-uninstall script for $cmp_full_name"\
3965         || exit $?
3966
3967     umask $old_umask
3968 }
3969
3970 pp_deb_make_data() {
3971     local _l t m o g f p st data
3972     local data share_doc owner group
3973     cmp=$1
3974     data=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
3975     cat $pp_wrkdir/%files.${cmp} | while read t m o g f p st; do
3976         test x"$o" = x"-" && o=root
3977         test x"$g" = x"-" && g=root
3978         case "$t" in
3979         f) # Files
3980            pp_deb_fakeroot install -D -o $o -g $g -m ${m} $pp_destdir/$p $data/$p;
3981            if [ x"$f" = x"v" ]
3982            then
3983                # File marked as "volatile". Assume this means it's a conffile
3984                # TODO: check this as admins like modified conffiles to be left
3985                #       behind
3986                echo "$p" >> $pp_wrkdir/%conffiles.$cmp
3987            fi;;
3988
3989         d) # Directories
3990            pp_deb_fakeroot install -m ${m} -o $o -g $g -d $data/$p;;
3991
3992         s) # Symlinks
3993            # Remove leading / from vars
3994            rel_p=`echo $p | sed s,^/,,`
3995            rel_st=`echo $st | sed s,^/,,`
3996            # TODO: we are always doing absolute links here. We should follow
3997            # the debian policy of relative links when in the same top-level
3998            # directory
3999            (cd $data; ln -sf $st $rel_p);;
4000             *) pp_error "Unsupported data file type: $t";;
4001         esac
4002     done
4003
4004     # If no copyright file is present add one. This is a debian requirement.
4005     share_doc="/usr/share/doc/`pp_deb_cmp_full_name $cmp`"
4006     if [ ! -f "$data/$share_doc/copyright" ]
4007     then
4008         echo "${pp_deb_copyright:-$copyright}" > "$pp_wrkdir/copyright"
4009         install -D -m 644 "$pp_wrkdir/copyright" "$data/$share_doc/copyright"
4010     fi
4011
4012 }
4013
4014 pp_deb_makedeb () {
4015     local cmp
4016     local package_build_dir
4017
4018     cmp="$1"
4019
4020     package_build_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
4021
4022     # Create package dir
4023     mkdir -p $package_build_dir
4024
4025     # Copy in data
4026     pp_deb_make_data $cmp ||
4027         pp_die "Could not make DEBIAN data files for $cmp"
4028
4029     # Make control files
4030     # must be done after copying data so conffiles are found
4031     pp_deb_make_DEBIAN $cmp ||
4032         pp_die "Could not make DEBIAN control files for $cmp"
4033
4034     # Create md5sums
4035     pp_deb_make_md5sums $cmp `(cd $package_build_dir;
4036         find . -type f -a -not -name DEBIAN | sed "s,^\./,,")` ||
4037             pp_die "Could not make DEBIAN md5sums for $cmp"
4038 }
4039
4040 pp_backend_deb () {
4041     local debname
4042
4043     # Handle services
4044     pp_deb_handle_services $cmp
4045
4046     for cmp in $pp_components
4047     do
4048         debname=`pp_deb_name $cmp`
4049         pp_deb_makedeb $cmp
4050     done
4051
4052     . $pp_wrkdir/%fixup
4053
4054     for cmp in $pp_components
4055     do
4056         debname=`pp_deb_name $cmp`
4057         # Create debian package
4058         pp_debug "Building `pp_deb_cmp_full_name $cmp` -> $output"
4059         pp_deb_fakeroot dpkg-deb \
4060             --build $pp_wrkdir/`pp_deb_cmp_full_name $cmp` \
4061             $pp_wrkdir/$debname ||
4062                 pp_error "failed to create $cmp package"
4063     done
4064 }
4065
4066 pp_backend_deb_cleanup () {
4067     # rm -rf $pp_wrkdir
4068     :
4069 }
4070
4071 pp_deb_name () {
4072     local cmp="${1:-run}"
4073     echo `pp_deb_cmp_full_name $cmp`"_"`pp_deb_version_final`"-${pp_deb_release:-1}_${pp_deb_arch}.deb"
4074 }
4075 pp_backend_deb_names () {
4076     for cmp in $pp_components
4077     do
4078         pp_deb_name $cmp
4079     done
4080 }
4081
4082 pp_backend_deb_install_script () {
4083     local cmp _cmp_full_name
4084
4085     echo "#!/bin/sh"
4086     pp_install_script_common
4087
4088     cat <<.
4089
4090         cmp_to_pkgname () {
4091             test x"\$*" = x"all" &&
4092                 set -- $pp_components
4093             for cmp
4094             do
4095                 case \$cmp in
4096 .
4097     for cmp in $pp_components; do
4098          echo "$cmp) echo '`pp_deb_cmp_full_name $cmp`';;"
4099     done
4100     cat <<.
4101                 *) usage;;
4102                 esac
4103             done
4104         }
4105
4106
4107         cmp_to_pathname () {
4108             test x"\$*" = x"all" &&
4109                 set -- $pp_components
4110             for cmp
4111             do
4112                 case \$cmp in
4113 .
4114     for cmp in $pp_components; do
4115          echo "$cmp) echo \${PP_PKGDESTDIR:-.}/'`pp_deb_name $cmp`';;"
4116     done
4117     cat <<.
4118                 *) usage;;
4119                 esac
4120             done
4121         }
4122
4123         test \$# -eq 0 && usage
4124         op="\$1"; shift
4125         case "\$op" in
4126             list-components)
4127                 test \$# -eq 0 || usage \$op
4128                 echo $pp_components
4129                 ;;
4130             list-services)
4131                 test \$# -eq 0 || usage \$op
4132                 echo $pp_services
4133                 ;;
4134             list-files)
4135                 test \$# -ge 1 || usage \$op
4136                 cmp_to_pathname "\$@"
4137                 ;;
4138             install)
4139                 test \$# -ge 1 || usage \$op
4140                 dpkg --install \`cmp_to_pathname "\$@"\`
4141                 ;;
4142             uninstall)
4143                 test \$# -ge 1 || usage \$op
4144                 dpkg --remove \`cmp_to_pkgname "\$@"\`; :
4145                 ;;
4146             start|stop)
4147                 test \$# -ge 1 || usage \$op
4148                 ec=0
4149                 for svc
4150                 do
4151                     /etc/init.d/\$svc \$op || ec=1
4152                 done
4153                 exit \$ec
4154                 ;;
4155             print-platform)
4156                 test \$# -eq 0 || usage \$op
4157                 echo "linux-${pp_deb_arch}"
4158                 ;;
4159             *)
4160                 usage
4161                 ;;
4162         esac
4163 .
4164 }
4165
4166 pp_backend_deb_probe() {
4167     local arch distro release
4168
4169     pp_deb_detect_arch
4170
4171     # /etc/debian_version exists on Debian & Ubuntu, so it's no use
4172     # to us. Use lsb_release instead.
4173
4174     case `(lsb_release -is || echo no-lsb) 2>/dev/null` in
4175         Debian)
4176             distro=deb
4177             ;;
4178         Ubuntu)
4179             distro=ubu
4180             ;;
4181         no-lsb)
4182             echo unknown-$pp_deb_arch_std
4183             return 0
4184             ;;
4185         *)
4186             distro=unknown
4187             ;;
4188     esac
4189
4190     release=`lsb_release -rs`
4191
4192     # If release is not numeric, use the codename
4193     case $release in
4194         *[!.0-9r]*)
4195             release=`lsb_release -cs`
4196             case $release in
4197                 buzz)
4198                     release="11"
4199                     ;;
4200                 rex)
4201                     release="12"
4202                     ;;
4203                 bo)
4204                     release="13"
4205                     ;;
4206                 hamm)
4207                     release="20"
4208                     ;;
4209                 slink)
4210                     release="21"
4211                     ;;
4212                 potato)
4213                     release="22"
4214                     ;;
4215                 woody)
4216                     release="30"
4217                     ;;
4218                 sarge)
4219                     release="31"
4220                     ;;
4221                 etch)
4222                     release="40"
4223                     ;;
4224                 lenny)
4225                     release="50"
4226                     ;;
4227                 squeeze)
4228                     release="60"
4229                     ;;
4230             esac
4231             ;;
4232         *)
4233             # Remove trailing revision number and any dots
4234             release=`echo $release | cut -dr -f1 | tr -d .`
4235             ;;
4236     esac
4237
4238     echo $distro$release-$pp_deb_arch_std
4239 }
4240
4241 pp_backend_deb_vas_platforms () {
4242     case "$pp_deb_arch_std" in
4243         x86_64) echo "linux-x86_64.deb";; # DO NOT add linux-x86.deb here!!
4244         *86)    echo "linux-x86.deb";;
4245         *)      pp_die "unknown architecture ${pp_deb_arch_std}";;
4246     esac
4247 }
4248 pp_backend_deb_init_svc_vars () {
4249     # Default multi-user runlevel on Debian is 2; 3-5 are also multi-user
4250     pp_deb_default_start_runlevels="2 3 4 5"
4251     pp_deb_default_svc_description="No description"
4252 }
4253
4254 pp_backend_deb_init_svc_vars () {
4255
4256     reload_signal=
4257     start_runlevels=${pp_deb_default_start_runlevels}   # == lsb default-start
4258     stop_runlevels="0 1 6"                              # == lsb default-stop
4259     svc_description="${pp_deb_default_svc_description}" # == lsb short descr
4260     svc_process=
4261
4262     lsb_required_start='$local_fs $network'
4263     lsb_should_start=
4264     lsb_required_stop=
4265     lsb_description=
4266
4267     start_priority=50
4268     stop_priority=50            #-- stop_priority = 100 - start_priority
4269 }
4270
4271 pp_deb_service_make_init_script () {
4272     local svc=$1
4273     local script=/etc/init.d/$svc
4274     local out=$pp_destdir$script
4275     local _process _cmd
4276
4277     pp_add_file_if_missing $script run 755 || return 0
4278
4279     #-- start out as an empty shell script
4280     cat <<-'.' >$out
4281         #!/bin/sh
4282 .
4283
4284     #-- determine the process name from $cmd unless $svc_process is given
4285     set -- $cmd
4286     #_process=${svc_process:-"$1"} --? WTF
4287
4288     #-- construct a start command that builds a pid file if needed
4289     _cmd="$cmd";
4290     _cmd_path=`echo $cmd | cut -d" " -f1`
4291     _cmd_name=`basename $_cmd_path`
4292     _cmd_args=`echo $cmd | cut -d" " -f2-`
4293     test x"$_cmd_path" != x"$_cmd_args" || _cmd_args=
4294
4295     #-- generate the LSB init info
4296     cat <<-. >>$out
4297         ### BEGIN INIT INFO
4298         # Provides: ${svc}
4299         # Required-Start: ${lsb_required_start}
4300         # Should-Start: ${lsb_should_start}
4301         # Required-Stop: ${lsb_required_stop}
4302         # Default-Start: ${start_runlevels}
4303         # Default-Stop: ${stop_runlevels}
4304         # Short-Description: ${svc_description}
4305         ### END INIT INFO
4306         # Generated by PolyPackage ${pp_version}
4307         # ${copyright}
4308
4309 .
4310
4311     if test x"${svc_description}" = x"${pp_deb_default_svc_description}"; then
4312         svc_description=
4313     fi
4314
4315     #-- write service-specific definitions
4316     cat <<. >>$out
4317 NAME="${_cmd_name}"
4318 DESC="${svc_description:-$svc service}"
4319 USER="${user}"
4320 GROUP="${group}"
4321 PIDFILE="${pidfile}"
4322 STOP_SIGNAL="${stop_signal}"
4323 RELOAD_SIGNAL="${reload_signal}"
4324 CMD="${_cmd}"
4325 DAEMON="${_cmd_path}"
4326 DAEMON_ARGS="${_cmd_args}"
4327 SCRIPTNAME=${script}
4328 .
4329
4330     #-- write the generic part of the init script
4331     cat <<'.' >>$out
4332
4333 [ -x "$DAEMON" ] || exit 0
4334
4335 [ -r /etc/default/$NAME ] && . /etc/default/$NAME
4336
4337 [ -f /etc/default/rcS ] && . /etc/default/rcS
4338
4339 . /lib/lsb/init-functions
4340
4341 do_start()
4342 {
4343         # Return
4344         #   0 if daemon has been started
4345         #   1 if daemon was already running
4346         #   2 if daemon could not be started
4347     if [ -n "$PIDFILE" ]
4348     then
4349         pidfile_opt="--pidfile $PIDFILE"
4350     else
4351         pidfile_opt="--make-pidfile --background --pidfile /var/run/$NAME.pid"
4352     fi
4353     if [ -n "$USER" ]
4354     then
4355         user_opt="--user $USER"
4356     fi
4357     if [ -n "$GROUP" ]
4358     then
4359         group_opt="--group $GROUP"
4360     fi
4361     if [ "$VERBOSE" = no ]
4362     then
4363         quiet_opt="--quiet"
4364     else
4365         quiet_opt="--verbose"
4366     fi
4367
4368         start-stop-daemon --start $quiet_opt $pidfile_opt $user_opt --exec $DAEMON --test > /dev/null \
4369             || return 1
4370
4371     # Note: there seems to be no way to tell whether the daemon will fork itself or not, so pass
4372     # --background for now
4373     start-stop-daemon --start $quiet_opt $pidfile_opt $user_opt --exec $DAEMON -- \
4374         $DAEMON_ARGS \
4375         || return 2
4376 }
4377
4378 do_stop()
4379 {
4380         # Return
4381         #   0 if daemon has been stopped
4382         #   1 if daemon was already stopped
4383         #   2 if daemon could not be stopped
4384         #   other if a failure occurred
4385     if [ -n "$PIDFILE" ]
4386     then
4387         pidfile_opt="--pidfile $PIDFILE"
4388     else
4389         pidfile_opt="--pidfile /var/run/$NAME.pid"
4390     fi
4391     if [ -n "$USER" ]
4392     then
4393         user_opt="--user $USER"
4394     fi
4395     if [ -n $STOP_SIGNAL ]
4396     then
4397         signal_opt="--signal $STOP_SIGNAL"
4398     fi
4399     if [ "$VERBOSE" = "no" ]
4400     then
4401         quiet_opt="--quiet"
4402     else
4403         quiet_opt="--verbose"
4404     fi
4405         start-stop-daemon --stop $quiet_opt $signal_opt --retry=TERM/30/KILL/5 $pidfile_opt --name $NAME
4406         RETVAL="$?"
4407         [ "$RETVAL" = 2 ] && return 2
4408         # Wait for children to finish too if this is a daemon that forks
4409         # and if the daemon is only ever run from this initscript.
4410         # If the above conditions are not satisfied then add some other code
4411         # that waits for the process to drop all resources that could be
4412         # needed by services started subsequently.  A last resort is to
4413         # sleep for some time.
4414         start-stop-daemon --stop $quiet_opt --oknodo --retry=0/30/KILL/5 --exec $DAEMON
4415         [ "$?" = 2 ] && return 2
4416         # Many daemons don't delete their pidfiles when they exit.
4417         test -z $PIDFILE || rm -f $PIDFILE
4418         return "$RETVAL"
4419 }
4420
4421 do_reload() {
4422         #
4423         # If the daemon can reload its configuration without
4424         # restarting (for example, when it is sent a SIGHUP),
4425         # then implement that here.
4426         #
4427     if [ -n "$PIDFILE" ]
4428     then
4429         pidfile_opt="--pidfile $PIDFILE"
4430     else
4431         pidfile_opt="--pidfile /var/run/$NAME.pid"
4432     fi
4433     if [ -n "$RELOAD_SIGNAL" ]
4434     then
4435             start-stop-daemon --stop --signal $RELOAD_SIGNAL $quiet_opt $pidfile_opt --name $NAME
4436     fi
4437         return 0
4438 }
4439
4440 case "$1" in
4441   start)
4442         [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
4443         do_start
4444         case "$?" in
4445                 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
4446                 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
4447         esac
4448         ;;
4449   stop)
4450         [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
4451         do_stop
4452         case "$?" in
4453                 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
4454                 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
4455         esac
4456         ;;
4457   reload|force-reload)
4458     if [ -n "$RELOAD_SIGNAL" ]
4459     then
4460             log_daemon_msg "Reloading $DESC" "$NAME"
4461             do_reload
4462             log_end_msg $?
4463     else
4464         # Do a restart instead
4465         "$0" restart
4466     fi
4467         ;;
4468   restart)
4469         #
4470         # If the "reload" option is implemented then remove the
4471         # 'force-reload' alias
4472         #
4473         log_daemon_msg "Restarting $DESC" "$NAME"
4474         do_stop
4475         case "$?" in
4476           0|1)
4477                 do_start
4478                 case "$?" in
4479                         0) log_end_msg 0 ;;
4480                         1) log_end_msg 1 ;; # Old process is still running
4481                         *) log_end_msg 1 ;; # Failed to start
4482                 esac
4483                 ;;
4484           *)
4485                 # Failed to stop
4486                 log_end_msg 1
4487                 ;;
4488         esac
4489         ;;
4490   *)
4491         #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
4492         echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
4493         exit 3
4494         ;;
4495 esac
4496
4497 :
4498 .
4499     chmod 755 $out
4500 }
4501 pp_backend_deb_function() {
4502     case $1 in
4503         pp_mkgroup) cat<<'.';;
4504             /usr/sbin/groupmod "$1" 2>/dev/null && return 0
4505             /usr/sbin/groupadd "$1"
4506 .
4507         pp_mkuser:depends) echo pp_mkgroup;;
4508         pp_mkuser) cat<<'.';;
4509             pp_tmp_system=
4510             id -u "$1" >/dev/null 2>/dev/null && return 0
4511             # deb 3.1's useradd changed API in 4.0. Gah!
4512             /usr/sbin/useradd --help 2>&1 | /bin/grep -q .--system &&
4513                 pp_tmp_system=--system
4514             pp_mkgroup "${2:-$1}" || return 1
4515             /usr/sbin/useradd \
4516                 -g "${2:-$1}" \
4517                 -d "${3:-/nonexistent}" \
4518                 -s "${4:-/bin/false}" \
4519                 $pp_tmp_system \
4520                 "$1"
4521 .
4522         pp_havelib) cat<<'.';;
4523             for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
4524                 test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
4525             done
4526             return 1
4527 .
4528     *) false;;
4529     esac
4530 }
4531
4532 pp_platforms="$pp_platforms kit"
4533
4534 pp_backend_kit_detect () {
4535     test x"$1" = x"OSF1"
4536 }
4537
4538 pp_backend_kit_init () {
4539         pp_kit_name=
4540         pp_kit_package=
4541         pp_kit_desc=
4542         pp_kit_version=
4543         pp_kit_subset=
4544         pp_readlink_fn=pp_ls_readlink
4545         pp_kit_startlevels="2 3"
4546         pp_kit_stoplevels="0 2 3"
4547 }
4548
4549 pp_backend_kit () {
4550     typeset mi_file k_file svc outfile
4551     typeset desc
4552
4553     pp_backend_kit_names > /dev/null
4554
4555     if test -z "$pp_kit_desc"; then
4556         pp_kit_desc="$description"
4557     fi
4558
4559     mi_file="$pp_wrkdir/$pp_kit_subset.mi"
4560     k_file="$pp_wrkdir/$pp_kit_subset.k"
4561     scp_file="$pp_wrkdir/$pp_kit_subset.scp"
4562
4563     desc="${pp_kit_desc:-$description}"
4564
4565     cat <<-. >> $k_file
4566         NAME='$name'
4567         CODE=$pp_kit_name
4568         VERS=$pp_kit_version
4569         MI=$mi_file
4570         COMPRESS=0
4571         %%
4572         $pp_kit_subset  .       0       '$desc'
4573 .
4574
4575     if test -n "$pp_services"; then
4576         for svc in $pp_services; do
4577             pp_kit_make_service $svc
4578             pp_prepend $pp_wrkdir/%preun.run <<-.
4579                 /sbin/init.d/$svc stop
4580 .
4581          done
4582     fi
4583
4584     pp_backend_kit_make_mi "$mi_file"
4585     pp_backend_kit_make_scp
4586     #rm -rf  $pp_wrkdir/kit_dest
4587     mkdir -p $pp_wrkdir/kit_dest
4588     pp_backend_kit_kits $k_file $pp_opt_destdir $pp_wrkdir/kit_dest
4589     tar cvf $pp_wrkdir/$pp_kit_subset.tar -C $pp_wrkdir/kit_dest .
4590     gzip -c $pp_wrkdir/$pp_kit_subset.tar > $pp_wrkdir/$pp_kit_subset.tar.gz
4591     #rm -rf $pp_wrkdir/$pp_kit_subset.tar $pp_wrkdir/scps
4592 }
4593
4594 pp_backend_kit_make_mi () {
4595     # XXX this information should go into the .inv files
4596     typeset t m o g f p st line dm
4597     while read t m o g f p st; do
4598         case $t in
4599             f|d)
4600                 echo "0 .$p     $pp_kit_subset"
4601                 echo "        chmod $m $p" >> $pp_wrkdir/%post.run
4602                 if [ x"$o" = x"-" ] ; then
4603                     echo "        chown root $p" >> $pp_wrkdir/%post.run
4604                 else
4605                     echo "        chown $o $p" >> $pp_wrkdir/%post.run
4606                 fi
4607                 if [ x"$g" = x"-" ] ; then
4608                     echo "        chgrp 0 $p" >> $pp_wrkdir/%post.run
4609                 else
4610                     echo "        chgrp $g $p" >> $pp_wrkdir/%post.run
4611                 fi
4612                 ;;
4613             s)
4614                 echo "        ln -s $st $p" >> $pp_wrkdir/%post.run
4615                 echo "        rm -f $p" >> $pp_wrkdir/%preun.run
4616                 ;;
4617          esac
4618     done < $pp_wrkdir/%files.run | sort -k3  |uniq > $1
4619 }
4620
4621
4622 pp_backend_kit_make_scp () {
4623     scpdir="$pp_wrkdir/scps"
4624     mkdir "$scpdir" && touch "$scpdir"/$pp_kit_subset.scp
4625     cat <<EOF >"$scpdir"/$pp_kit_subset.scp
4626
4627     . /usr/share/lib/shell/libscp
4628
4629     case "\$ACT" in
4630     PRE_L)
4631     STL_ScpInit
4632
4633
4634
4635     ;;
4636     POST_L)
4637         STL_ScpInit
4638         STL_LinkCreate
4639 EOF
4640
4641     cat $pp_wrkdir/%post.run >>"$scpdir"/$pp_kit_subset.scp
4642     cat >>"$scpdir"/$pp_kit_subset.scp <<EOF
4643     ;;
4644     PRE_D)
4645         STL_ScpInit
4646         STL_LinkRemove
4647 EOF
4648     cat $pp_wrkdir/%preun.run >>"$scpdir"/$pp_kit_subset.scp
4649     cat >>"$scpdir"/$pp_kit_subset.scp <<EOF
4650         ;;
4651     POST_D)
4652
4653         ;;
4654     C)
4655         STL_ScpInit
4656
4657         case "\$1" in
4658         INSTALL)
4659         echo "Installation of the \$_DESC (\$_SUB) subset is complete."
4660         ;;
4661     DELETE)
4662         ;;
4663     esac
4664
4665         ;;
4666     V)
4667
4668         ;;
4669     esac
4670
4671     exit 0
4672 EOF
4673     chmod 744 "$scpdir"/$pp_kit_subset.scp
4674 }
4675
4676
4677 pp_backend_kit_cleanup () {
4678     :
4679 }
4680
4681 pp_backend_kit_names () {
4682     if test -z "$pp_kit_name"; then
4683         pp_warn "pp_kit_name not specified, using XXX"
4684         pp_kit_name=XXX
4685     fi
4686     case "$pp_kit_name" in
4687         ???) : ok;;
4688         *) pp_error "\$pp_kit_name $pp_kit_name must be three characters";;
4689     esac
4690     if test -z "$pp_kit_package"; then
4691         pp_warn "pp_kit_package not specified, using YYYY"
4692         pp_kit_package=YYYY
4693     fi
4694     if test -z "$pp_kit_version"; then
4695         pp_kit_version=`echo $version|tr -d '.a-zA-Z'`
4696     fi
4697     case "$pp_kit_version" in
4698         [0-9]) pp_kit_version="${pp_kit_version}00";;
4699         [0-9][0-9]) pp_kit_version="${pp_kit_version}0";;
4700         [0-9][0-9][0-9]) : ok;;
4701         *) pp_error "\$pp_kit_version $pp_kit_version must be three digits, ";;
4702     esac
4703     if test -z "$pp_kit_subset"; then
4704         pp_kit_subset="$pp_kit_name$pp_kit_package$pp_kit_version"
4705     fi
4706     echo "$pp_kit_subset.tar.gz"
4707 }
4708
4709 pp_backend_kit_install_script () {
4710     typeset pkgname platform
4711
4712     pkgname=`pp_backend_kit_names`
4713     platform="`pp_backend_kit_probe`"
4714
4715     echo "#!/bin/sh"
4716     pp_install_script_common
4717     cat <<.
4718
4719         cpt_to_tags () {
4720             test x"\$*" = x"all" && set -- $pp_components
4721             for cpt
4722             do
4723                 echo "$name.\$cpt"
4724             done
4725         }
4726
4727         test \$# -eq 0 && usage
4728         op="\$1"; shift
4729
4730         case "\$op" in
4731             list-components)
4732                 test \$# -eq 0 || usage \$op
4733                 echo "$pp_components"
4734                 ;;
4735             list-services)
4736                 test \$# -eq 0 || usage \$op
4737                 echo "$pp_services"
4738                 ;;
4739             list-files)
4740                 test \$# -ge 1 || usage \$op
4741                 echo \${PP_PKGDESTDIR:-.}/$pkgname
4742                 ;;
4743             install)
4744                 test \$# -ge 1 || usage \$op
4745                 verbose echo \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\`
4746                 #verbose swinstall -x verbose=0 -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\`
4747                 ;;
4748             uninstall)
4749                 test \$# -ge 1 || usage \$op
4750                 verbose echo \`cpt_to_tags "\$@"\`
4751                 #verbose swremove -x verbose=0 \`cpt_to_tags "\$@"\`
4752                 ;;
4753             start|stop)
4754                 test \$# -ge 1 || usage \$op
4755                 ec=0
4756                 for svc
4757                 do
4758                     verbose /sbin/init.d/\$svc \$op
4759                     [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
4760                 done
4761                 exit \$ec
4762                 ;;
4763             print-platform)
4764                 echo "$platform"
4765                 ;;
4766             *)
4767                 usage
4768                 ;;
4769         esac
4770 .
4771 }
4772
4773 pp_backend_kit_function () {
4774     case "$1" in
4775         pp_mkgroup) cat <<'.';;
4776             grep "^$1:" /etc/group >/dev/null ||
4777                 /usr/sbin/groupadd $1
4778 .
4779         pp_mkuser) cat <<'.';;
4780             eval user=\$$#
4781             grep "^$user:" /etc/passwd >/dev/null ||
4782                 /usr/sbin/useradd -s /usr/bin/false "$@"
4783 .
4784         pp_havelib) cat <<'.';;
4785             for dir in `echo /usr/lib${3+:$3} | tr : ' '`; do
4786                 test -r "$dir/lib$1.${2-sl}" && return 0
4787             done
4788             return 1
4789 .
4790         *) pp_error "unknown function request: $1";;
4791     esac
4792 }
4793
4794 pp_backend_kit_init_svc_vars () {
4795     :
4796 }
4797
4798 pp_backend_kit_probe () {
4799     echo tru64-`uname -r | sed 's/V\([0-9]*\)\.\([0-9]*\)/\1\2/'`
4800 }
4801
4802 pp_kit_service_group_script () {
4803     typeset grp svcs scriptpath out
4804     grp="$1"
4805     svcs="$2"
4806     scriptpath="/sbin/init.d/$grp"
4807     out="$pp_destdir$scriptpath"
4808
4809     pp_add_file_if_missing $scriptpath run 755 || return 0
4810
4811     cat <<-. > $out
4812         #!/sbin/sh
4813         # generated by pp $pp_version
4814         svcs="$svcs"
4815 .
4816
4817 cat <<-'.' >> $out
4818         #-- starts services in order.. stops them all if any break
4819         pp_start () {
4820             undo=
4821             for svc in $svcs; do
4822                 /sbin/init.d/$svc start
4823                 case $? in
4824                     0|4)
4825                         undo="$svc $undo"
4826                         ;;
4827                     *)
4828                         if test -n "$undo"; then
4829                         for svc in $undo; do
4830                             /sbin/init.d/$svc stop
4831                         done
4832                         return 1
4833                         fi
4834                         ;;
4835                 esac
4836             done
4837             return 0
4838         }
4839
4840         #-- stops services in reverse
4841         pp_stop () {
4842             reverse=
4843                 for svc in $svcs; do
4844                     reverse="$svc $reverse"
4845                 done
4846                 rc=0
4847                 for svc in $reverse; do
4848                     /sbin/init.d/$svc stop || rc=$?
4849                 done
4850                 return $rc
4851         }
4852
4853         case $1 in
4854             start_msg) echo "Starting $svcs";;
4855         stop_msg)  echo "Stopping $svcs";;
4856         start)     pp_start;;
4857         stop)      pp_stop;;
4858         *)         echo "usage: $0 {start|stop|start_msg|stop_msg}"
4859             exit 1;;
4860         esac
4861 .
4862 }
4863
4864 pp_kit_service_script () {
4865     typeset svc scriptpath out
4866
4867     svc="$1"
4868     scriptpath="/sbin/init.d/$svc"
4869
4870     pp_load_service_vars "$svc"
4871
4872     test -n "$user" -a x"$user" != x"root" &&
4873     cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
4874     if test -z "$pidfile"; then
4875         pidfile="/var/run/$svc.pid"
4876         cmd="$cmd & echo \$! > \$pidfile"
4877     fi
4878
4879     pp_add_file_if_missing $scriptpath run 755
4880
4881     cat <<-. > $pp_destdir$scriptpath
4882         svc="$svc"
4883         pidfile="$pidfile"
4884
4885         pp_start () {
4886             $cmd
4887         }
4888 .
4889     cat <<-'.' >>$pp_destdir$scriptpath
4890             pp_stop () {
4891                 if test ! -s "$pidfile"; then
4892                     echo "Unable to stop $svc (no pid file)"
4893                         return 1
4894                 else
4895                     read pid < "$pidfile"
4896                     if kill -0 "$pid" 2>/dev/null; then
4897                         if kill -${stop_signal:-TERM} "$pid"; then
4898                             rm -f "$pidfile"
4899                             return 0
4900                         else
4901                             echo "Unable to stop $svc"
4902                             return 1
4903                         fi
4904                     else
4905                         rm -f "$pidfile"
4906                         return 0
4907                     fi
4908                 fi
4909             }
4910
4911             pp_running () {
4912                 if test ! -s "$pidfile"; then
4913                     return 1
4914                 else
4915                     read pid < "$pidfile"
4916                     kill -0 "$pid" 2>/dev/null
4917                 fi
4918             }
4919             case $1 in
4920                 start_msg) echo "Starting the $svc service";;
4921                 stop_msg)  echo "Stopping the $svc service";;
4922                 start)
4923                     if pp_running; then
4924                         echo "$svc already running";
4925                         exit 0
4926                     elif pp_start; then
4927                         echo "$svc started";
4928         # rc(1M) says we should exit 4, but nobody expects it!
4929                         exit 0
4930                     else
4931                         exit 1
4932                     fi
4933                     ;;
4934                 stop)
4935                     if pp_stop; then
4936                         echo "$svc stopped";
4937                         exit 0
4938                     else
4939                         exit 1
4940                     fi
4941                     ;;
4942                 *) echo "usage: $0 {start|stop|start_msg|stop_msg}"
4943                    exit 1
4944                    ;;
4945             esac
4946 .
4947 }
4948
4949 pp_kit_make_service () {
4950     typeset level priority startlevels stoplevels
4951     typeset svc svcvar
4952
4953     svc="$1"
4954     svcvar=`pp_makevar $svc`
4955
4956     #-- don't do anything if the script exists
4957     if test -s "$pp_destdir/sbin/init.d/$svc"; then
4958         pp_error "$pp_destdir/sbin/init.d/$svc exists"
4959         return
4960     fi
4961
4962     # symlink the script, depending on the priorities chosen
4963     eval priority='${pp_kit_priority_'$svcvar'}'
4964     test -z "$priority" && priority="${pp_kit_priority:-50}"
4965
4966     eval startlevels='${pp_kit_startlevels_'$svcvar'}'
4967     test -z "$startlevels" && startlevels="$pp_kit_startlevels"
4968
4969     eval stoplevels='${pp_kit_stoplevels_'$svcvar'}'
4970     test -z "$stoplevels" && stoplevels="$pp_kit_stoplevels"
4971
4972     # create the script and config file
4973     pp_kit_service_script $svc
4974
4975     # fix the priority up
4976     case "$priority" in
4977         ???) :;;
4978         ??) priority=0$priority;;
4979         ?) priority=00$priority;;
4980     esac
4981
4982     if test x"$stoplevels" = x"auto"; then
4983         stoplevels=
4984         test -z "$startlevels" || for level in $startlevels; do
4985             stoplevels="$stoplevels `expr $level - 1`"
4986         done
4987     fi
4988
4989     # create the symlinks
4990     test -z "$startlevels" || for level in $startlevels; do
4991         echo "        ln -s /sbin/init.d/$svc /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%post.run
4992         echo "        rm /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%preun.run
4993     done
4994     test -z "$stoplevels" || for level in $stoplevels; do
4995         echo "        ln -s /sbin/init.d/$svc /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%post.run
4996         echo "        rm -f /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%preun.run
4997     done
4998 }
4999
5000
5001
5002
5003 pp_backend_kit_sizes () {
5004     awk '
5005     BEGIN { root = usr = var = 0; }
5006     {
5007         if (substr($9, 1, 1) != "l")
5008             if (substr($10, 1, 6) == "./var/")
5009                 var += $2;
5010             else if (substr($10, 1, 10) == "./usr/var/")
5011                 var += $2
5012             else if (substr($10, 1, 6) == "./usr/")
5013                 usr += $2
5014             else
5015                 root += $2
5016     }
5017     END { printf "%d\t%d\t%d", root, usr, var }
5018     ' "$@"
5019 }
5020
5021 pp_kit_kits_global () {
5022     line=`sed -n '/^%%/q;/^'$2'=/{s/^'$2'=//p;q;}' <"$1"`
5023     test -z "$line" && return 1
5024     eval "echo $line"
5025     :
5026 }
5027
5028 pp_backend_kit_kits () {
5029     typeset KITFILE FROMDIR TODIR
5030     typeset SCPDIR
5031
5032     SCPDIR="$pp_wrkdir/scps"
5033
5034     PATH="/usr/lbin:/usr/bin:/etc:/usr/ucb:$PATH"; export PATH # XXX
5035     #umask 2 # XXX
5036
5037     test $# -ge 3 || pp_die "pp_backend_kit_kits: too few arguments"
5038     KITFILE="$1"; shift
5039     FROMDIR="$1"; shift
5040     TODIR="$1"; shift
5041
5042     test -f "$KITFILE" || pp_die "$KITFILE not found"
5043     test -d "$FROMDIR" || pp_die "$FROMDIR not found"
5044     test -d "$TODIR"   || pp_die "$TODIR not found"
5045
5046     INSTCTRL="$TODIR/instctrl"
5047     mkdir -p "$INSTCTRL" || pp_die "cannot create instctrl directory"
5048     chmod 775 "$INSTCTRL"
5049
5050     grep "%%" $KITFILE > /dev/null || pp_die "no %% in $KITFILE"
5051
5052     typeset NAME CODE VERS MI ROOT COMPRESS
5053     typeset S_LIST ALLSUBS
5054
5055     NAME=`pp_kit_kits_global "$KITFILE" NAME` || pp_die "no NAME in $KITFILE"
5056     CODE=`pp_kit_kits_global "$KITFILE" CODE` || pp_die "no CODE in $KITFILE"
5057     VERS=`pp_kit_kits_global "$KITFILE" VERS` || pp_die "no VERS in $KITFILE"
5058     MI=`pp_kit_kits_global "$KITFILE" MI` || pp_die "no MI in $KITFILE"
5059     ROOT=`pp_kit_kits_global "$KITFILE" ROOT`
5060     COMPRESS=`pp_kit_kits_global "$KITFILE" COMPRESS`
5061
5062     test -f "$MI" || pp_die "Inventory file $MI not found"
5063
5064     case "$ROOT" in
5065     *ROOT)
5066         test -f "$TODIR/$ROOT" ||
5067             pp_die "Root image $ROOT not found in $TODIR" ;;
5068     esac
5069
5070     ALLSUBS=`awk 'insub==1 {print $1} /^%%/ {insub=1}' <"$KITFILE"`
5071     test $# -eq 0 && set -- $ALLSUBS
5072
5073     pp_debug "Creating $# $NAME subsets."
5074     pp_debug "ALLSUBS=<$ALLSUBS>"
5075
5076     if test x"$COMPRESS" = x"1"; then
5077         COMPRESS=:
5078     else
5079         COMPRESS=false
5080     fi
5081
5082     #rm -f *.ctrl Volume*
5083
5084     for SUB
5085     do
5086         test -z "$SUB" && pp_die "SUB is empty"
5087
5088         typeset INV CTRL ROOTSIZE USRSIZE VARSIZE TSSUB
5089         #rm -f Volume*
5090         case $SUB in
5091             .*) :;;
5092             *)  pp_verbose rm -f "$TODIR/$SUB"* "$INSTCTRL/$SUB"*;;
5093         esac
5094
5095         TSSUB="$pp_wrkdir/ts.$SUB"
5096
5097         pp_debug "kits: Subset $SUB"
5098
5099         INV="$SUB.inv"
5100         CTRL="$SUB.ctrl"
5101         pp_debug "kits: Generating media creation information..."
5102
5103         # Invcutter takes as input
5104         #   SUB dir/path
5105         # and generates stl_inv(4) files, like this
5106         #   f 0 00000 0 0 100644 2/11/09 010 f dir/path none SUB
5107         grep "  $SUB\$" "$MI" |
5108             pp_verbose /usr/lbin/invcutter \
5109                 -v "$VERS" -f "$FROMDIR" > "$INSTCTRL/$INV" ||
5110             pp_die "failed to create $INSTCTRL/$INV"
5111         chmod 664 "$INSTCTRL/$INV"
5112
5113         pp_backend_kit_sizes "$INSTCTRL/$INV" > "$pp_wrkdir/kit.sizes"
5114         read ROOTSIZE USRSIZE VARSIZE < "$pp_wrkdir/kit.sizes"
5115
5116         # Prefix each line with $FROMDIR. This will be stripped
5117         awk '$1 != "d" {print from $10}' from="$FROMDIR/" \
5118             > "$TSSUB" < "$INSTCTRL/$INV" ||
5119             pp_die "failed"
5120
5121         NVOLS=0
5122
5123         pp_debug "kits: Creating $SUB control file..."
5124
5125         sed '1,/^%%/d;/^'"$SUB"'/{p;q;}' < "$KITFILE" > "$pp_wrkdir/kit.line"
5126         read _SUB _IGNOR DEPS FLAGS DESC < "$pp_wrkdir/kit.line"
5127         if test -z "$_SUB"; then
5128             pp_warn "No such subset $SUB in $KITFILE"
5129             continue
5130         fi
5131         DEPS=`echo $DEPS | tr '|' ' '`
5132         case $FLAGS in
5133             FLGEXP*) pp_verbose FLAGS='"${'"$FLAGS"'}"' ;;
5134         esac
5135         case $DESC in
5136             *%*) DESC=`echo $DESC|awk -F% '{printf "%-36s%%%s\n", $1, $2}'`;;
5137         esac
5138
5139         cat > "$INSTCTRL/$CTRL" <<-.
5140                 NAME='$NAME $SUB'
5141                 DESC=$DESC
5142                 ROOTSIZE=$ROOTSIZE
5143                 USRSIZE=$USRSIZE
5144                 VARSIZE=$VARSIZE
5145                 NVOLS=1:$NVOLS
5146                 MTLOC=1:$TLOC
5147                 DEPS="$DEPS"
5148                 FLAGS=$FLAGS
5149 .
5150         chmod 664 "$INSTCTRL/$CTRL"
5151
5152         pp_debug "kits: Making tar image"
5153
5154         pp_verbose tar cfPR "$TODIR/$SUB" "$FROMDIR/" "$TSSUB" ||
5155              pp_error "problem creating kit file"
5156
5157         if $COMPRESS; then
5158             pp_debug "kits: Compressing"
5159             (cd "$TODIR" && compress -f -v "$SUB") ||
5160                 pp_die "problem compressing $TODIR/$SUB"
5161             SPC=`expr $SUB : '\(...\).*'`    # first three characters
5162             SVC=`expr $SUB : '.*\(...\)'`    # last three characters
5163             : > "$INSTCTRL/$SPC$SVC.comp"
5164             chmod 664 "$INSTCTRL/$SPC$SVC.comp"
5165             pp_debug "kits: Padding compressed file to 10kB" # wtf?
5166             rm -f "$TODIR/$SUB"
5167             pp_verbose \
5168             dd if="$TODIR/$SUB.Z" of="$TODIR/$SUB" bs=10k conv=sync ||
5169                 pp_die "problem moving compressed file"
5170             rm -f "$TODIR/$SUB.Z"
5171         fi
5172         chmod 664 "$TODIR/$SUB"
5173
5174         if test -f "$SCPDIR/$SUB.scp"; then
5175                 cp "$SCPDIR/$SUB.scp" "$INSTCTRL/$SUB.scp"
5176                 chmod 755 "$INSTCTRL/$SUB.scp"
5177         else
5178                 pp_debug "kits: null subset control program for $SUB"
5179                 : > "$INSTCTRL/$SUB.scp"
5180                 chmod 744 "$INSTCTRL/$SUB.scp"
5181         fi
5182
5183         pp_debug "kits: Finished creating media image for $SUB"
5184     done
5185
5186     pp_debug "kits: Creating $CODE.image"
5187
5188     case "$ROOT" in
5189     *ROOT)      ALLSUBS="$ROOT $ALLSUBS"
5190                 ;;
5191     esac
5192
5193     (cd "$TODIR" && sum $ALLSUBS) > "$INSTCTRL/$CODE.image"
5194     chmod 664 "$INSTTRL/$CODE.image"
5195     pp_debug "kits: Creating INSTCTRL"
5196     (cd "$INSTCTRL" && tar cpvf - *) > "$TODIR/INSTCTRL"
5197     chmod 664 "$TODIR/INSTCTRL"
5198     cp "$INSTCTRL/$CODE.image" "$TODIR/$CODE.image"
5199     chmod 664 "$TODIR/$CODE.image"
5200
5201     pp_debug "kits: Media image production complete"
5202 }
5203
5204 pp_platforms="$pp_platforms rpm"
5205
5206 pp_backend_rpm_detect () {
5207     test x"$1" = x"Linux" -a ! -f /etc/debian_version
5208 }
5209
5210 pp_backend_rpm_init () {
5211
5212     pp_rpm_version=
5213     pp_rpm_summary=
5214     pp_rpm_description=
5215     pp_rpm_group="Applications/Internet"
5216     pp_rpm_license="Unspecified"
5217     pp_rpm_vendor=
5218     pp_rpm_url=
5219     pp_rpm_packager=
5220     pp_rpm_provides=
5221     pp_rpm_requires=
5222     pp_rpm_release=
5223     pp_rpm_epoch=
5224     pp_rpm_dev_group="Development/Libraries"
5225     pp_rpm_dbg_group="Development/Tools"
5226     pp_rpm_doc_group="Documentation"
5227     pp_rpm_dev_description=
5228     pp_rpm_dbg_description=
5229     pp_rpm_doc_description=
5230     pp_rpm_dev_requires=
5231     pp_rpm_dbg_requires=
5232     pp_rpm_doc_requires=
5233     pp_rpm_dev_provides=
5234     pp_rpm_dbg_provides=
5235     pp_rpm_doc_provides=
5236
5237     pp_rpm_dbg_pkgname=debug
5238     pp_rpm_dev_pkgname=devel
5239     pp_rpm_doc_pkgname=doc
5240
5241     pp_rpm_defattr_uid=root
5242     pp_rpm_defattr_gid=root
5243
5244     pp_rpm_detect_arch
5245     pp_rpm_detect_distro
5246     pp_rpm_rpmbuild=`pp_rpm_detect_rpmbuild`
5247
5248     # SLES8 doesn't always come with readlink
5249     test -x /usr/bin/readlink -o -x /bin/readlink ||
5250         pp_readlink_fn=pp_ls_readlink
5251 }
5252
5253 pp_rpm_detect_arch () {
5254     pp_rpm_arch=auto
5255
5256     #-- Find the default native architecture that RPM is configured to use
5257     cat <<-. >$pp_wrkdir/dummy.spec
5258         Name: dummy
5259         Version: 1
5260         Release: 1
5261         Summary: dummy
5262         Group: ${pp_rpm_group}
5263         License: ${pp_rpm_license}
5264         %description
5265         dummy
5266 .
5267     $pp_opt_debug && cat $pp_wrkdir/dummy.spec
5268     pp_rpm_arch_local=`rpm -q --qf '%{arch}\n' --specfile $pp_wrkdir/dummy.spec`
5269     rm $pp_wrkdir/dummy.spec
5270
5271     #-- Ask the kernel what machine architecture is in use
5272     local arch
5273     for arch in "`uname -m`" "`uname -p`"; do
5274         case "$arch" in
5275             i?86)
5276                 pp_rpm_arch_std=i386
5277                 break
5278                 ;;
5279             x86_64|ppc|ppc64|ia64|s390|s390x)
5280                 pp_rpm_arch_std="$arch"
5281                 break
5282                 ;;
5283             powerpc)
5284                 # Probably AIX
5285                 case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
5286                     PowerPC_POWER*)     pp_rpm_arch_std=ppc64;;
5287                     *)                  pp_rpm_arch_std=ppc;;
5288                 esac
5289                 break
5290                 ;;
5291             *)  pp_rpm_arch_std=unknown
5292                 ;;
5293         esac
5294     done
5295
5296     #-- Later on, when files are processed, we use 'file' to determine
5297     #   what platform ABIs are used. This is used when pp_rpm_arch == auto
5298     pp_rpm_arch_seen=
5299 }
5300
5301 pp_rpm_detect_distro () {
5302     pp_rpm_distro=
5303     if test -f /etc/whitebox-release; then
5304        pp_rpm_distro=`awk '
5305           /^White Box Enterprise Linux release/ { print "wbel" $6; exit; }
5306        ' /etc/whitebox-release`
5307     elif test -f /etc/mandrakelinux-release; then
5308        pp_rpm_distro=`awk '
5309           /^Mandrakelinux release/ { print "mand" $3; exit; }
5310        ' /etc/mandrake-release`
5311     elif test -f /etc/mandrake-release; then
5312        pp_rpm_distro=`awk '
5313           /^Linux Mandrake release/ { print "mand" $4; exit; }
5314           /^Mandrake Linux release/ { print "mand" $4; exit; }
5315        ' /etc/mandrake-release`
5316     elif test -f /etc/fedora-release; then
5317        pp_rpm_distro=`awk '
5318           /^Fedora Core release/ { print "fc" $4; exit; }
5319           /^Fedora release/ { print "f" $3; exit; }
5320        ' /etc/fedora-release`
5321     elif test -f /etc/redhat-release; then
5322        pp_rpm_distro=`awk '
5323           /^Red Hat Enterprise Linux/ { print "rhel" $7; exit; }
5324           /^CentOS release/           { print "centos" $3; exit; }
5325           /^Red Hat Linux release/    { print "rh" $5; exit; }
5326        ' /etc/redhat-release`
5327     elif test -f /etc/SuSE-release; then
5328        pp_rpm_distro=`awk '
5329           /^SuSE Linux [0-9]/ { print "suse" $3; exit; }
5330           /^SUSE LINUX [0-9]/ { print "suse" $3; exit; }
5331           /^openSUSE [0-9]/   { print "suse" $2; exit; }
5332           /^S[uU]SE Linux Enterprise Server [0-9]/ { print "sles" $5; exit; }
5333           /^S[uU]SE LINUX Enterprise Server [0-9]/ { print "sles" $5; exit; }
5334           /^SuSE SLES-[0-9]/  { print "sles" substr($2,6); exit; }
5335        ' /etc/SuSE-release`
5336     elif test -f /etc/pld-release; then
5337        pp_rpm_distro=`awk '
5338           /^[^ ]* PLD Linux/ { print "pld" $1; exit; }
5339        ' /etc/pld-release`
5340     elif test X"`uname -s 2>/dev/null`" = X"AIX"; then
5341         local r v
5342         r=`uname -r`
5343         v=`uname -v`
5344         pp_rpm_distro="aix$v$r"
5345     fi
5346     pp_rpm_distro=`echo $pp_rpm_distro | tr -d .`
5347     test -z "$pp_rpm_distro" &&
5348        pp_warn "unknown distro"
5349 }
5350
5351 pp_rpm_detect_rpmbuild () {
5352     local cmd
5353     for cmd in rpmbuild rpm; do
5354         if `which $cmd > /dev/null 2>&1`; then
5355             echo $cmd
5356             return 0
5357         fi
5358     done
5359
5360     pp_error "Could not find rpmbuild"
5361     # Default to `rpmbuild` in case it magically appears
5362     echo rpmbuild
5363     return 1
5364 }
5365
5366 pp_rpm_label () {
5367     local label arg
5368     label="$1"; shift
5369     for arg
5370     do
5371         test -z "$arg" || echo "$label: $arg"
5372     done
5373 }
5374
5375 pp_rpm_writefiles () {
5376     local _l t m o g f p st fo farch
5377     while read t m o g f p st; do
5378         _l="$p"
5379         test $t = d && _l="%dir ${_l%/}/"
5380         if test x"$m" = x"-"; then
5381             case "$t" in
5382                 d) m=755;;
5383                 f) m=644;;
5384             esac
5385         fi
5386         test x"$o" = x"-" && o="${pp_rpm_defattr_uid:-root}"
5387         test x"$g" = x"-" && g="${pp_rpm_defattr_gid:-root}"
5388         _l="%attr($m,$o,$g) $_l"
5389
5390         if test "$t" = "f" -a x"$pp_rpm_arch" = x"auto"; then
5391             fo=`file "${pp_destdir}$p" 2>/dev/null`
5392             #NB: The following should match executables and shared objects,
5393             #relocatable objects. It will not match .a files however.
5394             case "$fo" in
5395                 *": ELF 32-bit LSB "*", Intel 80386"*)
5396                     farch=i386;;
5397                 *": ELF 64-bit LSB "*", AMD x86-64"*|\
5398                 *": ELF 64-bit LSB "*", x86-64"*)
5399                     farch=x86_64;;
5400                 *": ELF 32-bit MSB "*", PowerPC"*)
5401                     farch=ppc;;
5402                 *": ELF 64-bit LSB "*", IA-64"*)
5403                     farch=ia64;;
5404                 *": ELF 32-bit MSB "*", IBM S/390"*)
5405                     farch=s390;;
5406                 *": ELF 64-bit MSB "*", IBM S/390"*)
5407                     farch=s390x;;
5408                 *"executable (RISC System/6000)"*)
5409                     farch=ppc;;
5410                 *"64-bit XCOFF executable"*)
5411                     farch=ppc64;;
5412                 *" ELF "*)
5413                     farch=ELF;;
5414                 *)
5415                     farch=noarch;;
5416             esac
5417             # If file(1) doesn't provide enough info, try readelf(1)
5418             if test "$farch" = "ELF"; then
5419                 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`
5420                 case "$fo" in
5421                     "ELF32 Intel 80386")
5422                         farch=i386;;
5423                     "ELF64 "*[xX]"86-64")
5424                         farch=x86_64;;
5425                     "ELF32 PowerPC")
5426                         farch=ppc;;
5427                     "ELF64 PowerPC")
5428                         farch=ppc64;;
5429                     "ELF64 IA-64")
5430                         farch=ia64;;
5431                     "ELF32 IBM S/390")
5432                         farch=s390;;
5433                     "ELF64 IBM S/390")
5434                         farch=s390x;;
5435                     *)
5436                         farch=noarch;;
5437                 esac
5438             fi
5439             pp_debug "file: $fo -> $farch"
5440             test x"$farch" = x"noarch" || pp_add_to_list pp_rpm_arch_seen $farch
5441         fi
5442
5443         case $f in *v*) _l="%config(noreplace) $_l";; esac
5444         echo "$_l"
5445     done
5446     echo
5447 }
5448
5449 pp_rpm_subname () {
5450     case "$1" in
5451         run) : ;;
5452         dbg) echo "${2}${pp_rpm_dbg_pkgname}";;
5453         dev) echo "${2}${pp_rpm_dev_pkgname}";;
5454         doc) echo "${2}${pp_rpm_doc_pkgname}";;
5455         *)   pp_error "unknown component '$1'";
5456     esac
5457 }
5458
5459 pp_rpm_depend () {
5460     while read _name _vers; do
5461         case "$_name" in ""| "#"*) continue ;; esac
5462         echo "Requires: $_name ${_vers:+>= $_vers}"
5463     done
5464 }
5465
5466 pp_rpm_override_requires () {
5467     local orig_find_requires
5468
5469     if test -z "$pp_rpm_depend_filter_cmd"; then
5470         return 0
5471     fi
5472
5473     orig_find_requires=`rpm --eval '%{__find_requires}'`
5474     cat << EOF > "$pp_wrkdir/filtered-find-requires"
5475 $orig_find_requires \$@ | $pp_rpm_depend_filter_cmd
5476 EOF
5477     chmod +x "$pp_wrkdir/filtered-find-requires"
5478     echo "%define __find_requires $pp_wrkdir/filtered-find-requires"
5479     # Might be necessary for old versions of RPM? Not for 4.4.2.
5480     #echo "%define _use_internal_dependency_generator 0"
5481 }
5482
5483 pp_backend_rpm () {
5484     local cmp specfile _summary _group _desc _pkg _subname svc
5485
5486         specfile=$pp_wrkdir/$name.spec
5487         : > $specfile
5488
5489         #-- force existence of a 'run' component
5490         pp_add_component run
5491         : >> $pp_wrkdir/%files.run
5492
5493         if test -z "$pp_rpm_arch"; then
5494             pp_error "Unknown RPM architecture"
5495             return 1
5496         fi
5497
5498         #-- Write the header components of the RPM spec file
5499         cat <<-. >>$specfile
5500                 Name: ${pp_rpm_name:-$name}
5501                 Version: ${pp_rpm_version:-$version}
5502                 Release: ${pp_rpm_release:-1}
5503                 Summary: ${pp_rpm_summary:-$summary}
5504                 Group:   ${pp_rpm_group}
5505                 License: ${pp_rpm_license}
5506 .
5507         if test -n "$pp_rpm_url"; then
5508             pp_rpm_label "URL"  "$pp_rpm_url"               >>$specfile
5509         fi
5510         pp_rpm_label "Vendor"   "${pp_rpm_vendor:-$vendor}" >>$specfile
5511         pp_rpm_label "Packager" "$pp_rpm_packager"          >>$specfile
5512         pp_rpm_label "Provides" "$pp_rpm_provides"          >>$specfile
5513         pp_rpm_label "Requires" "$pp_rpm_requires"          >>$specfile
5514
5515         test -n "$pp_rpm_serial" && pp_warn "pp_rpm_serial deprecated"
5516         if test -n "$pp_rpm_epoch"; then
5517             #-- Epoch was introduced in RPM 2.5.6
5518             case `$pp_rpm_rpmbuild --version 2>/dev/null` in
5519                 1.*|2.[0-5].*|2.5.[0-5])
5520                     pp_rpm_label "Serial" $pp_rpm_epoch >>$specfile;;
5521                 *)
5522                     pp_rpm_label "Epoch" $pp_rpm_epoch >>$specfile;;
5523             esac
5524         fi
5525
5526         if test -n "$pp_rpm_requires"; then
5527             pp_rpm_label "Requires" "$pp_rpm_requires" >>$specfile
5528         elif test -s $pp_wrkdir/%depend.run; then
5529             pp_rpm_depend < $pp_wrkdir/%depend.run >> $specfile
5530         fi
5531
5532         pp_rpm_override_requires >> $specfile
5533
5534         cat <<-. >>$specfile
5535
5536                 %description
5537                 ${pp_rpm_description:-$description}
5538 .
5539
5540         for cmp in $pp_components; do
5541                 case $cmp in
5542                    run) continue;;
5543                    dev) _summary="development tools for $pp_rpm_summary"
5544                         _group="$pp_rpm_dev_group"
5545                         _desc="${pp_rpm_dev_description:-Development libraries for $name. $pp_rpm_description.}"
5546                         ;;
5547                    doc) _summary="documentation for $pp_rpm_summary"
5548                         _group="$pp_rpm_doc_group"
5549                         _desc="${pp_rpm_doc_description:-Documentation for $name. $pp_rpm_description.}"
5550                         ;;
5551                    dbg) _summary="diagnostic tools for $pp_rpm_summary"
5552                         _group="$pp_rpm_dbg_group"
5553                         _desc="${pp_rpm_dbg_description:-Diagnostic tools for $name.}"
5554                         ;;
5555                 esac
5556
5557                 _subname=`pp_rpm_subname $cmp`
5558                 cat <<-.
5559
5560                         %package $_subname
5561                         Summary: $name $_summary
5562                         Group: $_group
5563 .
5564                 eval '_pkg="$pp_rpm_'$cmp'_requires"'
5565                 if test -n "$_pkg"; then
5566                     eval pp_rpm_label Requires ${pp_rpm_name:-$name} $_pkg
5567                 elif test -s $pp_wrkdir/%depend.$cmp; then
5568                     pp_rpm_depend < $pp_wrkdir/%depend.$cmp >> $specfile
5569                 fi
5570
5571                 eval '_pkg="$pp_rpm_'$cmp'_provides"'
5572                 eval pp_rpm_label Provides $_pkg
5573
5574                 cat <<-.
5575
5576                         %description $_subname
5577                         $_desc
5578 .
5579         done >>$specfile
5580
5581         #-- NB: we don't put any %prep, %build or %install RPM sections
5582         #   into the spec file.
5583
5584         #-- add service start/stop code
5585         if test -n "$pp_services"; then
5586             pp_rpm_service_install_common >> $pp_wrkdir/%post.run
5587
5588             #-- record the uninstall commands in reverse order
5589             for svc in $pp_services; do
5590                 pp_load_service_vars $svc
5591
5592                 pp_rpm_service_make_init_script $svc
5593
5594                 #-- append %post code to install the svc
5595                 pp_rpm_service_install $svc >> $pp_wrkdir/%post.run
5596
5597                 #-- prepend %preun code to uninstall svc
5598                 # (use files in case vars are modified)
5599                 pp_rpm_service_remove $svc | pp_prepend $pp_wrkdir/%preun.run
5600             done
5601             pp_rpm_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
5602         fi
5603
5604         # make convenience service groups
5605         if test -n "$pp_service_groups"; then
5606             for grp in $pp_service_groups; do
5607                 pp_rpm_service_group_make_init_script \
5608                     $grp "`pp_service_get_svc_group $grp`"
5609             done
5610         fi
5611
5612         #-- Write the RPM %file sections
5613         #   (do this after services, since services adds to %files.run)
5614         for cmp in $pp_components; do
5615             _subname=`pp_rpm_subname $cmp`
5616
5617             if test -s $pp_wrkdir/%check.$cmp; then
5618                 echo ""
5619                 echo "%pre $_subname"
5620                 cat $pp_wrkdir/%check.$cmp
5621                 echo :   # causes script to exit true by default
5622             fi
5623
5624             if test -s $pp_wrkdir/%files.$cmp; then
5625                 echo ""
5626                 echo "%files $_subname"
5627                 pp_rpm_writefiles < $pp_wrkdir/%files.$cmp
5628             fi
5629
5630             if test -n "$pp_rpm_ghost"; then
5631                 for ghost in $pp_rpm_ghost; do
5632                     echo "%ghost $ghost"
5633                 done
5634             fi
5635
5636             if test -s $pp_wrkdir/%pre.$cmp; then
5637                 echo ""
5638                 echo "%pre $_subname"
5639                 cat $pp_wrkdir/%pre.$cmp
5640                 echo :   # causes script to exit true
5641             fi
5642
5643             if test -s $pp_wrkdir/%post.$cmp; then
5644                 echo ""
5645                 echo "%post $_subname"
5646                 cat $pp_wrkdir/%post.$cmp
5647                 echo :   # causes script to exit true
5648             fi
5649
5650             if test -s $pp_wrkdir/%preun.$cmp; then
5651                 echo ""
5652                 echo "%preun $_subname"
5653                 cat $pp_wrkdir/%preun.$cmp
5654                 echo :   # causes script to exit true
5655             fi
5656         done >>$specfile
5657
5658         #-- create a suitable work area for rpmbuild
5659         cat <<-. >$pp_wrkdir/.rpmmacros
5660                 %_topdir $pp_wrkdir
5661                 # XXX Note escaped %% for use in headerSprintf
5662                 %_rpmfilename   %%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
5663         .
5664         mkdir $pp_wrkdir/RPMS
5665         mkdir $pp_wrkdir/BUILD
5666
5667         if test x"$pp_rpm_arch" = x"auto"; then
5668             #-- Reduce the arch_seen list to exactly one item
5669             case "$pp_rpm_arch_seen" in
5670                 "i386 x86_64"|"x86_64 i386")
5671                     pp_rpm_arch_seen=x86_64;;
5672                 *"s390 s390x"* | *"s390x s390"* )
5673                     pp_rpm_arch_seen=s390x;;
5674                 *" "*)
5675                     pp_error "detected multiple targets: $pp_rpm_arch_seen"
5676                     pp_rpm_arch_seen=unknown;;      # not detected
5677                 "")
5678                     pp_warn "detected no binaries: using target noarch"
5679                     pp_rpm_arch_seen=noarch;;
5680                 *)
5681                     pp_debug "detected architecture $pp_rpm_arch_seen"
5682             esac
5683             pp_rpm_arch="$pp_rpm_arch_seen"
5684         fi
5685
5686         . $pp_wrkdir/%fixup
5687
5688 $pp_opt_debug && cat $specfile
5689
5690         pp_debug "creating: `pp_backend_rpm_names`"
5691
5692 pp_debug "pp_rpm_arch_seen = <${pp_rpm_arch_seen}>"
5693 pp_debug "pp_rpm_arch = <${pp_rpm_arch}>"
5694
5695         HOME=$pp_wrkdir \
5696         pp_verbose \
5697         $pp_rpm_rpmbuild -bb \
5698                 --buildroot="$pp_destdir/" \
5699                 --target="${pp_rpm_arch}" \
5700                 --define='_unpackaged_files_terminate_build 0' \
5701                 --define='_use_internal_dependency_generator 0' \
5702                 `$pp_opt_debug && echo --verbose || echo --quiet` \
5703                 $pp_rpm_rpmbuild_extra_flags \
5704                 $specfile ||
5705             pp_error "Problem creating RPM packages"
5706
5707         for f in `pp_backend_rpm_names`; do
5708             # The package might be in an arch-specific subdir
5709             pkgfile=not-found
5710             for dir in $pp_wrkdir/RPMS/${pp_rpm_arch} $pp_wrkdir/RPMS; do
5711                 if test -f $dir/$f; then
5712                     pkgfile=$dir/$f
5713                 fi
5714             done
5715             if test x"$pkgfile" = x"not-found"; then
5716                 pp_error "Problem predicting RPM filename: $f"
5717             else
5718                 ln $pkgfile $pp_wrkdir/$f
5719             fi
5720         done
5721 }
5722
5723 pp_rpm_output_name () {
5724     echo "${pp_rpm_name:-$name}`pp_rpm_subname "$1" -`-${pp_rpm_version:-$version}-${pp_rpm_release:-1}.${pp_rpm_arch}.rpm"
5725 }
5726
5727 pp_backend_rpm_names () {
5728     local cmp _subname
5729     for cmp in $pp_components; do
5730         pp_rpm_output_name $cmp
5731     done
5732 }
5733
5734 pp_backend_rpm_cleanup () {
5735     :
5736 }
5737
5738 pp_rpm_print_requires () {
5739     local _subname _name
5740
5741     echo "CPU:$pp_rpm_arch"
5742     ## XXX should be lines of the form (from file/ldd/objdump)
5743     #    EXEC:/bin/sh
5744     #    RTLD:libc.so.4:open
5745     rpm -q --requires -p $pp_wrkdir/`pp_rpm_output_name $1` |sed -e '/^rpmlib(/d;s/ //g;s/^/RPM:/' | sort -u
5746 }
5747
5748 pp_backend_rpm_install_script () {
5749     local cmp _subname
5750
5751     echo "#!/bin/sh"
5752     pp_install_script_common
5753
5754     cat <<.
5755
5756         cmp_to_pkgname () {
5757             local oi name
5758             if test x"\$1" = x"--only-installed"; then
5759                 #-- only print if installation detected
5760                 oi=false
5761                 shift
5762             else
5763                 oi=true
5764             fi
5765             test x"\$*" = x"all" &&
5766                 set -- $pp_components
5767             for cmp
5768             do
5769                 case \$cmp in
5770 .
5771     for cmp in $pp_components; do
5772         _subname=`pp_rpm_subname $cmp -`
5773          echo "$cmp) name=${pp_rpm_name:-$name}${_subname};;"
5774     done
5775     cat <<.
5776                 *) usage;;
5777                 esac
5778                 if \$oi || rpm -q "\$name" >/dev/null 2>/dev/null; then
5779                     echo "\$name"
5780                 fi
5781             done
5782         }
5783
5784
5785         cmp_to_pathname () {
5786             test x"\$*" = x"all" &&
5787                 set -- $pp_components
5788             for cmp
5789             do
5790                 case \$cmp in
5791 .
5792     for cmp in $pp_components; do
5793         echo "$cmp) echo \${PP_PKGDESTDIR:-.}/`pp_rpm_output_name $cmp` ;;"
5794     done
5795     cat <<.
5796                 *) usage;;
5797                 esac
5798             done
5799         }
5800
5801         print_requires () {
5802             test x"\$*" = x"all" &&
5803                 set -- $pp_components
5804             for cmp
5805             do
5806                 case \$cmp in
5807 .
5808     for cmp in $pp_components; do
5809         echo "$cmp) cat <<'._end'"
5810         pp_rpm_print_requires $cmp
5811         echo "._end"; echo ';;'
5812     done
5813     cat <<.
5814                 *) usage;;
5815                 esac
5816             done
5817         }
5818
5819         test \$# -eq 0 && usage
5820         op="\$1"; shift
5821         case "\$op" in
5822             list-components)
5823                 test \$# -eq 0 || usage \$op
5824                 echo $pp_components
5825                 ;;
5826             list-services)
5827                 test \$# -eq 0 || usage \$op
5828                 echo $pp_services
5829                 ;;
5830             list-files)
5831                 test \$# -ge 1 || usage \$op
5832                 cmp_to_pathname "\$@"
5833                 ;;
5834             install)
5835                 test \$# -ge 1 || usage \$op
5836                 verbose rpm -U --replacepkgs --oldpackage \
5837                     \`cmp_to_pathname "\$@"\`
5838                 ;;
5839             uninstall)
5840                 test \$# -ge 1 || usage \$op
5841                 pkgs=\`cmp_to_pkgname --only-installed "\$@"\`
5842                 if test -z "\$pkgs"; then
5843                     verbosemsg "nothing to uninstall"
5844                 else
5845                     verbose rpm -e \$pkgs
5846                 fi
5847                 ;;
5848             start|stop)
5849                 test \$# -ge 1 || usage \$op
5850                 ec=0
5851                 for svc
5852                 do
5853                     verbose /etc/init.d/\$svc \$op || ec=1
5854                 done
5855                 exit \$ec
5856                 ;;
5857             print-platform)
5858                 test \$# -eq 0 || usage \$op
5859                 echo "linux-${pp_rpm_arch}"
5860                 ;;
5861             print-requires)
5862                 test \$# -ge 1 || usage \$op
5863                 print_requires "\$@"
5864                 ;;
5865             *)
5866                 usage
5867                 ;;
5868         esac
5869 .
5870
5871 }
5872
5873 pp_backend_rpm_probe () {
5874         echo "${pp_rpm_distro}-${pp_rpm_arch_std}"
5875 }
5876
5877 pp_backend_rpm_vas_platforms () {
5878     case "$pp_rpm_arch_std" in
5879         x86_64) echo "linux-x86_64.rpm linux-x86.rpm";;
5880         *86)    echo "linux-x86.rpm";;
5881         s390)   echo "linux-s390";;
5882         s390x)  echo "linux-s390x";;
5883         ppc*)   echo "linux-glibc23-ppc64 linux-glibc22-ppc64";;
5884         ia64)   echo "linux-ia64";;
5885         *)      pp_die "unknown architecture $pp_rpm_arch_std";;
5886     esac
5887 }
5888
5889 pp_backend_rpm_init_svc_vars () {
5890     pp_rpm_default_start_runlevels="2 3 4 5"
5891     pp_rpm_default_svc_description="No description"
5892 }
5893
5894 pp_rpm_service_install_common () {
5895     cat <<-'.'
5896
5897         _pp_install_service () {
5898             local svc level
5899             svc="$1"
5900             if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
5901             then
5902                 # LSB-style install
5903                 /usr/lib/lsb/install_initd /etc/init.d/$svc &> /dev/null
5904             elif [ -x /sbin/chkconfig ]; then
5905                 # Red Hat/chkconfig-style install
5906                 /sbin/chkconfig --add $svc &> /dev/null
5907                 /sbin/chkconfig $svc off &> /dev/null
5908             else
5909                 : # manual links under /etc/init.d
5910             fi
5911         }
5912
5913         _pp_enable_service () {
5914             local svc level
5915             svc="$1"
5916             if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
5917             then
5918                 # LSB-style install
5919                 : # not sure how to enable
5920             elif [ -x /sbin/chkconfig ]; then
5921                 # Red Hat/chkconfig-style install
5922                 /sbin/chkconfig $svc on &> /dev/null
5923             else
5924                 # manual install
5925                 set -- `sed -n -e 's/^# Default-Start://p' /etc/init.d/$svc`
5926                 start_priority=`sed -n -e 's/^# X-Quest-Start-Priority:[[:space:]]*//p' /etc/init.d/$svc`
5927                 stop_priority=`sed -n -e 's/^# X-Quest-Stop-Priority:[[:space:]]*//p' /etc/init.d/$svc`
5928
5929                 # Provide default start & stop priorities of 20 & 80 in
5930                 # accordance with Debian update-rc.d defaults
5931                 if [ -z "$start_priority" ]; then
5932                     start_priority=20
5933                 fi
5934                 if [ -z "$stop_priority" ]; then
5935                     stop_priority=80
5936                 fi
5937                     
5938                 if [ -d "/etc/rc.d" ];then
5939                     rcdir=/etc/rc.d
5940                 else
5941                     rcdir=/etc
5942                 fi
5943
5944                 for level
5945                 do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/S$start_priority$svc; done
5946                 set -- `sed -n -e 's/^# Default-Stop://p' /etc/init.d/$svc`
5947                 for level
5948                 do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/K$stop_priority$svc; done
5949             fi
5950         }
5951 .
5952 }
5953
5954 pp_rpm_service_remove_common () {
5955     cat <<-'.'
5956
5957         _pp_remove_service () {
5958             local svc
5959             svc="$1"
5960             /etc/init.d/$svc stop >/dev/null 2>&1
5961             if [ -x /usr/lib/lsb/remove_initd -a ! -r /etc/redhat-release ]
5962             then
5963                 /usr/lib/lsb/remove_initd /etc/init.d/$svc &> /dev/null
5964             elif [ -x /sbin/chkconfig ]; then
5965                 /sbin/chkconfig --del $svc &> /dev/null
5966             else
5967                 if [ -d "/etc/rc.d" ];then
5968                     rcdir=/etc/rc.d
5969                 else
5970                     rcdir=/etc
5971                 fi
5972
5973                 rm -f $rcdir/rc?.d/[SK]??$svc
5974             fi
5975         }
5976 .
5977 }
5978
5979
5980 pp_rpm_service_install () {
5981     pp_rpm_service_make_init_script $1 >/dev/null ||
5982         pp_error "could not create init script for service $1"
5983     echo "_pp_install_service $1"
5984     test $enable = yes && echo "_pp_enable_service $1"
5985 }
5986
5987 pp_rpm_service_remove () {
5988     cat <<-.
5989         if [ "\$1" = "remove" -o "\$1" = "0" ]; then
5990             # only remove the service if not upgrade
5991             _pp_remove_service $1
5992         fi
5993 .
5994 }
5995
5996
5997 pp_backend_rpm_init_svc_vars () {
5998
5999     reload_signal=
6000     start_runlevels=${pp_rpm_default_start_runlevels}   # == lsb default-start
6001     stop_runlevels="0 1 6"                              # == lsb default-stop
6002     svc_description="${pp_rpm_default_svc_description}" # == lsb short descr
6003     svc_process=
6004
6005     lsb_required_start='$local_fs $network'
6006     lsb_should_start=
6007     lsb_required_stop=
6008     lsb_description=
6009
6010     start_priority=50
6011     stop_priority=50            #-- stop_priority = 100 - start_priority
6012 }
6013
6014 pp_rpm_service_group_make_init_script () {
6015     local grp=$1
6016     local svcs="$2"
6017     local script=/etc/init.d/$grp
6018     local out=$pp_destdir$script
6019
6020     pp_add_file_if_missing $script run 755 || return 0
6021
6022     cat <<-. >>$out
6023         #!/bin/sh
6024         svcs="$svcs"
6025 .
6026
6027     cat <<-'.' >>$out
6028
6029         #-- prints usage message
6030         pp_usage () {
6031             echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
6032             return 2
6033         }
6034
6035         #-- starts services in order.. stops them all if any break
6036         pp_start () {
6037             undo=
6038             for svc in $svcs; do
6039                 if /etc/init.d/$svc start; then
6040                     undo="$svc $undo"
6041                 else
6042                     if test -n "$undo"; then
6043                         for svc in $undo; do
6044                            /etc/init.d/$svc stop
6045                         done
6046                         return 1
6047                     fi
6048                 fi
6049             done
6050             return 0
6051         }
6052
6053         #-- stops services in reverse
6054         pp_stop () {
6055             reverse=
6056             for svc in $svcs; do
6057                 reverse="$svc $reverse"
6058             done
6059             rc=0
6060             for svc in $reverse; do
6061                 /etc/init.d/$svc stop || rc=$?
6062             done
6063             return $rc
6064         }
6065
6066         #-- returns true only if all services return true status
6067         pp_status () {
6068             rc=0
6069             for svc in $svcs; do
6070                 /etc/init.d/$svc status || rc=$?
6071             done
6072             return $rc
6073         }
6074
6075         pp_reload () {
6076             rc=0
6077             for svc in $svcs; do
6078                 /etc/init.d/$svc reload || rc=$?
6079             done
6080             return $rc
6081         }
6082
6083         case "$1" in
6084             start)          pp_start;;
6085             stop)           pp_stop;;
6086             restart)        pp_stop; pp_start;;
6087             status)         pp_status;;
6088             try-restart|condrestart)
6089                             if pp_status >/dev/null; then
6090                                     pp_restart
6091                             fi;;
6092             reload)         pp_reload;;
6093             force-reload)   if pp_status >/dev/null; then
6094                                     pp_reload
6095                             else
6096                                     pp_restart
6097                             fi;;
6098             *)              pp_usage;;
6099         esac
6100 .
6101     chmod 755 $out
6102 }
6103
6104 pp_rpm_service_make_init_script () {
6105     local svc=$1
6106     local script=/etc/init.d/$svc
6107     local out=$pp_destdir$script
6108     local _process _cmd _rpmlevels
6109
6110     pp_add_file_if_missing $script run 755 || return 0
6111
6112     #-- start out as an empty shell script
6113     cat <<-'.' >$out
6114         #!/bin/sh
6115 .
6116
6117     #-- determine the process name from $cmd unless $svc_process is given
6118     set -- $cmd
6119     _process=${svc_process:-"$1"}
6120
6121     #-- construct a start command that builds a pid file if needed
6122     _cmd="$cmd";
6123     if test -z "$pidfile"; then
6124         pidfile=/var/run/$svc.pid
6125         _cmd="$cmd & echo \$! > \$pidfile"
6126     fi
6127     if test "$user" != "root"; then
6128         _cmd="su $user -c exec $_cmd";
6129     fi
6130
6131     #-- generate the Red Hat chkconfig headers
6132     _rpmlevels=`echo $start_runlevels | tr -d ' '`
6133     cat <<-. >>$out
6134         # chkconfig: ${_rpmlevels:--} ${start_priority:-50} ${stop_priority:-50}
6135         # description: ${svc_description:-no description}
6136         # processname: ${_process}
6137         # pidfile: ${pidfile}
6138 .
6139
6140     #-- generate the LSB init info
6141     cat <<-. >>$out
6142         ### BEGIN INIT INFO
6143         # Provides: ${svc}
6144         # Required-Start: ${lsb_required_start}
6145         # Should-Start: ${lsb_should_start}
6146         # Required-Stop: ${lsb_required_stop}
6147         # Default-Start: ${start_runlevels}
6148         # Default-Stop: ${stop_runlevels}
6149         # Short-Description: ${svc_description}
6150         ### END INIT INFO
6151         # Generated by PolyPackage ${pp_version}
6152         # ${copyright}
6153
6154 .
6155
6156     if test x"${svc_description}" = x"${pp_rpm_default_svc_description}"; then
6157         svc_description=
6158     fi
6159
6160     #-- write service-specific definitions
6161     cat <<. >>$out
6162         #-- definitions specific to service ${svc}
6163         svc_name="${svc_description:-$svc service}"
6164         user="${user}"
6165         pidfile="${pidfile}"
6166         stop_signal="${stop_signal}"
6167         reload_signal="${reload_signal}"
6168         pp_exec_cmd () { $_cmd; }
6169 .
6170
6171     #-- write the generic part of the init script
6172     cat <<'.' >>$out
6173
6174         #-- use system message logging, if available
6175         if [ -f /lib/lsb/init-functions -a ! -r /etc/redhat-release ]; then
6176             . /lib/lsb/init-functions
6177             pp_success_msg () { log_success_msg "$@"; }
6178             pp_failure_msg () { log_failure_msg "$@"; }
6179             pp_warning_msg () { log_warning_msg "$@"; }
6180         elif [ -f /etc/init.d/functions ]; then
6181             . /etc/init.d/functions
6182             pp_success_msg () { echo -n "$*"; success "$@"; echo; }
6183             pp_failure_msg () { echo -n "$*"; failure "$@"; echo; }
6184             pp_warning_msg () { echo -n "$*"; warning "$@"; echo; }
6185         else
6186             pp_success_msg () { echo ${1:+"$*:"} OK; }
6187             pp_failure_msg () { echo ${1:+"$*:"} FAIL; }
6188             pp_warning_msg () { echo ${1:+"$*:"} WARNING; }
6189         fi
6190
6191         #-- prints a status message
6192         pp_msg () { echo -n "$*: "; }
6193
6194         #-- prints usage message
6195         pp_usage () {
6196             echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
6197             return 2
6198         }
6199
6200         #-- reloads the service, if possible
6201         #   returns 0=success 1=failure 3=unimplemented
6202         pp_reload () {
6203             test -n "$reload_signal" || return 3 # unimplemented
6204             pp_msg "Reloading ${svc_name}"
6205             if pp_signal -${reload_signal}; then
6206                 pp_success_msg
6207                 return 0
6208             else
6209                 pp_failure_msg "not running"
6210                 return 1
6211             fi
6212         }
6213
6214         #-- delivers signal $1 to the pidfile
6215         #   returns 0=success 1=failure
6216         pp_signal () {
6217             if test -r "$pidfile"; then
6218                 read pid < $pidfile
6219                 kill "$@" "$pid" 2>/dev/null
6220             else
6221                 return 1
6222             fi
6223         }
6224
6225         #-- prints information about the service status
6226         #   returns 0=running 1=crashed 3=stopped
6227         pp_status () {
6228             pp_msg "Checking for ${svc_name}"
6229             if pp_signal -0; then
6230                 pp_success_msg "running"
6231                 return 0
6232             elif test -r "$pidfile"; then
6233                 pp_failure_msg "not running (crashed)"
6234                 return 1
6235             else
6236                 pp_failure_msg "not running"
6237                 return 3
6238             fi
6239         }
6240
6241         #-- starts the service
6242         #   returns 0=success 1=failure
6243         pp_start () {
6244             pp_msg "Starting ${svc_name}"
6245             if pp_status >/dev/null; then
6246                 pp_warning_msg "already started"
6247                 return 0
6248             elif pp_exec_cmd; then
6249                 pp_success_msg
6250                 return 0
6251             else
6252                 pp_failure_msg "cannot start"
6253                 return 1
6254             fi
6255         }
6256
6257         #-- stops the service
6258         #   returns 0=success (always)
6259         pp_stop () {
6260             pp_msg "Stopping ${svc_name}"
6261             if pp_signal -${stop_signal}; then
6262                 pp_success_msg
6263             else
6264                 pp_success_msg "already stopped"
6265             fi
6266             rm -f "$pidfile"
6267             return 0
6268         }
6269
6270         #-- stops and starts the service
6271         pp_restart () {
6272             pp_stop
6273             pp_start
6274         }
6275
6276         case "$1" in
6277             start)          pp_start;;
6278             stop)           pp_stop;;
6279             restart)        pp_restart;;
6280             status)         pp_status;;
6281             try-restart|condrestart)
6282                             if pp_status >/dev/null; then
6283                                     pp_restart
6284                             fi;;
6285             reload)         pp_reload;;
6286             force-reload)   if pp_status >/dev/null; then
6287                                     pp_reload
6288                             else
6289                                     pp_restart
6290                             fi;;
6291             *)              pp_usage;;
6292         esac
6293
6294 .
6295     chmod 755 $out
6296 }
6297 pp_backend_rpm_function () {
6298     case $1 in
6299         pp_mkgroup) cat<<'.';;
6300             /usr/sbin/groupadd -f -r "$1"
6301 .
6302         pp_mkuser:depends) echo pp_mkgroup;;
6303         pp_mkuser) cat<<'.';;
6304             pp_mkgroup "${2:-$1}" || return 1
6305             /usr/sbin/useradd \
6306                 -g "${2:-$1}" \
6307                 -M -d "${3:-/nonexistent}" \
6308                 -s "${4:-/bin/false}" \
6309                 -r "$1"
6310 .
6311         pp_havelib) cat<<'.';;
6312             for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do
6313                 test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0
6314             done
6315             return 1
6316 .
6317         *) false;;
6318     esac
6319 }
6320
6321 : NOTES <<.
6322
6323  # creating a dmg file for publishing on the web
6324     hdiutil create -srcfolder /path/foo foo.dmg
6325     hdiutil internet-enable -yes /path/foo.dmg
6326  # Layout for packages
6327     <name>-<cpy>/component/<file>
6328     <name>-<cpt>/extras/postinstall
6329     <name>-<cpt>/extras/postupgrade
6330  # /Developer/usr/bin/packagemaker (man packagemaker)
6331
6332     Make a bunch of packages, and then build a 'distribution'
6333     which is only understood by macos>10.4
6334
6335  # Message files in the resource path used are
6336     Welcome.{rtf,html,rtfd,txt} - limited text shown in Intro
6337     ReadMe.{rtf,html,rtfd,txt} - scrollable/printable, after Intro
6338     License.{rtf,html,rtfd,txt} - ditto, user must click 'Accept'
6339     background.{jpg,tif,gif,pict,eps,pdf} 620x418 background image
6340
6341  # These scripts looked for in the resource path
6342     InstallationCheck $pkgpath $defaultloc $targetvol
6343         0:ok 32:warn 32+x:warn[1] 64:stop 96+x:stop[2]
6344     VolumeCheck $volpath
6345         0:ok 32:failure 32+x:failure[3]
6346     preflight   $pkgpath $targetloc $targetvol    [priv]
6347     preinstall  $pkgpath $targetloc $targetvol    [priv]
6348     preupgrade  $pkgpath $targetloc $targetvol    [priv]
6349     postinstall $pkgpath $targetloc $targetvol    [priv]
6350     postupgrade $pkgpath $targetloc $targetvol    [priv]
6351     postflight  $pkgpath $targetloc $targetvol    [priv]
6352         0:ok else fail (for all scripts)
6353
6354     A detailed reason is deduced by finding an index x (16..31)
6355     in the file InstallationCheck.strings or VolumeCheck.strings.
6356
6357     Scripts marked [priv] are executed with root privileges.
6358     None of the [priv] scripts are used by metapackages.
6359
6360  # Default permissions
6361     Permissions of existing directories should match those
6362     of a clean install of the OS; typically root:admin 0775
6363     New directories or files should be 0775 or 0664 with the
6364     appropriate user:group.
6365     Exceptions:
6366         /etc    root:admin 0755
6367         /var    root:admin 0755
6368
6369     <http://developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution4/Concepts/sd_pkg_flags.html>
6370     Info.plist = {
6371      CFBundleGetInfoString: "1.2.3, Quest Software, Inc.",
6372      CFBundleIdentifier: "com.quest.rc.openssh",
6373      CFBundleShortVersionString: "1.2.3",
6374      IFMajorVersion: 1,
6375      IFMinorVersion: 2,
6376      IFPkgFlagAllowBackRev: false,
6377      IFPkgFlagAuthorizationAction: "AdminAuthorization",
6378      IFPkgFlagDefaultLocation: "/",
6379      IFPkgFlagFollowLinks: true,
6380      IFPkgFlagInstallFat: false,
6381      IFPkgFlagInstalledSize: <integer>,     # this is added by packagemaker
6382      IFPkgFlagIsRequired: false,
6383      IFPkgFlagOverwritePermissions: false,
6384      IFPkgFlagRelocatable: false,
6385      IFPkgFlagRestartAction: "NoRestart",
6386      IFPkgFlagRootVolumeOnly: false,
6387      IFPkgFlagUpdateInstalledLanguages: false,
6388      IFPkgFormatVersion= 0.10000000149011612,
6389      IFRequirementDicts: [ {
6390        Level = "requires",
6391        SpecArgument = "/opt/quest/lib/libvas.4.2.0.dylib",
6392        SpecType = "file",
6393        TestObject = true,
6394        TestOperator = "eq", } ]
6395     }
6396
6397     Description.plist = {
6398      IFPkgDescriptionDescription = "this is the description text",
6399      IFPkgDescriptionTitle = "quest-openssh"
6400     }
6401
6402  # Startup scripts
6403     'launchd' is a kind of combined inetd and rc/init.d system.
6404     <http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/DesigningDaemons.html>
6405     Create a /Library/LaunchDaemons/$daemonname.plist file
6406     Examples found in /System/Library/LaunchDaemons/
6407     See manual page launchd.plist(5) for details:
6408
6409     { Label: "com.quest.vintela.foo",                        # required
6410       Program: "/sbin/program",
6411       ProgramArguments: [ "/sbin/program", "arg1", "arg2" ], # required
6412       RunAtLoad: true,
6413       WatchPaths: [ "/etc/crontab" ],
6414       QueueDirectories: [ "/var/cron/tabs" ],
6415       inetdCompatibility: { Wait: false },                   # inetd-only
6416       OnDemand: false,                                       # recommended
6417       SessionCreate: true,
6418       UserName: "nobody",
6419       InitGroups: true,
6420       Sockets: {                                             # inetd only
6421         Listeners: {
6422            SockServiceName: "ssh",
6423            Bonjour: ["ssh", "sftp-ssh"], } },
6424       Disabled: false,
6425       StandardErrorPath: "/dev/null",
6426     }
6427
6428
6429     How to add a new user
6430         dscl . -create /Users/$user
6431         dscl . -create /Users/$user UserShell /bin/bash
6432         dscl . -create /Users/$user RealName "$user"
6433         dscl . -create /Users/$user UniqueID $uid
6434         dscl . -create /Users/$user PrimaryGroupID $gid
6435         dscl . -create /Users/$user NFSHomeDirectory /Users/$user
6436         dscl . -passwd /Users/$user "$passwd"
6437         mkdir /Users/$user
6438         chown $uid.$gid /Users/$user
6439
6440 .
6441
6442
6443 pp_platforms="$pp_platforms macos"
6444
6445 pp_backend_macos_detect () {
6446     [ x"$1" = x"Darwin" ]
6447 }
6448
6449 pp_backend_macos_init () {
6450     pp_macos_default_bundle_id_prefix="com.quest.rc."
6451     pp_macos_bundle_id=
6452     pp_macos_bundle_vendor=
6453     pp_macos_bundle_version=
6454     pp_macos_bundle_info_string=
6455     pp_macos_prog_packagemaker=/Developer/usr/bin/packagemaker
6456     pp_macos_pkg_domain=anywhere
6457     pp_macos_pkg_extra_flags=
6458     pp_macos_sudo=
6459     # OS X puts the library version *before* the .dylib extension
6460     pp_shlib_suffix='*.dylib'
6461 }
6462
6463 pp_macos_plist () {
6464     typeset in
6465     in=""
6466     while test $# -gt 0; do
6467      case "$1" in
6468
6469       start-plist) cat <<-.; in="  "; shift ;;
6470         <?xml version="1.0" encoding="UTF-8"?>
6471         <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
6472         <plist version="1.0">
6473 .
6474       end-plist) echo "</plist>"; in=; shift;;
6475
6476       '[')   echo "$in<array>"; in="$in  "; shift;;
6477       ']')   echo "$in</array>"; in="${in#  }"; shift;;
6478       '{')   echo "<dict>"; in="$in      "; shift;;
6479       '}')   echo "</dict>"; in="${in#      }"; shift;;
6480       key)         shift; echo "$in<key>$1</key>"; shift;;
6481       string)      shift;
6482                    echo "$1" | sed -e 's/&/&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;' \
6483                                    -e 's/^/'"$in"'<string>/;s/$/<\/string>/';
6484                    shift;;
6485       true)        echo "$in<true/>"; shift;;
6486       false)       echo "$in<false/>"; shift;;
6487       real)        shift; echo "$in<real>$1</real>"; shift;;
6488       integer)     shift; echo "$in<integer>$1</integer>"; shift;;
6489       date)        shift; echo "$in<date>$1</date>"; shift;; # ISO 8601 format
6490       data)        shift; echo "$in<data>$1</data>"; shift;; # base64 encoded
6491       *)           pp_error "pp_macos_plist: bad argument '$1'"; shift;;
6492      esac
6493     done
6494 }
6495
6496 pp_macos_rewrite_cpio () {
6497     typeset script
6498     script=$pp_wrkdir/cpio-rewrite.pl
6499     # rely on the fact that OS X comes with perl. It is a little easier to
6500     # re-write a binary stream with perl than it is with posix :)
6501     #
6502     # A CPIO header block has octal fields at the following offset/lengths:
6503     #   0  6 magic
6504     #   6  6 dev
6505     #  12  6 ino
6506     #  18  6 mode
6507     #  24  6 uid
6508     #  30  6 gid
6509     #  36  6 nlink
6510     #  42  6 rdev
6511     #  48 11 mtime
6512     #  59  6 namesize
6513     #  65 11 filesize
6514     #  76    --
6515     cat <<-'.' >$script
6516         while (<DATA>) {
6517                 my ($type,$mode,$uid,$gid,$flags,$name) =
6518                     m/^(.) (\d+) (\S+) (\S+) (\S+) (.*)/;
6519                 $uid = 0 if $uid eq "-";
6520                 $gid = 0 if $gid eq "-";
6521                 if ($uid ne "=" and $uid =~ m/\D/) {
6522                         my @pw = getpwnam($uid) or die "bad username '$uid'";
6523                         $uid = $pw[2];
6524                 }
6525                 if ($gid ne "=" and $gid =~ m/\D/) {
6526                         my @gr = getgrnam($gid) or die "bad group '$gid'";
6527                         $gid = $gr[2];
6528                 }
6529                 $name = ".".$name."\0";
6530                 $ok{$name} = 1;
6531                 $uid{$name} = sprintf("%06o",int($uid)) unless $uid eq "=";
6532                 $gid{$name} = sprintf("%06o",int($gid)) unless $gid eq "=";
6533                 $mode{$name} = sprintf("%06o",oct($mode)) unless $mode eq "=";
6534         }
6535         $ok{"TRAILER!!!\0"} = 1;
6536         while (!eof STDIN) {
6537                 read STDIN, $header, 76;
6538                 die "bad magic" unless $header =~ m/^070707/;
6539                 $namesize = oct(substr($header,59,6));
6540                 $filesize = oct(substr($header,65,11));
6541                 read STDIN, $name, $namesize;
6542                 # convert uid and gid to 0
6543                 substr($header, 24, 6) = $uid{$name} if defined($uid{$name});
6544                 substr($header, 30, 6) = $gid{$name} if defined($gid{$name});
6545                 substr($header, 18, 6) = $mode{$name} if defined($mode{$name});
6546                 print ($header, $name) if $ok{$name};
6547                 # copy-through the file data
6548                 while ($filesize > 0) {
6549                         my $seg = 8192;
6550                         $seg = $filesize if $filesize < $seg;
6551                         undef $data;
6552                         read STDIN, $data, $seg;
6553                         print $data if $ok{$name};
6554                         $filesize -= $seg;
6555                 }
6556         }
6557         exit(0);
6558         __DATA__
6559 .
6560     # Append to the script the %files data
6561     cat "$@" </dev/null >> $script
6562     /usr/bin/perl $script || pp_error "pp_macos_rewrite_cpio error";
6563 }
6564
6565 pp_macos_files_bom () {
6566     typeset _l t m o g f p st owner
6567     while read t m o g f p st; do
6568         # make sure that $m is padded up to 4 digits long
6569         case "$m" in
6570             ?) m="000$m";;
6571             ??) m="00$m";;
6572             ???) m="0$m";;
6573             ?????*) pp_fatal "pp_macos_writebom: mode '$m' too long";;
6574         esac
6575
6576         # convert owner,group into owner/group in octal
6577         case $o in -)   o=0;; esac
6578         case $g in -)   g=0;; esac
6579         owner=`pp_d2o $o`/`pp_d2o $g`
6580
6581         case $t in
6582             f)
6583                 echo ".$p       10$m    $owner  `
6584                     /usr/bin/cksum < "${pp_destdir}$p" |
6585                     awk '{print $2 "    " $1}'`";;
6586             d)
6587                 echo ".${p%/}   4$m     $owner";;
6588             s)
6589                 rl=`/usr/bin/readlink "${pp_destdir}$p"`
6590                 #test x"$rl" = x"$st" ||
6591                 #    pp_error "symlink mismatch $rl != $st"
6592                 echo ".$p       12$m    $owner  `
6593                     /usr/bin/readlink -n "${pp_destdir}$p" |
6594                     /usr/bin/cksum |
6595                     awk '{print $2 "    " $1}'` $st";;
6596         esac
6597     done
6598 }
6599
6600 pp_macos_bom_fix_parents () {
6601     perl -pe '
6602         sub dirname { my $d=shift; $d=~s,/[^/]*$,,; $d; }
6603         sub chk { my $d=shift;
6604                   &chk(&dirname($d)) if $d =~ m,/,;
6605                   unless ($seen{$d}++) {
6606                       print "$d\t40755\t0/0\n";
6607                   }
6608                 }
6609         m/^\S+/;
6610         &chk(&dirname($&));'
6611 }
6612
6613 pp_macos_files_size () {
6614     typeset _l t m o g f p st owner
6615     while read t m o g f p st; do
6616         case $t in
6617             f)  wc -c < "${pp_destdir}$p";;
6618             s)  echo 4095;;
6619             d)  ;; # always seems to be zero
6620         esac
6621     done | awk '{n+=1+int($1/4096)} END {print n*4}'
6622 }
6623
6624 pp_o2d () {
6625     awk 'BEGIN { x=0; '`echo "$1" |
6626         sed -e 's/./x=x*8+&;/g'`'print x;}' </dev/null
6627 }
6628 pp_d2o () {
6629     case "$1" in
6630         [0-7]) echo $1;;
6631         *) awk 'BEGIN { printf("%o\n", 0+('"$1"'));}' < /dev/null;;
6632     esac
6633 }
6634
6635 pp_macos_mkbom () {
6636     #/usr/bin/mkbom -i $1 $2
6637     typeset path mode ugid size cksum linkpath
6638     typeset bomstage
6639
6640     # Use mkbom if it understands -i (avoids a copy)
6641     if /usr/bin/mkbom -i /dev/null "$2" 2>/dev/null; then
6642         rm -f "$2"
6643         /usr/bin/mkbom -i "$1" "$2"
6644         return
6645     fi
6646
6647     # On 10.4 we have this nonsense.
6648     pp_warn "mkbom workaround: copying source files to staging area"
6649
6650     bomstage=$pp_wrkdir/bom_stage
6651     while IFS=' ' read path mode ugid size cksumi linkpath; do
6652         if test -h "$pp_destdir/$path"; then
6653             $pp_macos_sudo /bin/ln -s "$linkpath" "$bomstage/$path"
6654         else
6655             if test -d "$pp_destdir/$path"; then
6656                 $pp_macos_sudo /bin/mkdir -p "$bomstage/$path"
6657             else
6658                 $pp_macos_sudo /bin/cp "$pp_destdir/$path" "$bomstage/$path"
6659             fi
6660             $pp_macos_sudo /bin/chmod $mode "$bomstage/$path"
6661             $pp_macos_sudo /usr/sbin/chown `echo $ugid| tr / :` "$bomstage/$path"
6662         fi
6663     done <"$1"
6664     (cd $bomstage && $pp_macos_sudo mkbom . $pp_wrkdir/bom_stage.bom) ||
6665         pp_error "mkbom failed"
6666     $pp_macos_sudo mv $pp_wrkdir/bom_stage.bom "$2"
6667 }
6668
6669 pp_backend_macos () {
6670     typeset pkgdir Contents Resources lprojdir
6671     typeset Info_plist Description_plist
6672     typeset bundle_vendor bundle_version size
6673
6674     mac_version=`sw_vers -productVersion`
6675     bundle_vendor=${pp_macos_bundle_vendor:-$vendor}
6676
6677     if test -z "$pp_macos_bundle_version"; then
6678         bundle_version=`echo "$version.0.0.0" | sed -n -e 's/[^0-9.]//g' \
6679             -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'`
6680         #if test x"$bundle_version" != x"$version"; then
6681         #    pp_warn "converted version from '$version' to '$bundle_version'"
6682         #fi
6683     else
6684         bundle_version="$pp_macos_bundle_version"
6685     fi
6686     source_version=`echo $version | sed 's/.*\.//'`
6687
6688     # build the package layout
6689     pkgdir=$pp_wrkdir/$name.pkg
6690     Contents=$pkgdir/Contents
6691     Resources=$Contents/Resources
6692     lprojdir=$Resources/en.lproj
6693     mkdir $pkgdir $Contents $Resources $lprojdir ||
6694         pp_fatal "Can't make package temporary directories"
6695
6696     echo "major: 1" > $Resources/package_version
6697     echo "minor: 0" >> $Resources/package_version
6698     echo "pmkrpkg1" > $Contents/PkgInfo
6699     case $mac_version in
6700         "10.6"*)
6701             xattr -w "com.apple.TextEncoding" "macintosh;0" "$Resources/package_version"
6702             xattr -w "com.apple.TextEncoding" "macintosh;0" "$Resources/PkgInfo"
6703             ;;
6704     esac
6705
6706     # compute the installed size
6707     size=`cat $pp_wrkdir/%files.* | pp_macos_files_size`
6708
6709     #-- Create Info.plist
6710     Info_plist=$Contents/Info.plist
6711     pp_macos_plist \
6712         start-plist \{ \
6713         key CFBundleGetInfoString string \
6714             "${pp_macos_bundle_info_string:-$version $bundle_vendor}" \
6715         key CFBundleIdentifier string \
6716             "${pp_macos_bundle_id:-$pp_macos_default_bundle_id_prefix$name}" \
6717     key CFBundleName string "$name" \
6718         key CFBundleShortVersionString string "$bundle_version" \
6719         key IFMajorVersion integer 1 \
6720         key IFMinorVersion integer 0 \
6721         key IFPkgFlagAllowBackRev false \
6722         key IFPkgFlagAuthorizationAction string "RootAuthorization" \
6723         key IFPkgFlagDefaultLocation string "/" \
6724         key IFPkgFlagFollowLinks true \
6725         key IFPkgFlagInstallFat true \
6726         key IFPkgFlagInstalledSize integer $size \
6727         key IFPkgFlagIsRequired false \
6728         key IFPkgFlagOverwritePermissions true \
6729         key IFPkgFlagRelocatable false \
6730         key IFPkgFlagRestartAction string "NoRestart" \
6731         key IFPkgFlagRootVolumeOnly true \
6732         key IFPkgFlagUpdateInstalledLanguages false \
6733         key IFPkgFlagUseUserMask false \
6734         key IFPkgFormatVersion real 0.10000000149011612 \
6735         key SourceVersion string $source_version \
6736         \} end-plist> $Info_plist
6737
6738     # write en.lproj/Description.plist
6739     Description_plist=$lprojdir/Description.plist
6740     pp_macos_plist \
6741         start-plist \{ \
6742         key IFPkgDescriptionDeleteWarning string "" \
6743             key IFPkgDescriptionDescription string "$pp_macos_bundle_info_string" \
6744             key IFPkgDescriptionTitle       string "$name" \
6745             key IFPkgDescriptionVersion string "$version" \
6746         \} end-plist > $Description_plist
6747
6748         # write Resources/files
6749     cat $pp_wrkdir/%files.* | awk '{print $6}' > $Resources/files
6750
6751     # write package size file
6752     printf \
6753 "NumFiles 0
6754 InstalledSize $size
6755 CompressedSize 0
6756 " > $Resources/$name.sizes
6757
6758     # write Resources/postinstall
6759     for cmp in $pp_components; do
6760         if test -s $pp_wrkdir/%pre.$cmp; then
6761             if test ! -s $Resources/preinstall; then
6762                 echo "#!/bin/sh" > $Resources/preinstall
6763                 chmod +x $Resources/preinstall
6764             fi
6765             cat $pp_wrkdir/%pre.$cmp >> $Resources/preinstall
6766             echo : >> $Resources/preinstall
6767         fi
6768     done
6769
6770     # write Resources/postinstall
6771     for cmp in $pp_components; do
6772         if test -s $pp_wrkdir/%post.$cmp; then
6773             if test ! -s $Resources/postinstall; then
6774                 echo "#!/bin/sh" > $Resources/postinstall
6775                 chmod +x $Resources/postinstall
6776             fi
6777             cat $pp_wrkdir/%post.$cmp >> $Resources/postinstall
6778             echo : >> $Resources/postinstall
6779         fi
6780     done
6781
6782     # write Resources/postupgrade)
6783     for cmp in $pp_components; do
6784         if test -s $pp_wrkdir/%postup.$cmp; then
6785             if test ! -s $Resources/postupgrade; then
6786                 echo "#!/bin/sh" > $Resources/postupgrade
6787                 chmod +x $Resources/postupgrade
6788             fi
6789             cat $pp_wrkdir/%postup.$cmp >> $Resources/postupgrade
6790             echo : >> $Resources/postupgrade
6791         fi
6792     done
6793
6794     # write Resources/preremove)
6795     for cmp in $pp_components; do
6796         if test -s $pp_wrkdir/%preun.$cmp; then
6797             if test ! -s $Resources/preremove; then
6798                 echo "#!/bin/sh" > $Resources/preremove
6799                 chmod +x $Resources/preremove
6800             fi
6801             cat $pp_wrkdir/%preun.$cmp >> $Resources/preremove
6802             echo : >> $Resources/preremove
6803         fi
6804     done
6805
6806     # write Resources/postremove)
6807     for cmp in $pp_components; do
6808         if test -s $pp_wrkdir/%postun.$cmp; then
6809             if test ! -s $Resources/postremove; then
6810                 echo "#!/bin/sh" > $Resources/postremove
6811                 chmod +x $Resources/postremove
6812             fi
6813             cat $pp_wrkdir/%postun.$cmp >> $Resources/postremove
6814             echo : >> $Resources/postremove
6815         fi
6816     done
6817
6818     # write uninstall info
6819     echo "version=$version" > $Resources/uninstall
6820     if [ -n "$pp_macos_requires" ];then
6821         echo "requires=$pp_macos_requires" >> $Resources/uninstall
6822     fi
6823
6824     # Create the bill-of-materials (Archive.bom)
6825     cat $pp_wrkdir/%files.* | pp_macos_files_bom | sort |
6826         pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls
6827
6828     pp_macos_mkbom $pp_wrkdir/tmp.bomls $Contents/Archive.bom
6829
6830     # Create the cpio archive (Archive.pax.gz)
6831     # On 10.5, we used "-f -" to write explicitly to stdout
6832     (
6833     cd $pp_destdir &&
6834     cat $pp_wrkdir/%files.* | awk '{ print "." $6 }' | sed '/\/$/d' | sort | /bin/pax -w -f - | gzip -9 -c > $Contents/Archive.pax.gz
6835     )
6836
6837         $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage
6838
6839     hdiutil create -fs HFS+ -srcfolder $pkgdir -volname $name ${name}-${version}.dmg
6840 }
6841
6842 pp_backend_macos_cleanup () {
6843     :
6844 }
6845
6846 pp_backend_macos_names () {
6847     echo ${name}.pkg
6848 }
6849
6850 pp_backend_macos_install_script () {
6851     echo '#!/bin/sh'
6852     typeset pkgname platform
6853
6854     pkgname="`pp_backend_macos_names`"
6855     platform="`pp_backend_macos_probe`"
6856     pp_install_script_common
6857
6858     cat <<.
6859         test \$# -eq 0 && usage
6860         op="\$1"; shift
6861
6862         case "\$op" in
6863         list-components)
6864             test \$# -eq 0 || usage \$op
6865             echo "$pp_components"
6866             ;;
6867         list-services)
6868             test \$# -eq 0 || usage \$op
6869             echo "$pp_services"
6870             ;;
6871         list-files)
6872             test \$# -ge 1 || usage \$op
6873             echo \${PP_PKGDESTDIR:-.}/"$pkgname"
6874             ;;
6875         install)
6876             test \$# -ge 1 || usage \$op
6877             vol=/Volumes/pp\$\$
6878             pkg=\$vol/${name}-${version}.pkg
6879             hdiutil attach -readonly -mountpoint \$vol \
6880                 \${PP_PKGDESTDIR:-.}/"$pkgname"
6881             trap "hdiutil detach \$vol" 0
6882             installer -pkginfo -pkg \$pkg
6883             installer -verbose -pkg \$pkg -target /
6884             ;;
6885         uninstall)
6886             test \$# -ge 1 || usage \$op
6887             # XXX
6888             echo "Uninstall not implemented" >&2
6889             exit 1;;
6890         start|stop)
6891             test \$# -ge 1 || usage \$op
6892             ec=0
6893             for svc
6894             do
6895                 # XXX
6896                 echo "\${op} not implemented" >&2
6897                 ec=1
6898             done
6899             exit \$ec
6900             ;;
6901         print-platform)
6902             echo "$platform"
6903             ;;
6904         *)
6905             usage;;
6906         esac
6907 .
6908 }
6909
6910 pp_backend_macos_init_svc_vars () {
6911     :
6912 }
6913
6914 pp_backend_macos_probe () {
6915     typeset name vers arch
6916     case `sw_vers -productName` in
6917          "Mac OS X") name="macos";;
6918          *)          name="unknown";;
6919     esac
6920     vers=`sw_vers -productVersion | sed -e 's/^\([^.]*\)\.\([^.]*\).*/\1\2/'`
6921     arch=`arch`
6922     echo "$name$vers-$arch"
6923 }
6924
6925 pp_backend_macos_vas_platforms () {
6926     echo "osx"    # XXX non-really sure what they do.. it should be "macos"
6927 }
6928 pp_backend_macos_function () {
6929     case $1 in
6930         _pp_macos_search_unused) cat<<'.';;
6931             # Find an unused value in the given path
6932             # args: path attribute minid [maxid]
6933                 pp_tmp_val=$3
6934                 while :; do
6935                     test $pp_tmp_val -ge ${4:-999999} && return 1
6936                     /usr/bin/dscl . -search "$1" "$2" $pp_tmp_val |
6937                         grep . > /dev/null || break
6938                     pp_tmp_val=`expr $pp_tmp_val + 1`
6939                 done
6940                 echo $pp_tmp_val
6941 .
6942         pp_mkgroup:depends) echo _pp_macos_search_unused;;
6943         pp_mkgroup) cat<<'.';;
6944             set -e
6945             /usr/bin/dscl . -read /Groups/"$1" >/dev/null 2>&1 && return
6946             pp_tmp_gid=`_pp_macos_search_unused /Groups PrimaryGroupID 100`
6947             /usr/bin/dscl . -create /Groups/"$1"
6948             /usr/bin/dscl . -create /Groups/"$1" PrimaryGroupID $pp_tmp_gid
6949             /usr/bin/dscl . -create /Groups/"$1" RealName "Group $1"
6950             /usr/bin/dscl . -create /Groups/"$1" GroupMembership ""
6951             /usr/bin/dscl . -create /Groups/"$1" Password '*'
6952 .
6953         pp_mkuser:depends) echo pp_mkgroup _pp_macos_search_unused;;
6954         pp_mkuser) cat<<'.';;
6955             set -e
6956             /usr/bin/dscl . -read /Users/"$1" >/dev/null 2>&1 && return
6957             pp_tmp_uid=`_pp_macos_search_unused /Users UniqueID 100`
6958             pp_mkgroup "${2:-$1}"
6959             pp_tmp_gid=`/usr/bin/dscl . -read /Groups/"${2:-$1}" \
6960                 PrimaryGroupID | awk '{print $2}'`
6961             /usr/bin/dscl . -create /Users/"$1"
6962             /usr/bin/dscl . -create /Users/"$1" PrimaryGroupID $pp_tmp_gid
6963             /usr/bin/dscl . -create /Users/"$1" NFSHomeDirectory \
6964                                     "${3:-/var/empty}"
6965             /usr/bin/dscl . -create /Users/"$1" UserShell \
6966                                     "${4:-/usr/bin/false}"
6967             /usr/bin/dscl . -create /Users/"$1" RealName "$1"
6968             /usr/bin/dscl . -create /Users/"$1" UniqueID $pp_tmp_uid
6969             /usr/bin/dscl . -create /Users/"$1" Password '*'
6970 .
6971         pp_havelib) cat<<'.';;
6972             # (use otool -L to find dependent libraries)
6973             for pp_tmp_dir in `echo "${3:+$3:}/usr/local/lib:/lib:/usr/lib" |
6974                     tr : ' '`; do
6975                 test -r "$pp_tmp_dir/lib$1{$2:+.$2}.dylib" && return 0
6976             done
6977             return 1
6978 .
6979         *) false;;
6980     esac
6981 }
6982
6983 pp_platforms="$pp_platforms inst"
6984
6985 pp_backend_inst_detect () {
6986     case "$1" in
6987         IRIX*)  return 0;;
6988         *)      return 1;;
6989     esac
6990 }
6991
6992 pp_backend_inst_init () {
6993     pp_readlink_fn=pp_ls_readlink
6994 }
6995
6996 pp_backend_inst_create_idb()
6997 {
6998     typeset t m o g f p st
6999
7000     while read t m o g f p st; do
7001         if test x"$o" = x"-"; then
7002             o="root"
7003         fi
7004         if test x"$g" = x"-"; then
7005             g="sys"
7006         fi
7007         case "$t" in
7008             f)  test x"$m" = x"-" && m=444
7009                 echo "f 0$m $o $g $p $p $name.sw.base"
7010                 ;;
7011             d)  test x"$m" = x"-" && m=555
7012                 echo "d 0$m $o $g $p $p $name.sw.base"
7013                 ;;
7014             s)  test x"$m" = x"-" && m=777
7015                 test x"$m" = x"777" ||
7016                     pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
7017                 echo "l 0$m $o $g $p $p $name.sw.base symval($st)"
7018                 ;;
7019         esac
7020     done
7021 }
7022
7023 pp_backend_inst_create_spec()
7024 {
7025     echo "product $name"
7026     echo "    id \"${summary}. Version: ${version}\""
7027     echo "    image sw"
7028     echo "        id \"Software\""
7029     echo "        version $version"
7030     echo "        order 9999"
7031     echo "        subsys base"
7032     echo "            id \"Base Software\""
7033     echo "            replaces self"
7034     echo "            exp $name.sw.base"
7035     echo "        endsubsys"
7036     echo "    endimage"
7037     echo "endproduct"
7038 }
7039
7040 pp_backend_inst () {
7041     curdir=`pwd`
7042
7043     cd "$pp_opt_wrkdir"
7044
7045     # initialize
7046     pp_inst_tardist=tardist
7047     pp_inst_spec=${name}.spec
7048     pp_inst_idb=${name}.idb
7049  
7050     rm -rf $pp_inst_tardist $pp_inst_spec $pp_inst_idb
7051     mkdir -p $pp_inst_tardist
7052
7053     # Create idb file
7054     (for _cmp in $pp_components; do
7055         cat  %files.$_cmp | sort +4u -6 | pp_backend_inst_create_idb
7056     done) >> $pp_inst_idb
7057
7058     pp_backend_inst_create_spec >> $pp_inst_spec
7059
7060     # Generate tardist
7061     gendist -verbose -all -root / -source $pp_opt_destdir -idb $pp_inst_idb -spec $pp_inst_spec -dist $pp_inst_tardist $name
7062     tar -cvf `pp_backend_inst_names` $pp_inst_tardist
7063
7064     cd "$curdir"
7065 }
7066
7067 pp_backend_inst_cleanup () {
7068     :
7069 }
7070
7071 pp_backend_inst_names () {
7072     echo ${name}-${version}.tardist
7073 }
7074
7075 pp_backend_inst_install_script () {
7076     :
7077 }
7078
7079 pp_backend_inst_function () {
7080     echo false
7081 }
7082
7083 pp_backend_inst_init_svc_vars () {
7084     :
7085 }
7086
7087 pp_backend_inst_probe () {
7088     cpu=`hinv|sed -n '/^CPU/{s/000 /k /;s/^CPU: //;s/ Process.*//;s/^MIPS //;p;q;}'|tr A-Z a-z`
7089     echo irix`uname -r`-$cpu
7090 }
7091
7092 pp_backend_inst_vas_platforms () {
7093     echo "irix-65"
7094 }
7095
7096 pp_platforms="$pp_platforms null"
7097
7098 pp_backend_null_detect () {
7099     ! :
7100 }
7101
7102 pp_backend_null_init () {
7103     :
7104 }
7105
7106
7107 pp_backend_null () {
7108     :
7109 }
7110
7111 pp_backend_null_cleanup () {
7112     :
7113 }
7114
7115 pp_backend_null_names () {
7116     :
7117 }
7118
7119 pp_backend_null_install_script () {
7120     :
7121 }
7122
7123 pp_backend_null_function () {
7124     echo false
7125 }
7126
7127 pp_backend_null_init_svc_vars () {
7128     :
7129 }
7130
7131 pp_backend_null_probe () {
7132     echo unknown-unknown
7133 }
7134
7135 pp_backend_null_vas_platforms () {
7136 :
7137 }
7138
7139
7140 quest_require_vas () {
7141     typeset v d
7142
7143     if test $# -ne 1; then
7144         return
7145     fi
7146     set -- `echo "$1" | tr . ' '` 0 0 0
7147
7148     for d
7149     do
7150         echo $d | grep '^[0-9][0-9]*$' > /dev/null ||
7151             pp_error "quest_require_vas: Bad version component $d"
7152     done
7153
7154     test $# -lt 4 &&
7155             pp_error "quest_require_vas: missing version number"
7156
7157     case "$1.$2.$3.$4" in
7158         *.0.0.0) v=$1;;
7159         *.*.0.0) v=$1.$2;;
7160         *.*.*.0) v=$1.$2.$3;;
7161         *)       v=$1.$2.$3.$4;;
7162     esac
7163
7164     cat <<.
7165         if test -x /opt/quest/bin/vastool &&
7166            /opt/quest/bin/vastool -v |
7167             awk 'NR == 1 {print \$4}' |
7168             awk -F. '{ if (\$1<$1 || \$1==$1 && ( \
7169                            \$2<$2 || \$2==$2 && ( \
7170                            \$3<$3 || \$2==$3 && ( \
7171                            \$4<$4 )))) exit(1); }'
7172         then
7173             exit 0
7174         else
7175             echo "Requires VAS $v or later"
7176             exit 1
7177         fi
7178 .
7179 }
7180 pp_main ${1+"$@"}