#!/bin/sh
# (c) 2008 Quest Software, Inc. All rights reserved
pp_revision="exported"

 # (c) 2008 Quest Software, Inc.  All rights reserved.
 # 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 # are met:
 # 
 # 1. Redistributions of source code must retain the above copyright
 #    notice, this list of conditions and the following disclaimer.
 # 2. Redistributions in binary form must reproduce the above copyright
 #    notice, this list of conditions and the following disclaimer in the
 #    documentation and/or other materials provided with the distribution.
 # 3. Neither the name of Quest Software, Inc. nor the names of its
 #    contributors may be used to endorse or promote products derived from
 #    this software without specific prior written permission.
 # 
 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 # Please see <http://rc.vintela.com/topics/polypkg/> for more information

pp_version="1.0.0.$pp_revision"
pp_copyright="(c) 2008, Quest Software, Inc. All rights reserved."

pp_opt_debug=false
pp_opt_destdir="$DESTDIR"
pp_opt_install_script=
pp_opt_list=false
pp_opt_no_clean=false
pp_opt_no_package=false
pp_opt_only_front=false
pp_opt_platform=
pp_opt_probe=false
pp_opt_vas_platforms=false
pp_opt_wrkdir="${TMPDIR:-/var/tmp}/pp.work.$$"
pp_opt_verbose=false
pp_opt_version=false
pp_opt_input="-"
pp_opt_init_vars=""
pp_opt_eval=

test -n "$PP_NO_CLEAN" && pp_opt_no_clean=true
test -n "$PP_DEBUG" && pp_opt_debug=true

pp_main_cleanup () {
	pp_debug "main_cleanup"
        pp_remove_later_now
	if $pp_opt_no_clean || test x"$pp_platform" = x"unknown"; then
	    : no cleanup
	else
	    pp_backend_${pp_platform}_cleanup
	    $pp_errors && pp_die "Errors during cleanup"
	    if test -d "$pp_wrkdir"; then
		pp_debug "removing $pp_wrkdir"
		rm -rf "$pp_wrkdir"
	    fi
	fi
}

pp_parseopts () {
        typeset a n _var _val
	while test $# -gt 0; do

	  # convert -[dilpv] to --long-options
	  case "$1" in
	    --?*=?*) n=`echo "$1" | sed -ne 's/^--\([^=]*\)=.*/\1/p'`
	           a=`echo "$1" | sed -ne 's/^--[^=]*=\(.*\)/\1/p'`
		   shift
		   set -- "--$n" "$a" ${1+"$@"};;
	    --?*) : ;;

	    -d)  shift; set -- "--debug" ${1+"$@"};;
	    -d*) a=`echo "$1" | sed -ne 's/^-.//'` 
		 shift; set -- "--debug" ${1+"$@"};;

	    -i) shift; set -- "--install-script" ${1+"$@"};;
	    -i*) a=`echo "$1" | sed -ne 's/^-.//'`
		 shift; set -- "--install-script" "$a" ${1+"$@"};;

	    -l)  shift; set -- "--list" ${1+"$@"};;
	    -l*) a=`echo "$1" | sed -ne 's/^-.//'` 
		 shift; set -- "--list" ${1+"$@"};;

	    -p) shift; set -- "--platform" ${1+"$@"};;
	    -p*) a=`echo "$1" | sed -ne 's/^-.//'`
		 shift; set -- "--platform" "$a" ${1+"$@"};;

	    -v)  shift; set -- "--verbose" ${1+"$@"};;
	    -v*) a=`echo "$1" | sed -ne 's/^-.//'` 
		 shift; set -- "--verbose" ${1+"$@"};;

	    -\?)  shift; set -- "--help" ${1+"$@"};;
	    -\?*) a=`echo "$1" | sed -ne 's/^-.//'` 
		 shift; set -- "--help" ${1+"$@"};;
	  esac

	  case "$1" in
	    --destdir|--eval|--install-script|--platform|--wrkdir)
		test $# -ge 2 || pp_error "missing argument to $1";;
	  esac

	  case "$1" in
	    --) 				       shift;break;;
	    --debug)           pp_opt_debug=true;      shift;;
	    --destdir)         pp_opt_destdir="$2";    shift;shift;;
	    --eval)            pp_opt_eval="$2";       shift;shift;; # undoc
	    --install-script)  pp_opt_install_script="$2"; shift;shift;;
	    --list)            pp_opt_list=true;       shift;;
	    --no-clean)        pp_opt_no_clean=true;   shift;;
	    --no-package)      pp_opt_no_package=true; shift;;
	    --only-front)      pp_opt_only_front=true; shift;;
	    --platform)        pp_opt_platform="$2";   shift;shift;;
	    --probe)           pp_opt_probe=true;      shift;;
	    --wrkdir)          pp_opt_wrkdir="$2";     shift;shift;;
	    --vas-platforms)   pp_opt_vas_platforms=true; shift;;
	    --verbose)         pp_opt_verbose=true;    shift;;
	    --version)         pp_opt_version=true;    shift;;
	    --help)            pp_errors=true;         shift;;
	    -) break;;
	    -*) pp_error "unknown option $1"; shift;;
	    *) break;;
	  esac

	done

	pp_opt_input=-
	if test $# -gt 0; then
	    pp_opt_input="$1"
	    shift
	fi

        #-- extra arguments of the form Foo=bar alter *global* vars
        while test $# -gt 0; do
            case "$1" in
		-*)	pp_error "unexpected option '$1'"
			shift;;
                *=*)    _val="${1#*=}"
                        _var=${1%="$_val"}
                        _val=`echo "$_val"|sed -e 's/[$"\\]/\\&/g'`
                        pp_debug "setting $_var = \"$_val\""
                        pp_opt_init_vars="$pp_opt_init_vars$_var=\"$_val\";"
                        shift;;
                *)      pp_error "unexpected argument $1'"
			shift;;
            esac
        done

	test $# -gt 0 &&
            pp_error "unknown argument $1"

	if $pp_errors; then 
	    cat <<. >&2
polypkg $pp_version $pp_copyright
usage: $0 [options] [input.pp] [var=value ...]
    -d --debug                  -- write copious info to stderr
       --destdir=path           -- file root, defaults to \$DESTDIR
    -? --help                   -- display this information
    -i --install-script=path    -- create an install helper script
    -l --list                   -- write package filenames to stdout
       --no-clean               -- don't remove temporary files
       --no-package             -- do everything but create packages
       --only-front             -- only perform front-end actions
    -p --platform=platform      -- defaults to local platform
       --probe                  -- print local system identifier, then exit
       --wrkdir=path            -- defaults to subdirectory of \$TMPDIR or /tmp
    -v --verbose                -- write info to stderr
       --version                -- display version and quit
.
	    exit 1
	fi
}

pp_drive () {
	# initialise the front and back ends
        pp_model_init
	pp_frontend_init
	$pp_opt_only_front || pp_backend_init

	# run the front-end to generate the intermediate files
        # set $pp_input_dir to be the 'include dir' if needed
	pp_debug "calling frontend on $pp_opt_input"
	case "$pp_opt_input" in 
	    -)   pp_input_dir=.
		 test -t 1<&0 && 
		    pp_warn "reading directives from standard input"
                 pp_frontend
                 ;;
            */*) pp_input_dir=${pp_opt_input%/*}
	         pp_frontend <"$pp_opt_input"
                 ;;
            *)   pp_input_dir=.
	         pp_frontend <"$pp_opt_input"
                 ;;
	esac

        pp_files_ignore_others
        pp_service_scan_groups

	# some sanity checks after front-end processing
        if test x"$pp_platform" != x"null"; then
	    pp_debug "sanity checks"
	    test -n "$pp_components" || pp_error "No components?"
	    pp_check_var_is_defined  "name"
	    pp_check_var_is_defined  "version"
            pp_files_check_duplicates
            pp_files_check_coverage
	    pp_die_if_errors "Errors during sanity checks"
        fi

	# stop now if we're only running the front
	$pp_opt_only_front && return

	# run the back-end to generate the package
	pp_debug "calling backend"
	pp_backend
	pp_die_if_errors "Errors during backend processing"

	# copy the resulting package files to PP_PKGDESTDIR or .
	for f in `pp_backend_names` -; do
           test x"$f" = x"-" && continue
	   pp_debug "copying: $f to `pwd`"
	   if pp_verbose cp $pp_wrkdir/$f ${PP_PKGDESTDIR:-.}; then
               echo "${PP_PKGDESTDIR:+$PP_PKGDESTDIR/}$f"
           else
               pp_error "$f: missing package"
           fi
	done
	pp_die_if_errors "Errors during package copying"
}

pp_install_script () {
        pp_debug "writing install script to $pp_opt_install_script"
        rm -f $pp_opt_install_script
        pp_backend_install_script > $pp_opt_install_script
	pp_die_if_errors "Errors during package install script"
        chmod +x $pp_opt_install_script
}

pp_main () {

	pp_set_expand_converter_or_reexec ${1+"$@"}
	pp_parseopts ${1+"$@"}

        if $pp_opt_version; then
            #-- print version and exit 
            echo "polypkg $pp_version"
            exit 0
        fi

	pp_set_platform

	trap 'pp_main_cleanup' 0

	pp_wrkdir="$pp_opt_wrkdir"
	pp_debug "pp_wrkdir = $pp_wrkdir"
	rm -rf "$pp_wrkdir"
	mkdir -p "$pp_wrkdir"

	pp_destdir="$pp_opt_destdir"
	pp_debug "pp_destdir = $pp_destdir"

        if $pp_opt_probe; then
	    pp_backend_init
            pp_backend_probe
        elif $pp_opt_vas_platforms; then
	    pp_backend_init
            pp_backend_vas_platforms
	elif test -n "$pp_opt_eval"; then
	    #-- execute a shell command
	    eval "$pp_opt_eval" || exit
	else
	    pp_drive
	    if test -n "$pp_opt_install_script"; then
		pp_install_script
	    fi
        fi

	exit 0
}


pp_errors=false

if test -n "$TERM" -a -t 1 && (tput op) >/dev/null 2>/dev/null; then
   pp_col_redfg=`tput setf 4` 2>/dev/null
   pp_col_bluefg=`tput setf 1` 2>/dev/null
   pp_col_reset=`tput op` 2>/dev/null
else
   pp_col_redfg='['
   pp_col_bluefg='['
   pp_col_reset=']'
fi

pp__warn () {
	if test x"" = x"$pp_lineno"; then
	    echo "$1 $2" >&2
	else
	    echo "$1 line $pp_lineno: $2" >&2
	fi
}

pp_warn () {
	pp__warn "pp: ${pp_col_redfg}warning${pp_col_reset}" "$*"
}

pp_error () {
	pp__warn "pp: ${pp_col_redfg}error${pp_col_reset}" "$*"
	pp_errors=true
}

pp_die () {
	pp_error "pp: $@"
	exit 1
}

pp_die_if_errors () {
	$pp_errors && pp_die ${1+"$@"}
}

pp_debug () { 
	$pp_opt_debug && echo "${pp_col_bluefg}debug${pp_col_reset} $*" >&2
}

pp_verbose () {
	$pp_opt_verbose && echo "pp: ${pp_col_bluefg}info${pp_col_reset} $*" >&2
	"$@";
}

pp_substitute () { 
  sed -e 's,%(\([^)]*\)),`\1`,g' \
      -e 's,%{\([^}]*\)},${\1},g' \
      -e 's,$,,' |
  tr '' '\012' |
  sed -e '/^[^]/s/["$`\\]/\\&/g' \
      -e 's/^//' \
      -e '1s/^/echo "/' \
      -e '$s,$,",' \
      -e 's,,"echo ",g' |
  tr -d '\012' |
  tr '' '\012'
  echo
}

pp_incr () {
    eval "$1=\`expr \$$1 + 1\`"
}

pp_decr () {
    eval "$1=\`expr \$$1 - 1\`"
}

pp_check_var_is_defined () {
    if eval test -z "\"\$$1\""; then 
	pp_error "\$$1: not set"
	eval "$1=undefined"
    fi
}

pp_contains () {
    case " $1 " in
       *" $2 "*) return 0;;
       *) return 1;;
    esac
}

pp_contains_all () {
    typeset _s _c
    _l="$1"; shift
    for _w
    do
	pp_contains "$_l" "$_w" || return 1
    done
    return 0
}

pp_contains_any () {
    typeset _s _c
    _l="$1"; shift
    for _w
    do
	pp_contains "$_l" "$_w" && return 0
    done
    return 1
}

pp_add_to_list () {
    if eval test -z \"\$$1\"; then
	eval $1='"$2"'
    elif eval pp_contains '"$'$1'"' '"$2"'; then
	: already there
    else
	eval $1='"$'$1' $2"'
    fi
}
	

pp_mode_from_ls () {
   typeset umode gmode omode smode

   case "$1" in
	?--[-X]??????) umode=0;;
	?--[xs]??????) umode=1;;
	?-w[-X]??????) umode=2;;
	?-w[xs]??????) umode=3;;
	?r-[-X]??????) umode=4;;
	?r-[xs]??????) umode=5;;
	?rw[-X]??????) umode=6;;
	?rw[xs]??????) umode=7;;
	*) pp_error "bad user mode $1";;
   esac

   case "$1" in
	????--[-S]???) gmode=0;;
	????--[xs]???) gmode=1;;
	????-w[-S]???) gmode=2;;
	????-w[xs]???) gmode=3;;
	????r-[-X]???) gmode=4;;
	????r-[xs]???) gmode=5;;
	????rw[-X]???) gmode=6;;
	????rw[xs]???) gmode=7;;
	*) pp_error "bad group mode $1";;
   esac

   case "$1" in
	???????--[-T]) omode=0;;
	???????--[xt]) omode=1;;
	???????-w[-T]) omode=2;;
	???????-w[xt]) omode=3;;
	???????r-[-T]) omode=4;;
	???????r-[xt]) omode=5;;
	???????rw[-T]) omode=6;;
	???????rw[xt]) omode=7;;
	*) pp_error "bad other mode $1";;
   esac

   case "$1" in
	???[-x]??[-x]??[-x]) smode=;;
	???[-x]??[-x]??[tT]) smode=1;;
	???[-x]??[Ss]??[-x]) smode=2;;
	???[-x]??[Ss]??[tT]) smode=3;;
	???[Ss]??[-x]??[-x]) smode=4;;
	???[Ss]??[-x]??[tT]) smode=5;;
	???[Ss]??[Ss]??[-x]) smode=6;;
	???[Ss]??[Ss]??[tT]) smode=7;;
	*) pp_error "bad set-id mode $1";;
   esac

   echo "$smode$umode$gmode$omode"
}

pp_find_recurse () {
  pp_debug "find: ${1#$pp_destdir}/"
  for f in "$1"/.* "$1"/*; do
    case "$f" in */.|*/..) continue;; esac  # should never happen!
    if test -d "$f" -o -f "$f" -o -h "$f"; then
        if test -d "$f" -a ! -h "$f"; then
            echo "${f#$pp_destdir}/"
            pp_find_recurse "$f"
        else
            echo "${f#$pp_destdir}"
        fi
    fi
  done
}

pp_prepend () {
    #test -t && pp_warn "pp_prepend: stdin is a tty?"
    if test -f $1; then
        pp_debug "prepending to $1"
        mv $1 $1._prepend
        cat - $1._prepend >$1
        rm -f $1._prepend
    else
        pp_debug "prepend: creating $1"
        cat >$1
    fi
}

pp_note_file_used() {
    echo "$1" >> $pp_wrkdir/all.files
}

pp_create_dir_if_missing () {
    case "$1" in
        */) pp_error "pp_create_dir_if_missing: trailing / forbidden";;
	"") return 0;;
	*)  if test ! -d "$pp_destdir$1"; then
                pp_debug "fabricating directory $1/"
		pp_create_dir_if_missing "${1%/*}"
		mkdir "$pp_destdir$1" && 
                    pp_note_file_used "$1/"
		pp_remove_later "$1" &&
		chmod ${2-755} "$pp_destdir$1" 
	    fi;;
    esac
}

pp_add_file_if_missing () {
    typeset dir
    #-- check that the file isn't already declared in the component
    if test -s $pp_wrkdir/%files.${2:-run}; then
      awk "\$6 == \"$1\" {exit 1}" < $pp_wrkdir/%files.${2:-run} || return 1  
    fi
                
    pp_create_dir_if_missing "${1%/*}"
    pp_debug "fabricating file $1"
    echo "f ${3:-755} - - ${4:--} $1" >> $pp_wrkdir/%files.${2:-run}
    pp_note_file_used "$1"
    pp_remove_later "$1"
    return 0
}

pp_add_transient_file () {
    test -f "$pp_destdir$1" && pp_die "$pp_destdir$1: exists"
    pp_create_dir_if_missing "${1%/*}"
    pp_debug "transient file $1"
    pp_note_file_used "$1"
    pp_remove_later "$1"
}

pp_remove_later () {
   {
	echo "$1"
	test -s $pp_wrkdir/pp_cleanup && cat $pp_wrkdir/pp_cleanup
   } > $pp_wrkdir/pp_cleanup.new
   mv $pp_wrkdir/pp_cleanup.new $pp_wrkdir/pp_cleanup
}

pp_ls_readlink () {
    if test -h "$1"; then
        ls -1ld "$1" | sed -ne 's,.* -> ,,p'
    else
        echo "$1: not a symbolic link" >&2
        return 1
    fi
}

pp_remove_later_now () {
    typeset f
    if test -s $pp_wrkdir/pp_cleanup; then
        pp_debug "pp_remove_later_now"
        while read f; do
            pp_debug "removing $pp_destdir$f"
	    if test -d $pp_destdir$f; then 
		rmdir $pp_destdir$f
	    else
		rm $pp_destdir$f
	    fi
        done < $pp_wrkdir/pp_cleanup
        rm $pp_wrkdir/pp_cleanup
    fi
}

pp_readlink() {

pp_debug "&& pp_readlink_fn=$pp_readlink_fn"

    if test -n "$pp_readlink_fn"; then
pp_debug "&& calling $pp_readlink_fn $*"
        "$pp_readlink_fn" "$@"
    else
        readlink "$@"
    fi
}


pp_install_script_common () {
        cat <<-.

            # Automatically generated for
            #    $name $version ($pp_platform)
            # by PolyPackage $pp_version

            usage () {
              case "$1" in
              "list-services")
                echo "usage: \$0 list-services" ;;
              "list-components")
                echo "usage: \$0 list-components" ;;
              "list-files")
                echo "usage: \$0 list-files {cpt...|all}" ;;
              "install")
                echo "usage: \$0 install {cpt...|all}" ;;
              "uninstall")
                echo "usage: \$0 uninstall {cpt...|all}" ;;
              "start")
                echo "usage: \$0 start {svc...}" ;;
              "stop")
                echo "usage: \$0 stop {svc...}" ;;
              "print-platform")
                echo "usage: \$0 print-platform" ;;
              *)
                echo "usage: \$0 [-q] command [args]" 
                echo "   list-services" 
                echo "   list-components" 
                echo "   list-files {cpt...|all}" 
                echo "   install {cpt...|all}" 
                echo "   uninstall {cpt...|all}" 
                echo "   start {svc...}" 
                echo "   stop {svc...}" 
                echo "   print-platform" 
                ;;
              esac >&2
              exit 1
            }

            if test x"\$1" = x"-q"; then
                shift
                verbose () { "\$@"; }
                verbosemsg () { : ; }
            else
                verbose () { echo "+ \$*"; "\$@"; }
                verbosemsg () { echo "\$*"; }
            fi
.
}


pp_functions () {
    typeset func
    for func
    do
        pp_debug "generating function code for '$1'"
        echo ""
        echo "$func () {"
        pp_backend_function "$func" ||
            echo "false"
        echo "}"
    done
}

pp_function () { 
    pp_functions "$1"
}

pp_makevar () {
    #-- convert all non alpha/digits to underscores
    echo "$*" | tr -c '[a-z][A-Z][0-9]\012' '[_*]'
}

pp_getpwuid () {
    awk -F: '$3 == uid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' uid="$1" \
	< /etc/passwd || pp_error "no local username for uid $1"
}

pp_getgrgid () {
    awk -F: '$3 == gid { if (!found) print $1; found=1; } END { if (!found) exit 1; }' gid="$1" \
	< /etc/group || pp_error "no local group for gid $1"
}

pp_backend_function_getopt () {
    cat <<'..'
pp_getopt () {
     _pp_optstring="$1"; shift; eval `_pp_getopt "$_pp_optstring"`
}
_pp_getopt_meta=s,[\\\\\"\'\`\$\&\;\(\)\{\}\#\%\ \	],\\\\\&,g
_pp_protect () { 
    sed "$_pp_getopt_meta" <<. | tr '\012' ' ' 
$*
.
}
_pp_protect2 () { 
    sed "s,^..,,$pp_getopt_meta" <<. | tr '\012' ' '
$*
.
}
_pp_nonl () { 
    tr '\012' ' ' <<.
$*
.
}
_pp_getopt () {
    _pp_nonl '_pp_nonl set --; while test $# -gt 0; do case "$1" in "--") shift; break;;'
    sed 's/\([^: 	]:*\)/<@<\1>@>/g;
	 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' <<.
$1
.
    _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'
    echo
}
..
}

pp_if_true=0
pp_if_false=0

pp_frontend_init () {
    name=
    version=
    summary="no summary"
    description="No description"
    copyright="(c) 2008 Quest Software, Inc. All rights reserved"

    #-- if the user supplied extra arguments on the command line
    #   then load them now.
    pp_debug "pp_opt_init_vars=$pp_opt_init_vars"
    test -n "$pp_opt_init_vars" && eval "$pp_opt_init_vars"
}

pp_is_qualifier () {
    typeset ret

    case "$1" in
        "["*"]") ret=true;;
        *)       ret=false;;
    esac
    pp_debug "is_qualifier: $* -> $ret"
    test $ret = true
}

pp_eval_qualifier () {
    typeset ret

    case "$1" in
        "[!$pp_platform]"| \
         "[!"*",$pp_platform]"| \
         "[!$pp_platform,"*"]"| \
         "[!"*",$pp_platform,"*"]") ret=false;;
        "[!"*"]") ret=true;;
        "[$pp_platform]"| \
         "["*",$pp_platform]"| \
         "[$pp_platform,"*"]"| \
         "["*",$pp_platform,"*"]") ret=true;;
        "["*"]") ret=false;;
        *) pp_die "pp_eval_qualifier: bad qualifier '$1'"
    esac
    pp_debug "eval: $* -> $ret"
    test true = $ret
}

pp_frontend_if () {
    typeset ifcmd ifret
    ifcmd="$1";
    shift
    case "$ifcmd" in
	%if) if test 0 = $pp_if_false; then
		case "$*" in 
		    true |1) pp_incr pp_if_true;;
		    false|0) pp_incr pp_if_false;;
                    *)
			ifret=true
                        if pp_is_qualifier "$*"; then
                            pp_eval_qualifier "$*" || ifret=false
                        else
			    eval test "$@" || ifret=false
			    pp_debug "evaluating test $* -> $ifret"
			fi
			pp_incr pp_if_$ifret
                        ;;
		esac
	     else
		pp_incr pp_if_false
	     fi;;
	%else)  test $# = 0 || warn "ignoring argument to %else"
		if test $pp_if_false -gt 1; then
		  : no change
		elif test $pp_if_false = 1; then
		  pp_incr pp_if_true
		  pp_decr pp_if_false
		elif test $pp_if_true = 0; then
		  pp_die "unmatched %else"
		else
		  pp_incr pp_if_false
		  pp_decr pp_if_true
		fi;;
	%endif) test $# = 0 || warn "ignoring argument to %endif"
		if test $pp_if_false -gt 0; then
		  pp_decr pp_if_false
		elif test $pp_if_true -gt 0; then
		  pp_decr pp_if_true
		else
		  pp_die "unmatched %endif"
		fi;;
	*) pp_die "frontend_if: unknown cmd $ifcmd";;
    esac
}


pp_frontend () {
  typeset section newsection sed_word sed_ws line cpt svc
  typeset section_enabled newsection_enabled s sed sed_candidate

  section='%_initial'
  newsection='%_initial'
  section_enabled=:
  newsection_enabled=:
  sed_word="[a-zA-Z_][a-zA-Z_0-9]*"
  sed_ws="[ 	]"

  #-- not all seds are created equal
  sed=
  for sed_candidate in ${PP_SED:-sed} /usr/xpg4/bin/sed; do
      if echo 'foo' | $sed_candidate -ne '/^\(x\)*foo/p' | grep foo > /dev/null
      then
        sed="$sed_candidate"
        break
      fi
  done
  test -z "$sed" &&
        pp_die "sed is broken on this system"

  pp_lineno=0

  #-- Note: this sed script should perform similar to pp_eval_qualifier()
  $sed -e "/^#/s/.*//" \
       -e "/^\\[!\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]/s/.*//" \
       -e "s/^\\[\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]$sed_ws*//" \
       -e "s/^\\[!\\($sed_word,\\)*$sed_word\\]$sed_ws*//" \
       -e "/^\\[\\($sed_word,\\)*$sed_word\\]/s/.*//" \
       -e "s/^%$sed_ws*/%/" \
       -e "s/^$sed_ws/%\\\\&/" \
     > $pp_wrkdir/frontend.tmp

  #-- add an ignore section at the end to force section completion
  echo '%ignore' >> $pp_wrkdir/frontend.tmp
  echo  >> $pp_wrkdir/frontend.tmp

  exec 0<$pp_wrkdir/frontend.tmp
  : > $pp_wrkdir/tmp
  : > $pp_wrkdir/%fixup
  while read -r line; do
     #-- Convert leading double-% to single-%, or switch sections
     pp_incr pp_lineno

     pp_debug "line $pp_lineno: $line"
     set -f
     set -- $line
     set +f
     #pp_debug "line $pp_lineno: $*"

     case "$line" in %*)
        case "$1" in 
	   %if|%else|%endif) 
                pp_debug "processing if directive $1"
	   	pp_frontend_if ${1+"$@"}
		continue;;
	esac
	test 0 -ne $pp_if_false && continue	# ignore lines %if'd out

        case "$1" in 
	  %set|%fixup|%ignore)
             pp_debug "processing new section $1"
	     newsection="$1"; shift
             newsection_enabled=:
             if pp_is_qualifier "$1"; then
                pp_eval_qualifier "$1" || newsection_enabled=false
                shift
             fi
	     test $# -eq 0 || pp_warn "ignoring extra arguments: $line"
	     continue;;
	  %post|%preun|%files|%depend|%check) 
             pp_debug "processing new component section $*"
             s="$1"; shift
             if test $# -eq 0 || pp_is_qualifier "$1"; then
                cpt=run
             else
                cpt="$1"
                shift
             fi
             newsection="$s.$cpt"
             newsection_enabled=:
             if test $# -gt 0 && pp_is_qualifier "$1"; then
                pp_eval_qualifier "$1" || newsection_enabled=false
                shift
             fi
             test $# -eq 0 ||
                pp_warn "ignoring extra arguments: $line"
             case "$cpt" in 
                run|dbg|doc|dev) 
                    $newsection_enabled && pp_add_component "$cpt";;
                x-*) :;;    # useful for discarding stuff
                *) pp_error "unknown component: $1 $cpt";;
             esac
	     continue;;
          %pp)
            newsection="%ignore"; shift
            if test $# -gt 0; then
                pp_set_api_version "$1"
                shift
            else
                pp_error "%pp: missing version"
            fi
            test $# -gt 0 &&
                pp_error "%pp: too many arguments"
            continue;;
	  %service)
             pp_debug "processing new service section $1 $2"
             s="$1"; shift
             if test $# -eq 0 || pp_is_qualifier "$1"; then
                pp_error "$s: service name required"
                svc=unknown
             else
                svc="$1"; shift
             fi

	     newsection="$s.$svc"
             newsection_enabled=:
	     if test $# -gt 0 && pp_is_qualifier "$1"; then
                pp_eval_qualifier "$1" || newsection_enabled=false
                shift
             fi
             test $# -eq 0 ||
                pp_warn "ignoring extra arguments: $line"
	     $newsection_enabled && pp_add_service "$svc"
	     continue;;
	  %\\*) 
             pp_debug "removing leading %\\"
	     line="${line#??}"
             pp_debug "  result is <$line>"
             set -f
             set -- $line
             set +f
             ;;
	  %%*) 
             pp_debug "removing leading %"
	     line="${line#%}"
             set -f
             set -- $line
             set +f
	     ;;
	  %*) 
	     pp_error "unknown section $1"
	     newsection='%ignore'
             newsection_enabled=:
	     continue;;
	esac;;
     esac

     test 0 != $pp_if_false && continue	# ignore lines %if'd out

     pp_debug "section=$section (enabled=$section_enabled) newsection=$newsection (enabled=$newsection_enabled)"

     #-- finish processing a previous section
     if test x"$newsection" != x""; then
      $section_enabled && case "$section" in
     	%ignore|%_initial) 
                pp_debug "leaving ignored section $section"
		: ignore  # guaranteed to be the last section
		;;
	%set)
                pp_debug "leaving $section: sourcing $pp_wrkdir/tmp"
                $pp_opt_debug && cat $pp_wrkdir/tmp >&2
		. $pp_wrkdir/tmp
		: > $pp_wrkdir/tmp
		;;
	%preun.*|%post.*|%depend.*|%check.*|%service.*|%fixup)
                pp_debug "leaving $section: substituting $pp_wrkdir/tmp"
                # cat $pp_wrkdir/tmp >&2    # debugging
                $pp_opt_debug && pp_substitute < $pp_wrkdir/tmp >&2
		pp_substitute < $pp_wrkdir/tmp > $pp_wrkdir/tmp.sh
                . $pp_wrkdir/tmp.sh >> $pp_wrkdir/$section ||
                    pp_error "shell error in $section"
		rm -f $pp_wrkdir/tmp.sh
		: > $pp_wrkdir/tmp
		;;
      esac
      section="$newsection"
      section_enabled="$newsection_enabled"
      newsection=
     fi

     #-- ignore section content that is disabled
     $section_enabled || continue

     #-- process some lines in-place
     case "$section" in
	%_initial)	
		case "$line" in "") continue;; esac # ignore non-section blanks
		pp_die "Ignoring text before % section introducer";;
	%set|%preun.*|%post.*|%check.*|%depend.*|%service.*|%fixup)
                pp_debug "appending line to \$pp_wrkdir/tmp"
		echo "$line" >> $pp_wrkdir/tmp
		;;
	%files.*)
		test $# -eq 0 && continue;
		pp_files_expand "$@" >> $pp_wrkdir/$section
		;;
     esac
  done 
  exec <&-

  if test $pp_if_true != 0 -o $pp_if_false != 0; then
	pp_die "missing %endif at end of file"
  fi

  pp_lineno=

  pp_debug " name        = $name"
  pp_debug " version     = $version"
  pp_debug " summary     = $summary"
  pp_debug " description = $description"
  pp_debug " copyright   = $copyright"
  pp_debug ""
  pp_debug "\$pp_components: $pp_components"
  pp_debug "\$pp_services:   $pp_services"
}

pp_set_api_version() {
    case "$1" in
        1.0)    : ;;
        *)      pp_error "This version of polypackage is too old";;
    esac
}

pp_platform=

pp_set_platform () {
    if test -n "$pp_opt_platform"; then
	pp_contains "$pp_platforms" "$pp_opt_platform" ||
		pp_die "$pp_opt_platform: unknown platform"
	pp_platform="$pp_opt_platform"
    else
	uname_s=`uname -s 2>/dev/null`
	pp_platform=
	for p in $pp_platforms; do
	    pp_debug "probing for platform $p"
	    if eval pp_backend_${p}_detect "$uname_s"; then
		pp_platform="$p"
		break;
	    fi
	done
	test -z "$pp_platform" && 
		pp_die "cannot detect platform (supported: $pp_platforms)"
    fi
    pp_debug "pp_platform = $pp_platform"
}

pp_expand_path=

pp_expand_test_usr_bin () {
	awk '$1 == "/usr" || $2 == "/usr" {usr++} 
	     $1 == "/bin" || $2 == "/bin" {bin++} 
	     END { if (usr == 1 && bin == 1) exit(0); else exit(1); }'
}

pp_set_expand_converter_or_reexec () {
    test -d /usr -a -d /bin || 
	pp_die "missing /usr or /bin"
    echo /usr /bin | pp_expand_test_usr_bin || pp_die "pp_expand_test_usr_bin?"
    if (eval "echo /{usr,bin}" | pp_expand_test_usr_bin) 2>/dev/null; then
	pp_expand_path=pp_expand_path_brace
    elif (eval "echo /@(usr|bin)" | pp_expand_test_usr_bin) 2>/dev/null; then
	pp_expand_path=pp_expand_path_at
    else
	test x"$pp_expand_rexec" != x"true" ||
	    pp_die "problem finding shell that can do brace expansion"
	for shell in ksh ksh93 bash; do
	    if ($shell -c 'echo /{usr,bin}' | 
			pp_expand_test_usr_bin) 2>/dev/null || 
	       ($shell -c 'echo /@(usr|bin)' |
			pp_expand_test_usr_bin) 2>/dev/null
	    then
                pp_debug "switching to shell $shell"
		pp_expand_rexec=true exec $shell "$0" ${1+"$@"}
	    fi
	done
	pp_die "cannot find a shell that does brace expansion"
    fi
}

pp_expand_path_brace () {
	typeset f
	eval "for f in $1; do echo \"\$f\"; done|sort -u"
}

pp_expand_path_at () {
	typeset f
	eval "for f in `
	    echo "$1" | sed -e 's/{/@(/g' -e 's/}/)/g' -e 's/,/|/g'
		`; do echo \"\$f\"; done|sort -u"
}

pp_shlib_suffix='.so*'

pp_model_init () {
    #@ $pp_components: whitespace-delimited list of components seen in %files
    pp_components=
    #@ $pp_services: whitespace-delimited list of %service seen
    pp_services=

    rm -f $pp_wrkdir/%files.* \
          $pp_wrkdir/%post.* \
          $pp_wrkdir/%preun.* \
          $pp_wrkdir/%service.* \
          $pp_wrkdir/%set \
          $pp_wrkdir/%fixup
}


pp_have_component () {
	pp_contains "$pp_components" "$1"
}

pp_have_all_components () {
	pp_contains_all "$pp_components" ${1+"$@"}
}

pp_add_component () {
	pp_add_to_list 'pp_components' "$1"
}

pp_add_service () {
	pp_add_to_list 'pp_services' "$1"
}

pp_service_init_vars () {
	cmd=
	pidfile=
	stop_signal=15		# SIGTERM
	user=root
	group=
	enable=yes		# make it so the service starts on boot
	pp_backend_init_svc_vars
}

pp_service_check_vars () {
	test -n "$cmd" ||
		pp_error "%service $1: cmd not defined"
	case "$enable" in
	    yes|no) : ;;
	    *) pp_error "%service $1: \$enable must be set to yes or no";;
	esac
}

pp_load_service_vars () {
	pp_service_init_vars
	. "$pp_wrkdir/%service.$1" 
	pp_service_check_vars "$1"
}

pp_files_expand () {
    typeset _p _mode _group _owner _flags _path _optional _has_target _tree
    typeset _path _file _tgt _m _o _g _f _type _lm _ll _lo _lg _ls _lx
    typeset _ignore _a

    test $# -eq 0 && return

    pp_debug "pp_files_expand: path is: $1"

    case "$1" in "#"*) return;; esac
    _p="$1"; shift

    pp_debug "pp_files_expand: other arguments: $*"

    #-- the mode must be an octal number of at least three digits
    _mode="="
    _a=`eval echo \"$1\"`
    case "$_a" in
	*:*) :;;
	-|=|[01234567][01234567][01234567]*) _mode="$_a"; shift;;
    esac

    #-- the owner:group field may have optional parts
    _a=`eval echo \"$1\"`
    case "$_a" in
	*:*) _group=${_a#*:}; _owner=${_a%:*}; shift;;
	=|-) _group=$_a;      _owner=$_a; shift;;
	*)   _group=;         _owner=;;
    esac

    #-- process the flags argument
    _flags=
    _optional=false
    _has_target=false
    _ignore=false
    if test $# -gt 0; then
        _a=`eval echo \"$1\"`
	case ",$_a," in *,volatile,*) _flags="${_flags}v";; esac
	case ",$_a," in *,optional,*) _optional=true;; esac
	case ",$_a," in *,symlink,*) _has_target=true;; esac
	case ",$_a," in *,ignore-others,*) _flags="${_flags}i";; esac
	case ",$_a," in *,ignore,*) _ignore=true;; esac
	shift
    fi

    #-- process the target argument
    if $_has_target; then
	test $# -ne 0 || pp_error "$_p: missing target"
	_a=`eval echo \"$1\"`
	_target="$_a"
	shift
    fi

    pp_debug "pp_files_expand: $_mode|$_owner:$_group|$_flags|$_target|$*"

    test $# -eq 0 || pp_error "$_p: too many arguments"

    #-- process speciall suffixes
    tree=
    case "$_p" in
        *"/**")  _p="${_p%"/**"}"; tree="**";;
        *".%so") _p="${_p%".%so"}$pp_shlib_suffix";;
    esac

    #-- expand the path using the shell glob
    pp_debug "expanding .$_p ... with $pp_expand_path"
    (cd ${pp_destdir} && $pp_expand_path ".$_p") > $pp_wrkdir/tmp.files.exp

    #-- expand path/** by rewriting the glob output file
    case "$tree" in
        "") : ;;
        "**")
            pp_debug "expanding /** tree ..."
            while read _path; do
                _path="${_path#.}"
                pp_find_recurse "$pp_destdir${_path%/}"
            done < $pp_wrkdir/tmp.files.exp | 
                 sort -u > $pp_wrkdir/tmp.files.exp2
            mv $pp_wrkdir/tmp.files.exp2 $pp_wrkdir/tmp.files.exp
            ;;
    esac

    while read _path; do
	_path="${_path#.}"
	_file="${pp_destdir}${_path}"
	_tgt=
	_m="$_mode"
	_o="${_owner:--}" 
	_g="${_group:--}"
	_f="$_flags"

        case "$_path" in 
            /*) :;; 
            *)  pp_warn "$_path: inserting leading /"
                _path="/$_path";;  # ensure leading /
        esac

        #-- sanity checks
        case "$_path" in
            */../*|*/..) pp_error "$_path: invalid .. in path";;
            */./*|*/.)   pp_warn  "$_path: invalid component . in path";;
            *//*)        pp_warn  "$_path: redundant / in path";;
        esac

	#-- set the type based on the real file's type
        if $_ignore; then
           _type=f _m=_ _o=_ _g=_
	elif test -h "$_file"; then
	   case "$_path" in
		*/) pp_warn "$_path (symlink $_file): removing trailing /"
		    _path="${_path%/}"
		    ;;
	   esac
	   _type=s
	   if test x"$_target" != x"=" -a -n "$_target"; then
	       _tgt="$_target"
pp_debug "symlink target is $_tgt"
	   else
	       _tgt=`pp_readlink "$_file"`;
               test -z "$_tgt" && pp_error "can't readlink $_file"
               case "$_tgt" in 
                    ${pp_destdir}/*) 
                       pp_warn "stripped \$destdir from symlink ($_path)"
                       _tgt="${_tgt#$pp_destdir}";;
                    /*) :;;
                    *)  
                       pp_warn "converted relative symlink to absolute ($_path)"
                       _tgt="${_path%/*}/$_tgt";;
               esac
	   fi
	   _m=777
	elif test -d "$_file"; then
	   #-- display a warning if the user forgot the trailing /
	   case "$_path" in 
		*/) :;; 
		*) pp_warn "$_path (matching $_file): adding trailing /"
		   _path="$_path/";;
	   esac
	   _type=d
	   $_has_target && pp_error "$_file: not a symlink"
	elif test -f "$_file"; then
	   case "$_path" in
		*/) pp_warn "$_path (matching $_file): removing trailing /"
		    _path="${_path%/}"
		    ;;
	   esac
	   _type=f
	   $_has_target && pp_error "$_file: not a symlink"
	else
	   $_optional && continue
	   pp_error "$_file: missing"
	   _type=f
	fi

	#-- convert '=' shortcuts into mode/owner/group from ls
	case ":$_m:$_o:$_g:" in *:=:*)
	    if LS_OPTIONS=--color=never /bin/ls -ld "$_file" \
		    > $pp_wrkdir/ls.tmp
	    then
                read _lm _ll _lo _lg _ls _lx < $pp_wrkdir/ls.tmp
                test x"$_m" = x"=" && _m=`pp_mode_from_ls "$_lm"`
                test x"$_o" = x"=" && _o="$_lo"
                test x"$_g" = x"=" && _g="$_lg"
            else
                pp_error "cannot read $_file"
                test x"$_m" = x"=" && _m=-
                test x"$_o" = x"=" && _o=-
                test x"$_g" = x"=" && _g=-
            fi
	    ;;
	esac
	
	test -n "$_f" || _f=-
	
	#-- sanity checks
	test -n "$_type" || pp_die "_type empty"
	test -n "$_path" || pp_die "_path empty"
	test -n "$_m" || pp_die "_m empty"
	test -n "$_o" || pp_die "_o empty"
	test -n "$_g" || pp_die "_g empty"

	#-- setuid/gid files must be given an explicit owner/group (or =)
	case "$_o:$_g:$_m" in
	    -:*:[4657][1357]??|-:*:[4657]?[1357]?|-:*:[4657]??[1357])
		pp_error "$_path: setuid file ($_m) missing explicit owner";;
	    *:-:[2367][1357]??|*:-:[2367]?[1357]?|*:-:[2367]??[1357])
		pp_error "$_path: setgid file ($_m) missing explicit group";;
	esac

	# convert numeric uids into usernames; only works for /etc/passwd
	case "$_o" in [0-9]*) _o=`pp_getpwuid $_o`;; esac
	case "$_g" in [0-9]*) _g=`pp_getgrgid $_g`;; esac

	pp_debug "$_type $_m $_o $_g $_f $_path" $_tgt
	$_ignore || echo "$_type $_m $_o $_g $_f $_path" $_tgt
        pp_note_file_used "$_path"
        case "$_f" in *i*) echo "$_path" >> $pp_wrkdir/ign.files;; esac
    done < $pp_wrkdir/tmp.files.exp
}

pp_files_check_duplicates () {
    typeset _path
    if test -s $pp_wrkdir/all.files; then
        sort < $pp_wrkdir/all.files | uniq -d > $pp_wrkdir/duplicate.files
        while read _path; do
            pp_warn "$_path: file declared more than once"
        done <$pp_wrkdir/duplicate.files
    fi
}

pp_files_check_coverage () {
    pp_find_recurse "$pp_destdir" | sort > $pp_wrkdir/coverage.avail
    if test -s $pp_wrkdir/all.files; then
        sort -u < $pp_wrkdir/all.files
    else
        :
    fi > $pp_wrkdir/coverage.used
    join -v1 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
        > $pp_wrkdir/coverage.not-packaged
    if test -s $pp_wrkdir/coverage.not-packaged; then
        pp_warn "The following files/directories were found but not packaged:"
        sed -e 's,^,    ,' <  $pp_wrkdir/coverage.not-packaged >&2
    fi
    join -v2 $pp_wrkdir/coverage.avail $pp_wrkdir/coverage.used \
        > $pp_wrkdir/coverage.not-avail
    if test -s $pp_wrkdir/coverage.not-avail; then
        pp_warn "The following files/directories were named but not found:"
        sed -e 's,^,    ,' <  $pp_wrkdir/coverage.not-avail >&2
    fi
}

pp_files_ignore_others () {
    typeset p f

    test -s $pp_wrkdir/ign.files || return

    #-- for each file in ign.files, we remove it from all the
    #   other %files.* lists, except where it has an i flag.
    #   rather than scan each list multiple times, we build
    #   an awk script

    pp_debug "stripping ignore files"

    while read p; do
        echo '$6 == "'"$p"'" { skip unless $5 ~ /i/; }'
    done < $pp_wrkdir/ign.files > $pp_wrkdir/ign.awk

    $pp_opt_debug && cat $pp_wrkdir/ign.awk

    for f in $pp_wrkdir/%files.*; do
        awk -f $pp_wrkdir/ign.awk < $f > $f.i || pp_error "awk"
        mv $f.i $f
    done
}

pp_service_scan_groups () {
    typeset svc

    #-- scan for "group" commands, and build a list of groups
    pp_service_groups=
    if test -n "$pp_services"; then
        for svc in $pp_services; do
	    group=
	    . $pp_wrkdir/%service.$svc
	    if test -n "$group"; then
		pp_contains "$pp_services" "$group" && pp_error \
		    "%service $svc: group name $group in use by a service"
		pp_add_to_list 'pp_service_groups' "$group"
		echo "$svc" >> $pp_wrkdir/%svcgrp.$group
	    fi
        done
    fi
}

pp_service_get_svc_group () {
    (tr '\012' ' ' < $pp_wrkdir/%svcgrp.$1 ; echo) | sed -e 's/ $//'
}

for _sufx in _init '' _names _cleanup _install_script \
    _init_svc_vars _function _probe _vas_platforms
do
 eval "pp_backend$_sufx () { pp_debug pp_backend$_sufx; pp_backend_\${pp_platform}$_sufx \${1+\"\$@\"}; }"
done

pp_platforms="$pp_platforms aix"

pp_backend_aix_detect () {
	test x"$1" = x"AIX"
}

pp_backend_aix_init () {
        pp_aix_detect_arch
        pp_aix_detect_os

	pp_aix_bosboot=		# components that need bosboot
	pp_aix_lang=en_US
	pp_aix_copyright="$pp_copyright"
        pp_aix_start_services_after_install=false
        pp_aix_init_services_after_install=true

        case "$pp_aix_os" in
            *) pp_readlink_fn=pp_ls_readlink;;  # XXX
        esac

}

pp_aix_detect_arch () {
	pp_aix_arch_p=`uname -p 2>/dev/null`
	case "$pp_aix_arch_p"  in
	   "")      pp_debug "can't get processor type from uname -p"
                    pp_aix_arch_p=powerpc
                    pp_aix_arch=R;;  # guess (lsattr -l proc0 ??)
	   powerpc) pp_aix_arch=R;;
	   *)       pp_aix_arch_p=intel
                    pp_aix_arch=I;;  # XXX? verify
	esac

	case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in
	    PowerPC_POWER*) pp_aix_arch_std=ppc64;;	
	    PowerPC*) pp_aix_arch_std=ppc;;	
	    *) pp_aix_arch_std=unknown;;	
	esac
}

pp_aix_detect_os () {
        typeset r v

        r=`uname -r`
        v=`uname -v`
        pp_aix_os=aix$v$r
}

pp_aix_version_fix () {
    typeset v
    v=`echo $1 | tr -c -d '[0-9].\012'`
    if test x"$v" != x"$1"; then
        pp_warn "stripped version '$1' to '$v'"
    fi
    case $v in
        ""|*..*|.*|*.) pp_error "malformed '$1'"
                 echo "0.0.0.0";;
        *.*.*.*.*.*) pp_error "version '$1' has too many dots for AIX"
                 echo "0.0.0.0";;
        *.*.*.*.*|*.*.*.*) echo "$v";;
        *.*.*) echo "$v.0";;
        *.*) echo "$v.0.0";;
        *) echo "$v.0.0.0";;
    esac
}

pp_aix_select () {
	case "$1" in
	    -user) op="";;
	    -root) op="!";;
	    *) pp_die "pp_aix_select: bad argument";;
	esac
	#pp_debug awk '$5 '$op' /^\/(usr|opt)(\/|$)/ { print; }'
	#awk '$5 '$op' /^\/(usr|opt)(\/|$)/ { print; }'
	awk $op'($6 ~ /^\/usr\// || $6 ~ /^\/opt\//) { print; }'
}

pp_aix_copy_root () {
    typeset t m o g f p st target
    while read t m o g f p st; do
        case "$t" in
           d) pp_create_dir_if_missing "$1${p%/}";;
           f) pp_add_transient_file "$1$p"
	      pp_verbose ln "$pp_destdir$p" "$pp_destdir$1$p" || 
		pp_error "can't link $p into $1";;
           *) pp_warn "pp_aix_copy_root: filetype $t not handled";;
        esac
    done
}


pp_aix_size () {
    typeset prefix t m o g f p st

    prefix="$1"
    while read t m o g f p st; do
      case "$t" in f) du -a "$pp_destdir$p";; esac
    done | sed -e 's!/[^/]*$!!' | sort +1 |
    awk '{ if ($2 != d) 
           { if (sz) print d,sz; 
             d=$2; sz=0 }
           sz += $1; }
         END { if (sz) print d,sz }' |
    sed -n -e "s!^$pp_destdir!$prefix!p"
}

pp_aix_list () {
    awk '{ print "." pfx $6; }' pfx="$1"
}

pp_aix_make_liblpp () {
    typeset out dn fl f

    out="$1"; shift
    dn=`dirname "$2"`
    fl=
    for f
    do
	case "$f" in "$dn/"*) fl="$fl `basename $f`" ;; 
		     *) pp_die "liblpp name $f not in $dn/";; esac
    done
    (cd "$dn" && pp_verbose  ar -c -g -r "$out" $fl) || pp_error "ar error"
}

pp_aix_make_script () {
    rm -f "$1"
    echo "#!/bin/sh" > "$1"
    cat >> "$1"
    echo "exit 0" >> "$1"
    chmod +x "$1"
}

pp_aix_inventory () {
    typeset fileset t m o g f p st type

    fileset="$1"
    while read t m o g f p st; do
      case "$p" in *:*) pp_error "path $p contains colon";; esac
      echo "$p:"
      case "$t" in
	f)   type=FILE;      defm=644 ;;
	s)   type=SYMLINK;   defm=777 ;;
	d)   type=DIRECTORY; defm=755 ;;
      esac
      echo " type = $type"
      echo " class = inventory,apply,$fileset"
      set -- `/bin/ls -ld "$pp_destdir$p" 2>/dev/null`
      owner=$3 group=$4 size=$5
      if test x"$m" = x"-"; then m="$defm"; fi
      if test x"$o" = x"-"; then o="root"; fi
      if test x"$g" = x"-"; then g="system"; fi
      echo " owner = $o"
      echo " group = $g"

      case "$m" in ????)
	m=`echo $m|sed -e 's/^1/TCB,/' \
		       -e 's/^[23]/TCB,SGID,/' \
		       -e 's/^[45]/TCB,SUID,/' \
		       -e 's/^[67]/TCB,SUID,SGID,/'`;;  # vtx bit ignored
      esac
      echo " mode = $m"
      case "$t" in
	f) if test ! -f "$pp_destdir$p"; then
		pp_error "$p: missing file"
	   fi
	   case "$flags" in
	    *v*)
	      echo " size = VOLATILE"
	      echo " checksum = VOLATILE"
	      ;;
	    *)
	      if test -r "$pp_destdir$p"; then
	        echo " size = $size"
                pp_verbose  sum -r < "$pp_destdir$p" | 
	      	  sed -e 's/.*/ checksum = "&"/'
	      fi
	      ;;
	   esac;;
	s) 
	   echo " target = $st"
	   ;;
      esac
    done
}

pp_aix_depend ()
{
    if test -s "$1"; then
       pp_warn "aix dependencies not implemented"
    fi
}

pp_aix_add_service () {
	typeset svc cmd_cmd cmd_arg f
	svc="$1"

	pp_load_service_vars $svc

	set -- $cmd
	cmd_cmd="$1"; shift
	cmd_arg="$*";
	
	case "$stop_signal" in
		HUP) stop_signal=1;;
		INT) stop_signal=2;;
		QUIT) stop_signal=3;;
		KILL) stop_signal=9;;
		TERM) stop_signal=15;;
		USR1) stop_signal=30;;
		USR2) stop_signal=31;;
		"") 
		  pp_error "%service $svc: stop_signal not set";;
		[a-zA-Z]*) 
		  pp_error "%service $svc: bad stop_signal ($stop_signal)";;
	esac

	test -z "$pidfile" || pp_error "aix requires empty pidfile (non daemon)"

	pp_add_component run
	if test "$user" = "root"; then
	    uid=0
	else
            uid="\"\`/usr/bin/id -u $user\`\""
	fi


        #-- add command text to create/remove the service
	cat <<-. >> $pp_wrkdir/%post.run
           # install service '$svc'
           mkssys -s $svc -u $uid -p "$cmd_cmd" ${cmd_arg:+-a "$cmd_arg"} -O -S -n $stop_signal -f 9 ${pp_aix_mkssys_args} ${group+-G "$group"}
.

        #-- add code to start the service on reboot
        ${pp_aix_init_services_after_install} &&
          cat <<-. >> $pp_wrkdir/%post.run
            # start service '$svc' on reboot
            mkitab "$svc:2:once:/usr/bin/startsrc -s $svc >/dev/console 2>&1"
.

	${pp_aix_start_services_after_install} && 
          cat <<-. >> $pp_wrkdir/%post.run
            # start service '$svc' automatically after install
            startsrc -s $svc
.

        ${pp_aix_init_services_after_install} &&
           pp_prepend $pp_wrkdir/%preun.run <<-.
            # stop starting service '$svc' at boot
	    rmitab $svc
.
	pp_prepend $pp_wrkdir/%preun.run <<-.
	    # stop service '$svc'
	    stopsrc -s $svc >/dev/null 2>&1
	    # uninstall service '$svc' from SRC
	    rmssys -s $svc
.
}

pp_backend_aix () {
        typeset briefex instuser instroot svc cmp outbff
        typeset user_wrkdir root_wrkdir
        typeset user_files root_files

	test -n "$pp_destdir" ||
	   pp_error "AIX backend requires the '--destdir' option"

	instuser="/usr/lpp/$name"
	instroot="$instuser/inst_root"

	# Here is the component mapping:
	#  run -> $name.rte ('Run time environment')
	#  doc -> $name.doc (non-standard)
	#  dev -> $name.adt ('Application developer toolkit')
	#  dbg -> $name.diag ('Diagnostics')

	test `echo "$summary" | wc -c ` -gt 40 && pp_error "\$summary too long"

	user_wrkdir=$pp_wrkdir/u
	root_wrkdir=$pp_wrkdir/r
	pp_verbose  rm -rf $user_wrkdir $root_wrkdir
	pp_verbose  mkdir -p $user_wrkdir $root_wrkdir

	for svc in $pp_services .; do
	    test . = "$svc" && continue
            pp_aix_add_service $svc
	done

        {
	  echo "4 $pp_aix_arch I $name {" 

	  for cmp in $pp_components; do
	    case "$cmp" in 
		run) ex=rte  briefex="runtime";;
		doc) ex=doc  briefex="documentation";;
		dev) ex=adt  briefex="developer toolkit";;
		dbg) ex=diag briefex="diagnostics";;
	    esac

	    user_files=$pp_wrkdir/%files.$cmp.u
	    root_files=$pp_wrkdir/%files.$cmp.r

	    pp_aix_select -user < $pp_wrkdir/%files.$cmp > $user_files
	    pp_aix_select -root < $pp_wrkdir/%files.$cmp > $root_files

            # Default to USR only unless there are root files,
            # or a post/pre/check script associated
	    content=U
            if test -s $root_files \
                    -o -s $pp_wrkdir/%post.$cmp \
                    -o -s $pp_wrkdir/%preun.$cmp \
                    -o -s $pp_wrkdir/%check.$cmp
            then
                content=B
            fi

if $pp_opt_debug; then
    echo "$cmp USER %files:"
    cat $user_files
    echo "$cmp ROOT %files:"
    cat $root_files
fi >&2

	    bosboot=N; pp_contains_any "$pp_aix_bosboot" $cmp && bosboot=b

            echo $name.$ex \
                 ${pp_aix_version:-`pp_aix_version_fix "$version"`} \
	         1 $bosboot $content \
	         $pp_aix_lang "$summary $briefex"
	    echo "["

	    pp_aix_depend $pp_wrkdir/%depend.$cmp 

	    echo "%"

	    # generate per-directory size information
	    pp_aix_size < $user_files
	    pp_aix_size $instroot < $root_files

	    pp_aix_list            < $user_files  > $user_wrkdir/$name.$ex.al
	    pp_aix_list $instroot  < $root_files >> $user_wrkdir/$name.$ex.al
	    pp_aix_list            < $root_files  > $root_wrkdir/$name.$ex.al

if $pp_opt_debug; then
    echo "$cmp USER $name.$ex.al:"
    cat $user_wrkdir/$name.$ex.al 
    echo "$cmp ROOT $name.$ex.al:"
    cat $root_wrkdir/$name.$ex.al
fi >&2

	    pp_aix_inventory $name.$ex < $user_files \
                                       > $user_wrkdir/$name.$ex.inventory
	    pp_aix_inventory $name.$ex < $root_files \
                                       > $root_wrkdir/$name.$ex.inventory

if $pp_opt_debug; then
    pp_debug "$cmp USER $name.$ex.inventory:"
    cat $user_wrkdir/$name.$ex.inventory 
    pp_debug "$cmp ROOT $name.$ex.inventory:"
    cat $root_wrkdir/$name.$ex.inventory
fi >&2

	    if test x"" != x"$pp_aix_copyright"; then
	        echo "$pp_aix_copyright" > $user_wrkdir/$name.$ex.copyright
	        echo "$pp_aix_copyright" > $root_wrkdir/$name.$ex.copyright
	    fi

	    #-- assume that post/pre uninstall scripts only make
	    #   sense when installed in a root context

	    if test -r $pp_wrkdir/%post.$cmp; then
		pp_aix_make_script $root_wrkdir/$name.$ex.post_i \
			< $pp_wrkdir/%post.$cmp
	    fi

	    if test -r $pp_wrkdir/%preun.$cmp; then
		pp_aix_make_script $root_wrkdir/$name.$ex.unpost_i \
			< $pp_wrkdir/%preun.$cmp
	    fi

	    if test -r $pp_wrkdir/%check.$cmp; then
                #-- if this script exits false, then it should print a msg
		pp_aix_make_script $root_wrkdir/$name.$ex.pre_i \
			< $pp_wrkdir/%check.$cmp
	    fi

	    # remove empty files
	    for f in $user_wrkdir/$name.$ex.* $root_wrkdir/$name.$ex.*; do
	      if test ! -s "$f"; then
                pp_debug "removing empty $f"
                rm -f "$f"
              fi
	    done

	    # copy/link the root files so we can do an easy backup later
	    pp_aix_copy_root $instroot < $root_files

	    echo "%"
	    echo "]"
	  done
	  echo "}"
	} > $pp_wrkdir/lpp_name

if $pp_opt_debug; then
    echo "/lpp_name :"
    cat $pp_wrkdir/lpp_name
fi >&2

        #-- copy the /lpp_name file to the destdir
        pp_add_transient_file /lpp_name
        cp $pp_wrkdir/lpp_name $pp_destdir/lpp_name

        #-- copy the liblpp.a files under destdir for packaging
	(cd $user_wrkdir && pp_verbose  ar -c -g -r liblpp.a $name.*) ||
		pp_error "ar error"
	if test -s $user_wrkdir/liblpp.a; then
           pp_add_transient_file $instuser/liblpp.a
	   pp_verbose cp $user_wrkdir/liblpp.a $pp_destdir$instuser/liblpp.a || 
		pp_error "cannot create user liblpp.a"
	fi
	(cd $root_wrkdir && pp_verbose  ar -c -g -r liblpp.a $name.*) ||
		pp_error "ar error"
	if test -s $root_wrkdir/liblpp.a; then
           pp_add_transient_file $instroot/liblpp.a
	   pp_verbose cp $root_wrkdir/liblpp.a $pp_destdir$instroot/liblpp.a || 
		pp_error "cannot create root liblpp.a"
	fi

        { echo ./lpp_name
	  test -s $user_wrkdir/liblpp.a && echo .$instuser/liblpp.a
	  test -s $root_wrkdir/liblpp.a && echo .$instroot/liblpp.a
	  cat $user_wrkdir/$name.*.al   # includes the relocated root files!
	} > $pp_wrkdir/bff.list
        
	. $pp_wrkdir/%fixup

        outbff=`pp_backend_aix_names`
        pp_debug "creating: $pp_wrkdir/$outbff"
	(cd $pp_destdir && pp_verbose  /usr/sbin/backup -i -q -p -f -) \
          < $pp_wrkdir/bff.list \
	  > $pp_wrkdir/$outbff || pp_error "backup failed"
        ${SUDO:-sudo} /usr/sbin/installp -l -d $pp_wrkdir/$outbff
}

pp_backend_aix_cleanup () {
    :
}

pp_backend_aix_names () {
	echo "$name.${pp_aix_version:-`pp_aix_version_fix "$version"`}.bff"
}

pp_backend_aix_install_script () {
	typeset pkgname platform
        #
        # The script should take a first argument being the
        # operation; further arguments refer to components or services
        #
        # list-components           -- lists components in the pkg
        # install component...      -- installs the components
        # uninstall component...    -- uninstalles the components
        # list-services             -- lists the services in the pkg
        # start service...          -- starts the name service
        # stop service...           -- stops the named services
        # print-platform            -- prints the platform group
        #
        pkgname="`pp_backend_aix_names`"
	platform="`pp_backend_aix_probe`"   # XXX should be derived from files

        fsets=
        for cmp in $pp_components; do
	    case "$cmp" in 
		run) ex=rte;;
		doc) ex=doc;;
		dev) ex=adt;;
		dbg) ex=diag;;
	    esac
            fsets="$fsets $name.$ex"
        done

        echo '#!/bin/sh'
        pp_install_script_common

        cat <<-.

            cpt_to_fileset () {
                test x"\$*" = x"all" &&
                    set -- $pp_components
                for cpt
                do
                    case "\$cpt" in 
                        run) echo "$name.rte";;
                        doc) echo "$name.doc";;
                        dev) echo "$name.adt";;
                        dbg) echo "$name.diag";;
                        *) usage;;
                    esac
                done
            }

	    test \$# -eq 0 && usage
            op="\$1"; shift

            case "\$op" in
                list-components)
                    test \$# -eq 0 || usage \$op
                    echo "$pp_components"
                    ;;
                list-services)
                    test \$# -eq 0 || usage \$op
                    echo "$pp_services"
                    ;;
                list-files)
                    test \$# -ge 1 || usage \$op
                    echo \${PP_PKGDESTDIR:-.}/$pkgname
                    ;;
                install)
                    test \$# -ge 1 || usage \$op
                    verbose /usr/sbin/installp -acX -V0 -F \
                        -d \${PP_PKGDESTDIR:-.}/$pkgname \
                        \`cpt_to_fileset "\$@"\`
                    ;;
                uninstall)
                    test \$# -ge 1 || usage \$op
                    verbose /usr/sbin/installp -u -e/dev/null \
			-V0 \`cpt_to_fileset "\$@"\`
                    ;;
                start|stop)
                    test \$# -ge 1 || usage \$op
                    ec=0
                    for svc
                    do
                        verbose \${op}src -s \$svc || ec=1
                    done
                    exit \$ec
                    ;;
                print-platform)
                    echo "$platform"
		    ;;
                *)
                    usage;;
            esac
.
}

pp_backend_aix_function () {
    case "$1" in
    pp_mkgroup) cat <<'.';;
            # group
	    if test $# -ge 1; then
              if lsgroup "$1" >/dev/null; then :; else
		echo "Creating group $1"
                mkgroup -A "$1"
	      fi
	    else
	      echo "pp_mkgroup: missing arg" >&2
	    fi
.
    pp_mkuser) 
	    cat <<'.';;
            # [-d dir] [-g group] user
            typeset home group
	    while test $# -gt 0; do case "$1" in
	       --) shift; break;;
	       -d) shift; home="$1"; shift;;
	       -g) shift; group="$1"; shift;;
	       -*) echo "pp_mkuser: bad option '$1'" >&2; shift;;
	       *) break;;
	    esac; done
	    if test $# -ge 1; then
              if lsuser "$1" >/dev/null; then :; else
	        echo "Creating user $1"
                mkuser login=false rlogin=false account_locked=true \
                    home=${home:-/nohome.$1} ${group:+pgrp=$group} \
                    "$1"
	      fi
	    else
	     echo "pp_mkuser: missing arg" >&2
	    fi
.
    pp_havelib) cat <<'.';;
            # libname major[.minor] [path]
            # Returns true if the shared library can be found
            # 'path' should a colon-separated list of directories
            # major may be an empty string if a path is required.
            typeset name dir
            case "$2" in
                "")    name="lib$1.so";;
                *.*.*) name="lib$1.so.$2";;
                *.*)   name="lib$1.so.$2.0";;
                *)     name="lib$1.so.$2";;
            esac
            for dir in `echo "/usr/lib:/lib${3+:$3}" | tr : ' '`; do
                test -r "$dir/$name" -a -r "$dir/lib$1.so" && return 0
            done
            return 1
.
    *)
            pp_error "unknown function request: $1" ;;
    esac
}

pp_backend_aix_init_svc_vars () {
    :
}

pp_backend_aix_probe () {
	echo "${pp_aix_os}-${pp_aix_arch_std}"
}

pp_backend_aix_vas_platforms () {
    case "${pp_aix_arch_std}" in
	ppc*)	:;;
	*)	pp_die "unknown architecture ${pp_aix_arch_std}";;
    esac
    case "${pp_aix_os}" in
	aix43)	echo "aix-43";;
	aix51)	echo "aix-51 aix-43";;
	aix52)	echo "aix-51 aix-43";;
	aix53)	echo "aix-53 aix-51 aix-43";;
	*)	pp_die "unknown system ${pp_aix_os}";;
    esac
}

pp_platforms="$pp_platforms sd"

pp_backend_sd_detect () {
    test x"$1" = x"HP-UX"
}

pp_backend_sd_init () {
    pp_sd_sudo=sudo     # FIXME: argh why is hpux so braindead
    pp_sd_startlevels=2
    pp_sd_stoplevels=auto
    pp_sd_config_file=
    pp_sd_default_start=1           # config_file default start value

    pp_readlink_fn=pp_ls_readlink   # HPUX has no readlink

    pp_sd_detect_os
}

pp_sd_detect_os () {
    typeset revision

    revision=`uname -r`
    pp_sd_os="${revision#?.}"
    test -z "$pp_sd_os" &&
        pp_warn "cannot detect OS version"
    pp_sd_os_std="hpux`echo $pp_sd_os | tr -d .`"

    case "`uname -m`" in
	9000/[678]??) pp_sd_arch_std=hppa;;
	ia64) pp_sd_arch_std=ia64;;
	*) pp_sd_arch_std=unknown;;
    esac
}

pp_sd_write_files () {
    typeset t m o g f p st line dm
    while read t m o g f p st; do
        line="                file"
        case "$f" in *v*) line="$line -v";; esac    # FIXME for uninstall
        case $t in 
            f) dm=644;;
            d) line="$line -t d"; p=${p%/}; dm=755;;
            s) line="$line -t s";;
        esac

        test x"$o" = x"-" && o=bin
        test x"$g" = x"-" && g=bin
        test x"$m" = x"-" && m=$dm

        case $t in
            s) echo "$line $st $p";;
            *) echo "$line -o $o -g $g -m $m $pp_destdir$p $p";;
        esac

    done
}

pp_sd_service_group_script () {
    typeset grp svcs scriptpath out
    grp="$1"
    svcs="$2"
    scriptpath="/sbin/init.d/$grp"
    out="$pp_destdir$scriptpath"

    pp_add_file_if_missing $scriptpath run 755 || return 0

    cat <<-. > $out
	#!/sbin/sh
	# generated by pp $pp_version
	svcs="$svcs"
.

    cat <<-'.' >> $out
        #-- starts services in order.. stops them all if any break
        pp_start () {
            undo=
            for svc in $svcs; do
                /sbin/init.d/$svc start
		case $? in
		  0|4)
		    undo="$svc $undo"
		    ;;
		  *)
                    if test -n "$undo"; then
                        for svc in $undo; do
                           /sbin/init.d/$svc stop
                        done
                        return 1
                    fi
		    ;;
                esac
            done
            return 0
        }

        #-- stops services in reverse
        pp_stop () {
            reverse=
            for svc in $svcs; do
                reverse="$svc $reverse"
            done
            rc=0
            for svc in $reverse; do
                /sbin/init.d/$svc stop || rc=$?
            done
            return $rc
        }

        case $1 in
            start_msg) echo "Starting $svcs";;
            stop_msg)  echo "Stopping $svcs";;
	    start)     pp_start;;
	    stop)      pp_stop;;
            *)	       echo "usage: $0 {start|stop|start_msg|stop_msg}"
                       exit 1;;
        esac
.
}

pp_sd_service_script () {
    typeset svc config_file config_value scriptpath out

    svc="$1"
    scriptpath="/sbin/init.d/$svc"

    config_file=${pp_sd_config_file:-/etc/rc.config.d/$name}
    sd_config_var=`echo start-$svc | tr '[a-z]-' '[A-Z]_'`
    sd_config_value=${pp_sd_default_start:-0}
    pp_load_service_vars "$svc"

    test -n "$user" -a x"$user" != x"root" &&
        cmd="SHELL=/usr/bin/sh /usr/bin/su $user -c \"exec `echo $cmd | sed -e 's,[$\\\`],\\&,g'`\""
    if test -z "$pidfile"; then
        pidfile="/var/run/$svc.pid"
        cmd="$cmd & echo \$! > \$pidfile"
    fi

pp_debug "config file is $config_file"

    pp_add_file_if_missing $scriptpath run 755
    pp_add_file_if_missing $config_file run 644 v

    cat <<-. >> $pp_destdir$config_file

	# Controls whether the $svc service is started
	$sd_config_var=$sd_config_value
.

    cat <<. > $pp_destdir$scriptpath

        svc="$svc"
        pidfile="$pidfile"
        config_file="$config_file"

        pp_start () {
            $cmd
        }

        pp_disabled () {
            test \${$sd_config_var:-0} -eq 0
        }

.

    cat <<'.' >>$pp_destdir$scriptpath

        pp_stop () {
            if test ! -s "$pidfile"; then
                echo "Unable to stop $svc (no pid file)"
                return 1
            else
                read pid < "$pidfile" 
		if kill -0 "$pid" 2>/dev/null; then
		    if kill -${stop_signal:-TERM} "$pid"; then
			rm -f "$pidfile"
			return 0
		    else
			echo "Unable to stop $svc"
			return 1
		    fi
		else
		    rm -f "$pidfile"
		    return 0
                fi
            fi
        }

        pp_running () {
            if test ! -s "$pidfile"; then
                return 1
            else
                read pid < "$pidfile" 
                kill -0 "$pid" 2>/dev/null
            fi
        }

        case $1 in
            start_msg) echo "Starting the $svc service";;
            stop_msg)  echo "Stopping the $svc service";;
            start)  
                    if test -f "$config_file"; then
                        . $config_file
                    fi
                    if pp_disabled; then
                        exit 2
                    elif pp_running; then
                        echo "$svc already running";
                        exit 0
                    elif pp_start; then
                        echo "$svc started";
                        # rc(1M) says we should exit 4, but nobody expects it!
			exit 0
                    else
                        exit 1
                    fi;;
            stop)   if pp_stop; then
                        echo "$svc stopped";
                        exit 0
                    else
                        exit 1
                    fi;;
            *) echo "usage: $0 {start|stop|start_msg|stop_msg}"
               exit 1;;
        esac
.
}

pp_sd_make_service () {
        typeset level startpriority stoppriority startlevels stoplevels
        typeset svc svcvar

        svc="$1"
	svcvar=`pp_makevar $svc`

        #-- don't do anything if the script exists
        if test -s "$pp_destdir/sbin/init.d/$svc"; then
            pp_error "$pp_destdir/sbin/init.d/$svc exists"
            return
        fi

        # symlink the script, depending on the priorities chosen
        eval startpriority='${pp_sd_startpriority_'$svcvar'}'
        eval stoppriority='${pp_sd_stoppriority_'$svcvar'}'
        test -z "$startpriority" && startpriority="${pp_sd_startpriority:-50}"
        test -z "$stoppriority" && stoppriority="${pp_sd_stoppriority:-50}"

        eval startlevels='${pp_sd_startlevels_'$svcvar'}'
        test -z "$startlevels" && startlevels="$pp_sd_startlevels"

        eval stoplevels='${pp_sd_stoplevels_'$svcvar'}'
        test -z "$stoplevels" && stoplevels="$pp_sd_stoplevels"

        # create the script and config file
        pp_sd_service_script $svc

        # fix the priority up
        case "$startpriority" in 
            ???) :;;
            ??) startpriority=0$startpriority;;
            ?) startpriority=00$startpriority;;
        esac
        case "$stoppriority" in 
            ???) :;;
            ??) stoppriority=0$stoppriority;;
            ?) stoppriority=00$stoppriority;;
        esac

        if test x"$stoplevels" = x"auto"; then
            stoplevels=
            test -z "$startlevels" || for level in $startlevels; do
                stoplevels="$stoplevels `expr $level - 1`"
            done
        fi

        # create the symlinks
        test -z "$startlevels" || for level in $startlevels; do
            echo "                file -t s" \
                    "/sbin/init.d/$svc" \
                    "/sbin/rc$level.d/S$startpriority$svc"
        done
        test -z "$stoplevels" || for level in $stoplevels; do
            echo "                file -t s" \
                    "/sbin/init.d/$svc" \
                    "/sbin/rc$level.d/K$stoppriority$svc" 
        done
}

pp_sd_control () {
    typeset ctrl script
    typeset cpt

    ctrl="$1"; shift
    cpt="$1"; shift
    script="$pp_wrkdir/control.$ctrl.$cpt"
    cat <<. >$script
.
    cat "$@" >> $script
    echo "exit 0" >> $script
    /usr/bin/chmod +x $script
    echo "                $ctrl $script"
}

pp_backend_sd () {
    typeset psf cpt svc outfile

    psf=$pp_wrkdir/psf

    echo "depot" > $psf
    echo "layout_version 1.0" >>$psf

    #-- vendor
    cat <<. >>$psf
        vendor
            tag             Quest
            title           Quest Software, Inc.

        product
            tag             $name
            revision        $version
            vendor_tag      Quest
            is_patch        false
            title           "$summary"
            copyright       "$copyright"
            machine_type    *
            os_name         HP-UX
            os_release      ?.11.*
            os_version      ?
            directory       /
            is_locatable    false
.
    test -n "$description" && cat <<. >>$psf
            description     "$description"
.

    # make convenience service groups
    if test -n "$pp_service_groups"; then
	for grp in $pp_service_groups; do
	    pp_sd_service_group_script \
		$grp "`pp_service_get_svc_group $grp`"
	done
    fi

    for cpt in $pp_components; do
        cat <<. >>$psf
            fileset
                tag             $cpt
                title           $cpt
.

	#-- make sure services are shut down during uninstall
        if test $cpt = run -a -n "$pp_services"; then
            for svc in $pp_services; do
                pp_prepend $pp_wrkdir/%preun.$cpt <<-.
			/sbin/init.d/$svc stop
.
            done
        fi

        #-- we put the post/preun code into configure/unconfigure
        # and not postinstall/preremove, because configure/unconfigure
        # scripts are run on the hosts where the package is installed,
        # not loaded (a subtle difference).
        test -s $pp_wrkdir/%post.$cpt &&
            pp_sd_control configure $cpt $pp_wrkdir/%post.$cpt >> $psf
        test -s $pp_wrkdir/%preun.$cpt &&
            pp_sd_control unconfigure $cpt $pp_wrkdir/%preun.$cpt >> $psf
        test -s $pp_wrkdir/%check.$cpt &&
            pp_sd_control checkinstall $cpt $pp_wrkdir/%check.$cpt >> $psf

        if test $cpt = run -a -n "$pp_services"; then
            for svc in $pp_services; do
                #-- service names are 10 chars max on hpux
                case "$svc" in ???????????*) 
                    pp_warn "service name '$svc' is too long for hpux";;
                esac
                pp_sd_make_service $svc >> $psf
            done
            #pp_sd_make_service_config
        fi

        pp_sd_write_files < $pp_wrkdir/%files.$cpt >> $psf

        #-- end fileset clause
        cat <<. >>$psf
            end
.
        
    done

    #-- end product clause
    cat <<. >>$psf
        end
.

    $pp_opt_debug && cat $psf >&2

    test -s $pp_wrkdir/%fixup && . $pp_wrkdir/%fixup

    outfile=`pp_backend_sd_names`
    if pp_verbose ${pp_sd_sudo} /usr/sbin/swpackage \
        -s $psf \
        -x run_as_superuser=false \
        -x media_type=tape \
        @ $pp_wrkdir/$outfile
    then
        pp_verbose ${pp_sd_sudo} /usr/sbin/swlist -l file -s $pp_wrkdir/$outfile
    else
        pp_error "swpackage failed"
    fi
}

pp_backend_sd_cleanup () {
    :
}

pp_backend_sd_names () {
    echo "$name-$version.depot"
}

pp_backend_sd_install_script () {
    typeset pkgname platform

    pkgname=`pp_backend_sd_names`
    platform="`pp_backend_sd_probe`"

    echo "#!/bin/sh"
    pp_install_script_common
    cat <<.

        cpt_to_tags () {
            test x"\$*" = x"all" && set -- $pp_components
            for cpt
            do
                echo "$name.\$cpt"
            done
        }

        test \$# -eq 0 && usage
        op="\$1"; shift

        case "\$op" in 
            list-components)
                test \$# -eq 0 || usage \$op
                echo "$pp_components"
                ;;
            list-services)
                test \$# -eq 0 || usage \$op
                echo "$pp_services"
                ;;
            list-files)
                test \$# -ge 1 || usage \$op
                echo \${PP_PKGDESTDIR:-.}/$pkgname
                ;;
            install)
                test \$# -ge 1 || usage \$op
                verbose /usr/sbin/swinstall -x verbose=0 \
                    -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \
                    \`cpt_to_tags "\$@"\`
                ;;
            uninstall)
                test \$# -ge 1 || usage \$op
                verbose /usr/sbin/swremove -x verbose=0 \
                    \`cpt_to_tags "\$@"\`
                ;;
            start|stop)
                test \$# -ge 1 || usage \$op
                ec=0
                for svc
                do
                    verbose /sbin/init.d/\$svc \$op
                    [ \$? -eq 4 -o \$? -eq 0 ] || ec=1
                done
                exit \$ec
                ;;
            print-platform)
		echo "$platform"
		;;
            *)
                usage
                ;;
        esac
.
}

pp_backend_sd_function () {
    case "$1" in
        pp_mkgroup) cat <<'.';;
            grep "^$1:" /etc/group >/dev/null ||
                /usr/sbin/groupadd $1
.
        pp_mkuser) cat <<'.';;
            typeset user
            eval user=\$$#
            grep "^$user:" /etc/passwd >/dev/null ||
                /usr/sbin/useradd -s /usr/bin/false "$@"
.
        pp_havelib) cat <<'.';;
            typeset dir
            for dir in `echo /usr/lib${3+:$3} | tr : ' '`; do
                test -r "$dir/lib$1.${2-sl}" && return 0
            done
            return 1
.
        *) pp_error "unknown function request: $1";;
    esac
}

pp_backend_sd_probe () {
    echo "${pp_sd_os_std}-${pp_sd_arch_std}"
}

pp_backend_sd_vas_platforms () {
    case "`pp_backend_sd_probe`" in
	hpux*-hppa) echo hpux-pa;;
	hpux*-ia64) echo hpux-ia64;;
	*)	    pp_die "unknown system `pp_backend_sd_probe`";;
    esac
}

pp_backend_sd_init_svc_vars () {
    :
}

pp_platforms="$pp_platforms solaris"

pp_backend_solaris_detect () {
	test x"$1" = x"SunOS"
}

pp_backend_solaris_init () {
	pp_solaris_category=
	pp_solaris_istates="s S 1 2 3"	# run-states when install is ok
	pp_solaris_rstates="s S 1 2 3"	# run-states when remove is ok
	pp_solaris_vendor="Quest Software, Inc."
	pp_solaris_copyright=
	pp_solaris_name=
	pp_solaris_desc=
	pp_solaris_package_arch=auto

        pp_solaris_detect_os
        pp_solaris_detect_arch

        pp_solaris_init_svc

        #-- readlink not reliably available on Solaris
	pp_readlink_fn=pp_ls_readlink
}

pp_solaris_detect_os () {
        typeset osrel

        osrel=`/usr/bin/uname -r`
        case "$osrel" in
	    5.[0-6])	pp_solaris_os="sol2${osrel#5.}";;
	    5.*)        pp_solaris_os="sol${osrel#5.}";;
        esac
        test -z "$pp_solaris_os" &&
             pp_warn "can't determine OS suffix from uname -r"

}

pp_solaris_detect_arch () {
	pp_solaris_arch=`/usr/bin/optisa amd64 sparcv9 i386 sparc`
	[ -z "$pp_solaris_arch" ] &&
	    pp_error "can't determine processor architecture"
	case "$pp_solaris_arch" in
	    amd64)   pp_solaris_arch_std=x86_64;;
	    i386)    pp_solaris_arch_std=i386;;
	    sparcv9) pp_solaris_arch_std=sparc64;;
	    sparc)   pp_solaris_arch_std=sparc;;
	    *)       pp_solaris_arch_std=unknown;;
	esac
}

pp_solaris_request () {
    typeset _cmp _svc
        
    #-- The common part of the request script contains the ask() function
    #   and resets the CLASSES list to empty
    cat <<'.'
	trap 'exit 3' 15
	ask () {
	   ans=`ckyorn -d "$1" \
                -p "Do you want to $2"` \
            || exit $?
	   case "$ans" in y*|Y*) return 0;; *) return 1;; esac
	}
	CLASSES=
.
    #-- each of our components adds itself to the CLASSES list
    for _cmp in $pp_components; do
      case "$_cmp" in
            run) :;;
            doc) echo 'ask y "install the documentation files" &&';;
            dev) echo 'ask y "install the development files" &&';;
            dbg) echo 'ask n "install the diagnostic files" &&';;
      esac
      echo '    CLASSES="$CLASSES '$_cmp'"'
    done

    #-- the request script writes the CLASSES var to its output
    cat <<'.'
	echo "CLASSES=$CLASSES" > $1
.

    if test -n "$pp_services"; then
        echo 'SERVICES='
        for _svc in $pp_services; do
            echo 'ask n "install '$_svc' service" &&'
            echo '    SERVICES="$SERVICES '$_svc'"'
        done
        echo 'echo "SERVICES=$SERVICES" >> $1'
    fi

}

pp_solaris_procedure () {
    cat <<.

        #-- $2 for $1 component of $name
        case " \$CLASSES " in *" $1 "*)
.
    cat
    cat <<.
        ;; esac
.
}

pp_solaris_depend () {
    typeset _name _vers
    while read _name _vers; do
	if test -n "$_name"; then
	    echo "P $_name $_name" 
	    test -n "$_vers" && echo " $_vers" 
	fi
    done
}

pp_solaris_space() {
    echo "$2:$3:$1" >> $pp_wrkdir/space.cumulative
}

pp_solaris_sum_space () {
    if test -s $pp_wrkdir/space.cumulative; then
        sort -t: +2 < $pp_wrkdir/space.cumulative |
        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
    fi
}

pp_solaris_proto () {
	typeset t m o g f p st
	typeset abi

	while read t m o g f p st; do
	  if test x"$o" = x"-"; then 
            o="bin"
          fi
	  if test x"$g" = x"-"; then 
            g="bin"
          fi
	  case "$t" in
	    f) test x"$m" = x"-" && m=444
	       case "$f" in 
		*v*) echo "v $1 $p=$pp_destdir$p $m $o $g";;
		*)   echo "f $1 $p=$pp_destdir$p $m $o $g";;
	       esac
	       if test -r "$pp_destdir$p"; then
		  #-- Use file to record ABI types seen 
		  case "`file "$pp_destdir$p"`" in
		    *"ELF 32"*80386*) abi=i386;;
		    *"ELF 64"*AMD*) abi=x86_64;;
		    *"ELF 32"*SPARC*) abi=sparc;;
		    *"ELF 64"*SPARC*) abi=sparc64;;
		    *) abi=;;
		  esac
		  if test -n "$abi"; then
		    pp_add_to_list pp_solaris_abis_seen $abi
		  fi
	       fi
               ;;
	    d) test x"$m" = x"-" && m=555
	       echo "d $1 $p $m $o $g"
               ;;
	    s) test x"$m" = x"-" && m=777
               test x"$m" = x"777" ||
                  pp_warn "$p: invalid mode $m for symlink, should be 777 or -"
	       echo "s $1 $p=$st $m $o $g"
               ;;
	  esac
	done
}

pp_backend_solaris () {
        typeset _cmp _svc _grp

	prototype=$pp_wrkdir/prototype
	: > $prototype

	pkginfo=$pp_wrkdir/pkginfo
	: > $pkginfo
	echo "i pkginfo=$pkginfo" >> $prototype

        case "${pp_solaris_name:-$name}" in
            [0-9]*)
                pp_error "Package name '${pp_solaris_name:-$name}'" \
                        "cannot start with a number"
                ;;
            ???????????????*)
                pp_warn "Package name '${pp_solaris_name:-$name}'" \
                        "too long for Solaris 2.6 or 2.7 (max 9 characters)"
                ;;
            ??????????*)
                pp_warn "Package name '${pp_solaris_name:-$name}'" \
                        "too long for 2.7 Solaris (max 9 characters)"
                ;;
        esac

        #-- generate the package info file
	echo "VERSION=$version" >> $pkginfo
	echo "PKG=${pp_solaris_name:-$name}" >> $pkginfo
	echo "CLASSES=$pp_components" >> $pkginfo
	echo "BASEDIR=/" >> $pkginfo
	echo "NAME=$name $version" >> $pkginfo
	echo "CATEGORY=${pp_solaris_category:-application}" >> $pkginfo

	desc="${pp_solaris_desc:-$description}"
	test -n "$desc" &&
	  echo "DESC=$desc" >> $pkginfo

	test -n "$pp_solaris_rstates" &&
	  echo "RSTATES=$pp_solaris_rstates" >> $pkginfo
	test -n "$pp_solaris_istates" &&
	  echo "ISTATES=$pp_solaris_istates" >> $pkginfo
	test -n "$pp_solaris_vendor" &&
	  echo "VENDOR=$pp_solaris_vendor" >> $pkginfo

	if test -n "${pp_solaris_copyright:-$copyright}"; then
	    echo "${pp_solaris_copyright:-$copyright}" > $pp_wrkdir/copyright
	    echo "i copyright=$pp_wrkdir/copyright" >> $prototype
	fi

        #-- scripts to run before and after install
        : > $pp_wrkdir/postinstall
        : > $pp_wrkdir/preremove
	for _cmp in $pp_components; do
          #-- add the postinstall scripts in definition order
	  if test -s $pp_wrkdir/%post.$_cmp; then
		pp_solaris_procedure $_cmp postinst < $pp_wrkdir/%post.$_cmp \
			>> $pp_wrkdir/postinstall
          fi
          #-- add the preremove rules in reverse definition order
	  if test -s $pp_wrkdir/%preun.$_cmp; then
		pp_solaris_procedure $_cmp preremove < $pp_wrkdir/%preun.$_cmp |
                    pp_prepend $pp_wrkdir/preremove
          fi
          #-- Add the check script in definition order
	  if test -s $pp_wrkdir/%check.$_cmp; then
		pp_solaris_procedure $_cmp checkinstall \
                        < $pp_wrkdir/%check.$_cmp \
			>> $pp_wrkdir/checkinstall
          fi
          #-- All dependencies are merged together for Solaris pkgs
          test -s $pp_wrkdir/%depend.$_cmp &&
              pp_solaris_depend < $pp_wrkdir/%depend.$_cmp > $pp_wrkdir/depend
	done


        pp_solaris_request > $pp_wrkdir/request

        test -n "$pp_services" && 
            for _svc in $pp_services; do
                pp_load_service_vars $_svc
                pp_solaris_make_service $_svc
                pp_solaris_install_service $_svc >> $pp_wrkdir/postinstall
                pp_prepend $pp_wrkdir/preremove <<-.
                    /etc/init.d/$_svc stop >/dev/null 2>/dev/null
.
            done

        test -n "$pp_service_groups" && 
	    for _grp in $pp_service_groups; do
		pp_solaris_make_service_group \
		    $_grp "`pp_service_get_svc_group $_grp`"
	    done

        #-- if installf was used; we need to indicate a termination
        grep installf $pp_wrkdir/postinstall >/dev/null &&
            echo 'installf -f $PKGINST' >> $pp_wrkdir/postinstall

        pp_solaris_sum_space

        # NB: pkginfo and copyright are added earlier
        for f in compver depend space checkinstall \
                 request preinstall postinstall \
                 preremove postremove; do
            if test -s $pp_wrkdir/$f; then
		case $f in
		    *install|*remove|request)
			# turn scripts into a proper shell scripts
			mv $pp_wrkdir/$f $pp_wrkdir/$f.tmp
			{ echo "#!/bin/sh"; 
			  echo "# $f script for ${pp_solaris_name:-$name}-$version"
			  cat $pp_wrkdir/$f.tmp
			  echo "exit 0"; } > $pp_wrkdir/$f
			chmod +x $pp_wrkdir/$f
			rm -f $pp_wrkdir/$f.tmp
			;;
		esac
                if $pp_opt_debug; then
                    pp_debug "contents of $f:"
                    cat $pp_wrkdir/$f >&2
                fi
                echo "i $f=$pp_wrkdir/$f" >> $prototype
            fi
        done

        #-- create the prototype file which lists the files to install
        # do this as late as possible because files could be added
	pp_solaris_abis_seen=
	for _cmp in $pp_components; do
	  pp_solaris_proto $_cmp < $pp_wrkdir/%files.$_cmp
	done >> $prototype

	if test x"$pp_solaris_package_arch" = x"auto"; then
	    if pp_contains "$pp_solaris_abis_seen" sparc64; then
		pp_solaris_package_arch_std="sparc64"
		echo "ARCH=sparcv9" >> $pkginfo
	    elif pp_contains "$pp_solaris_abis_seen" sparc; then
		pp_solaris_package_arch_std="sparc"
		echo "ARCH=sparc" >> $pkginfo
	    elif pp_contains "$pp_solaris_abis_seen" x86_64; then
		pp_solaris_package_arch_std="x86_64"
		echo "ARCH=amd64" >> $pkginfo
	    elif pp_contains "$pp_solaris_abis_seen" i386; then
		pp_solaris_package_arch_std="i386"
		echo "ARCH=i386" >> $pkginfo
	    else
		pp_warn "No ELF files found: not supplying an ARCH type"
		pp_solaris_package_arch_std="noarch"
	    fi
	else
	    pp_solaris_package_arch_std="$pp_solaris_package_arch"
	    echo "ARCH=$pp_solaris_package_arch" >> $pkginfo
	fi

	mkdir $pp_wrkdir/pkg

	. $pp_wrkdir/%fixup

if $pp_opt_debug; then
  echo "$pkginfo::"; cat $pkginfo
  echo "$prototype::"; cat $prototype
fi >&2

	pkgmk -a $pp_solaris_arch -d $pp_wrkdir/pkg \
	      -f $prototype || { error "pkgmk failed"; return; }
        pkgtrans -s $pp_wrkdir/pkg \
		$pp_wrkdir/`pp_backend_solaris_names` \
                ${pp_solaris_name:-$name} \
		|| { error "pkgtrans failed"; return; }
}

pp_backend_solaris_cleanup () {
	:
}

pp_backend_solaris_names () {
	echo ${pp_solaris_name:-$name}-$version-${pp_solaris_package_arch_std-$pp_solaris_arch}.pkg
}

pp_backend_solaris_install_script () {
        typeset pkgname platform

	platform="${pp_solaris_os-solaris}-${pp_solaris_package_arch_std-$pp_solaris_arch}"

        echo "#! /sbin/sh"
        pp_install_script_common
        pkgname=`pp_backend_solaris_names`

        cat <<.
            tmpnocheck=/tmp/nocheck\$\$
            tmpresponse=/tmp/response\$\$
            trap 'rm -f \$tmpnocheck \$tmpresponse' 0

            make_tmpfiles () {
                cat <<-.. > \$tmpresponse
                        CLASSES=\$*
                        SERVICES=$pp_services
..
                cat <<-.. > \$tmpnocheck
			mail=
			instance=overwrite
			partial=nocheck
			runlevel=nocheck
			idepend=nocheck
			rdepend=nocheck
			space=nocheck
			setuid=nocheck
			conflict=nocheck
			action=nocheck
			basedir=default
..
            }

            test \$# -eq 0 && usage
            op="\$1"; shift

            case "\$op" in 
                list-components)
                    test \$# -eq 0 || usage \$op
                    echo "$pp_components"
                    ;;
                list-services)
                    test \$# -eq 0 || usage \$op
                    echo "$pp_services"
                    ;;
                list-files)
                    test \$# -ge 1 || usage \$op
                    echo \${PP_PKGDESTDIR:-.}/$pkgname
                    ;;
                install)
                    test \$# -ge 1 || usage \$op
                    make_tmpfiles "\$@"
                    verbose /usr/sbin/pkgadd -n -d \${PP_PKGDESTDIR:-.}/$pkgname \
                        -r \$tmpresponse \
                        -a \$tmpnocheck \
                        ${pp_solaris_name:-$name}
                    ;;
                uninstall)
                    test \$# -ge 1 || usage \$op
                    make_tmpfiles "\$@"
                    verbose /usr/sbin/pkgrm -n \
                        -a \$tmpnocheck \
                        ${pp_solaris_name:-$name}
                    ;;
                start|stop)
                    test \$# -ge 1 || usage \$op
                    ec=0
                    for svc
                    do
                        verbose /etc/init.d/\$svc \$op || ec=1
                    done
                    exit \$ec
                    ;;
                print-platform)
		    echo "$platform"
		    ;;
                *)
                    usage
                    ;;
            esac
.
}

pp_backend_solaris_function () {
    case "$1" in
        pp_mkgroup) cat <<'.';;
            grep "^$1:" /etc/group >/dev/null ||
                /usr/sbin/groupadd $1
.
        pp_mkuser) cat <<'.';;
            eval _user=\$$#
            grep "^$_user:" /etc/passwd >/dev/null ||
                /usr/sbin/useradd -s /usr/bin/false "$@"
.
        pp_havelib) cat <<'.';;
            for _dir in `echo "/usr/lib${3+:$3}" | tr : ' '`; do
                test -r "$_dir/lib$1.so{$2+.$2}" && return 0
            done
            return 1
.
        *) pp_error "unknown function request: $1";;
    esac
}

pp_solaris_dynlib_depend () {
	xargs ldd 2>/dev/null |
	sed -e '/^[^ 	]*:$/d' -e 's,.*=>[	 ]*,,' -e 's,^[ 	]*,,' | 
	sort -u | 
	grep -v '^/usr/platform/' | (
	  set -- ""; shift
	  while read p; do
	    set -- "$@" -p "$p"
	    if [ $# -gt 32 ]; then
		echo "$# is $#" >&2
		pkgchk -l "$@"
		set -- ""; shift
	    fi
	  done
	  [ $# -gt 0 ] && pkgchk -l "$@"
	)|
	awk '/^Current status:/{p=0} p==1 {print $1} /^Referenced by/ {p=1}' |
	sort -u |
	xargs -l32 pkginfo -x |
	awk 'NR % 2 == 1 { name=$1; } NR%2 == 0 { print name, $2 }'
}

pp_solaris_add_dynlib_depends () {
    typeset tmp
    tmp=$pp_wrkdir/tmp.dynlib

    for _cmp in $pp_components; do
	awk '{print destdir $6}' destdir="$pp_destdir" \
		< $pp_wrkdir/%files.$_cmp |
	pp_solaris_dynlib_depend > $tmp
	if test -s $tmp; then
	    cat $tmp >> $pp_wrkdir/%depend.$_cmp
	fi
	rm -f $tmp
    done
}

pp_backend_solaris_probe () {
    echo "${pp_solaris_os}-${pp_solaris_arch_std}"
}

pp_backend_solaris_vas_platforms () {
    case `pp_backend_solaris_probe` in
	sol10-sparc* | sol9-sparc* | sol8-sparc*)	
			echo solaris8-sparc solaris7-sparc solaris26-sparc;;
	sol7-sparc*)	echo                solaris7-sparc solaris26-sparc;;
	sol26-sparc*)	echo                               solaris26-sparc;;
	sol8-*86)	echo solaris8-x86;;
	sol10-*86 | sol10-x86_64)	
			echo solaris10-x64 solaris8-x86;;
	*)		pp_die "unknown system `pp_backend_solaris_probe`";;
    esac
}

pp_backend_solaris_init_svc_vars () {
    pp_solaris_smf_category=
    pp_solaris_service_shell=/sbin/sh
}

pp_solaris_init_svc () {
    smf_category=${pp_solaris_smf_category:-application}
    smf_version=1
    smf_type=service
    solaris_user=
    solaris_stop_signal=
    solaris_sysv_init_start=S98     # invocation order for start scripts
    solaris_sysv_init_kill=K30      # invocation order for kill scripts
    solaris_sysv_init_start_states="2" # states to install start link
    solaris_sysv_init_kill_states="S 0 1"  # states to install kill link

    #
    # To have the service be installed to start automatically,
    #   %service foo
    #   solaris_sysv_init_start_states="S 0 1 2"
    #
}

pp_solaris_smf () {
    typeset f
    f=/var/svc/manifest/$smf_category/$1
    pp_add_file_if_missing $f ||
        return 0

    cat <<-. >$pp_destdir$f
	<?xml version="1.0"?>
        <!-- 
            $copyright 
            Generated by PolyPackage $pp_version
	-->

        <service name='$smf_category/$1'
                 type='$smf_type'
                 version='$smf_version'>

            <single_instance />

            <exec_method type='method' name='start'
                exec='' 
                timeout_seconds='60'>
                <method_context>
                  <method_credential user='${solaris_user:-$user}' />
                </method_context>
            </exec>

            <exec_method type='method' name='stop'
                exec=':kill -${solaris_stop_signal:-$stop_signal}'>
                <method_context>
                  <method_credential user='${solaris_user:-$user}' />
                </method_context>
            </exec>

        </service>
.
}

pp_solaris_make_service_group () {
    typeset group out file svcs svc

    group="$1"
    svcs="$2"
    file="/etc/init.d/$group"
    out="$pp_destdir$file"

    #-- return if the script is supplued already
    pp_add_file_if_missing "$file" run 755 || return 0

    echo "#! /sbin/sh" > $out
    echo "# polypkg service group script for these services:" >> $out
    echo "svcs=\"$svcs\"" >> $out

    cat <<'.' >>$out

	#-- starts services in order.. stops them all if any break
	pp_start () {
	    undo=
	    for svc in $svcs; do
		if /etc/init.d/$svc start; then
		    undo="$svc $undo"
		else
		    if test -n "$undo"; then
		        for svc in $undo; do
			   /etc/init.d/$svc stop
			done
			return 1
		    fi
		fi
	    done
	    return 0
	}

	#-- stops services in reverse
	pp_stop () {
	    reverse=
	    for svc in $svcs; do
		reverse="$svc $reverse"
	    done
	    rc=0
	    for svc in $reverse; do
		/etc/init.d/$svc stop || rc=$?
	    done
	    return $rc
	}

	#-- returns true only if all services return true status
	pp_status () {
	    rc=0
	    for svc in $reverse; do
		/etc/init.d/$svc status || rc=$?
	    done
	    return $rc
	}

        case "$1" in
            start)   pp_start;;
            stop)    pp_stop;;
            status)  pp_status;;
            restart) pp_stop && pp_start;;
            *)       echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
        esac
.
}


pp_solaris_make_service () {
    typeset file out _cmd svc

    svc="$1"
    file="/etc/init.d/$svc"
    out="$pp_destdir$file"


    #-- return if we don't need to create the init script
    pp_add_file_if_missing "$file" run 755 ||
        return 0

    # FIXME: the pidfile directory may need to be added as well??
    echo "#! /sbin/sh" >$out
    echo "#-- This service init file generated by polypkg" >>$out

    #-- construct a start command that builds a pid file as needed
    #   and forks the daemon
    _cmd="$cmd";
    if test -z "$pidfile"; then
	# We wrap the start command with something to write the PID file
	cat <<. >>$out
	    if test -d /var/run; then
		piddir="/var/run"
	    else
		piddir="/var/tmp"
	    fi
	    pidfile="\$piddir/$svc.pid"
.
        _cmd="$cmd & echo \$! > \$pidfile"
    else
	# The service is able to write its own PID file
	cat <<. >>$out
	    pidfile="$pidfile"
.
    fi

    if test "${user:-root}" != "root"; then
        _cmd="su $user -c exec $_cmd";
    fi

    cat <<. >>$out
	stop_signal="${stop_signal:-TERM}"
	svc="${svc}"

        # generated command to run $svc as a daemon process
        pp_exec () { $_cmd; }
.

    #-- write the invariant section of the init script
    cat <<'.' >>$out

        # returns true if $svc is running
        pp_running () {
            test -r "$pidfile" &&
            read pid junk < "$pidfile" &&
            test ${pid:-0} -gt 1 &&
            kill -0 "$pid" 2>/dev/null
        }

        # prints a message describing $svc's running state
        pp_status () {
            if pp_running; then
                echo "service $svc is running (pid $pid)"
                return 0
            elif test -f "$pidfile"; then
                echo "service $svc is not running, but pid file exists" 
                return 2
            else
                echo "service $svc is not running" 
                return 1
            fi
        }

        # starts $svc
        pp_start () {
            if pp_running; then
                echo "service $svc already running" >&2
                return 0
            fi
            echo "starting $svc... \c"
            if pp_exec; then
                echo "done."
            else
                echo "ERROR."
                exit 1
            fi
        }

        # stops $svc
        pp_stop () {
            if pp_running; then
                echo "stopping $svc... \c"
                if kill -$stop_signal $pid; then
                    rm -f "$pidfile"
                    echo "done."
                else
                    echo "ERROR."
                    return 1
                fi
            else
                echo "service $svc already stopped" >&2
                return 0
            fi
        }

        umask 022
        case "$1" in
            start)   pp_start;;
            stop)    pp_stop;;
            status)  pp_status;;
            restart) pp_stop && pp_start;;
            *)       echo "usage: $0 {start|stop|restart|status}" >&2; exit 1;;
        esac
.
}


pp_solaris_install_service () {
    typeset s k l
    s="${solaris_sysv_init_start}$1"
    k="${solaris_sysv_init_kill}$1"

    echo 'case " $SERVICES " in *" '$1' "*)'
    test -n "${solaris_sysv_init_start_states}" &&
        for state in ${solaris_sysv_init_start_states}; do
            l="/etc/rc$state.d/$s"
            echo "echo '$l'"
            echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=../init.d/$1 s"
            pp_solaris_space /etc/rc$state.d 0 1
        done
    test -n "${solaris_sysv_init_kill_states}" &&
        for state in ${solaris_sysv_init_kill_states}; do
            l="/etc/rc$state.d/$k"
            echo "echo '$l'"
            echo "installf -c run \$PKGINST \$PKG_INSTALL_ROOT$l=../init.d/$1 s"
            pp_solaris_space /etc/rc$state.d 0 1
        done
    echo " :;; esac"

}

pp_platforms="$pp_platforms deb"

pp_backend_deb_detect () {
    test -f /etc/debian_version
}

pp_deb_cmp_full_name () {
    typeset prefix
    prefix="${pp_deb_name:-$name}"
    case "$1" in
        run) echo "${prefix}" ;;
        dbg) echo "${prefix}-${pp_deb_dbg_pkgname}";;
        dev) echo "${prefix}-${pp_deb_dev_pkgname}";;
        doc) echo "${prefix}-${pp_deb_doc_pkgname}";;
        *)   pp_error "unknown component '$1'";
    esac
}

pp_backend_deb_init () {
    pp_deb_dpkg_version="2.0"
    pp_deb_name=
    pp_deb_version=
    pp_deb_release=
    pp_deb_arch=
    pp_deb_arch_std=
    pp_deb_maintainer=support@quest.com
    pp_deb_copyright=
    pp_deb_distro=
    pp_deb_control_description=
    pp_deb_summary=
    pp_deb_description=
    pp_deb_dbg_pkgname="dbg"
    pp_deb_dev_pkgname="dev"
    pp_deb_doc_pkgname="doc"
    pp_deb_section=contrib # Free software that depends on non-free software

    # Detect the host architecture
    pp_deb_detect_arch

    # Make sure any programs we require are installed
    pp_deb_check_required_programs

    # Set generated/interrogated platforms variables
    pp_deb_munge_description
}

pp_deb_check_required_programs () {
    typeset p needed notfound ok
    needed= notfound=
    for prog in dpkg dpkg-deb install md5sum fakeroot
    do
        if which $prog 2>/dev/null >/dev/null; then
	    pp_debug "$prog: found"
	else
	    pp_debug "$prog: not found"
	    case "$prog" in
		dpkg|dpkg-deb)	p=dpkg;;
		install|md5sum) p=coreutils;;
		fakeroot)	p=fakeroot;;
		*)		pp_die "unexpected dpkg tool $prog";;
	    esac
	    notfound="$notfound $prog"
	    pp_contains "$needed" "$p" || needed="$needed $p"
	fi
    done
    if [ -n "$notfound" ]; then
	pp_error "cannot find these programs: $notfound"
	pp_error "please install these packages: $needed"
    fi
}

pp_deb_munge_description () {
    # Insert a leading space on each line, replace blank lines with a 
    #space followed by a full-stop.
    pp_deb_control_description=`echo ${pp_deb_description:-$description} | \
        sed "s,^\(.*\)$, \1, " \
        | sed "s,^[ \t]*$, .,g"`

}

pp_deb_detect_arch () {
   pp_deb_arch=`dpkg --print-architecture`
   pp_deb_arch_std=`uname -m`
}

pp_deb_make_control() {
    package_name=`pp_deb_cmp_full_name "$1"`
    cat <<-.
	Package: ${package_name}
	Version: ${pp_deb_version:-$version}-${pp_deb_release:-1}
	Section: ${pp_deb_section:-contrib}
	Priority: optional
	Architecture: ${pp_deb_arch}
	Maintainer: ${pp_deb_maintainer:-$maintainer} 
	Description: ${pp_deb_summary:-$summary}
	${pp_deb_control_description}
.
}

pp_deb_make_md5sums() {
    typeset cmp="$1"; shift
    typeset pkg_dir

    pkg_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
    (cd $pkg_dir && md5sum "$@") > $pkg_dir/DEBIAN/md5sums || 
	pp_error "cannot make md5sums"
}

pp_deb_make_package_maintainer_script() {
    typeset output="$1"
    typeset source="$2"
    typeset desc="$3"

    # See if we need to create this script at all
    if [ -s "$source" ] 
    then

        # Create header 
        cat <<-. >$output || pp_error "Cannot create $output"
	#!/bin/sh
	# $desc 
	# Generated by PolyPackage $pp_version

.

        cat $source >> "$output" || pp_error "Cannot append to $output"
 
        # Set perms
        chmod 755 "$output" || pp_error "Cannot chmod $output"
    fi
}

pp_deb_handle_services() {
    typeset svc

    #-- add service start/stop code
    if test -n "$pp_services"; then
        #-- record the uninstall commands in reverse order
        for svc in $pp_services; do
            pp_load_service_vars $svc

            # Create init script (unless one exists)
            pp_deb_service_make_init_script $svc

            #-- append %post code to install the svc
	    test x"yes" = x"$enable" &&
            cat<<-. >> $pp_wrkdir/%post.run
		# Install the service links
		/usr/sbin/update-rc.d $svc defaults
.

            #-- prepend %preun code to stop svc
            cat<<-. | pp_prepend $pp_wrkdir/%preun.run
		# Stop the $svc service
		if test -x /usr/sbin/invoke-rc.d; then
		    /usr/sbin/invoke-rc.d $svc stop
		else
		    /etc/init.d/$svc stop
		fi
		# Remove the service links
		/usr/sbin/update-rc.d -f $svc remove
.
        done
        #pp_deb_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
    fi

}
pp_deb_fakeroot () {
    if test -s $pp_wrkdir/fakeroot.save; then
	fakeroot -i $pp_wrkdir/fakeroot.save -s $pp_wrkdir/fakeroot.save "$@"
    else
	fakeroot -s $pp_wrkdir/fakeroot.save "$@"
    fi
}

pp_deb_make_DEBIAN() {
    typeset cmp="${1:-run}"
    typeset data cmp_full_name
    typeset old_umask

    old_umask=`umask`
    umask 0022
    cmp_full_name=`pp_deb_cmp_full_name $cmp`
    data=$pp_wrkdir/$cmp_full_name

    # Create DEBIAN dir $data/DEBIAN
    mkdir -p $data/DEBIAN

    # Create control file
    pp_deb_make_control $cmp > $data/DEBIAN/control

    # Copy in conffiles
    if test -f $pp_wrkdir/%conffiles.$cmp; then
	cp $pp_wrkdir/%conffiles.$cmp $data/DEBIAN/conffiles
    fi

    # Create postinst
    pp_deb_make_package_maintainer_script "$data/DEBIAN/postinst" \
        "$pp_wrkdir/%post.$cmp" "Post install script for $cmp_full_name"\
        || exit $?

    # Create prerm
    pp_deb_make_package_maintainer_script "$data/DEBIAN/prerm" \
        "$pp_wrkdir/%preun.$cmp" "Pre-uninstall script for $cmp_full_name"\
        || exit $?

    umask $old_umask
}

pp_deb_make_data() {
    typeset _l t m o g f p st data
    typeset data share_doc owner group
    cmp=$1
    data=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
    cat $pp_wrkdir/%files.${cmp} | while read t m o g f p st; do
	test x"$o" = x"-" && o=root 
	test x"$g" = x"-" && g=root 
        case "$t" in
        f) # Files 
           pp_deb_fakeroot install -D -o $o -g $g -m ${m} $pp_destdir/$p $data/$p;
           if [ x"$f" = x"v" ]
           then
               # File marked as "volatile". Assume this means it's a conffile
	       # TODO: check this as admins like modified conffiles to be left
	       #       behind
               echo "$p" >> $pp_wrkdir/%conffiles.$cmp
           fi;;

        d) # Directories 
           pp_deb_fakeroot install -m ${m} -o $o -g $g -d $data/$p;;

        s) # Symlinks 
           # Remove leading / from vars
           rel_p=`echo $p | sed s,^/,,`
           rel_st=`echo $st | sed s,^/,,`
           # TODO: we are always doing absolute links here. We should follow 
	   # the debian policy of relative links when in the same top-level 
	   # directory
           (cd $data; ln -sf $st $rel_p);;
	    *) pp_error "Unsupported data file type: $t";;
	esac
    done 

    # If no copyright file is present add one. This is a debian requirement.
    share_doc="/usr/share/doc/`pp_deb_cmp_full_name $cmp`"
    if [ ! -f "$data/$share_doc/copyright" ]
    then
        echo "${pp_deb_copyright:-$copyright}" > "$pp_wrkdir/copyright"
        install -D -m 644 "$pp_wrkdir/copyright" "$data/$share_doc/copyright" 
    fi

}

pp_deb_makedeb () {
    typeset cmp
    typeset package_build_dir

    cmp="$1"

    package_build_dir=$pp_wrkdir/`pp_deb_cmp_full_name $cmp`
        
    # Create package dir
    mkdir -p $package_build_dir

    # Copy in data
    pp_deb_make_data $cmp || 
	pp_die "Could not make DEBIAN data files for $cmp"

    # Make control files
    # must be done after copying data so conffiles are found
    pp_deb_make_DEBIAN $cmp ||
	pp_die "Could not make DEBIAN control files for $cmp"

    # Create md5sums
    pp_deb_make_md5sums $cmp `(cd $package_build_dir; 
	find . -type f -a -not -name DEBIAN | sed "s,^\./,,")` || 
	    pp_die "Could not make DEBIAN md5sums for $cmp"
}

pp_backend_deb () {
    typeset debname

    # Handle services
    pp_deb_handle_services $cmp

    for cmp in $pp_components
    do
        debname=`pp_deb_name $cmp`
        pp_deb_makedeb $cmp
    done

    . $pp_wrkdir/%fixup

    for cmp in $pp_components
    do
        debname=`pp_deb_name $cmp`
	# Create debian package
	pp_debug "Building `pp_deb_cmp_full_name $cmp` -> $output"
	pp_deb_fakeroot dpkg-deb \
	    --build $pp_wrkdir/`pp_deb_cmp_full_name $cmp` \
	    $pp_wrkdir/$debname || 
		pp_error "failed to create $cmp package"
    done
}

pp_backend_deb_cleanup () {
    # rm -rf $pp_wrkdir
    :
}

pp_deb_name () {
    typeset cmp="${1:-run}"
    echo `pp_deb_cmp_full_name $cmp`"_${pp_deb_version:-$version}-${pp_deb_release:-1}_${pp_deb_arch}.deb"
}
pp_backend_deb_names () {
    for cmp in $pp_components
    do
        pp_deb_name $cmp
    done
}

pp_backend_deb_install_script () {
    typeset cmp _cmp_full_name

    echo "#!/bin/sh"
    pp_install_script_common

    cat <<.

        cmp_to_pkgname () {
            test x"\$*" = x"all" && 
                set -- $pp_components
            for cmp
            do
                case \$cmp in
.
    for cmp in $pp_components; do
         echo "$cmp) echo '`pp_deb_cmp_full_name $cmp`';;"
    done
    cat <<.
                *) usage;;
                esac
            done
        }


        cmp_to_pathname () {
            test x"\$*" = x"all" && 
                set -- $pp_components
            for cmp
            do
                case \$cmp in
.
    for cmp in $pp_components; do
         echo "$cmp) echo \${PP_PKGDESTDIR:-.}/'`pp_deb_name $cmp`';;"
    done
    cat <<.
                *) usage;;
		esac
            done
        }

        test \$# -eq 0 && usage
        op="\$1"; shift
        case "\$op" in
            list-components) 
                test \$# -eq 0 || usage \$op
                echo $pp_components
                ;;
            list-services)
                test \$# -eq 0 || usage \$op
                echo $pp_services
                ;;
            list-files)
                test \$# -ge 1 || usage \$op
                cmp_to_pathname "\$@"
                ;;
            install)
                test \$# -ge 1 || usage \$op
                dpkg --install \`cmp_to_pathname "\$@"\`
                ;;
            uninstall)
                test \$# -ge 1 || usage \$op
                dpkg --remove \`cmp_to_pkgname "\$@"\`; :
                ;;
            start|stop)
                test \$# -ge 1 || usage \$op
                ec=0
                for svc
                do
                    /etc/init.d/\$svc \$op || ec=1
                done
                exit \$ec
                ;;
            print-platform)
                test \$# -eq 0 || usage \$op
		echo "linux-${pp_deb_arch}"
		;;
            *)
                usage
                ;;
        esac
.
}

pp_backend_deb_function() {

    case "$1" in
        pp_mkgroup) 
	    # could use groupadd --force but its not avail on deb 3.1
            cat<<'.';;
	    if /usr/sbin/groupmod $1 2>/dev/null; then :; else
                /usr/sbin/groupadd $1
	    fi
.
        pp_mkuser) 
	    # deb 3.1's useradd changed API in 4.0. Gah!
            cat<<'.';;
	    if /usr/sbin/useradd --help 2>&1 | grep -q .--system; then
                /usr/sbin/useradd -s /bin/false --system $@ 
	    else
                /usr/sbin/useradd -s /bin/false $@ 
	    fi
.
        pp_havelib) cat<<'.';;
            typeset dir
            for dir in `echo "/usr/lib:/lib${3+:$3}" | tr : ' '`; do
                test -r "$dir/lib$1.so{$2+.$2}" && return 0
            done
            return 1
.
        *)
            pp_error "unknown function request: $1";;
    esac
}

pp_backend_deb_probe() {
    typeset arch distro release

    pp_deb_detect_arch

    # /etc/debian_version exists on Debian & Ubuntu, so it's no use
    # to us. Use lsb_release instead.

    case `(lsb_release -is || echo no-lsb) 2>/dev/null` in
        Debian)
            distro=deb
	    ;;
        Ubuntu)
            distro=ubu
	    ;;
	no-lsb)
	    echo unknown-$pp_deb_arch_std
	    return 0
	    ;;
        *)
            distro=unknown
	    ;;
    esac

    release=`lsb_release -rs`

    # If release is not numeric, use the codename
    case $release in
        *[!.0-9r]*)
	    release=`lsb_release -cs`
	    ;;
	*)
	    # Remove trailing revision number and any dots
            release=`echo $release | cut -dr -f1 | tr -d .`
	    ;;
    esac

    echo $distro$release-$pp_deb_arch_std
}

pp_backend_deb_vas_platforms () {
    case "$pp_deb_arch_std" in
	x86_64)	echo "linux-x86_64.deb";; # DO NOT add linux-x86.deb here!!
	*86)	echo "linux-x86.deb";;
	*)	pp_die "unknown architecture ${pp_deb_arch_std}";;
    esac
}
pp_backend_deb_init_svc_vars () {
    pp_deb_default_start_runlevels=         # should be "3 4 5"??
    pp_deb_default_svc_description="No description"
}

pp_backend_deb_init_svc_vars () {

    reload_signal=
    start_runlevels=${pp_deb_default_start_runlevels}   # == lsb default-start
    stop_runlevels="0 1 2 6"                            # == lsb default-stop
    svc_description="${pp_deb_default_svc_description}" # == lsb short descr
    svc_process=

    lsb_required_start='$local_fs $network'
    lsb_should_start=
    lsb_required_stop=
    lsb_description=

    start_priority=50
    stop_priority=50            #-- stop_priority = 100 - start_priority
}

pp_deb_service_make_init_script () {
    typeset svc=$1 
    typeset script=/etc/init.d/$svc
    typeset out=$pp_destdir$script
    typeset _process _cmd

    pp_add_file_if_missing $script run 755 || return 0

    #-- start out as an empty shell script
    cat <<-'.' >$out
	#!/bin/sh
.

    #-- determine the process name from $cmd unless $svc_process is given
    set -- $cmd
    #_process=${svc_process:-"$1"} --? WTF

    #-- construct a start command that builds a pid file if needed
    _cmd="$cmd";
    _cmd_path=`echo $cmd | cut -d" " -f1`
    _cmd_name=`basename $_cmd_path`
    _cmd_args=`echo $cmd | cut -d" " -f2-`
    test x"$_cmd_path" != x"$_cmd_args" || _cmd_args=

    #-- generate the LSB init info
    cat <<-. >>$out
	### BEGIN INIT INFO
	# Provides: ${svc}
	# Required-Start: ${lsb_required_start}
	# Should-Start: ${lsb_should_start}
	# Required-Stop: ${lsb_required_stop}
	# Default-Start: ${start_runlevels}
	# Default-Stop: ${stop_runlevels}
	# Short-Description: ${svc_description}
	### END INIT INFO
	# Generated by PolyPackage ${pp_version}
	# ${copyright}

.

    if test x"${svc_description}" = x"${pp_deb_default_svc_description}"; then
        svc_description=
    fi

    #-- write service-specific definitions
    cat <<. >>$out
NAME="${_cmd_name}"
DESC="${svc_description:-$svc service}"
USER="${user}"
GROUP="${group}"
PIDFILE="${pidfile}"
STOP_SIGNAL="${stop_signal}"
RELOAD_SIGNAL="${reload_signal}"
CMD="${_cmd}"
DAEMON="${_cmd_path}"
DAEMON_ARGS="${_cmd_args}"
SCRIPTNAME=${script}
.

    #-- write the generic part of the init script
    cat <<'.' >>$out

[ -x "$DAEMON" ] || exit 0

[ -r /etc/default/$NAME ] && . /etc/default/$NAME

[ -f /etc/default/rcS ] && . /etc/default/rcS

. /lib/lsb/init-functions

do_start()
{
	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started
    if [ -n "$PIDFILE" ]
    then
        pidfile_opt="--pidfile $PIDFILE"
    else
        pidfile_opt="--make-pidfile --background --pidfile /var/run/$NAME.pid"
    fi
    if [ -n "$USER" ]
    then
        user_opt="--user $USER"
    fi
    if [ -n "$GROUP" ]
    then
        group_opt="--group $GROUP"
    fi
    if [ "$VERBOSE" = no ]
    then
        quiet_opt="--quiet"
    else
        quiet_opt="--verbose"
    fi

	start-stop-daemon --start $quiet_opt $pidfile_opt $user_opt --exec $DAEMON --test > /dev/null \
	    || return 1

    # Note: there seems to be no way to tell whether the daemon will fork itself or not, so pass
    # --background for now
    start-stop-daemon --start $quiet_opt $pidfile_opt $user_opt --exec $DAEMON -- \
    	$DAEMON_ARGS \
    	|| return 2
}

do_stop()
{
	# Return
	#   0 if daemon has been stopped
	#   1 if daemon was already stopped
	#   2 if daemon could not be stopped
	#   other if a failure occurred
    if [ -n "$PIDFILE" ]
    then
        pidfile_opt="--pidfile $PIDFILE"
    else
        pidfile_opt="--pidfile /var/run/$NAME.pid"
    fi
    if [ -n "$USER" ]
    then
        user_opt="--user $USER"
    fi
    if [ -n $STOP_SIGNAL ]
    then
        signal_opt="--signal $STOP_SIGNAL"
    fi
    if [ "$VERBOSE" = "no" ]
    then
        quiet_opt="--quiet"
    else
        quiet_opt="--verbose"
    fi
	start-stop-daemon --stop $quiet_opt $signal_opt --retry=TERM/30/KILL/5 $pidfile_opt --name $NAME 
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	# Wait for children to finish too if this is a daemon that forks
	# and if the daemon is only ever run from this initscript.
	# If the above conditions are not satisfied then add some other code
	# that waits for the process to drop all resources that could be
	# needed by services started subsequently.  A last resort is to
	# sleep for some time.
	start-stop-daemon --stop $quiet_opt --oknodo --retry=0/30/KILL/5 --exec $DAEMON
	[ "$?" = 2 ] && return 2
	# Many daemons don't delete their pidfiles when they exit.
	test -z $PIDFILE || rm -f $PIDFILE
	return "$RETVAL"
}

do_reload() {
	#
	# If the daemon can reload its configuration without
	# restarting (for example, when it is sent a SIGHUP),
	# then implement that here.
	#
    if [ -n "$PIDFILE" ]
    then
        pidfile_opt="--pidfile $PIDFILE"
    else
        pidfile_opt="--pidfile /var/run/$NAME.pid"
    fi
    if [ -n "$RELOAD_SIGNAL" ]
    then
	    start-stop-daemon --stop --signal $RELOAD_SIGNAL $quiet_opt $pidfile_opt --name $NAME
    fi
	return 0
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  reload|force-reload)
    if [ -n "$RELOAD_SIGNAL" ]
    then
	    log_daemon_msg "Reloading $DESC" "$NAME"
	    do_reload
	    log_end_msg $?
    else
        # Do a restart instead
        "$0" restart
    fi
	;;
  restart)
	#
	# If the "reload" option is implemented then remove the
	# 'force-reload' alias
	#
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  *)
	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
	exit 3
	;;
esac

:
.
    chmod 755 $out
}

pp_platforms="$pp_platforms rpm"

pp_backend_rpm_detect () {
    test x"$1" = x"Linux" -a ! -f /etc/debian_version
}

pp_backend_rpm_init () {

    pp_rpm_version=
    pp_rpm_summary=
    pp_rpm_description=
    pp_rpm_group="Applications/Internet"
    pp_rpm_license=Unspecified
    pp_rpm_vendor="Quest Software, Inc."
    pp_rpm_packager=
    pp_rpm_provides=
    pp_rpm_requires=
    pp_rpm_release=
    pp_rpm_epoch=
    pp_rpm_dev_group="Development/Libraries"
    pp_rpm_dbg_group="Development/Tools"
    pp_rpm_doc_group="Documentation"
    pp_rpm_dev_description=
    pp_rpm_dbg_description=
    pp_rpm_doc_description=
    pp_rpm_dev_requires=
    pp_rpm_dbg_requires=
    pp_rpm_doc_requires=
    pp_rpm_dev_provides=
    pp_rpm_dbg_provides=
    pp_rpm_doc_provides=

    pp_rpm_dbg_pkgname=debug
    pp_rpm_dev_pkgname=devel
    pp_rpm_doc_pkgname=doc

    pp_rpm_defattr_uid=root
    pp_rpm_defattr_gid=root

    pp_rpm_detect_arch
    pp_rpm_detect_distro
}

pp_rpm_detect_arch () {
    pp_rpm_arch=auto

    #-- Find the default native architecture that RPM is configured to use
    cat <<-. >$pp_wrkdir/dummy.spec
	Name: dummy
	Version: 1
	Release: 1
	Summary: dummy
	Group: ${pp_rpm_group}
	License: ${pp_rpm_license}
	%description
	dummy
.
    $pp_opt_debug && cat $pp_wrkdir/dummy.spec
    pp_rpm_arch_local=`rpm -q --qf '%{arch}\n' --specfile $pp_wrkdir/dummy.spec`
    rm $pp_wrkdir/dummy.spec

    #-- Ask the kernel what machine architecture is in use
    case "`uname -m`" in
	i?86)	pp_rpm_arch_std=i386;;
	x86_64)	pp_rpm_arch_std=x86_64;;
	ppc)	pp_rpm_arch_std=ppc;;
	ppc64)	pp_rpm_arch_std=ppc64;;
	ia64)	pp_rpm_arch_std=ia64;;
	s390)	pp_rpm_arch_std=s390;;
	s390x)	pp_rpm_arch_std=s390x;;
	*)	pp_rpm_arch_std=unknown;;
    esac

    #-- Later on, when files are processed, we use 'file' to determine
    #   what platform ABIs are used. This is used when pp_rpm_arch == auto
    pp_rpm_arch_seen=
}

pp_rpm_detect_distro () {
    pp_rpm_distro=
    if test -f /etc/whitebox-release; then
       pp_rpm_distro=`awk '
          /^White Box Enterprise Linux release/ { print "wbel" $6; exit; }
       ' /etc/whitebox-release`
    elif test -f /etc/fedora-release; then
       pp_rpm_distro=`awk '
          /^Fedora Core release/ { print "fc" $4; exit; }
       ' /etc/fedora-release`
    elif test -f /etc/redhat-release; then
       pp_rpm_distro=`awk '
          /^Red Hat Enterprise Linux/ { print "rhel" $7; exit; }
          /^CentOS release/           { print "centos" $3; exit; }
          /^Red Hat Linux release/    { print "rh" $5; exit; }
       ' /etc/redhat-release`
    elif test -f /etc/SuSE-release; then
       pp_rpm_distro=`awk '
          /^SuSE Linux [0-9]/ { print "suse" $3; exit; }
          /^SUSE LINUX [0-9]/ { print "suse" $3; exit; }
          /^openSUSE [0-9]/   { print "suse" $2; exit; }
          /^SuSE Linux Enterprise Server [0-9]/ { print "sles" $5; exit; }
          /^SUSE LINUX Enterprise Server [0-9]/ { print "sles" $5; exit; }
       ' /etc/SuSE-release`
    fi
    pp_rpm_distro=`echo $pp_rpm_distro | tr -d .`
    test -z "$pp_rpm_distro" &&
       pp_warn "unknown distro"
}

pp_rpm_label () {
    typeset label arg
    label="$1"; shift
    for arg
    do
        test -z "$arg" || echo "$label: $arg"
    done
}

pp_rpm_writefiles () {
    typeset _l t m o g f p st fo
    while read t m o g f p st; do
        _l="$p"
	test $t = d && _l="%dir ${_l%/}/"
        if test x"$m" = x"-"; then
            case "$t" in
                d) m=755;;
                f) m=644;;
            esac
        fi
        test x"$o" = x"-" && o="${pp_rpm_defattr_uid:-root}"
        test x"$g" = x"-" && g="${pp_rpm_defattr_gid:-root}"
	_l="%attr($m,$o,$g) $_l"

	if test "$t" = "f" -a x"$pp_rpm_arch" = x"auto"; then
	    fo=`file "${pp_destdir}$p" 2>/dev/null`
	    pp_debug "file: $fo"
	    #NB: The following should match executables and shared objects,
	    #relocatable objects. It will not match .a files however.
	    case "$fo" in
		*": ELF 32-bit LSB "*", Intel 80386"*)
		    pp_add_to_list pp_rpm_arch_seen i386;;
		*": ELF 64-bit LSB "*", AMD x86-64"*)
		    pp_add_to_list pp_rpm_arch_seen x86_64;;
		*": ELF 32-bit MSB "*", PowerPC"*)
		    pp_add_to_list pp_rpm_arch_seen ppc;;
		*": ELF 64-bit LSB "*", IA-64"*)
		    pp_add_to_list pp_rpm_arch_seen ia64;;
		*": ELF 32-bit MSB "*", IBM S/390"*)
		    pp_add_to_list pp_rpm_arch_seen s390;;
		*": ELF 64-bit LSB "*", IBM S/390"*)
		    pp_add_to_list pp_rpm_arch_seen s390x;;
	    esac
	fi

	case $f in *v*) _l="%config $_l";; esac
	echo "$_l"
    done
    echo
}

pp_rpm_subname () {
    case "$1" in
        run) : ;;
        dbg) echo "${2}${pp_rpm_dbg_pkgname}";;
        dev) echo "${2}${pp_rpm_dev_pkgname}";;
        doc) echo "${2}${pp_rpm_doc_pkgname}";;
        *)   pp_error "unknown component '$1'";
    esac
}

pp_rpm_depend () {
    while read _name _vers; do
        case "$_name" in ""| "#"*) continue ;; esac
        echo "Requires: $_name ${_vers:+>= $_vers}"
    done
}

pp_backend_rpm () {
        typeset cmp specfile _summary _group _desc _pkg _subname svc

	specfile=$pp_wrkdir/$name.spec
        : > $specfile

        #-- force existence of a 'run' component
        pp_add_component run
        : >> $pp_wrkdir/%files.run

	if test -z "$pp_rpm_arch"; then
            pp_error "Unknown RPM architecture"
            return 1
        fi

	#-- Write the header components of the RPM spec file
	cat <<-. >>$specfile
		Name: ${pp_rpm_name:-$name}
		Version: ${pp_rpm_version:-$version}
		Release: ${pp_rpm_release:-1}
		Summary: ${pp_rpm_summary:-$summary}
		Group:   ${pp_rpm_group}
		License: ${pp_rpm_license}
.
	pp_rpm_label "Vendor"   "$pp_rpm_vendor"   >>$specfile
	pp_rpm_label "Packager" "$pp_rpm_packager" >>$specfile
	pp_rpm_label "Provides" "$pp_rpm_provides" >>$specfile
	
	test -n "$pp_rpm_serial" && pp_warn "pp_rpm_serial deprecated"
	if test -n "$pp_rpm_epoch"; then
	    #-- Epoch was introduced in RPM 2.5.6
	    case `rpmbuild --version 2>/dev/null` in
		1.*|2.[0-5].*|2.5.[0-5]) 
		    pp_rpm_label "Serial" $pp_rpm_epoch >>$specfile;;
		*)
		    pp_rpm_label "Epoch" $pp_rpm_epoch >>$specfile;;
	    esac
	fi

        if test -n "$pp_rpm_requires"; then
            pp_rpm_label "Requires" "$pp_rpm_requires" >>$specfile
        elif test -s $pp_wrkdir/%depend.run; then
            pp_rpm_depend < $pp_wrkdir/%depend.run >> $specfile
        fi

	cat <<-. >>$specfile

		%description
		${pp_rpm_description:-$description}
.

	for cmp in $pp_components; do
		case $cmp in
		   run) continue;;
		   dev) _summary="development tools for $pp_rpm_summary"
		   	_group="$pp_rpm_dev_group"
			_desc="${pp_rpm_dev_description:-Development libraries for $name. $pp_rpm_description.}"
		   	;;
		   doc) _summary="documentation for $pp_rpm_summary"
		   	_group="$pp_rpm_doc_group"
			_desc="${pp_rpm_doc_description:-Documentation for $name. $pp_rpm_description.}"
		   	;;
		   dbg) _summary="diagnostic tools for $pp_rpm_summary"
		   	_group="$pp_rpm_dbg_group"
			_desc="${pp_rpm_dbg_description:-Diagnostic tools for $name.}"
		   	;;
		esac

                _subname=`pp_rpm_subname $cmp`
		cat <<-.

			%package $_subname
			Summary: $name $_summary
			Group: $_group
.
                eval '_pkg="$pp_rpm_'$cmp'_requires"'
                if test -n "$_pkg"; then
                    eval pp_rpm_label Requires ${pp_rpm_name:-$name} $_pkg
                elif test -s $pp_wrkdir/%depend.$cmp; then
                    pp_rpm_depend < $pp_wrkdir/%depend.$cmp >> $specfile
                fi

                eval '_pkg="$pp_rpm_'$cmp'_provides"'
		eval pp_rpm_label Provides $_pkg

		cat <<-.

			%description $_subname
			$_desc
.
	done >>$specfile

        #-- NB: we don't put any %prep, %build or %install RPM sections 
	#   into the spec file.

        #-- add service start/stop code
        if test -n "$pp_services"; then
            pp_rpm_service_install_common >> $pp_wrkdir/%post.run

            #-- record the uninstall commands in reverse order
            for svc in $pp_services; do
                pp_load_service_vars $svc

                pp_rpm_service_make_init_script $svc

                #-- append %post code to install the svc
                pp_rpm_service_install $svc >> $pp_wrkdir/%post.run

                #-- prepend %preun code to uninstall svc
                # (use files in case vars are modified)
                pp_rpm_service_remove $svc | pp_prepend $pp_wrkdir/%preun.run 
            done
            pp_rpm_service_remove_common | pp_prepend $pp_wrkdir/%preun.run
        fi

	# make convenience service groups
        if test -n "$pp_service_groups"; then
	    for grp in $pp_service_groups; do
		pp_rpm_service_group_make_init_script \
		    $grp "`pp_service_get_svc_group $grp`"
	    done
	fi

	#-- Write the RPM %file sections
        #   (do this after services, since services adds to %files.run)
	for cmp in $pp_components; do
            _subname=`pp_rpm_subname $cmp`

            if test -s $pp_wrkdir/%check.$cmp; then
                echo ""
                echo "%pre $_subname"
                cat $pp_wrkdir/%check.$cmp
                echo :   # causes script to exit true by default
            fi

            if test -s $pp_wrkdir/%files.$cmp; then
                echo ""
                echo "%files $_subname"
                pp_rpm_writefiles < $pp_wrkdir/%files.$cmp
            fi

            if test -s $pp_wrkdir/%post.$cmp; then
                echo ""
                echo "%post $_subname"
                cat $pp_wrkdir/%post.$cmp
                echo :   # causes script to exit true
            fi

            if test -s $pp_wrkdir/%preun.$cmp; then
                echo ""
                echo "%preun $_subname"
                cat $pp_wrkdir/%preun.$cmp
                echo :   # causes script to exit true
            fi
	done >>$specfile

        #-- create a suitable work area for rpmbuild
        echo "%_topdir $pp_wrkdir" >$pp_wrkdir/.rpmmacros
	mkdir $pp_wrkdir/RPMS
	mkdir $pp_wrkdir/BUILD

	if test x"$pp_rpm_arch" = x"auto"; then
	    #-- Reduce the arch_seen list to exactly one item
	    case "$pp_rpm_arch_seen" in
		"i386 x86_64"|"x86_64 i386")
		    pp_rpm_arch_seen=x86_64;;
		*" "*)
		    pp_warn "detected multiple targets: $pp_rpm_arch_seen"
		    pp_rpm_arch_seen=unknown;;	    # not detected
		"")
		    pp_warn "detected no binaries: using target noarch"
		    pp_rpm_arch_seen=noarch;;
		*)
		    pp_debug "detected architecture $pp_rpm_arch_seen"
	    esac
	    pp_rpm_arch="$pp_rpm_arch_seen"
	fi

        . $pp_wrkdir/%fixup

$pp_opt_debug && cat $specfile 

        pp_debug "creating: `pp_backend_rpm_names`"

pp_debug "pp_rpm_arch_seen = <${pp_rpm_arch_seen}>"
pp_debug "pp_rpm_arch = <${pp_rpm_arch}>"

	HOME=$pp_wrkdir \
	pp_verbose \
        rpmbuild -bb \
		--buildroot="$pp_destdir/" \
                --target="${pp_rpm_arch}" \
                --define='_unpackaged_files_terminate_build 0' \
                `$pp_opt_debug && echo --verbose || echo --quiet` \
                $pp_rpm_rpmbuild_extra_flags \
		$specfile || 
            pp_error "Problem creating RPM packages"

	for f in `pp_backend_rpm_names`; do
	    ln $pp_wrkdir/RPMS/${pp_rpm_arch}/$f $pp_wrkdir/$f ||
                pp_error "Problem predicting RPM filenames: $f"
	done
}

pp_rpm_output_name () {
    echo "${pp_rpm_name:-$name}`pp_rpm_subname "$1" -`-${pp_rpm_version:-$version}-${pp_rpm_release:-1}.${pp_rpm_arch}.rpm"
}

pp_backend_rpm_names () {
    typeset cmp _subname
    for cmp in $pp_components; do
	pp_rpm_output_name $cmp
    done
}

pp_backend_rpm_cleanup () {
    :
}

pp_rpm_print_requires () {
    typeset _subname _name

    echo "CPU:$pp_rpm_arch"
    ## XXX should be lines of the form (from file/ldd/objdump)
    #    EXEC:/bin/sh
    #    RTLD:libc.so.4:open
    rpm -q --requires -p $pp_wrkdir/`pp_rpm_output_name $1` |sed -e '/^rpmlib(/d;s/ //g;s/^/RPM:/' | sort -u
}

pp_backend_rpm_install_script () {
    typeset cmp _subname

    echo "#!/bin/sh"
    pp_install_script_common

    cat <<.

        cmp_to_pkgname () {
	    typeset oi name
	    if test x"\$1" = x"--only-installed"; then
		#-- only print if installation detected
		oi=false
		shift
	    else
		oi=true
	    fi
            test x"\$*" = x"all" && 
                set -- $pp_components
            for cmp
            do
                case \$cmp in
.
    for cmp in $pp_components; do
        _subname=`pp_rpm_subname $cmp -`
         echo "$cmp) name=${pp_rpm_name:-$name}${_subname};;"
    done
    cat <<.
                *) usage;;
                esac
		if \$oi || rpm -q "\$name" >/dev/null 2>/dev/null; then
		    echo "\$name"
		fi
            done
        }


        cmp_to_pathname () {
            test x"\$*" = x"all" && 
                set -- $pp_components
            for cmp
            do
                case \$cmp in
.
    for cmp in $pp_components; do
        echo "$cmp) echo \${PP_PKGDESTDIR:-.}/`pp_rpm_output_name $cmp` ;;"
    done
    cat <<.
                *) usage;;
                esac
            done
        }
	
	print_requires () {
            test x"\$*" = x"all" && 
                set -- $pp_components
            for cmp
            do
                case \$cmp in
.
    for cmp in $pp_components; do
        echo "$cmp) cat <<'._end'"
	pp_rpm_print_requires $cmp
        echo "._end"; echo ';;'
    done
    cat <<.
                *) usage;;
                esac
            done
        }

        test \$# -eq 0 && usage
        op="\$1"; shift
        case "\$op" in
            list-components) 
                test \$# -eq 0 || usage \$op
                echo $pp_components
                ;;
            list-services)
                test \$# -eq 0 || usage \$op
                echo $pp_services
                ;;
            list-files)
                test \$# -ge 1 || usage \$op
                cmp_to_pathname "\$@"
                ;;
            install)
                test \$# -ge 1 || usage \$op
                verbose rpm -U --replacepkgs --oldpackage \
                    \`cmp_to_pathname "\$@"\`
                ;;
            uninstall)
                test \$# -ge 1 || usage \$op
                pkgs=\`cmp_to_pkgname --only-installed "\$@"\`
                if test -z "\$pkgs"; then
                    verbosemsg "nothing to uninstall"
                else
                    verbose rpm -e \$pkgs
                fi
                ;;
            start|stop)
                test \$# -ge 1 || usage \$op
                ec=0
                for svc
                do
                    verbose /etc/init.d/\$svc \$op || ec=1
                done
                exit \$ec
                ;;
            print-platform)
                test \$# -eq 0 || usage \$op
		echo "linux-${pp_rpm_arch}"
		;;
            print-requires)
                test \$# -ge 1 || usage \$op
                print_requires "\$@"
		;;
            *)
                usage
                ;;
        esac
.

}

pp_backend_rpm_function () {
    case "$1" in
        pp_mkgroup) cat<<'.';;
            /usr/sbin/groupadd -r $1
.
        pp_mkuser) cat<<'.';;
            /usr/sbin/useradd -s /bin/false -M -r $@ 
.
        pp_havelib) cat<<'.';;
            typeset dir
            for dir in `echo "/usr/lib:/lib${3+:$3}" | tr : ' '`; do
                test -r "$dir/lib$1.so{$2+.$2}" && return 0
            done
            return 1
.
        *) pp_error "unknown function request: $1" ;;
    esac
}

pp_backend_rpm_probe () {
        echo "${pp_rpm_distro}-${pp_rpm_arch_std}"
}

pp_backend_rpm_vas_platforms () {
    case "$pp_rpm_arch_std" in
	x86_64)	echo "linux-x86_64.rpm linux-x86.rpm";;
	*86)	echo "linux-x86.rpm";;
	s390)	echo "linux-s390";;
	s390x)	echo "linux-s390x";;
	ppc*)	echo "linux-glibc23-ppc64 linux-glibc22-ppc64";;
	ia64)	echo "linux-ia64";;
	*)	pp_die "unknown architecture $pp_rpm_arch_std";;
    esac
}

pp_backend_rpm_init_svc_vars () {
    pp_rpm_default_start_runlevels=         # should be "3 4 5"??
    pp_rpm_default_svc_description="No description"
}

pp_rpm_service_install_common () {
    cat <<-'.'

        _pp_install_service () {
            typeset svc level
            svc="$1"
            if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
            then
                # LSB-style install
                /usr/lib/lsb/install_initd /etc/init.d/$svc
            elif [ -x /sbin/chkconfig ]; then
                # Red Hat/chkconfig-style install
                /sbin/chkconfig --add $svc 
                /sbin/chkconfig $svc off
            else
		: # manual links under /etc/init.d
            fi
        }

        _pp_enable_service () {
            typeset svc level
            svc="$1"
            if [ -x /usr/lib/lsb/install_initd -a ! -r /etc/redhat-release ]
            then
                # LSB-style install
		: not sure how to enable
            elif [ -x /sbin/chkconfig ]; then
                # Red Hat/chkconfig-style install
                /sbin/chkconfig $svc on
            else
                # manual install
                set -- `sed -n -e 's/^# Default-Start://p' /etc/init.d/$svc`
                for level
                do ln -sf /etc/init.d/$svc /etc/rc.d/rc$level.d/S90$svc; done
                set -- `sed -n -e 's/^# Default-Stop://p' /etc/init.d/$svc`
                for level
                do ln -sf /etc/init.d/$svc /etc/rc.d/rc$level.d/K10$svc; done
            fi
        }
.
}

pp_rpm_service_remove_common () {
    cat <<-'.'

        _pp_remove_service () {
            typeset svc
            svc="$1"
            /etc/init.d/$svc stop >/dev/null 2>&1
            if [ -x /usr/lib/lsb/remove_initd -a ! -r /etc/redhat-release ]
            then
                /usr/lib/lsb/remove_initd /etc/init.d/$svc
            elif [ -x /sbin/chkconfig ]; then
                /sbin/chkconfig --del $svc
            else
                rm -f /etc/rc.d/rc?.d/[SK]??$svc
            fi
        }
.
}


pp_rpm_service_install () {
    pp_rpm_service_make_init_script $1 >/dev/null ||
        pp_error "could not create init script for service $1"
    echo "_pp_install_service $1"
    test $enable = yes && echo "_pp_enable_service $1"
}

pp_rpm_service_remove () {
    echo "_pp_remove_service $1"
}


pp_backend_rpm_init_svc_vars () {

    reload_signal=
    start_runlevels=${pp_rpm_default_start_runlevels}   # == lsb default-start
    stop_runlevels="0 1 2 6"                            # == lsb default-stop
    svc_description="${pp_rpm_default_svc_description}" # == lsb short descr
    svc_process=

    lsb_required_start='$local_fs $network'
    lsb_should_start=
    lsb_required_stop=
    lsb_description=

    start_priority=50
    stop_priority=50            #-- stop_priority = 100 - start_priority
}

pp_rpm_service_group_make_init_script () {
    typeset grp=$1
    typeset svcs="$2"
    typeset script=/etc/init.d/$grp
    typeset out=$pp_destdir$script

    pp_add_file_if_missing $script run 755 || return 0

    cat <<-. >>$out
	#!/bin/sh
	svcs="$svcs"
.

    cat <<-'.' >>$out

        #-- prints usage message
        pp_usage () {
            echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
            return 2
        }

        #-- starts services in order.. stops them all if any break
        pp_start () {
            undo=
            for svc in $svcs; do
                if /etc/init.d/$svc start; then
                    undo="$svc $undo"
                else
                    if test -n "$undo"; then
                        for svc in $undo; do
                           /etc/init.d/$svc stop
                        done
                        return 1
                    fi
                fi
            done
            return 0
        }

        #-- stops services in reverse
        pp_stop () {
            reverse=
            for svc in $svcs; do
                reverse="$svc $reverse"
            done
            rc=0
            for svc in $reverse; do
                /etc/init.d/$svc stop || rc=$?
            done
            return $rc
        }

        #-- returns true only if all services return true status
        pp_status () {
            rc=0
            for svc in $reverse; do
                /etc/init.d/$svc status || rc=$?
            done
            return $rc
        }

        pp_reload () {
            rc=0
            for svc in $svcs; do
                /etc/init.d/$svc reload || rc=$?
            done
            return $rc
        }

        case "$1" in
            start)          pp_start;;
            stop)           pp_stop;;
            restart)        pp_stop; pp_start;;
            status)         pp_status;;
            try-restart|condrestart)    
                            if pp_status >/dev/null; then
                                    pp_restart
                            fi;;
            reload)         pp_reload;;
            force-reload)   if pp_status >/dev/null; then
                                    pp_reload
                            else
                                    pp_restart
                            fi;;
            *)              pp_usage;;
        esac
.
    chmod 755 $out
}

pp_rpm_service_make_init_script () {
    typeset svc=$1 
    typeset script=/etc/init.d/$svc
    typeset out=$pp_destdir$script
    typeset _process _cmd _rpmlevels

    pp_add_file_if_missing $script run 755 || return 0

    #-- start out as an empty shell script
    cat <<-'.' >$out
	#!/bin/sh
.

    #-- determine the process name from $cmd unless $svc_process is given
    set -- $cmd
    _process=${svc_process:-"$1"}

    #-- construct a start command that builds a pid file if needed
    _cmd="$cmd";
    if test -z "$pidfile"; then
        pidfile=/var/run/$svc.pid
        _cmd="$cmd & echo \$! > \$pidfile"
    fi
    if test "$user" != "root"; then
        _cmd="su $user -c exec $_cmd";
    fi

    #-- generate the Red Hat chkconfig headers
    _rpmlevels=`echo $start_runlevels | tr -d ' '`
    cat <<-. >>$out
	# chkconfig: ${_rpmlevels:--} ${start_priority:-50} ${stop_priority:-50}
	# description: ${svc_description:-no description}
	# processname: ${_process}
	# pidfile: ${pidfile}
.

    #-- generate the LSB init info
    cat <<-. >>$out
	### BEGIN INIT INFO
	# Provides: ${svc}
	# Required-Start: ${lsb_required_start}
	# Should-Start: ${lsb_should_start}
	# Required-Stop: ${lsb_required_stop}
	# Default-Start: ${start_runlevels}
	# Default-Stop: ${stop_runlevels}
	# Short-Description: ${svc_description}
	### END INIT INFO
	# Generated by PolyPackage ${pp_version}
	# ${copyright}

.

    if test x"${svc_description}" = x"${pp_rpm_default_svc_description}"; then
        svc_description=
    fi

    #-- write service-specific definitions
    cat <<. >>$out
	#-- definitions specific to service ${svc}
	svc_name="${svc_description:-$svc service}"
	user="${user}"
	pidfile="${pidfile}"
	stop_signal="${stop_signal}"
	reload_signal="${reload_signal}"
	pp_exec_cmd () { $_cmd; }
.

    #-- write the generic part of the init script
    cat <<'.' >>$out

        #-- use system message logging, if available
        if [ -f /lib/lsb/init-functions -a ! -r /etc/redhat-release ]; then
            . /lib/lsb/init-functions
            pp_success_msg () { log_success_msg ${1+"$@"}; }
            pp_failure_msg () { log_failure_msg ${1+"$@"}; }
            pp_warning_msg () { log_warning_msg ${1+"$@"}; }
        elif [ -f /etc/init.d/functions ]; then
            . /etc/init.d/functions
            pp_success_msg () { echo -n "$*"; success ${1+"$@"}; echo; }
            pp_failure_msg () { echo -n "$*"; failure ${1+"$@"}; echo; }
            pp_warning_msg () { echo -n "$*"; warning ${1+"$@"}; echo; }
        else
            pp_success_msg () { echo ${1+"$@":} OK; }
            pp_failure_msg () { echo ${1+"$@":} FAIL; }
            pp_warning_msg () { echo ${1+"$@":} WARNING; }
        fi

        #-- prints a status message
        pp_msg () { echo -n "$*: "; }

        #-- prints usage message
        pp_usage () {
            echo "usage: $0 {start|stop|status|restart|reload|condrestart|try-restart|force-reload}" >&2
            return 2
        }

        #-- reloads the service, if possible
        #   returns 0=success 1=failure 3=unimplemented
        pp_reload () {
            test -n "$reload_signal" || return 3 # unimplemented
            pp_msg "Reloading ${svc_name}"
            if pp_signal -${reload_signal}; then
                pp_success_msg
                return 0
            else
                pp_failure_msg "not running"
                return 1
            fi
        }

        #-- delivers signal $1 to the pidfile
        #   returns 0=success 1=failure
        pp_signal () {
            if test -r "$pidfile"; then
                read pid < $pidfile
                kill "$@" "$pid" 2>/dev/null
            else
                return 1
            fi
        }

        #-- prints information about the service status
        #   returns 0=running 1=crashed 3=stopped
        pp_status () {
            pp_msg "Checking for ${svc_name}"
            if pp_signal -0; then
                pp_success_msg "running"
                return 0
            elif test -r "$pidfile"; then
                pp_failure_msg "not running (crashed)"
                return 1
            else
                pp_failure_msg "not running"
                return 3
            fi
        }

        #-- starts the service
        #   returns 0=success 1=failure
        pp_start () {
            pp_msg "Starting ${svc_name}"
            if pp_status >/dev/null; then
                pp_warning_msg "already started"
                return 0
            elif pp_exec_cmd; then
                pp_success_msg
                return 0
            else
                pp_failure_msg "cannot start"
                return 1
            fi
        }

        #-- stops the service
        #   returns 0=success (always)
        pp_stop () {
            pp_msg "Stopping ${svc_name}"
            if pp_signal -${stop_signal}; then
                pp_success_msg
            else
                pp_success_msg "already stopped"
            fi
            rm -f "$pidfile"
            return 0
        }

        #-- stops and starts the service
        pp_restart () {
            pp_stop
            pp_start
        }

        case "$1" in
            start)          pp_start;;
            stop)           pp_stop;;
            restart)        pp_restart;;
            status)         pp_status;;
            try-restart|condrestart)    
                            if pp_status >/dev/null; then
                                    pp_restart
                            fi;;
            reload)         pp_reload;;
            force-reload)   if pp_status >/dev/null; then
                                    pp_reload
                            else
                                    pp_restart
                            fi;;
            *)              pp_usage;;
        esac

.
    chmod 755 $out
}

: NOTES <<.

 # creating a dmg file for publishing on the web
    hdiutil create -srcfolder /path/foo foo.dmg
    hdiutil internet-enable -yes /path/foo.dmg
 # Layout for packages
    <name>-<cpy>/component/<file>
    <name>-<cpt>/extras/postinstall
    <name>-<cpt>/extras/postupgrade
 # /Developer/Tools/packagemaker (man packagemaker)

    Make a bunch of packages, and then build a 'distribution'
    which is only understood by macos>10.4 

 # Message files in the resource path (-r) used are
    Welcome.{rtf,html,rtfd,txt} - limited text shown in Intro
    ReadMe.{rtf,html,rtfd,txt} - scrollable/printable, after Intro
    License.{rtf,html,rtfd,txt} - ditto, user must click 'Accept'
    background.{jpg,tif,gif,pict,eps,pdf} 620x418 background image

 # These scripts looked for in the resource path (-r)
    InstallationCheck $pkgpath $defaultloc $targetvol
	0:ok 32:warn 32+x:warn[1] 64:stop 96+x:stop[2]
    VolumeCheck $volpath
	0:ok 32:failure 32+x:failure[3]
    preflight   $pkgpath $targetloc $targetvol    [priv]
    preinstall  $pkgpath $targetloc $targetvol    [priv]
    preupgrade  $pkgpath $targetloc $targetvol    [priv]
    postinstall $pkgpath $targetloc $targetvol    [priv]
    postupgrade $pkgpath $targetloc $targetvol    [priv]
    postflight  $pkgpath $targetloc $targetvol    [priv]
	0:ok else fail (for all scripts)

    A detailed reason is deduced by finding an index x (16..31)
    in the file InstallationCheck.strings or VolumeCheck.strings.

    Scripts marked [priv] are executed with root privileges.
    None of the [priv] scripts are used by metapackages.

 # Default permissions
    Permissions of existing directories should match those
    of a clean install of the OS; typically root:admin 0775
    New directories or files should be 0775 or 0664 with the
    appropriate user:group.
    Exceptions:
	/etc	root:admin 0755
	/var    root:admin 0755

    <http://developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution4/Concepts/sd_pkg_flags.html>
    Info.plist = {
     CFBundleGetInfoString: "1.2.3, Quest Software, Inc.",
     CFBundleIdentifier: "com.quest.vintela.rc.openssh",
     CFBundleShortVersionString: "1.2.3",
     IFMajorVersion: 1,
     IFMinorVersion: 2,
     IFPkgFlagAllowBackRev: false,
     IFPkgFlagAuthorizationAction: "AdminAuthorization",
     IFPkgFlagDefaultLocation: "/",
     IFPkgFlagFollowLinks: true,
     IFPkgFlagInstallFat: false,
     IFPkgFlagInstalledSize: <integer>,	    # this is added by packagemaker
     IFPkgFlagIsRequired: false,
     IFPkgFlagOverwritePermissions: false,
     IFPkgFlagRelocatable: false,
     IFPkgFlagRestartAction: "NoRestart",
     IFPkgFlagRootVolumeOnly: false,
     IFPkgFlagUpdateInstalledLanguages: false,
     IFPkgFormatVersion= 0.10000000149011612,
     IFRequirementDicts: [ {
       Level = "requires",
       SpecArgument = "/opt/quest/lib/libvas.4.2.0.dylib",
       SpecType = "file",
       TestObject = true,
       TestOperator = "eq", } ]
    }

    Description.plist = {
     IFPkgDescriptionDescription = "this is the description text",
     IFPkgDescriptionTitle = "quest-openssh"
    }

 # Startup scripts
    'launchd' is a kind of combined inetd and rc/init.d system.
    <http://developer.apple.com/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/DesigningDaemons.html>
    Create a /Library/LaunchDaemons/$daemonname.plist file
    Examples found in /System/Library/LaunchDaemons/
    See manual page launchd.plist(5) for details:

    { Label: "com.quest.vintela.foo",                        # required
      Program: "/sbin/program",
      ProgramArguments: [ "/sbin/program", "arg1", "arg2" ], # required
      RunAtLoad: true,
      WatchPaths: [ "/etc/crontab" ],
      QueueDirectories: [ "/var/cron/tabs" ],
      inetdCompatibility: { Wait: false },                   # inetd-only 
      OnDemand: false,                                       # recommended
      SessionCreate: true,
      UserName: "nobody",
      InitGroups: true,
      Sockets: {                                             # inetd only
	Listeners: { 
	   SockServiceName: "ssh",
	   Bonjour: ["ssh", "sftp-ssh"], } },
      Disabled: false,
      StandardErrorPath: "/dev/null",
    }
.


pp_platforms="$pp_platforms macos"

pp_backend_macos_detect () {
    [ x"$1" = x"Darwin" ]
}

pp_backend_macos_init () {
    pp_macos_default_bundle_id_prefix="com.quest.rc."
    pp_macos_bundle_id=
    pp_macos_bundle_vendor=
    pp_macos_bundle_version=
    pp_macos_bundle_info_string=
}

pp_macos_plist () {
    while test $# -gt 0; do
     case "$1" in

      start-plist) cat <<-.; shift ;;
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" 
		"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
	<plist version="1.0">
.
      end-plist) echo "</plist>"; shift;;

      '(')   echo "<array>"; shift;;
      ')')   echo "</array>"; shift;;
      '{')   echo "<dict>"; shift;;
      '}')   echo "</dict>"; shift;;
      key)         shift; echo "<key>$1</key>"; shift;;
      string)      shift; 
		   echo "$1" | sed -e 's/&/&amp;/g;s/</\&lt;/g;s/>/\&gt;/g;' \
				   -e 's/^/<string>/;s/$/<\/string>/';
		   shift;;
      true)        echo "<true />"; shift;;
      false)       echo "<false />"; shift;;
      real)        shift; echo "<real>$1</real>"; shift;;
      integer)     shift; echo "<integer>$1</integer>"; shift;;
      date)        shift; echo "<date>$1</date>"; shift;; # ISO 8601 format
      data)        shift; echo "<data>$1</data>"; shift;; # base64 encoded
      *)	   pp_error "pp_macos_plist: bad argument '$1'"; shift;;
     esac
    done
}


pp_backend_macos () {
    typeset info_plist desc_plist bundle_vendor bundle_version

    bundle_vendor=${pp_macos_bundle_vendor:-"Quest Software, Inc."}

    if test -z "$pp_macos_bundle_version"; then
	bundle_version=`echo "$version.0.0.0" | sed -n -e 's/[^0-9.]//g' \
	    -e 's/^\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'`
	if test x"$bundle_version" != x"$version"; then
	    pp_warn "converted version from '$version' to '$bundle_version'"
	fi
    else
	bundle_version="$pp_macos_bundle_version"
    fi

    info_plist=$pp_wrkdir/Info.plist
    desc_plist=$pp_wrkdir/Description.plist

    #-- Create Info.plist
    pp_macos_plist \
	start-plist \{ \
	key CFBundleGetInfoString string \
	    "${pp_macos_bundle_info_string:-$version $bundle_vendor}" \
	key CFBundleIdentifier string \
	    "${pp_macos_bundle_id:-$pp_macos_default_bundle_id_prefix$name}" \
	key CFBundleShortVersionString string "$bundle_version" \
	key IFMajorVersion integer 1 \
	key IFMinorVersion integer 2 \
	key IFPkgFlagAllowBackRev false \
	key IFPkgFlagAuthorizationAction string "AdminAuthorization" \
	key IFPkgFlagDefaultLocation string "/" \
	key IFPkgFlagFollowLinks true \
	key IFPkgFlagInstallFat false \
	key IFPkgFlagIsRequired false \
	key IFPkgFlagOverwritePermissions false \
	key IFPkgFlagRelocatable false \
	key IFPkgFlagRestartAction string "NoRestart" \
	key IFPkgFlagRootVolumeOnly false \
	key IFPkgFlagUpdateInstalledLanguages false \
	key IFPkgFormatVersion real 0.10000000149011612 > $info_plist

    pp_macos_plist \
	key IFRequirementDicts \( \{ \
	    key Level string "requires" \
	    key SpecArgument string "/opt/quest/lib/libvas.4.2.0.dylib" \
	    key SpecType string "file" \
	    key TestObject true \
	    key TestOperator string "eq" \
	    \} \) >> $info_plist

    pp_macos_plist \} end-plist >> $info_plist

    #-- Create Description.plist
    pp_macos_plist \
	start-plist \{ \
	key IFPkgDescriptionDescription string "this is the description text" \
	key IFPkgDescriptionTitle string "quest-openssh" \
	\} end-plist > $desc_plist

    #-- create a package
    mkdir $pp_wrkdir/dmg $pp_wrkdir/build
    pp_verbose /Developer/Tools/packagemaker \
	-build -v \
	-p $pp_wrkdir/dmg/$name-$version.pkg \
	-f $pp_destdir -i $info_plist -d $desc_plist ||
	    pp_error "packagemaker failed"

    #-- convert the pkg file into a dmg file
    if [ -d $pp_wrkdir/dmg/$name-$version.pkg ]; then
	dmg=`pp_backend_macos_names`
	pp_verbose hdiutil create -srcfolder $pp_wrkdir/dmg $pp_wrkdir/$dmg
	pp_verbose hdiutil internet-enable -yes $pp_wrkdir/$dmg
    else
	pp_error "$pp_wrkdir/dmg/$name-$version.pkg: not created"
    fi
}

pp_backend_macos_cleanup () {
    :
}

pp_backend_macos_names () {
    echo ${name}-${version}.dmg
}

pp_backend_macos_install_script () {
    :
}

pp_backend_macos_function () {
    echo false
}

pp_backend_macos_init_svc_vars () {
    :
}

pp_backend_macos_probe () {
    typeset name vers arch
    case `sw_vers -productName` in
         "Mac OS X") name="macos";;
	 *)          name="unknown";;
    esac
    vers=`sw_vers -productVersion | sed -e 's/^\([^.]*\)\.\([^.]*\).*/\1\2/'`
    arch=`arch`
    echo "$name$vers-$arch"
}

pp_backend_macos_vas_platforms () {
    echo "OSX"    # XXX non-really sure what they do.. it should be "macos"
}

pp_platforms="$pp_platforms null"

pp_backend_null_detect () {
    ! :
}

pp_backend_null_init () {
    :
}


pp_backend_null () {
    :
}

pp_backend_null_cleanup () {
    :
}

pp_backend_null_names () {
    :
}

pp_backend_null_install_script () {
    :
}

pp_backend_null_function () {
    echo false
}

pp_backend_null_init_svc_vars () {
    :
}

pp_backend_null_probe () {
    echo unknown-unknown
}


quest_require_vas () {
    typeset v d

    if test $# -ne 1; then
        return
    fi
    set -- `echo "$1" | tr . ' '` 0 0 0

    for d
    do
        echo $d | grep '^[0-9][0-9]*$' > /dev/null ||
            pp_error "quest_require_vas: Bad version component $d"
    done

    test $# -lt 4 &&
            pp_error "quest_require_vas: missing version number"

    case "$1.$2.$3.$4" in
        *.0.0.0) v=$1;;
        *.*.0.0) v=$1.$2;;
        *.*.*.0) v=$1.$2.$3;;
        *)       v=$1.$2.$3.$4;;
    esac
        
    cat <<.
        if test -x /opt/quest/bin/vastool &&
           /opt/quest/bin/vastool -v | 
            awk 'NR == 1 {print \$4}' |
            awk -F. '{ if (\$1<$1 || \$1==$1 && ( \
                           \$2<$2 || \$2==$2 && ( \
                           \$3<$3 || \$2==$3 && ( \
                           \$4<$4 )))) exit(1); }'
        then
            exit 0
        else
            echo "Requires VAS $v or later"
            exit 1
        fi
.
}
pp_main ${1+"$@"}
