diff options
Diffstat (limited to 'scripts/pp')
-rwxr-xr-x | scripts/pp | 9115 |
1 files changed, 9115 insertions, 0 deletions
diff --git a/scripts/pp b/scripts/pp new file mode 100755 index 0000000..855acc4 --- /dev/null +++ b/scripts/pp @@ -0,0 +1,9115 @@ +#!/bin/sh +# Copyright 2023 One Identity LLC. ALL RIGHTS RESERVED +pp_revision="20230127" + # Copyright 2018 One Identity LLC. 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 One Identity LLC. 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.quest.com/topics/polypkg/> for more information + +pp_version="1.0.0.$pp_revision" +pp_copyright="Copyright 2018, One Identity LLC. 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_strip=false +pp_opt_save_unstripped=false +pp_opt_vas_platforms=false +pp_opt_wrkdir="`pwd`/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 +test -n "$PP_VERBOSE" && pp_opt_verbose=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 + if $pp_opt_debug; then + pp_debug "not removing $pp_wrkdir" + else + pp_verbose rm -rf "$pp_wrkdir" + fi + 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" "$@";; + --?*) : ;; + + -d) shift; set -- "--debug" "$@";; + -d*) a=`echo "$1" | sed -ne 's/^-.//'` + shift; set -- "--debug" "$@";; + + -i) shift; set -- "--install-script" "$@";; + -i*) a=`echo "$1" | sed -ne 's/^-.//'` + shift; set -- "--install-script" "$a" "$@";; + + -l) shift; set -- "--list" "$@";; + -l*) a=`echo "$1" | sed -ne 's/^-.//'` + shift; set -- "--list" "$@";; + + -p) shift; set -- "--platform" "$@";; + -p*) a=`echo "$1" | sed -ne 's/^-.//'` + shift; set -- "--platform" "$a" "$@";; + + -v) shift; set -- "--verbose" "$@";; + -v*) a=`echo "$1" | sed -ne 's/^-.//'` + shift; set -- "--verbose" "$@";; + + -\?) shift; set -- "--help" "$@";; + -\?*) a=`echo "$1" | sed -ne 's/^-.//'` + shift; set -- "--help" "$@";; + 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;; + --strip) pp_opt_strip=true; shift;; + --save-unstripped) pp_opt_save_unstripped=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 + --strip -- strip debug symbols from binaries before + packaging (modifies files in destdir) + --save-unstripped -- save unstripped binaries to + \$name-\$version-unstripped.tar.gz + --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 + + if test x"$pp_opt_strip" = x"true"; then + pp_strip_binaries + fi + + # 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 -r $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 () { + # If PP_DEV_PATH is set, then jump to that script. + # (Useful when working on polypkg source that isn't installed) + if test -n "$PP_DEV_PATH" -a x"$PP_DEV_PATH" != x"$0"; then + pp_warn "switching from $0 to $PP_DEV_PATH ..." + exec "$PP_DEV_PATH" "$@" || exit 1 + fi + + pp_set_expand_converter_or_reexec "$@" + pp_parseopts "$@" + + 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 "$@" + exit 1 +} + +pp_die_if_errors () { + $pp_errors && pp_die "$@" +} + +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_unique () { + typeset result element + result= + for element + do + pp_add_to_list result $element + done + echo $result +} + +pp_mode_strip_altaccess () { + case "$1" in + ??????????[+.]) + echo `echo "$1" | cut -b -10`;; + *) + echo "$1";; + esac +} + +pp_mode_from_ls () { + typeset umode gmode omode smode + + set -- `pp_mode_strip_altaccess "$1"` + + 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 deps allfuncs + allfuncs= + while test $# -gt 0; do + pp_add_to_list allfuncs "$1" + deps=`pp_backend_function "$1:depends"` + shift + set -- `pp_unique "$@" $deps` + done + + for func in $allfuncs + do + pp_debug "generating function code for '$1'" + echo "" + echo "$func () {" + case "$func" in + pp_mkgroup|pp_mkuser|pp_havelib) echo <<.;; + if test \$# -lt 1; then + echo "$func: not enough arguments" >&2 + return 1 + fi +. + esac + pp_backend_function "$func" || cat <<. + echo "$func: not implemented" >&2 + return 1 +. + 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_copy_unstripped () { + typeset filedir realdir + filedir="`dirname ${1#$pp_destdir}`" + realdir="$pp_wrkdir/unstripped/$filedir" + + mkdir -p "$realdir" + # Can't use hardlinks because `strip` modifies the original file in-place + cp "$1" "$realdir" +} + +pp_package_stripped_binaries () { + (cd "$pp_wrkdir/unstripped" && tar -c .) \ + | gzip > "$name-dbg-$version.tar.gz" + rm -rf "$pp_wrkdir/unstripped" +} + +pp_strip_binaries () { + if test x"$pp_opt_save_unstripped" = x"true"; then + rm -rf "$pp_wrkdir/unstripped" + mkdir "$pp_wrkdir/unstripped" + fi + + for f in `find "$pp_destdir" -type f`; do + if file "$f" | awk '{print $2}' | grep ^ELF >/dev/null 2>&1; then + if test x"$pp_opt_save_unstripped" = x"true"; then + if file "$f" | LC_MESSAGES=C grep 'not stripped' >/dev/null 2>&1; then + pp_debug "Saving unstripped binary $f" + pp_copy_unstripped "$f" + else + pp_debug "$f is already stripped; not saving a copy" + fi + fi + pp_debug "Stripping unnecessary symbols from $f" + strip "$f" + fi + done + + if test x"$pp_opt_save_unstripped" = x"true"; then + pp_package_stripped_binaries + fi +} + +pp_if_true=0 +pp_if_false=0 + +pp_frontend_init () { + name= + version= + build_number= + summary="no summary" + description="No description" + copyright="Copyright 2018 One Identity LLC. 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 || pp_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 || pp_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 "$@" + 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;; + %pre|%post|%preun|%postup|%preup|%postun|%files|%depend|%check|%conflict) + 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 + ;; + %pre.*|%preun.*|%post.*|%postup.*|%preup.*|%postun.*|%depend.*|%check.*|%conflict.*|%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|%pre.*|%preun.*|%post.*|%postup.*|%preup.*|%postun.*|%check.*|%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 + ;; + %depend.*) + pp_debug "Adding explicit dependency $@ to $cpt" + echo "$@" >> $pp_wrkdir/%depend.$cpt + ;; + %conflict.*) + pp_debug "Adding explicit conflict $@ to $cpt" + echo "$@" >> $pp_wrkdir/%conflict.$cpt + ;; + 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 bash ksh ksh93; 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" "$@" + 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/%pre.* \ + $pp_wrkdir/%preun.* \ + $pp_wrkdir/%postup.* \ + $pp_wrkdir/%postun.* \ + $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" "$@" +} + +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 + optional=no # Whether installing this service is optional + 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 _target _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= + _target= + _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}";; + 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 + if test -f $pp_wrkdir/ign.awk; then + # Remove ignored files + mv $pp_wrkdir/duplicate.files $pp_wrkdir/duplicate.files.ign + sed -e 's/^/_ _ _ _ _ /' < $pp_wrkdir/duplicate.files.ign | + awk -f $pp_wrkdir/ign.awk | + sed -e 's/^_ _ _ _ _ //' > $pp_wrkdir/duplicate.files + fi + 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"'" && $5 !~ /i/ { next }' + done < $pp_wrkdir/ign.files > $pp_wrkdir/ign.awk + echo '{ print }' >> $pp_wrkdir/ign.awk + + $pp_opt_debug && cat $pp_wrkdir/ign.awk + + for f in $pp_wrkdir/%files.*; do + mv $f $f.ign + awk -f $pp_wrkdir/ign.awk < $f.ign > $f || pp_error "awk" + 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 \"\$@\"; }" +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_aix_start_services_after_install=false + pp_aix_init_services_after_install=true + + pp_aix_sudo=sudo # AIX package tools must run as root + + case "$pp_aix_os" in + *) pp_readlink_fn=pp_ls_readlink;; # XXX + esac + + pp_aix_abis_seen= +} + +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 | sed 's/[-+]/./' | tr -c -d '[0-9].\012' | awk -F"." '{ printf "%d.%d.%d.%.4s\n", $1, $2, $3, $4 }' | sed 's/[.]*$//g'` + 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";; + *.*.*.*.*) + # 5 components are only valid for fileset updates, not base + # filesets (full packages). We trim 5+ components down to 4. + pp_warn "version '$1' has too many dots for AIX, truncating" + echo "$v" | cut -d. -f1-4;; + *.*.*.*) 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 + awk $op'($6 ~ /^\/(dev|etc|sbin|var)\//) { 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" + 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 + + #-- Record ABI types seen + case "$t" in + f) if test -r "$pp_destdir$p"; then + case "`file "$pp_destdir$p"`" in + *"executable (RISC System/6000)"*) abi=ppc;; + *"64-bit XCOFF executable"*) abi=ppc64;; + *) abi=;; + esac + if test -n "$abi"; then + pp_add_to_list pp_aix_abis_seen $abi + fi + fi;; + 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="${pp_aix_mkssys_cmd_args:-$*}"; + + 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.$svc +svc=$svc +uid=0 +cmd_cmd="$cmd_cmd" +cmd_arg="$cmd_arg" +stop_signal=$stop_signal +force_signal=9 +srcgroup="$pp_aix_mkssys_group" +instances_allowed=${pp_aix_mkssys_instances_allowed:--Q} + +lssrc -s \$svc > /dev/null 2>&1 +if [ \$? -eq 0 ]; then + lssrc -s \$svc | grep "active" > /dev/null 2>&1 + if [ \$? -eq 0 ]; then + stopsrc -s \$svc > /dev/null 2>&1 + fi + rmsys -s \$svc > /dev/null 2>&1 +fi + +mkssys -s \$svc -u \$uid -p "\$cmd_cmd" \${cmd_arg:+-a "\$cmd_arg"} -S -n \$stop_signal -f 9 ${pp_aix_mkssys_args} \${srcgroup:+-G \$srcgroup} \$instances_allowed +. + + #-- add code to start the service on reboot + ${pp_aix_init_services_after_install} && + cat <<-. >> $pp_wrkdir/%post.$svc +id=\`echo "\$svc" | cut -c1-14\` +mkitab "\$id:2:once:/usr/bin/startsrc -s \$svc" > /dev/null 2>&1 +. + + ${pp_aix_start_services_after_install} && + cat <<-. >> $pp_wrkdir/%post.$svc +startsrc -s \$svc +. + +if [ -f "$pp_wrkdir/%post.run" ];then + cat $pp_wrkdir/%post.run >> $pp_wrkdir/%post.$svc +fi +mv $pp_wrkdir/%post.$svc $pp_wrkdir/%post.run + + + ${pp_aix_init_services_after_install} && + pp_prepend $pp_wrkdir/%preun.$svc <<-. +rmitab `echo "$svc" | cut -c1-14` > /dev/null 2>&1 +. + pp_prepend $pp_wrkdir/%preun.$svc <<-. +stopsrc -s $svc >/dev/null 2>&1 +rmssys -s $svc +. + +if [ -f "$pp_wrkdir/%preun.run" ];then + cat $pp_wrkdir/%preun.run >> $pp_wrkdir/%preun.$svc +fi +mv $pp_wrkdir/%preun.$svc $pp_wrkdir/%preun.run +} + +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" + pp_aix_bff_name=${pp_aix_bff_name:-$name} + + # Here is the component mapping: + # run -> $pp_aix_bff_name.rte ('Run time environment') + # doc -> $pp_aix_bff_name.doc (non-standard) + # dev -> $pp_aix_bff_name.adt ('Application developer toolkit') + # dbg -> $pp_aix_bff_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/%pre.$cmp \ + -o -s $pp_wrkdir/%post.$cmp \ + -o -s $pp_wrkdir/%preun.$cmp \ + -o -s $pp_wrkdir/%postun.$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 $pp_aix_bff_name.$ex \ + `[ $pp_aix_version ] && pp_aix_version_fix $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/$pp_aix_bff_name.$ex.al + pp_aix_list $instroot < $root_files >> $user_wrkdir/$pp_aix_bff_name.$ex.al + pp_aix_list < $root_files > $root_wrkdir/$pp_aix_bff_name.$ex.al + + if $pp_opt_debug; then + echo "$cmp USER $pp_aix_bff_name.$ex.al:" + cat $user_wrkdir/$pp_aix_bff_name.$ex.al + echo "$cmp ROOT $pp_aix_bff_name.$ex.al:" + cat $root_wrkdir/$pp_aix_bff_name.$ex.al + fi >&2 + + pp_aix_inventory $pp_aix_bff_name.$ex < $user_files \ + > $user_wrkdir/$pp_aix_bff_name.$ex.inventory + pp_aix_inventory $pp_aix_bff_name.$ex < $root_files \ + > $root_wrkdir/$pp_aix_bff_name.$ex.inventory + + if $pp_opt_debug; then + pp_debug "$cmp USER $pp_aix_bff_name.$ex.inventory:" + cat $user_wrkdir/$pp_aix_bff_name.$ex.inventory + pp_debug "$cmp ROOT $pp_aix_bff_name.$ex.inventory:" + cat $root_wrkdir/$pp_aix_bff_name.$ex.inventory + fi >&2 + + if test x"" != x"${pp_aix_copyright:-$copyright}"; then + echo "${pp_aix_copyright:-$copyright}" > $user_wrkdir/$pp_aix_bff_name.$ex.copyright + echo "${pp_aix_copyright:-$copyright}" > $root_wrkdir/$pp_aix_bff_name.$ex.copyright + fi + + #-- assume that post/pre uninstall scripts only make + # sense when installed in a root context + + if test -r $pp_wrkdir/%pre.$cmp; then + pp_aix_make_script $user_wrkdir/$pp_aix_bff_name.$ex.pre_i \ + < $pp_wrkdir/%pre.$cmp + fi + + if test -r $pp_wrkdir/%post.$cmp; then + pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.post_i \ + < $pp_wrkdir/%post.$cmp + fi + + if test -r $pp_wrkdir/%preun.$cmp; then + pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpost_i \ + < $pp_wrkdir/%preun.$cmp + fi + + if test -r $pp_wrkdir/%postun.$cmp; then + pp_aix_make_script $root_wrkdir/$pp_aix_bff_name.$ex.unpre_i \ + < $pp_wrkdir/%postun.$cmp + fi + + # remove empty files + for f in $user_wrkdir/$pp_aix_bff_name.$ex.* $root_wrkdir/$pp_aix_bff_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 + + if test -n "$pp_aix_abis_seen" -a x"$pp_aix_arch_std" = x"auto"; then + case "$pp_aix_abis_seen" in + "ppc ppc64"|"ppc64 ppc") + pp_aix_arch_std=ppc64 + ;; + ppc|ppc64) + pp_aix_arch_std=$pp_aix_abis_seen + ;; + *" "*) + pp_warn "multiple architectures detected: $pp_aix_abis_seen" + pp_aix_arch_std=unknown + ;; + "") + pp_warn "no binary executables detected; using noarch" + pp_aix_arch_std=noarch + ;; + *) + pp_warn "unknown architecture detected $pp_aix_abis_seen" + pp_aix_arch_std=$pp_aix_abis_seen + ;; + esac + fi + + . $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" + if test -n "$pp_aix_sudo" -o -x /usr/sbin/installp; then + $pp_aix_sudo /usr/sbin/installp -l -d $pp_wrkdir/$outbff + fi +} + +pp_backend_aix_cleanup () { + : +} + +pp_backend_aix_names () { + echo "$name.`[ $pp_aix_version ] && pp_aix_version_fix $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_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";; + aix61) echo "aix-53 aix-51 aix-43";; + *) pp_die "unknown system ${pp_aix_os}";; + esac +} +pp_backend_aix_function () { + case "$1" in + pp_mkgroup) cat <<'.';; + /usr/sbin/lsgroup "$1" >/dev/null && + return 0 + echo "Creating group $1" + /usr/bin/mkgroup -A "$1" +. + pp_mkuser:depends) echo pp_mkgroup;; + pp_mkuser) cat <<'.';; + /usr/sbin/lsuser "$1" >/dev/null && + return 0 + pp_mkgroup "${2:-$1}" || return 1 + echo "Creating user $1" + /usr/bin/mkuser \ + login=false \ + rlogin=false \ + account_locked=true \ + home="${3:-/nohome.$1}" \ + pgrp="${2:-$1}" \ + "$1" +. + pp_havelib) cat <<'.';; + case "$2" in + "") pp_tmp_name="lib$1.so";; + *.*.*) pp_tmp_name="lib$1.so.$2";; + *.*) pp_tmp_name="lib$1.so.$2.0";; + *) pp_tmp_name="lib$1.so.$2";; + esac + for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do + test -r "$pp_tmp_dir/$pp_tmp_name" -a \ + -r "$pp_tmp_dir/lib$1.so" && return 0 + done + return 1 +. + *) false;; + esac +} + +pp_platforms="$pp_platforms sd" + +pp_backend_sd_detect () { + test x"$1" = x"HP-UX" +} + +pp_backend_sd_init () { + pp_sd_sudo=sudo + pp_sd_startlevels=2 + pp_sd_stoplevels=auto + pp_sd_config_file= + pp_sd_vendor= + pp_sd_vendor_tag=OneIdentity + pp_sd_default_start=1 # config_file default start value + + pp_readlink_fn=pp_ls_readlink # HPUX has no readlink + pp_shlib_suffix='.sl' # .so on most other platforms + + 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 ${pp_sd_os} in + 10.*) + case $t in + f) dm=644;; + d) p=${p%/}; dm=755;; + esac + ;; + *) + case $t in + f) dm=644;; + d) line="$line -t d"; p=${p%/}; dm=755;; + s) line="$line -t s";; + esac + ;; + esac + + test x"$o" = x"-" && o=root + test x"$g" = x"-" && g=sys + test x"$m" = x"-" && m=$dm + + case $t in + s) + # swpackage will make unqualified links relative to the + # current working (source) directory, not the destination; + # we need to qualify them to prevent this. + case "$st" in + [!/]*) st="`dirname \"$p\"`/$st";; + esac + echo "$line -o $o -g $g -m $m $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/$svc} + sd_config_var=`echo run-$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 +. + + if test ! -f $pp_destdir$scriptpath; then + cat <<-. > $pp_destdir$scriptpath + #!/sbin/sh + # generated by pp $pp_version + + svc="$svc" + pidfile="$pidfile" + config_file="$config_file" + + pp_start () { + $cmd + } + + pp_disabled () { + test \${$sd_config_var:-0} -eq 0 + } + + 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 + read pid < "\$pidfile" 2>/dev/null + if test \${pid:-0} -gt 1 && kill -0 "\$pid" 2>/dev/null; then + # make sure command name matches + c="\`echo $cmd | sed -e 's: .*::' -e 's:^.*/::'\`" + pid="\`ps -p \$pid 2>/dev/null | sed -n \"s/^ *\(\$pid\) .*\$c *\$/\1/p\"\`" + if test -n "\$pid"; then + return 0 + fi + fi + fi + return 1 + } + + 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 +. + fi +} + +pp_sd_make_service () { + typeset level startpriority stoppriority startlevels stoplevels + typeset svc svcvar symtype + + svc="$1" + svcvar=`pp_makevar $svc` + + case ${pp_sd_os} in + 10.*) symtype="file";; + *) symtype="file -t s";; + esac + + # TODO: Figure out why this check is here + #-- 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 " ${symtype}" \ + "/sbin/init.d/$svc" \ + "/sbin/rc$level.d/S$startpriority$svc" + done + test -z "$stoplevels" || for level in $stoplevels; do + echo " ${symtype}" \ + "/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_sd_depend () { + typeset _name _vers + while read _name _vers; do + case "$_name" in ""| "#"*) continue ;; esac + echo " prerequisites $_name ${_vers:+r>= $_vers}" + done +} + +pp_sd_conflict () { + typeset _name _vers + while read _name _vers; do + case "$_name" in ""| "#"*) continue ;; esac + echo " exrequisites $_name ${_vers:+r>= $_vers}" + done +} + +pp_backend_sd () { + typeset psf cpt svc outfile release swp_flags + + psf=$pp_wrkdir/psf + release="?.${pp_sd_os%.[0-9][0-9]}.*" + + echo "depot" > $psf + echo "layout_version 1.0" >>$psf + + #-- vendor + cat <<. >>$psf + vendor + tag $pp_sd_vendor_tag + title "${pp_sd_vendor:-$vendor}" + end + + product + tag $name + revision $version + vendor_tag $pp_sd_vendor_tag + is_patch false + title "$summary" + copyright "$copyright" + machine_type * + os_name HP-UX + os_release $release + os_version ? + directory / + is_locatable false +. + test -n "$description" \ + && echo $description > $pp_wrkdir/description \ + && cat <<. >> $psf + description < $pp_wrkdir/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 ${pp_sd_fileset_tag:-$cpt} + title "${summary:-cpt}" + revision $version +. + test -s $pp_wrkdir/%depend.$cpt && + pp_sd_depend < $pp_wrkdir/%depend.$cpt >> $psf + test -s $pp_wrkdir/%conflict.$cpt && + pp_sd_conflict < $pp_wrkdir/%conflict.$cpt >> $psf + + #-- 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/%pre.$cpt && + pp_sd_control checkinstall $cpt $pp_wrkdir/%pre.$cpt >> $psf + 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/%postun.$cpt && + pp_sd_control postremove $cpt $pp_wrkdir/%postun.$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` + case ${pp_sd_os} in + 10.*) + swp_flags="-x target_type=tape" + ;; + *) + swp_flags="-x media_type=tape" + ;; + esac + if pp_verbose ${pp_sd_sudo} /usr/sbin/swpackage -s $psf $swp_flags \ + @ $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.$pp_sd_arch_std.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_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 hpux-pa;; + *) pp_die "unknown system `pp_backend_sd_probe`";; + esac +} + +pp_backend_sd_init_svc_vars () { + : +} +pp_backend_sd_function () { + case "$1" in + pp_mkgroup) cat <<'.';; + /usr/sbin/groupmod "$1" 2>/dev/null || + /usr/sbin/groupadd "$1" +. + pp_mkuser:depends) echo pp_mkgroup;; + pp_mkuser) cat <<'.';; + pp_mkgroup "${2:-$1}" || return 1 + /usr/sbin/useradd \ + -g "${2:-$1}" \ + -d "${3:-/nonexistent}" \ + -s "${4:-/bin/false}" \ + "$1" +. + pp_havelib) cat <<'.';; + for pp_tmp_dir in `echo /usr/lib${3:+:$3} | tr : ' '`; do + test -r "$pp_tmp_dir/lib$1${2:+.$2}.sl" && return 0 + done + return 1 +. + *) false;; + esac +} + +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_maxinst= + pp_solaris_vendor= + pp_solaris_pstamp= + 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 () { + if [ -x /usr/bin/isainfo ]; then + pp_solaris_arch=`/usr/bin/isainfo -n` + else + pp_solaris_arch=`/usr/bin/optisa amd64 sparcv9 i386 sparc` + fi + [ -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_is_request_script_necessary () { + typeset has_optional_services + + has_optional_services=no + for _svc in $pp_services; do + pp_load_service_vars $_svc + if test "$optional" = "yes"; then + has_optional_services=yes + fi + done + + # If the package has no optional services and only one component, don't + # create a request script at all. + if test "$has_optional_services" = "no" && + test `echo $pp_components | wc -w` -eq 1; then + return 1 # no + fi + + return 0 # yes +} + +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 + pp_load_service_vars $_svc + if test "$enable" = "yes"; then + _default_prompt=y + else + _default_prompt=n + fi + if test "$optional" = "yes"; then + echo 'ask '$_default_prompt' "install '$_svc' service" &&' + fi + 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_conflict () { + typeset _name _vers + while read _name _vers; do + if test -n "$_name"; then + echo "I $_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 + # Use Solaris default mode, owner and group if all unspecified + if test x"$m$o$g" = x"---"; then + m="?"; o="?"; g="?" + fi + test x"$o" = x"-" && o="root" + case "$t" in + f) test x"$g" = x"-" && g="bin" + 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"$g" = x"-" && g="sys" + test x"$m" = x"-" && m=555 + echo "d $1 $p $m $o $g" + ;; + s) test x"$g" = x"-" && g="bin" + test x"$m" = x"-" && m=777 + if test x"$m" != x"777" -a x"$m" != x"?"; then + pp_warn "$p: invalid mode $m for symlink, should be 777 or -" + fi + 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_maxinst" && + echo "MAXINST=$pp_solaris_maxinst" >> $pkginfo + test -n "${pp_solaris_vendor:-$vendor}" && + echo "VENDOR=${pp_solaris_vendor:-$vendor}" >> $pkginfo + test -n "$pp_solaris_pstamp" && + echo "PSTAMP=$pp_solaris_pstamp" >> $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 + : > $pp_wrkdir/postremove + for _cmp in $pp_components; do + #-- add the preinstall scripts in definition order + if test -s $pp_wrkdir/%pre.$_cmp; then + pp_solaris_procedure $_cmp preinst < $pp_wrkdir/%pre.$_cmp \ + >> $pp_wrkdir/preinstall + fi + #-- 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 postremove scripts in definition order + if test -s $pp_wrkdir/%postun.$_cmp; then + pp_solaris_procedure $_cmp postremove < $pp_wrkdir/%postun.$_cmp \ + >> $pp_wrkdir/postremove + 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 and conflicts are merged together for Solaris pkgs + test -s $pp_wrkdir/%depend.$_cmp && + pp_solaris_depend < $pp_wrkdir/%depend.$_cmp >> $pp_wrkdir/depend + test -s $pp_wrkdir/%conflict.$_cmp && + pp_solaris_conflict < $pp_wrkdir/%conflict.$_cmp >> $pp_wrkdir/depend + done + + + if pp_solaris_is_request_script_necessary; then + pp_solaris_request > $pp_wrkdir/request + fi + + test -n "$pp_services" && + for _svc in $pp_services; do + pp_load_service_vars $_svc + pp_solaris_smf $_svc + pp_solaris_make_service $_svc + pp_solaris_install_service $_svc | pp_prepend $pp_wrkdir/postinstall + pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/preremove + pp_solaris_remove_service $_svc | pp_prepend $pp_wrkdir/postremove + unset pp_svc_xml_file + 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 \ + preinstall request 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 -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_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_function() { + case "$1" in + pp_mkgroup) cat<<'.';; + /usr/sbin/groupmod "$1" 2>/dev/null && return 0 + /usr/sbin/groupadd "$1" +. + pp_mkuser:depends) echo pp_mkgroup;; + pp_mkuser) cat<<'.';; + id "$1" >/dev/null 2>/dev/null && return 0 + pp_mkgroup "${2:-$1}" || return 1 + /usr/sbin/useradd \ + -g "${2:-$1}" \ + -d "${3:-/nonexistent}" \ + -s "${4:-/bin/false}" \ + "$1" +. + *) false;; + esac +} + +pp_backend_solaris_init_svc_vars () { + _smf_category=${pp_solaris_smf_category:-application} + _smf_method_envvar_name=${smf_method_envvar_name:-"PP_SMF_SERVICE"} + pp_solaris_service_shell=/sbin/sh +} + +pp_solaris_init_svc () { + smf_version=1 + smf_type=service + solaris_user= + solaris_stop_signal= + solaris_sysv_init_start=S70 # 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 _pp_solaris_service_script svc _pp_solaris_manpage + + pp_solaris_name=${pp_solaris_name:-$name} + pp_solaris_manpath=${pp_solaris_manpath:-"/usr/share/man"} + pp_solaris_mansect=${pp_solaris_mansect:-1} + smf_start_timeout=${smf_start_timeout:-60} + smf_stop_timeout=${smf_stop_timeout:-60} + smf_restart_timeout=${smf_restart_timeout:-60} + + svc=${pp_solaris_smf_service_name:-$1} + _pp_solaris_service_script=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"} + _pp_solaris_manpage=${pp_solaris_manpage:-$svc} + + if [ -z $pp_svc_xml_file ]; then + pp_svc_xml_file="/var/svc/manifest/$_smf_category/$svc.xml" + echo "## Generating the smf service manifest file for $pp_svc_xml_file" + else + echo "## SMF service manifest file already defined at $pp_svc_xml_file" + if [ -z $pp_solaris_smf_service_name ] || [ -z $pp_solaris_smf_category ] || [ -z $pp_solaris_service_script ] || [ -z $smf_method_envvar_name ]; then + pp_error "All required variables are not set.\n"\ + "When using a custom manifest file all of the following variables must be set:\n"\ + "pp_solaris_smf_service_name, pp_solaris_smf_category, pp_solaris_service_script and smf_method_envvar_name.\n\n"\ + "Example:\n"\ + " \$pp_solaris_smf_category=application\n"\ + " \$pp_solaris_smf_service_name=pp\n\n"\ + " <service name='application/pp' type='service' version='1'>\n\n"\ + "Example:\n"\ + " \$pp_solaris_service_script=/etc/init.d/pp\n\n"\ + " <exec_method type='method' name='start' exec='/etc/init.d/pp' />\n\n"\ + "Example:\n"\ + " \$smf_method_envvar_name=PP_SMF_SERVICE\n\n"\ + " <method_environment>\n"\ + " <envvar name='PP_SMF_SERVICE' value='1'/>\n"\ + " </method_environment>\n" + + return 1 + fi + return 0 + fi + + f=$pp_svc_xml_file + pp_add_file_if_missing $f || + return 0 + pp_solaris_add_parent_dirs "$f" + + _pp_solaris_smf_dependencies=" + <dependency name='pp_local_filesystems' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/system/filesystem/local'/> + </dependency> + + <dependency name='pp_single-user' + grouping='require_all' + restart_on='none' + type='service'> + <service_fmri value='svc:/milestone/single-user' /> + </dependency> +" + _pp_solaris_smf_dependencies=${pp_solaris_smf_dependencies:-$_pp_solaris_smf_dependencies} + + cat <<-. >$pp_destdir$f +<?xml version="1.0"?> +<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'> +<!-- + $copyright + Generated by PolyPackage $pp_version +--> + + <service_bundle type='manifest' name='${pp_solaris_name}:${svc}' > + <service name='$_smf_category/$svc' + type='$smf_type' + version='$smf_version'> + + <create_default_instance enabled='false'/> + + <single_instance /> + + $_pp_solaris_smf_dependencies + + $pp_solaris_smf_additional_dependencies + + <method_context> + <method_credential user='${solaris_user:-$user}' /> + <method_environment> + <envvar name='$_smf_method_envvar_name' value='1'/> + </method_environment> + </method_context> + + <exec_method type='method' name='start' + exec='$_pp_solaris_service_script start' + timeout_seconds='$smf_start_timeout' /> + + <exec_method type='method' name='stop' + exec='$_pp_solaris_service_script stop' + timeout_seconds='$smf_stop_timeout' /> + + <exec_method type='method' name='restart' + exec='$_pp_solaris_service_script restart' + timeout_seconds='$smf_restart_timeout' /> + + $pp_solaris_smf_property_groups + + <template> + <common_name> + <loctext xml:lang='C'>$description</loctext> + </common_name> + <documentation> + <manpage title='$pp_solaris_manpage' section='$pp_solaris_mansect' manpath='$pp_solaris_manpath'/> + </documentation> + </template> + </service> + </service_bundle> +. +} + +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 supplied already + pp_add_file_if_missing "$file" run 755 || return 0 + pp_solaris_add_parent_dirs "$file" + + 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 $svcs; 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 svc + + svc="${pp_solaris_smf_service_name:-$1}" + file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$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 + pp_solaris_add_parent_dirs "$file" + + echo "#! /sbin/sh" >$out + echo "#-- This service init file generated by polypkg" >>$out + + #-- Start SMF integration. + if [ -n "$pp_svc_xml_file" ] ; then + cat <<_EOF >>$out +if [ -x /usr/sbin/svcadm ] && [ "x\$1" != "xstatus" ] && [ "t\$$_smf_method_envvar_name" = "t" ] ; then + case "\$1" in + start) + echo "starting $svc" + /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1 + /usr/sbin/svcadm enable -s $_smf_category/$svc + RESULT=\$? + if [ "\$RESULT" -ne 0 ] ; then + echo "Error \$RESULT starting $svc" >&2 + fi + ;; + stop) + echo "stopping $svc" + /usr/sbin/svcadm disable -ts $_smf_category/$svc + RESULT=0 + ;; + restart) + echo "restarting $svc" + /usr/sbin/svcadm disable -ts $_smf_category/$svc + /usr/sbin/svcadm clear svc:/$_smf_category/$svc:default >/dev/null 2>&1 + /usr/sbin/svcadm enable -s $_smf_category/$svc + RESULT=\$? + if [ "\$RESULT" -ne 0 ] ; then + echo "Error \$RESULT starting $svc" >&2 + fi + ;; + *) + echo "Usage: $file {start|stop|restart|status}" >&2 + RESULT=1 + esac + exit $RESULT +fi +_EOF + fi + + #-- Construct a start command that builds a pid file as needed + # and forks the daemon. Services started by smf may not fork. + if test -z "$pidfile"; then + # The service does not define a pidfile, so we have to make + # our own up. On Solaris systems where there is no /var/run + # we must use /tmp to guarantee the pid files are removed after + # a system crash. + if test -z "$pp_piddir"; then + pp_piddir="/var/run" + fi + cat <<. >>$out + pp_isdaemon=0 + pp_piddirs="${pp_piddir}${pp_piddir+ }/var/run /tmp" + for pp_piddir in \$pp_piddirs; do + test -d "\$pp_piddir/." && break + done + pidfile="\$pp_piddir/$svc.pid" +. + else + # The service is able to write its own PID file + cat <<. >>$out + pp_isdaemon=1 + pidfile="$pidfile" +. + fi + + pp_su= + if test "${user:-root}" != "root"; then + pp_su="su $user -c exec " + fi + + cat <<. >>$out + stop_signal="${stop_signal:-TERM}" + svc="${svc}" + + # generated command to run $svc as a service + pp_exec () { + if [ \$pp_isdaemon -ne 1 ]; then + if [ "t\$PP_SMF_SERVICE" = "t" ]; then + ${pp_su}$cmd & + echo \$! > \$pidfile + else + echo "via exec." + echo \$$ > \$pidfile + exec ${pp_su}$cmd + return 1 + fi + else + ${pp_su}$cmd + fi + } +. + + #-- write the invariant section of the init script + cat <<'.' >>$out + + # returns true if $svc is running + pp_running () { + if test -s "$pidfile"; then + read pid < "$pidfile" 2>/dev/null + if test ${pid:-0} -gt 1 && kill -0 "$pid" 2>/dev/null; then + # make sure command name matches up to the first 8 chars + c="`echo $cmd | sed -e 's: .*::' -e 's:^.*/::' -e 's/^\(........\).*$/\1/'`" + pid="`ps -p $pid 2>/dev/null | sed -n \"s/^ *\($pid\) .*$c *$/\1/p\"`" + if test -n "$pid"; then + return 0 + fi + fi + fi + return 1 + } + + # 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_remove_service () { + typeset file svc + + svc="${pp_solaris_smf_service_name:-$1}" + file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"} + + echo ' +if [ "x${PKG_INSTALL_ROOT}" = 'x' ]; then + if [ -x /usr/sbin/svcadm ] ; then + /usr/sbin/svcadm disable -s '$svc' 2>/dev/null + if [ `uname -r` = 5.10 ] || [ "'${pp_svc_xml_file%/*/*}'" != "/var/svc/manifest" ]; then + /usr/sbin/svccfg delete '$svc' 2>/dev/null + else + /usr/sbin/svcadm restart manifest-import 2>/dev/null + fi + else + '$file' stop >/dev/null 2>/dev/null + fi +fi + ' +} + +pp_solaris_install_service () { + typeset s k l file svc + + svc="${pp_solaris_smf_service_name:-$1}" + file=${pp_solaris_service_script:-"/etc/init.d/${pp_solaris_service_script_name:-$svc}"} + + s="${solaris_sysv_init_start}$svc" + k="${solaris_sysv_init_kill}$svc" + + echo ' +if [ "x${PKG_INSTALL_ROOT}" != "x" ]; then + if [ -x ${PKG_INSTALL_ROOT}/usr/sbin/svcadm ]; then + if [ `uname -r` = 5.10 ] || [ "'${pp_svc_xml_file%/*/*}'" != "/var/svc/manifest" ]; then + echo "/usr/sbin/svccfg import '$pp_svc_xml_file' 2>/dev/null" >> ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade + else + echo "/usr/sbin/svcadm restart manifest-import 2>/dev/null" >> ${PKG_INSTALL_ROOT}/var/svc/profile/upgrade + fi + else' + 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=$file 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=$file s" + pp_solaris_space /etc/rc$state.d 0 1 + done + echo ' + fi +else + if [ -x /usr/sbin/svcadm ]; then + echo "Registering '$svc' with SMF" + /usr/sbin/svcadm disable -s '$svc' 2>/dev/null + if [ `uname -r` = 5.10 ] || [ "'${pp_svc_xml_file%/*/*}'" != "/var/svc/manifest" ]; then + /usr/sbin/svccfg delete '$svc' 2>/dev/null + /usr/sbin/svccfg import '$pp_svc_xml_file' + else + /usr/sbin/svcadm restart manifest-import + # Wait for import to complete, otherwise it will not know + # about our service until after we try to start it + echo Waiting for manifest-import... + typeset waited + waited=0 + while [ $waited -lt 15 ] && ! /usr/bin/svcs -l '$svc' >/dev/null 2>&1; do + sleep 1 + waited=`expr $waited + 1` + done + if /usr/bin/svcs -l '$svc' >/dev/null 2>&1; then + echo OK + else + echo manifest-import took to long, you might have to control '$svc' manually. + fi + fi + else' + 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=$file 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=$file s" + pp_solaris_space /etc/rc$state.d 0 1 + done + echo ' + fi +fi' +} + +pp_solaris_add_parent_dirs () { + typeset dir + + dir=${1%/*} + while test -n "$dir"; do + if awk "\$6 == \"$dir/\" {exit 1}" < $pp_wrkdir/%files.run; then + echo "d - - - - $dir/" >> $pp_wrkdir/%files.run + fi + dir=${dir%/*} + done +} + +pp_platforms="$pp_platforms deb" + +pp_backend_deb_detect () { + test -f /etc/debian_version +} + +pp_deb_cmp_full_name () { + local 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="One Identity LLC <support@oneidentity.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 +} + +pp_deb_check_required_programs () { + local p needed notfound ok + needed= notfound= + for prog in dpkg dpkg-deb install md5sum fakeroot + do + if command -v $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' | fmt -w 80`" +} + +pp_deb_detect_arch () { + pp_deb_arch=`dpkg-architecture -qDEB_HOST_ARCH` + pp_deb_arch_std=`uname -m` +} + +pp_deb_sanitize_version() { + echo "$@" | tr -d -c '[:alnum:].+-:~' +} + +pp_deb_version_final() { + if test -n "$pp_deb_version"; then + # Don't sanitize; assume the user is sane (hah!) + echo "$pp_deb_version" + else + pp_deb_sanitize_version "$version" + fi +} + +pp_deb_conflict () { + local _name _vers _conflicts + + _conflicts="Conflicts:" + while read _name _vers; do + case "$_name" in ""| "#"*) continue ;; esac + _conflicts="$_conflicts $_name" + test -n "$_vers" && _conflicts="$_conflicts $_name (>= $vers)" + _conflicts="${_conflicts}," + done + echo "${_conflicts%,}" +} + +pp_deb_make_control() { + local cmp="$1" + local installed_size + + # compute the installed size + installed_size=`pp_deb_files_size < $pp_wrkdir/%files.$cmp` + + package_name=`pp_deb_cmp_full_name "$cmp"` + cat <<-. + Package: ${package_name} + Version: `pp_deb_version_final`-${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} + Installed-Size: ${installed_size} +. + if test -s $pp_wrkdir/%depend."$cmp"; then + sed -ne '/^[ ]*$/!s/^[ ]*/Depends: /p' \ + < $pp_wrkdir/%depend."$cmp" + fi + if test -s $pp_wrkdir/%conflict."$cmp"; then + pp_deb_conflict < $pp_wrkdir/%conflict."$cmp" + fi +} + +pp_deb_make_md5sums() { + local cmp="$1"; shift + local 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() { + local output="$1" + local source="$2" + local 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() { + local svc + + #-- add service start/stop code + if test -n "$pp_services"; then + #-- append common %post install code + pp_systemd_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 + + # Create init script and systemd service file (unless they exists) + pp_deb_service_make_service_files $svc || + pp_error "could not create service files for $svc" + + #-- append %post code to install the svc + test x"yes" = x"$enable" && + cat<<-. >> $pp_wrkdir/%post.run + + case "\$1" in + configure) + # Install the service links + _pp_systemd_init + if test -n "\$systemctl_cmd"; then + _pp_systemd_install $svc + _pp_systemd_enable $svc + else + update-rc.d $svc defaults + fi + ;; + esac +. + + #-- prepend %preun code to stop svc + cat<<-. | pp_prepend $pp_wrkdir/%preun.run + + case "\$1" in + remove|deconfigure|upgrade) + # Stop the $svc service + invoke-rc.d $svc stop + _pp_systemd_disable $svc + ;; + esac +. + + #-- prepend %postun code to remove service + cat<<-. | pp_prepend $pp_wrkdir/%postun.run + + case "\$1" in + purge) + # Remove the service links + update-rc.d $svc remove + _pp_systemd_remove $svc + ;; + esac +. + done + + pp_systemd_service_remove_common | pp_prepend $pp_wrkdir/%preun.run + #pp_deb_service_remove_common | pp_prepend $pp_wrkdir/%preun.run + + # Actual systemd service removal is done in %postun. + # Otherwise, systemd may pick up the init.d script if it exists. + pp_systemd_service_remove_common | pp_prepend $pp_wrkdir/%postun.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_files_size () { + local t m o g f p st + while read t m o g f p st; do + case $t in + f|s) du -k "${pp_destdir}$p";; + d) echo 4;; + esac + done | awk '{n+=$1} END {print n}' +} + +pp_deb_make_DEBIAN() { + local cmp="${1:-run}" + local data cmp_full_name + local 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 preinst + pp_deb_make_package_maintainer_script "$data/DEBIAN/preinst" \ + "$pp_wrkdir/%pre.$cmp" "Pre-install script for $cmp_full_name"\ + || exit $? + + # 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 $? + + # Create postrm + pp_deb_make_package_maintainer_script "$data/DEBIAN/postrm" \ + "$pp_wrkdir/%postun.$cmp" "Post-uninstall script for $cmp_full_name"\ + || exit $? + + umask $old_umask +} + +pp_deb_make_data() { + local _l t m o g f p st data + local 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 + if test x"$m" = x"-"; then + case "$t" in + d) m=755;; + f) m=644;; + esac + fi + 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; + case "$f" in + *v*) + # 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 + ;; + esac + ;; + + 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 () { + local cmp + local 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 . -name DEBIAN -prune -o -type f -print | sed "s,^\./,,")` || + pp_die "Could not make DEBIAN md5sums for $cmp" +} + +pp_backend_deb () { + local debname + + # Munge description for control file inclusion + pp_deb_munge_description + + # 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 () { + local cmp="${1:-run}" + echo `pp_deb_cmp_full_name $cmp`"_"`pp_deb_version_final`"-${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 () { + local 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_probe() { + local 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` + case $release in + buzz) + release="11" + ;; + rex) + release="12" + ;; + bo) + release="13" + ;; + hamm) + release="20" + ;; + slink) + release="21" + ;; + potato) + release="22" + ;; + woody) + release="30" + ;; + sarge) + release="31" + ;; + etch) + release="40" + ;; + lenny) + release="50" + ;; + squeeze) + release="60" + ;; + wheezy) + release="70" + ;; + jessie) + release="80" + ;; + stretch) + release="90" + ;; + esac + ;; + *) + # 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 () { + + reload_signal= + start_runlevels=${pp_deb_default_start_runlevels-"2 3 4 5"} # == lsb default-start + stop_runlevels=${pp_deb_default_stop_runlevels-"0 1 6"} # == lsb default-stop + svc_description="${pp_deb_default_svc_description}" # == lsb short descr + svc_process= + svc_init_filename="${pp_deb_svc_init_filename}" # == $svc.init + svc_init_filepath="${pp_deb_svc_init_filepath}" # == /etc/init.d/ by default + + lsb_required_start='$local_fs $network' + lsb_should_start= + lsb_required_stop='$local_fs' + lsb_description= + + start_priority=50 + stop_priority=50 #-- stop_priority = 100 - start_priority +} + +pp_deb_service_make_service_files () { + local svc=${svc_init_filename:-$1} + local script="${svc_init_filepath:-"/etc/init.d"}/$svc" + local out=$pp_destdir$script + local _process _cmd + + pp_add_file_if_missing $script run 755 v || 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 + #-- the command name in /proc/[pid]/stat is limited to 15 characters + _cmd="$cmd"; + _cmd_path=`echo $cmd | cut -d" " -f1` + _cmd_name=`basename $_cmd_path | cut -c1-15` + _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:-no 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 + + start-stop-daemon --start --quiet $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 $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 + start-stop-daemon --stop --quiet $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 --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 $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 + + # Create systemd service file + pp_systemd_make_service_file $svc +} +pp_backend_deb_function() { + case "$1" in + pp_mkgroup) cat<<'.';; + /usr/sbin/groupmod "$1" 2>/dev/null && return 0 + /usr/sbin/groupadd "$1" +. + pp_mkuser:depends) echo pp_mkgroup;; + pp_mkuser) cat<<'.';; + pp_tmp_system= + id -u "$1" >/dev/null 2>/dev/null && return 0 + # deb 3.1's useradd changed API in 4.0. Gah! + /usr/sbin/useradd --help 2>&1 | /bin/grep -q .--system && + pp_tmp_system=--system + pp_mkgroup "${2:-$1}" || return 1 + /usr/sbin/useradd \ + -g "${2:-$1}" \ + -d "${3:-/nonexistent}" \ + -s "${4:-/bin/false}" \ + $pp_tmp_system \ + "$1" +. + pp_havelib) cat<<'.';; + for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do + test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0 + done + return 1 +. + *) false;; + esac +} + +pp_platforms="$pp_platforms kit" + +pp_backend_kit_detect () { + test x"$1" = x"OSF1" +} + +pp_backend_kit_init () { + pp_kit_name= + pp_kit_package= + pp_kit_desc= + pp_kit_version= + pp_kit_subset= + pp_readlink_fn=pp_ls_readlink + pp_kit_startlevels="2 3" + pp_kit_stoplevels="0 2 3" +} + +pp_backend_kit () { + typeset mi_file k_file svc outfile + typeset desc + + pp_backend_kit_names > /dev/null + + if test -z "$pp_kit_desc"; then + pp_kit_desc="$description" + fi + + mi_file="$pp_wrkdir/$pp_kit_subset.mi" + k_file="$pp_wrkdir/$pp_kit_subset.k" + scp_file="$pp_wrkdir/$pp_kit_subset.scp" + + desc="${pp_kit_desc:-$description}" + + cat <<-. >> $k_file + NAME='$name' + CODE=$pp_kit_name + VERS=$pp_kit_version + MI=$mi_file + COMPRESS=0 + %% + $pp_kit_subset . 0 '$desc' +. + + if test -n "$pp_services"; then + for svc in $pp_services; do + pp_kit_make_service $svc + pp_prepend $pp_wrkdir/%preun.run <<-. + /sbin/init.d/$svc stop +. + done + fi + + pp_backend_kit_make_mi "$mi_file" + pp_backend_kit_make_scp + #rm -rf $pp_wrkdir/kit_dest + mkdir -p $pp_wrkdir/kit_dest + pp_backend_kit_kits $k_file $pp_opt_destdir $pp_wrkdir/kit_dest + tar cvf $pp_wrkdir/$pp_kit_subset.tar -C $pp_wrkdir/kit_dest . + gzip -c $pp_wrkdir/$pp_kit_subset.tar > $pp_wrkdir/$pp_kit_subset.tar.gz + #rm -rf $pp_wrkdir/$pp_kit_subset.tar $pp_wrkdir/scps +} + +pp_backend_kit_make_mi () { + # XXX this information should go into the .inv files + typeset t m o g f p st line dm + while read t m o g f p st; do + case $t in + f|d) + echo "0 .$p $pp_kit_subset" + echo " chmod $m $p" >> $pp_wrkdir/%post.run + if [ x"$o" = x"-" ] ; then + echo " chown root $p" >> $pp_wrkdir/%post.run + else + echo " chown $o $p" >> $pp_wrkdir/%post.run + fi + if [ x"$g" = x"-" ] ; then + echo " chgrp 0 $p" >> $pp_wrkdir/%post.run + else + echo " chgrp $g $p" >> $pp_wrkdir/%post.run + fi + ;; + s) + echo " ln -s $st $p" >> $pp_wrkdir/%post.run + echo " rm -f $p" >> $pp_wrkdir/%preun.run + ;; + esac + done < $pp_wrkdir/%files.run | sort -k3 |uniq > $1 +} + + +pp_backend_kit_make_scp () { + scpdir="$pp_wrkdir/scps" + mkdir "$scpdir" && touch "$scpdir"/$pp_kit_subset.scp + cat <<EOF >"$scpdir"/$pp_kit_subset.scp + + . /usr/share/lib/shell/libscp + + case "\$ACT" in + PRE_L) + STL_ScpInit + + + + ;; + POST_L) + STL_ScpInit + STL_LinkCreate +EOF + + cat $pp_wrkdir/%post.run >>"$scpdir"/$pp_kit_subset.scp + cat >>"$scpdir"/$pp_kit_subset.scp <<EOF + ;; + PRE_D) + STL_ScpInit + STL_LinkRemove +EOF + cat $pp_wrkdir/%preun.run >>"$scpdir"/$pp_kit_subset.scp + cat >>"$scpdir"/$pp_kit_subset.scp <<EOF + ;; + POST_D) + + ;; + C) + STL_ScpInit + + case "\$1" in + INSTALL) + echo "Installation of the \$_DESC (\$_SUB) subset is complete." + ;; + DELETE) + ;; + esac + + ;; + V) + + ;; + esac + + exit 0 +EOF + chmod 744 "$scpdir"/$pp_kit_subset.scp +} + + +pp_backend_kit_cleanup () { + : +} + +pp_backend_kit_names () { + if test -z "$pp_kit_name"; then + pp_warn "pp_kit_name not specified, using XXX" + pp_kit_name=XXX + fi + case "$pp_kit_name" in + ???) : ok;; + *) pp_error "\$pp_kit_name $pp_kit_name must be three characters";; + esac + if test -z "$pp_kit_package"; then + pp_warn "pp_kit_package not specified, using YYYY" + pp_kit_package=YYYY + fi + if test -z "$pp_kit_version"; then + pp_kit_version=`echo $version|tr -d '.a-zA-Z'` + fi + case "$pp_kit_version" in + [0-9]) pp_kit_version="${pp_kit_version}00";; + [0-9][0-9]) pp_kit_version="${pp_kit_version}0";; + [0-9][0-9][0-9]) : ok;; + *) pp_error "\$pp_kit_version $pp_kit_version must be three digits, ";; + esac + if test -z "$pp_kit_subset"; then + pp_kit_subset="$pp_kit_name$pp_kit_package$pp_kit_version" + fi + echo "$pp_kit_subset.tar.gz" +} + +pp_backend_kit_install_script () { + typeset pkgname platform + + pkgname=`pp_backend_kit_names` + platform="`pp_backend_kit_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 echo \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\` + #verbose swinstall -x verbose=0 -s \${PP_PKGDESTDIR:-\`pwd\`}/$pkgname \`cpt_to_tags "\$@"\` + ;; + uninstall) + test \$# -ge 1 || usage \$op + verbose echo \`cpt_to_tags "\$@"\` + #verbose 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_kit_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.${2-sl}" && return 0 + done + return 1 +. + *) pp_error "unknown function request: $1";; + esac +} + +pp_backend_kit_init_svc_vars () { + : +} + +pp_backend_kit_probe () { + echo tru64-`uname -r | sed 's/V\([0-9]*\)\.\([0-9]*\)/\1\2/'` +} + +pp_kit_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_kit_service_script () { + typeset svc scriptpath out + + svc="$1" + scriptpath="/sbin/init.d/$svc" + + 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_add_file_if_missing $scriptpath run 755 + + cat <<-. > $pp_destdir$scriptpath + svc="$svc" + pidfile="$pidfile" + + pp_start () { + $cmd + } +. + 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 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_kit_make_service () { + typeset level priority 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 priority='${pp_kit_priority_'$svcvar'}' + test -z "$priority" && priority="${pp_kit_priority:-50}" + + eval startlevels='${pp_kit_startlevels_'$svcvar'}' + test -z "$startlevels" && startlevels="$pp_kit_startlevels" + + eval stoplevels='${pp_kit_stoplevels_'$svcvar'}' + test -z "$stoplevels" && stoplevels="$pp_kit_stoplevels" + + # create the script and config file + pp_kit_service_script $svc + + # fix the priority up + case "$priority" in + ???) :;; + ??) priority=0$priority;; + ?) priority=00$priority;; + 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 " ln -s /sbin/init.d/$svc /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%post.run + echo " rm /sbin/rc$level.d/S$priority$svc" >>$pp_wrkdir/%preun.run + done + test -z "$stoplevels" || for level in $stoplevels; do + echo " ln -s /sbin/init.d/$svc /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%post.run + echo " rm -f /sbin/rc$level.d/K$priority$svc" >>$pp_wrkdir/%preun.run + done +} + + + + +pp_backend_kit_sizes () { + awk ' + BEGIN { root = usr = var = 0; } + { + if (substr($9, 1, 1) != "l") + if (substr($10, 1, 6) == "./var/") + var += $2; + else if (substr($10, 1, 10) == "./usr/var/") + var += $2 + else if (substr($10, 1, 6) == "./usr/") + usr += $2 + else + root += $2 + } + END { printf "%d\t%d\t%d", root, usr, var } + ' "$@" +} + +pp_kit_kits_global () { + line=`sed -n '/^%%/q;/^'$2'=/{s/^'$2'=//p;q;}' <"$1"` + test -z "$line" && return 1 + eval "echo $line" + : +} + +pp_backend_kit_kits () { + typeset KITFILE FROMDIR TODIR + typeset SCPDIR + + SCPDIR="$pp_wrkdir/scps" + + PATH="/usr/lbin:/usr/bin:/etc:/usr/ucb:$PATH"; export PATH # XXX + #umask 2 # XXX + + test $# -ge 3 || pp_die "pp_backend_kit_kits: too few arguments" + KITFILE="$1"; shift + FROMDIR="$1"; shift + TODIR="$1"; shift + + test -f "$KITFILE" || pp_die "$KITFILE not found" + test -d "$FROMDIR" || pp_die "$FROMDIR not found" + test -d "$TODIR" || pp_die "$TODIR not found" + + INSTCTRL="$TODIR/instctrl" + mkdir -p "$INSTCTRL" || pp_die "cannot create instctrl directory" + chmod 775 "$INSTCTRL" + + grep "%%" $KITFILE > /dev/null || pp_die "no %% in $KITFILE" + + typeset NAME CODE VERS MI ROOT COMPRESS + typeset S_LIST ALLSUBS + + NAME=`pp_kit_kits_global "$KITFILE" NAME` || pp_die "no NAME in $KITFILE" + CODE=`pp_kit_kits_global "$KITFILE" CODE` || pp_die "no CODE in $KITFILE" + VERS=`pp_kit_kits_global "$KITFILE" VERS` || pp_die "no VERS in $KITFILE" + MI=`pp_kit_kits_global "$KITFILE" MI` || pp_die "no MI in $KITFILE" + ROOT=`pp_kit_kits_global "$KITFILE" ROOT` + COMPRESS=`pp_kit_kits_global "$KITFILE" COMPRESS` + + test -f "$MI" || pp_die "Inventory file $MI not found" + + case "$ROOT" in + *ROOT) + test -f "$TODIR/$ROOT" || + pp_die "Root image $ROOT not found in $TODIR" ;; + esac + + ALLSUBS=`awk 'insub==1 {print $1} /^%%/ {insub=1}' <"$KITFILE"` + test $# -eq 0 && set -- $ALLSUBS + + pp_debug "Creating $# $NAME subsets." + pp_debug "ALLSUBS=<$ALLSUBS>" + + if test x"$COMPRESS" = x"1"; then + COMPRESS=: + else + COMPRESS=false + fi + + #rm -f *.ctrl Volume* + + for SUB + do + test -z "$SUB" && pp_die "SUB is empty" + + typeset INV CTRL ROOTSIZE USRSIZE VARSIZE TSSUB + #rm -f Volume* + case $SUB in + .*) :;; + *) pp_verbose rm -f "$TODIR/$SUB"* "$INSTCTRL/$SUB"*;; + esac + + TSSUB="$pp_wrkdir/ts.$SUB" + + pp_debug "kits: Subset $SUB" + + INV="$SUB.inv" + CTRL="$SUB.ctrl" + pp_debug "kits: Generating media creation information..." + + # Invcutter takes as input + # SUB dir/path + # and generates stl_inv(4) files, like this + # f 0 00000 0 0 100644 2/11/09 010 f dir/path none SUB + grep " $SUB\$" "$MI" | + pp_verbose /usr/lbin/invcutter \ + -v "$VERS" -f "$FROMDIR" > "$INSTCTRL/$INV" || + pp_die "failed to create $INSTCTRL/$INV" + chmod 664 "$INSTCTRL/$INV" + + pp_backend_kit_sizes "$INSTCTRL/$INV" > "$pp_wrkdir/kit.sizes" + read ROOTSIZE USRSIZE VARSIZE < "$pp_wrkdir/kit.sizes" + + # Prefix each line with $FROMDIR. This will be stripped + awk '$1 != "d" {print from $10}' from="$FROMDIR/" \ + > "$TSSUB" < "$INSTCTRL/$INV" || + pp_die "failed" + + NVOLS=0 + + pp_debug "kits: Creating $SUB control file..." + + sed '1,/^%%/d;/^'"$SUB"'/{p;q;}' < "$KITFILE" > "$pp_wrkdir/kit.line" + read _SUB _IGNOR DEPS FLAGS DESC < "$pp_wrkdir/kit.line" + if test -z "$_SUB"; then + pp_warn "No such subset $SUB in $KITFILE" + continue + fi + DEPS=`echo $DEPS | tr '|' ' '` + case $FLAGS in + FLGEXP*) pp_verbose FLAGS='"${'"$FLAGS"'}"' ;; + esac + case $DESC in + *%*) DESC=`echo $DESC|awk -F% '{printf "%-36s%%%s\n", $1, $2}'`;; + esac + + cat > "$INSTCTRL/$CTRL" <<-. + NAME='$NAME $SUB' + DESC=$DESC + ROOTSIZE=$ROOTSIZE + USRSIZE=$USRSIZE + VARSIZE=$VARSIZE + NVOLS=1:$NVOLS + MTLOC=1:$TLOC + DEPS="$DEPS" + FLAGS=$FLAGS +. + chmod 664 "$INSTCTRL/$CTRL" + + pp_debug "kits: Making tar image" + + pp_verbose tar cfPR "$TODIR/$SUB" "$FROMDIR/" "$TSSUB" || + pp_error "problem creating kit file" + + if $COMPRESS; then + pp_debug "kits: Compressing" + (cd "$TODIR" && compress -f -v "$SUB") || + pp_die "problem compressing $TODIR/$SUB" + SPC=`expr $SUB : '\(...\).*'` # first three characters + SVC=`expr $SUB : '.*\(...\)'` # last three characters + : > "$INSTCTRL/$SPC$SVC.comp" + chmod 664 "$INSTCTRL/$SPC$SVC.comp" + pp_debug "kits: Padding compressed file to 10kB" # wtf? + rm -f "$TODIR/$SUB" + pp_verbose \ + dd if="$TODIR/$SUB.Z" of="$TODIR/$SUB" bs=10k conv=sync || + pp_die "problem moving compressed file" + rm -f "$TODIR/$SUB.Z" + fi + chmod 664 "$TODIR/$SUB" + + if test -f "$SCPDIR/$SUB.scp"; then + cp "$SCPDIR/$SUB.scp" "$INSTCTRL/$SUB.scp" + chmod 755 "$INSTCTRL/$SUB.scp" + else + pp_debug "kits: null subset control program for $SUB" + : > "$INSTCTRL/$SUB.scp" + chmod 744 "$INSTCTRL/$SUB.scp" + fi + + pp_debug "kits: Finished creating media image for $SUB" + done + + pp_debug "kits: Creating $CODE.image" + + case "$ROOT" in + *ROOT) ALLSUBS="$ROOT $ALLSUBS" + ;; + esac + + (cd "$TODIR" && sum $ALLSUBS) > "$INSTCTRL/$CODE.image" + chmod 664 "$INSTTRL/$CODE.image" + pp_debug "kits: Creating INSTCTRL" + (cd "$INSTCTRL" && tar cpvf - *) > "$TODIR/INSTCTRL" + chmod 664 "$TODIR/INSTCTRL" + cp "$INSTCTRL/$CODE.image" "$TODIR/$CODE.image" + chmod 664 "$TODIR/$CODE.image" + + pp_debug "kits: Media image production complete" +} + +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= + pp_rpm_url= + pp_rpm_packager= + pp_rpm_provides= + pp_rpm_requires= + pp_rpm_requires_pre= + pp_rpm_requires_post= + pp_rpm_requires_preun= + pp_rpm_requires_postun= + 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_dev_requires_pre= + pp_rpm_dev_requires_post= + pp_rpm_dev_requires_preun= + pp_rpm_dev_requires_postun= + pp_rpm_dbg_requires= + pp_rpm_dbg_requires_pre= + pp_rpm_dbg_requires_post= + pp_rpm_dbg_requires_preun= + pp_rpm_dbg_requires_postun= + pp_rpm_doc_requires= + pp_rpm_doc_requires_pre= + pp_rpm_doc_requires_post= + pp_rpm_doc_requires_preun= + pp_rpm_doc_requires_postun= + pp_rpm_dev_provides= + pp_rpm_dbg_provides= + pp_rpm_doc_provides= + + pp_rpm_autoprov= + pp_rpm_autoreq= + pp_rpm_autoreqprov= + + 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_rpmbuild=`pp_rpm_detect_rpmbuild` + + # SLES8 doesn't always come with readlink + test -x /usr/bin/readlink -o -x /bin/readlink || + pp_readlink_fn=pp_ls_readlink +} + +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 + local arch + for arch in "`uname -m`" "`uname -p`"; do + case "$arch" in + i?86) + pp_rpm_arch_std=i386 + break + ;; + x86_64|ppc|ppc64|ppc64le|ia64|s390|s390x) + pp_rpm_arch_std="$arch" + break + ;; + powerpc) + # Probably AIX + case "`/usr/sbin/lsattr -El proc0 -a type -F value`" in + PowerPC_POWER*) pp_rpm_arch_std=ppc64;; + *) pp_rpm_arch_std=ppc;; + esac + break + ;; + *) pp_rpm_arch_std=unknown + ;; + esac + done + + #-- 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/mandrakelinux-release; then + pp_rpm_distro=`awk ' + /^Mandrakelinux release/ { print "mand" $3; exit; } + ' /etc/mandrake-release` + elif test -f /etc/mandrake-release; then + pp_rpm_distro=`awk ' + /^Linux Mandrake release/ { print "mand" $4; exit; } + /^Mandrake Linux release/ { print "mand" $4; exit; } + ' /etc/mandrake-release` + elif test -f /etc/fedora-release; then + pp_rpm_distro=`awk ' + /^Fedora Core release/ { print "fc" $4; exit; } + /^Fedora release/ { print "f" $3; exit; } + ' /etc/fedora-release` + elif test -f /etc/redhat-release; then + pp_rpm_distro=`sed -n \ + -e 's/^Red Hat Linux.*release \([0-9][0-9\.]*\).*/rh\1/p' \ + -e 's/^Red Hat Enterprise Linux.*release \([0-9][0-9\.]*\).*/rhel\1/p' \ + -e 's/^Rocky Linux.*release \([0-9][0-9\.]*\).*/rhel\1/p' \ + -e 's/^AlmaLinux.*release \([0-9][0-9\.]*\).*/rhel\1/p' \ + -e 's/^CentOS.*release \([0-9][0-9\.]*\).*/centos\1/p' \ + /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; } + /^S[uU]SE Linux Enterprise Server [0-9]/ { print "sles" $5; exit; } + /^S[uU]SE LINUX Enterprise Server [0-9]/ { print "sles" $5; exit; } + /^SuSE SLES-[0-9]/ { print "sles" substr($2,6); exit; } + ' /etc/SuSE-release` + elif test -f /etc/os-release; then + pp_rpm_distro="`. /etc/os-release && echo \$ID\$VERSION`" + elif test -f /etc/pld-release; then + pp_rpm_distro=`awk ' + /^[^ ]* PLD Linux/ { print "pld" $1; exit; } + ' /etc/pld-release` + elif test X"`uname -s 2>/dev/null`" = X"AIX"; then + local r v + r=`uname -r` + v=`uname -v` + pp_rpm_distro="aix$v$r" + fi + pp_rpm_distro=`echo $pp_rpm_distro | tr -d .` + test -z "$pp_rpm_distro" && + pp_warn "unknown distro" +} + +pp_rpm_detect_rpmbuild () { + local cmd + for cmd in rpmbuild rpm; do + if command -v $cmd > /dev/null 2>&1; then + echo $cmd + return 0 + fi + done + + pp_error "Could not find rpmbuild" + # Default to `rpmbuild` in case it magically appears + echo rpmbuild + return 1 +} + +pp_rpm_label () { + local label arg + label="$1"; shift + for arg + do + test -z "$arg" || echo "$label: $arg" + done +} + +pp_rpm_writefiles () { + local _l t m o g f p st fo farch + while read t m o g f p st; do + _l="$p" + test $t = d && _l="%dir ${_l%/}/" + if test $t = s; then + # rpm warns if %attr contains a mode for symlinks + m=- + elif 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` + #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"*) + farch=i386;; + *": ELF 64-bit LSB "*", AMD x86-64"*|\ + *": ELF 64-bit LSB "*", x86-64"*) + farch=x86_64;; + *": ELF 32-bit MSB "*", PowerPC"*) + farch=ppc;; + *": ELF 64-bit LSB "*", 64-bit PowerPC"*) + farch=ppc64le;; + *": ELF 64-bit MSB "*", 64-bit PowerPC"*) + farch=ppc64;; + *": ELF 64-bit LSB "*", IA-64"*) + farch=ia64;; + *": ELF 32-bit MSB "*", IBM S/390"*) + farch=s390;; + *": ELF 64-bit MSB "*", IBM S/390"*) + farch=s390x;; + *"executable (RISC System/6000)"*) + farch=ppc;; + *"64-bit XCOFF executable"*) + farch=ppc64;; + *": ELF 64-bit LSB "*", ARM aarch64"*) + farch=aarch64;; + *" ELF "*) + farch=ELF;; + *) + farch=noarch;; + esac + # If file(1) doesn't provide enough info, try readelf(1) + if test "$farch" = "ELF"; then + fo=`readelf -h "${pp_destdir}$p" | awk '{if ($1 == "Class:") {class=$2} else if ($1 == "Machine:") {machine=$0; sub(/^ *Machine: */, "", machine)}} END {print class " " machine}' 2>/dev/null` + case "$fo" in + "ELF32 Intel 80386") + farch=i386;; + "ELF64 "*[xX]"86-64") + farch=x86_64;; + "ELF32 PowerPC") + farch=ppc;; + "ELF64 PowerPC"*) + farch=ppc64;; + "ELF64 IA-64") + farch=ia64;; + "ELF32 IBM S/390") + farch=s390;; + "ELF64 IBM S/390") + farch=s390x;; + "ELF64 AArch64") + farch=aarch64;; + *) + farch=noarch;; + esac + fi + pp_debug "file: $fo -> $farch" + test x"$farch" = x"noarch" || pp_add_to_list pp_rpm_arch_seen $farch + fi + + case $f in *v*) _l="%config(noreplace) $_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 () { + local _name _vers + while read _name _vers; do + case "$_name" in ""| "#"*) continue ;; esac + echo "Requires: $_name ${_vers:+>= $_vers}" + done +} + +pp_rpm_conflict () { + local _name _vers + while read _name _vers; do + case "$_name" in ""| "#"*) continue ;; esac + echo "Conflicts: $_name ${_vers:+>= $_vers}" + done +} + +pp_rpm_override_requires () { + local orig_find_requires + + if test -z "$pp_rpm_depend_filter_cmd"; then + return 0 + fi + + orig_find_requires=`rpm --eval '%{__find_requires}'` + cat << EOF > "$pp_wrkdir/filtered-find-requires" +$orig_find_requires \$@ | $pp_rpm_depend_filter_cmd +EOF + chmod +x "$pp_wrkdir/filtered-find-requires" + echo "%define __find_requires $pp_wrkdir/filtered-find-requires" + # Might be necessary for old versions of RPM? Not for 4.4.2. + #echo "%define _use_internal_dependency_generator 0" +} + +pp_backend_rpm () { + local cmp specfile _summary _group _desc _pkg _subname svc _script + + 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 "URL" "$pp_rpm_url" >>$specfile + pp_rpm_label "Vendor" "${pp_rpm_vendor:-$vendor}" >>$specfile + pp_rpm_label "Packager" "$pp_rpm_packager" >>$specfile + pp_rpm_label "Provides" "$pp_rpm_provides" >>$specfile + pp_rpm_label "Requires(pre)" "$pp_rpm_requires_pre" >>$specfile + pp_rpm_label "Requires(post)" "$pp_rpm_requires_post" >>$specfile + pp_rpm_label "Requires(preun)" "$pp_rpm_requires_preun" >>$specfile + pp_rpm_label "Requires(postun)" "$pp_rpm_requires_postun" >>$specfile + pp_rpm_label "AutoProv" "$pp_rpm_autoprov" >>$specfile + pp_rpm_label "AutoReq" "$pp_rpm_autoreq" >>$specfile + pp_rpm_label "AutoReqProv" "$pp_rpm_autoreqprov" >>$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 `$pp_rpm_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 + if test -s $pp_wrkdir/%conflict.run; then + pp_rpm_conflict < $pp_wrkdir/%conflict.run >> $specfile + fi + + pp_rpm_override_requires >> $specfile + + 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 +. + for _script in pre post preun postun; do + eval '_pkg="$pp_rpm_'$cmp'_requires_'$_script'"' + if test -n "$_pkg"; then + eval pp_rpm_label "Requires($_script)" $_pkg + fi + done + 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 + if test -s $pp_wrkdir/%conflict.$cmp; then + pp_rpm_conflict < $pp_wrkdir/%conflict.$cmp >> $specfile + fi + + eval '_pkg="$pp_rpm_'$cmp'_provides"' + eval pp_rpm_label Provides $_pkg + + cat <<-. + + %description $_subname + $_desc +. + done >>$specfile + + #-- NB: we do not 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_service_files $svc || + pp_error "could not create service files for $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 -n "$pp_rpm_ghost"; then + for ghost in $pp_rpm_ghost; do + echo "%ghost $ghost" + done + fi + + if test -s $pp_wrkdir/%pre.$cmp; then + echo "" + echo "%pre $_subname" + cat $pp_wrkdir/%pre.$cmp + echo : # causes script to exit true + 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 + + if test -s $pp_wrkdir/%postun.$cmp; then + echo "" + echo "%postun $_subname" + cat $pp_wrkdir/%postun.$cmp + echo : # causes script to exit true + fi + done >>$specfile + + #-- create a suitable work area for rpmbuild + cat <<-. >$pp_wrkdir/.rpmmacros + %_topdir $pp_wrkdir + # XXX Note escaped %% for use in headerSprintf + %_rpmfilename %%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm + . + 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;; + *"s390 s390x"* | *"s390x s390"* ) + pp_rpm_arch_seen=s390x;; + *"aarch64"* ) + pp_rpm_arch_seen=aarch64;; + *" "*) + pp_error "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 \ + $pp_rpm_rpmbuild -bb \ + --buildroot="$pp_destdir/" \ + --target="${pp_rpm_arch}" \ + --define='_unpackaged_files_terminate_build 0' \ + --define='_use_internal_dependency_generator 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 + # The package might be in an arch-specific subdir + pkgfile=not-found + for dir in $pp_wrkdir/RPMS/${pp_rpm_arch} $pp_wrkdir/RPMS; do + if test -f $dir/$f; then + pkgfile=$dir/$f + fi + done + if test x"$pkgfile" = x"not-found"; then + pp_error "Problem predicting RPM filename: $f" + else + ln $pkgfile $pp_wrkdir/$f + fi + 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 () { + local cmp _subname + for cmp in $pp_components; do + pp_rpm_output_name $cmp + done +} + +pp_backend_rpm_cleanup () { + : +} + +pp_rpm_print_requires () { + local _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 () { + local cmp _subname + + echo "#!/bin/sh" + pp_install_script_common + + cat <<. + + cmp_to_pkgname () { + local 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_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_rpm_service_install_common () { + cat <<-'.' + + _pp_install_service () { + local 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 &> /dev/null + elif [ -x /sbin/chkconfig ]; then + # Red Hat/chkconfig-style install + /sbin/chkconfig --add $svc &> /dev/null + /sbin/chkconfig $svc off &> /dev/null + else + : # manual links under /etc/init.d + fi + } + + _pp_enable_service () { + local 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 &> /dev/null + else + # manual install + set -- `sed -n -e 's/^# Default-Start://p' /etc/init.d/$svc` + start_priority=`sed -n -e 's/^# X-Quest-Start-Priority:[[:space:]]*//p' /etc/init.d/$svc` + stop_priority=`sed -n -e 's/^# X-Quest-Stop-Priority:[[:space:]]*//p' /etc/init.d/$svc` + + # Provide default start & stop priorities of 20 & 80 in + # accordance with Debian update-rc.d defaults + if [ -z "$start_priority" ]; then + start_priority=20 + fi + if [ -z "$stop_priority" ]; then + stop_priority=80 + fi + + if [ -d "/etc/rc.d" ];then + rcdir=/etc/rc.d + else + rcdir=/etc + fi + + for level + do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/S$start_priority$svc; done + set -- `sed -n -e 's/^# Default-Stop://p' /etc/init.d/$svc` + for level + do ln -sf /etc/init.d/$svc $rcdir/rc$level.d/K$stop_priority$svc; done + fi + } +. + pp_systemd_service_install_common +} + +pp_rpm_service_remove_common () { + cat <<-'.' + + _pp_remove_service () { + local 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 &> /dev/null + elif [ -x /sbin/chkconfig ]; then + /sbin/chkconfig --del $svc &> /dev/null + else + if [ -d "/etc/rc.d" ];then + rcdir=/etc/rc.d + else + rcdir=/etc + fi + + rm -f $rcdir/rc?.d/[SK]??$svc + fi + } +. + pp_systemd_service_remove_common +} + +pp_rpm_service_install () { + echo "" + echo "_pp_systemd_init" + echo 'if test -n "$systemctl_cmd"; then' + echo " _pp_systemd_install $1" + test $enable = yes && echo " _pp_systemd_enable $1" + echo "else" + echo " _pp_install_service $1" + test $enable = yes && echo " _pp_enable_service $1" + echo "fi" +} + +pp_rpm_service_remove () { + cat <<-. + + if [ "\$1" = "remove" -o "\$1" = "0" ]; then + # only remove the service if not upgrade + _pp_remove_service $1 + _pp_systemd_disable $1 + _pp_systemd_remove $1 + fi +. +} + + +pp_backend_rpm_init_svc_vars () { + + reload_signal= + start_runlevels=${pp_rpm_default_start_runlevels-"2 3 4 5"} # == lsb default-start + stop_runlevels=${pp_rpm_default_stop_runlevels-"0 1 6"} # == lsb default-stop + svc_description="${pp_rpm_default_svc_description}" # == lsb short descr + svc_process= + svc_init_filename="${pp_rpm_svc_init_filename}" # == $svc.init + svc_init_filepath="${pp_rpm_svc_init_filepath}" # == /etc/init.d/ by default + + 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 () { + local grp=$1 + local svcs="$2" + local script=/etc/init.d/$grp + local 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 $svcs; 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_service_files () { + local svc=${svc_init_filename:-$1} + local script="${svc_init_filepath:-"/etc/init.d"}/$svc" + local out=$pp_destdir$script + local _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} + + prog="`echo $cmd | sed -e 's: .*::' -e 's:^.*/::'`" + +. + + 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 "$@"; } + pp_failure_msg () { log_failure_msg "$@"; } + pp_warning_msg () { log_warning_msg "$@"; } + elif [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions + pp_success_msg () { echo -n "$*"; success "$@"; echo; } + pp_failure_msg () { echo -n "$*"; failure "$@"; echo; } + pp_warning_msg () { echo -n "$*"; warning "$@"; 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 -s "$pidfile"; then + read pid < "$pidfile" 2>/dev/null + kill "$@" "$pid" 2>/dev/null + else + return 1 + fi + } + + #-- verifies that ${svc_name} is running + # returns 0=success 1=failure + pp_running () { + if test -s "$pidfile"; then + read pid < "$pidfile" 2>/dev/null + if test ${pid:-0} -gt 1 && kill -0 "$pid" 2>/dev/null; then + # make sure name matches + pid="`ps -p $pid 2>/dev/null | sed -n \"s/^ *\($pid\) .*$prog *$/\1/p\"`" + if test -n "$pid"; then + return 0 + fi + fi + fi + return 1 + } + + #-- prints information about the service status + # returns 0=running 1=crashed 3=stopped + pp_status () { + pp_msg "Checking for ${svc_name}" + if pp_running; then + pp_success_msg "running" + return 0 + elif test -s "$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 + + # Create systemd service file + pp_systemd_make_service_file $svc +} +pp_backend_rpm_function () { + case "$1" in + pp_mkgroup) cat<<'.';; + /usr/sbin/groupadd -f -r "$1" +. + pp_mkuser:depends) echo pp_mkgroup;; + pp_mkuser) cat<<'.';; + pp_mkgroup "${2:-$1}" || return 1 + /usr/sbin/useradd \ + -g "${2:-$1}" \ + -M -d "${3:-/nonexistent}" \ + -s "${4:-/bin/false}" \ + -r "$1" +. + pp_havelib) cat<<'.';; + for pp_tmp_dir in `echo "/usr/lib:/lib${3:+:$3}" | tr : ' '`; do + test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0 + done + return 1 +. + *) false;; + esac +} + +: 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/usr/bin/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 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 + 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://mirror.informatimago.com/next/developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution/Concepts/sd_pkg_flags.html> + Info.plist = { + CFBundleGetInfoString: "1.2.3, One Identity LLC.", + CFBundleIdentifier: "com.quest.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. + <https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/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.rc.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", + } + + + How to add a new user + dscl . -create /Users/$user + dscl . -create /Users/$user UserShell /bin/bash + dscl . -create /Users/$user RealName "$user" + dscl . -create /Users/$user UniqueID $uid + dscl . -create /Users/$user PrimaryGroupID $gid + dscl . -create /Users/$user NFSHomeDirectory /Users/$user + dscl . -passwd /Users/$user "$passwd" + mkdir /Users/$user + chown $uid.$gid /Users/$user + +. + + +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_pkg_type=bundle + pp_macos_pkg_background= + pp_macos_pkg_background_dark= + pp_macos_pkg_license= + pp_macos_pkg_readme= + pp_macos_pkg_welcome= + pp_macos_sudo=sudo + pp_macos_installer_plugin= + # OS X puts the library version *before* the .dylib extension + pp_shlib_suffix='*.dylib' +} + +pp_macos_plist () { + typeset in + in="" + while test $# -gt 0; do + case "$1" in + + start-plist) cat <<-.; in=" "; shift ;; + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> +. + end-plist) echo "</plist>"; in=; shift;; + + '[') echo "$in<array>"; in="$in "; shift;; + ']') echo "$in</array>"; in="${in# }"; shift;; + '{') echo "<dict>"; in="$in "; shift;; + '}') echo "</dict>"; in="${in# }"; shift;; + key) shift; echo "$in<key>$1</key>"; shift;; + string) shift; + echo "$1" | sed -e 's/&/&/g;s/</\</g;s/>/\>/g;' \ + -e 's/^/'"$in"'<string>/;s/$/<\/string>/'; + shift;; + true) echo "$in<true/>"; shift;; + false) echo "$in<false/>"; shift;; + real) shift; echo "$in<real>$1</real>"; shift;; + integer) shift; echo "$in<integer>$1</integer>"; shift;; + date) shift; echo "$in<date>$1</date>"; shift;; # ISO 8601 format + data) shift; echo "$in<data>$1</data>"; shift;; # base64 encoded + *) pp_error "pp_macos_plist: bad argument '$1'"; shift;; + esac + done +} + +pp_macos_rewrite_cpio () { + typeset script + script=$pp_wrkdir/cpio-rewrite.pl + cat <<-'.' >$script + #!/usr/bin/perl + # + # Filter a cpio file, applying the user/group/mode specified in %files + # + # A CPIO header block has octal fields at the following offset/lengths: + # 0 6 magic + # 6 6 dev + # 12 6 ino + # 18 6 mode + # 24 6 uid + # 30 6 gid + # 36 6 nlink + # 42 6 rdev + # 48 11 mtime + # 59 6 namesize (including NUL terminator) + # 65 11 filesize + # 76 -- + # + use strict; + use warnings; + no strict 'subs'; + + # set %uid, %gid, %mode based on %files + my (%uid, %gid, %mode, %users, %groups); + my %type_map = ( d => 0040000, f => 0100000, s => 0120000 ); + while (<DATA>) { + my ($type,$mode,$uid,$gid,$flags,$name) = + m/^(.) (\S+) (\S+) (\S+) (\S+) (\S+)/; + $mode = $type eq "f" ? "0644" : "0755" if $mode eq "-"; + $uid = 0 if $uid eq "-"; + $gid = 0 if $gid eq "-"; + if ($uid ne "=" and $uid =~ m/\D/) { + unless (exists $users{$uid}) { + my @pw = getpwnam($uid) or die "bad username '$uid'"; + $users{$uid} = $pw[2]; + } + $uid = $users{$uid}; + } + if ($gid ne "=" and $gid =~ m/\D/) { + unless (exists $groups{$gid}) { + my @gr = getgrnam($gid) or die "bad group'$gid'"; + $groups{$gid} = $gr[2]; + } + $gid = $groups{$gid}; + } + $name =~ s:/$:: if $type eq "d"; + $name = ".".$name."\0"; + $uid{$name} = sprintf("%06o",int($uid)) unless $uid eq "="; + $gid{$name} = sprintf("%06o",int($gid)) unless $gid eq "="; + $mode{$name} = sprintf("%06o",oct($mode)|$type_map{$type}) unless $mode eq "="; + } + undef %users; + undef %groups; + # parse the cpio file + my $hdrlen = 76; + while (read(STDIN, my $header, $hdrlen)) { + my ($name, $namesize, $filesize); + my $filepad = 0; + if ($header =~ m/^07070[12]/) { + # SVR4 ASCII format, convert to ODC + if ($hdrlen == 76) { + # Read in rest of header and update header len for SVR4 + read(STDIN, $header, 110 - 76, 76); + $hdrlen = 110; + } + my $ino = hex(substr($header, 6, 8)) & 0x3ffff; + my $mode = hex(substr($header, 14, 8)) & 0x3ffff; + my $uid = hex(substr($header, 22, 8)) & 0x3ffff; + my $gid = hex(substr($header, 30, 8)) & 0x3ffff; + my $nlink = hex(substr($header, 38, 8)) & 0x3ffff; + my $mtime = hex(substr($header, 46, 8)) & 0xffffffff; + $filesize = hex(substr($header, 54, 8)) & 0xffffffff; + my $dev_maj = hex(substr($header, 62, 8)); + my $dev_min = hex(substr($header, 70, 8)); + my $dev = &makedev($dev_maj, $dev_min) & 0x3ffff; + my $rdev_maj = hex(substr($header, 78, 8)); + my $rdev_min = hex(substr($header, 86, 8)); + my $rdev = &makedev($rdev_maj, $rdev_min) & 0x3ffff; + $namesize = hex(substr($header, 94, 8)) & 0x3ffff; + read(STDIN, $name, $namesize); + # Header + name is padded to a multiple of 4 bytes + my $namepad = (($hdrlen + $namesize + 3) & 0xfffffffc) - ($hdrlen + $namesize); + read(STDIN, my $padding, $namepad) if ($namepad); + # File data is padded to be a multiple of 4 bytes + $filepad = (($filesize + 3) & 0xfffffffc) - $filesize; + + my $new_header = sprintf("070707%06o%06o%06o%06o%06o%06o%06o%011o%06o%011o", $dev, $ino, $mode, $uid, $gid, $nlink, $rdev, $mtime, $namesize, $filesize); + $header = $new_header; + } elsif ($header =~ m/^070707/) { + # POSIX Portable ASCII Format + $namesize = oct(substr($header, 59, 6)); + $filesize = oct(substr($header, 65, 11)); + read(STDIN, $name, $namesize); + } else { + die "bad magic"; + } + # update uid, gid and mode (already in octal) + substr($header, 24, 6) = $uid{$name} if exists $uid{$name}; + substr($header, 30, 6) = $gid{$name} if exists $gid{$name}; + substr($header, 18, 6) = $mode{$name} if exists $mode{$name}; + print($header, $name); + # check for trailer at EOF + last if $filesize == 0 && $name =~ /^TRAILER!!!\0/; + # copy-through the file data + while ($filesize > 0) { + my $seg = 8192; + $seg = $filesize if $filesize < $seg; + read(STDIN, my $data, $seg); + print $data; + $filesize -= $seg; + } + # If file data is padded, skip it + read(STDIN, my $padding, $filepad) if ($filepad); + } + # pass through any padding at the end (blocksize-dependent) + for (;;) { + my $numread = read(STDIN, my $data, 8192); + last unless $numread; + print $data; + } + exit(0); + + sub makedev { + (((($_[0] & 0xff)) << 24) | ($_[1] & 0xffffff)); + } + __DATA__ +. + # Append to the script the %files data + cat "$@" </dev/null >> $script + /usr/bin/perl $script || pp_error "pp_macos_rewrite_cpio error"; +} + +pp_macos_files_bom () { + typeset _l t m o g f p st owner + while read t m o g f p st; do + # make sure that $m is padded up to 4 digits long + case "$m" in + ?) m="000$m";; + ??) m="00$m";; + ???) m="0$m";; + ?????*) pp_error "pp_macos_writebom: mode '$m' too long";; + esac + + # convert owner,group into owner/group in octal + case $o in -) o=0;; esac + case $g in -) g=0;; esac + owner=`pp_d2o $o`/`pp_d2o $g` + + case $t in + f) + test x"$m" = x"000-" && m=0644 + echo ".$p 10$m $owner ` + /usr/bin/cksum < "${pp_destdir}$p" | + awk '{print $2 " " $1}'`" + ;; + d) + test x"$m" = x"000-" && m=0755 + echo ".${p%/} 4$m $owner" + ;; + s) + test x"$m" = x"000-" && m=0755 + rl=`/usr/bin/readlink "${pp_destdir}$p"` + #test x"$rl" = x"$st" || + # pp_error "symlink mismatch $rl != $st" + echo ".$p 12$m $owner ` + /usr/bin/readlink -n "${pp_destdir}$p" | + /usr/bin/cksum | + awk '{print $2 " " $1}'` $st" + ;; + esac + done +} + +pp_macos_bom_fix_parents () { + perl -pe ' + sub dirname { my $d=shift; $d=~s,/[^/]*$,,; $d; } + sub chk { my $d=shift; + &chk(&dirname($d)) if $d =~ m,/,; + unless ($seen{$d}++) { + # Make sure we do not override system directories + if ($d =~ m:^\./(etc|var)$:) { + my $tgt = "private/$1"; + my ($sum, $len) = split(/\s+/, `/usr/bin/printf "$tgt" | /usr/bin/cksum /dev/stdin`); + print "$d\t120755\t0/0\t$len\t$sum\t$tgt\n"; + } elsif ($d eq "." || $d eq "./Library") { + print "$d\t41775\t0/80\n"; + } elsif ($d eq "./Applications" || $d eq "./Developer") { + print "$d\t40775\t0/80\n"; + } else { + print "$d\t40755\t0/0\n"; + } + } + } + m/^(\S+)\s+(\d+)/; + if (oct($2) & 040000) { + $seen{$1}++; # directory + } + &chk(&dirname($1));' +} + +pp_macos_files_size () { + typeset _l t m o g f p st owner + while read t m o g f p st; do + case $t in + f) wc -c < "${pp_destdir}$p";; + s) echo 4095;; + d) ;; # always seems to be zero + esac + done | awk '{n+=1+int($1/4096)} END {print n*4}' +} + +pp_o2d () { + awk 'BEGIN { x=0; '`echo "$1" | + sed -e 's/./x=x*8+&;/g'`'print x;}' </dev/null +} +pp_d2o () { + case "$1" in + [0-7]) echo $1;; + *) awk 'BEGIN { printf("%o\n", 0+('"$1"'));}' < /dev/null;; + esac +} + +pp_macos_mkbom () { + #/usr/bin/mkbom -i $1 $2 + typeset path mode ugid size cksum linkpath + typeset bomstage + + # Use mkbom if it understands -i (avoids a copy) + if /usr/bin/mkbom -i /dev/null "$2" 2>/dev/null; then + rm -f "$2" + /usr/bin/mkbom -i "$1" "$2" + return + fi + + # On 10.4 we have this nonsense. + pp_warn "mkbom workaround: copying source files to staging area" + + bomstage=$pp_wrkdir/bom_stage + $pp_macos_sudo /bin/mkdir "$bomstage" + while IFS=' ' read path mode ugid size cksumi linkpath; do + if test -h "$pp_destdir/$path"; then + $pp_macos_sudo /bin/ln -s "$linkpath" "$bomstage/$path" + else + if test -d "$pp_destdir/$path"; then + $pp_macos_sudo /bin/mkdir -p "$bomstage/$path" + else + $pp_macos_sudo /bin/cp "$pp_destdir/$path" "$bomstage/$path" + fi + $pp_macos_sudo /bin/chmod $mode "$bomstage/$path" + $pp_macos_sudo /usr/sbin/chown `echo $ugid| tr / :` "$bomstage/$path" + fi + done <"$1" + (cd $bomstage && $pp_macos_sudo mkbom . $pp_wrkdir/bom_stage.bom) || + pp_error "mkbom failed" + $pp_macos_sudo mv $pp_wrkdir/bom_stage.bom "$2" +} + +pp_backend_macos () { + : ${pp_macos_bundle_id:=$pp_macos_default_bundle_id_prefix$name} + case "$pp_macos_pkg_type" in + bundle) pp_backend_macos_bundle;; + flat) pp_backend_macos_flat;; + *) pp_error "unsupported package type $pp_macos_pkg_type";; + esac +} + +pp_backend_macos_bundle () { + typeset pkgdir Contents Resources lprojdir svc + typeset Info_plist Description_plist + typeset bundle_vendor bundle_version size cmp filelists + + mac_version=`sw_vers -productVersion` + bundle_vendor=${pp_macos_bundle_vendor:-$vendor} + + 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'` + else + bundle_version="$pp_macos_bundle_version" + fi + source_version=`echo $version | sed 's/.*\.//'` + + # build the package layout + pkgdir=$pp_wrkdir/$name.pkg + Contents=$pkgdir/Contents + Resources=$Contents/Resources + lprojdir=$Resources/en.lproj + mkdir $pkgdir $Contents $Resources $lprojdir || + pp_error "Can't make package temporary directories" + + echo "major: 1" > $Resources/package_version + echo "minor: 0" >> $Resources/package_version + echo "pmkrpkg1" > $Contents/PkgInfo + case $mac_version in + "10.6"*) + xattr -w "com.apple.TextEncoding" "macintosh;0" "$Resources/package_version" + xattr -w "com.apple.TextEncoding" "macintosh;0" "$Contents/PkgInfo" + ;; + esac + + # Copy welcome file/dir for display at package install time. + if test -n "$pp_macos_pkg_welcome"; then + typeset sfx + sfx=`echo "$pp_macos_pkg_welcome"|sed 's/^.*\.\([^\.]*\)$/\1/'` + case "$sfx" in + rtf|html|rtfd|txt) ;; + *) sfx=txt;; + esac + cp -R ${pp_macos_pkg_welcome} $Resources/Welcome.$sfx + fi + + # Copy readme file/dir for display at package install time. + if test -n "$pp_macos_pkg_readme"; then + typeset sfx + sfx=`echo "$pp_macos_pkg_readme"|sed 's/^.*\.\([^\.]*\)$/\1/'` + case "$sfx" in + rtf|html|rtfd|txt) ;; + *) sfx=txt;; + esac + cp -R ${pp_macos_pkg_readme} $Resources/ReadMe.$sfx + fi + + # Copy license file/dir for display at package install time. + if test -n "$pp_macos_pkg_license"; then + typeset sfx + sfx=`echo "$pp_macos_pkg_license"|sed 's/^.*\.\([^\.]*\)$/\1/'` + case "$sfx" in + rtf|html|rtfd|txt) ;; + *) sfx=txt;; + esac + cp -R ${pp_macos_pkg_license} $Resources/License.$sfx + fi + + # Add services (may modify %files) + for svc in $pp_services .; do + test . = "$svc" && continue + pp_macos_add_service $svc + done + + # Find file lists (%files.* includes ignore files) + for cmp in $pp_components; do + test -f $pp_wrkdir/%files.$cmp && filelists="$filelists${filelists:+ }$pp_wrkdir/%files.$cmp" + done + + # compute the installed size + size=`cat $filelists | pp_macos_files_size` + + #-- Create Info.plist + Info_plist=$Contents/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}" \ + key CFBundleName string "$name" \ + key CFBundleShortVersionString string "$bundle_version.$source_version" \ + key IFMajorVersion integer 1 \ + key IFMinorVersion integer 0 \ + key IFPkgFlagAllowBackRev false \ + key IFPkgFlagAuthorizationAction string "RootAuthorization" \ + key IFPkgFlagDefaultLocation string "/" \ + key IFPkgFlagFollowLinks true \ + key IFPkgFlagInstallFat true \ + key IFPkgFlagInstalledSize integer $size \ + key IFPkgFlagIsRequired false \ + key IFPkgFlagOverwritePermissions true \ + key IFPkgFlagRelocatable false \ + key IFPkgFlagRestartAction string "NoRestart" \ + key IFPkgFlagRootVolumeOnly true \ + key IFPkgFlagUpdateInstalledLanguages false \ + key IFPkgFlagUseUserMask false \ + key IFPkgFormatVersion real 0.10000000149011612 \ + key SourceVersion string $source_version \ + \} end-plist> $Info_plist + + # write en.lproj/Description.plist + Description_plist=$lprojdir/Description.plist + pp_macos_plist \ + start-plist \{ \ + key IFPkgDescriptionDeleteWarning string "" \ + key IFPkgDescriptionDescription string "$pp_macos_bundle_info_string" \ + key IFPkgDescriptionTitle string "$name" \ + key IFPkgDescriptionVersion string "$bundle_version.$source_version" \ + \} end-plist > $Description_plist + + # write Resources/files + awk '{print $6}' $filelists > $Resources/files + + # write package size file + printf \ +"NumFiles 0 +InstalledSize $size +CompressedSize 0 +" > $Resources/$name.sizes + + # write Resources/preinstall + for cmp in $pp_components; do + if test -s $pp_wrkdir/%pre.$cmp; then + if test ! -s $Resources/preinstall; then + echo "#!/bin/sh" > $Resources/preinstall + chmod +x $Resources/preinstall + fi + cat $pp_wrkdir/%pre.$cmp >> $Resources/preinstall + echo : >> $Resources/preinstall + fi + done + + # write Resources/postinstall + for cmp in $pp_components; do + if test -s $pp_wrkdir/%post.$cmp; then + if test ! -s $Resources/postinstall; then + echo "#!/bin/sh" > $Resources/postinstall + chmod +x $Resources/postinstall + fi + cat $pp_wrkdir/%post.$cmp >> $Resources/postinstall + echo : >> $Resources/postinstall + fi + done + + # write Resources/postupgrade + for cmp in $pp_components; do + if test -s $pp_wrkdir/%postup.$cmp; then + if test ! -s $Resources/postupgrade; then + echo "#!/bin/sh" > $Resources/postupgrade + chmod +x $Resources/postupgrade + fi + cat $pp_wrkdir/%postup.$cmp >> $Resources/postupgrade + echo : >> $Resources/postupgrade + fi + done + + # write Resources/preremove + for cmp in $pp_components; do + if test -s $pp_wrkdir/%preun.$cmp; then + if test ! -s $Resources/preremove; then + echo "#!/bin/sh" > $Resources/preremove + chmod +x $Resources/preremove + fi + cat $pp_wrkdir/%preun.$cmp >> $Resources/preremove + echo : >> $Resources/preremove + fi + done + + # write Resources/postremove + for cmp in $pp_components; do + if test -s $pp_wrkdir/%postun.$cmp; then + if test ! -s $Resources/postremove; then + echo "#!/bin/sh" > $Resources/postremove + chmod +x $Resources/postremove + fi + cat $pp_wrkdir/%postun.$cmp >> $Resources/postremove + echo : >> $Resources/postremove + fi + done + + # write uninstall info + echo "version=$version" > $Resources/uninstall + if [ -n "$pp_macos_requires" ];then + echo "requires=$pp_macos_requires" >> $Resources/uninstall + fi + + . $pp_wrkdir/%fixup + + # Create the bill-of-materials (Archive.bom) + cat $filelists | pp_macos_files_bom | sort | + pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls + + pp_macos_mkbom $pp_wrkdir/tmp.bomls $Contents/Archive.bom + + # Create the cpio archive (Archive.pax.gz) + ( + cd $pp_destdir && + awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $Contents/Archive.pax.gz + ) + + # Copy installer plugins if any + if test -n "$pp_macos_installer_plugin"; then + if test ! -f "$pp_macos_installer_plugin/InstallerSections.plist"; then + pp_error "Missing InstallerSections.plist file in $pp_macos_installer_plugin" + fi + mkdir -p $pkgdir/Plugins + cp -R "$pp_macos_installer_plugin"/* $pkgdir/Plugins + fi + + test -d $pp_wrkdir/bom_stage && $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage + + rm -f ${name}-${version}.dmg + hdiutil create -fs HFS+ -srcfolder $pkgdir -volname $name ${name}-${version}.dmg +} + +pp_backend_macos_flat () { + typeset pkgdir bundledir Resources lprojdir svc + typeset Info_plist Description_plist + typeset bundle_vendor bundle_version size numfiles cmp filelists + + mac_version=`sw_vers -productVersion` + bundle_vendor=${pp_macos_bundle_vendor:-$vendor} + + 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'` + else + bundle_version="$pp_macos_bundle_version" + fi + source_version=`echo $version | sed 's/.*\.//'` + + # build the flat package layout + pkgdir=$pp_wrkdir/pkg + pkgfile=$name-$version.pkg + bundledir=$pp_wrkdir/pkg/$pkgfile + Resources=$pkgdir/Resources + lprojdir=$Resources/en.lproj + mkdir $pkgdir $bundledir $Resources $lprojdir || + pp_error "Can't make package temporary directories" + + # Add services (may modify %files) + for svc in $pp_services .; do + test . = "$svc" && continue + pp_macos_add_service $svc + done + + # Find file lists (%files.* includes ignore files) + for cmp in $pp_components; do + test -f $pp_wrkdir/%files.$cmp && filelists="$filelists${filelists:+ }$pp_wrkdir/%files.$cmp" + done + + # compute the installed size and number of files/dirs + size=`cat $filelists | pp_macos_files_size` + numfiles=`cat $filelists | wc -l` + numfiles="${numfiles##* }" + + # Write Distribution file + cat <<-. >$pkgdir/Distribution + <?xml version="1.0" encoding="UTF-8"?> + <installer-gui-script minSpecVersion="1"> + <title>$name $version</title> + <options customize="never" allow-external-scripts="no"/> + <domains enable_localSystem="true"/> +. + if test -n "$pp_macos_pkg_welcome"; then + cp -R "${pp_macos_pkg_welcome}" $Resources + echo " <welcome file=\"${pp_macos_pkg_welcome##*/}\"/>" >>$pkgdir/Distribution + fi + if test -n "$pp_macos_pkg_readme"; then + cp -R "${pp_macos_pkg_readme}" $Resources + echo " <readme file=\"${pp_macos_pkg_readme##*/}\"/>" >>$pkgdir/Distribution + fi + if test -n "$pp_macos_pkg_license"; then + cp -R "${pp_macos_pkg_license}" $Resources + echo " <license file=\"${pp_macos_pkg_license##*/}\"/>" >>$pkgdir/Distribution + fi + if test -n "$pp_macos_pkg_background"; then + cp -R "${pp_macos_pkg_background}" $Resources + echo " <background file=\"${pp_macos_pkg_background##*/}\" scaling=\"proportional\" alignment=\"left\"/>" >>$pkgdir/Distribution + fi + if test -n "$pp_macos_pkg_background_dark"; then + cp -R "${pp_macos_pkg_background_dark}" $Resources + echo " <background-darkAqua file=\"${pp_macos_pkg_background_dark##*/}\" scaling=\"proportional\" alignment=\"left\"/>" >>$pkgdir/Distribution + fi + cat <<-. >>$pkgdir/Distribution + <choices-outline> + <line choice="choice0"/> + </choices-outline> + <choice id="choice0" title="$name $version"> + <pkg-ref id="${pp_macos_bundle_id}"/> + </choice> + <pkg-ref id="${pp_macos_bundle_id}" installKBytes="$size" version="$version" auth="Root">#$pkgfile</pkg-ref> + </installer-gui-script> +. + + # write scripts archive + # XXX - missing preupgrade, preflight, postflight + mkdir $pp_wrkdir/scripts + for cmp in $pp_components; do + if test -s $pp_wrkdir/%pre.$cmp; then + if test ! -s $pp_wrkdir/scripts/preinstall; then + echo "#!/bin/sh" > $pp_wrkdir/scripts/preinstall + chmod +x $pp_wrkdir/scripts/preinstall + fi + cat $pp_wrkdir/%pre.$cmp >> $pp_wrkdir/scripts/preinstall + echo : >> $pp_wrkdir/scripts/preinstall + fi + if test -s $pp_wrkdir/%post.$cmp; then + if test ! -s $pp_wrkdir/scripts/postinstall; then + echo "#!/bin/sh" > $pp_wrkdir/scripts/postinstall + chmod +x $pp_wrkdir/scripts/postinstall + fi + cat $pp_wrkdir/%post.$cmp >> $pp_wrkdir/scripts/postinstall + echo : >> $pp_wrkdir/scripts/postinstall + fi + if test -s $pp_wrkdir/%postup.$cmp; then + if test ! -s $pp_wrkdir/scripts/postupgrade; then + echo "#!/bin/sh" > $pp_wrkdir/scripts/postupgrade + chmod +x $pp_wrkdir/scripts/postupgrade + fi + cat $pp_wrkdir/%postup.$cmp >> $pp_wrkdir/scripts/postupgrade + echo : >> $pp_wrkdir/scripts/postupgrade + fi + # XXX - not supported + if test -s $pp_wrkdir/%preun.$cmp; then + if test ! -s $pp_wrkdir/scripts/preremove; then + echo "#!/bin/sh" > $pp_wrkdir/scripts/preremove + chmod +x $pp_wrkdir/scripts/preremove + fi + cat $pp_wrkdir/%preun.$cmp >> $pp_wrkdir/scripts/preremove + echo : >> $pp_wrkdir/scripts/preremove + fi + # XXX - not supported + if test -s $pp_wrkdir/%postun.$cmp; then + if test ! -s $pp_wrkdir/scripts/postremove; then + echo "#!/bin/sh" > $pp_wrkdir/scripts/postremove + chmod +x $pp_wrkdir/scripts/postremove + fi + cat $pp_wrkdir/%postun.$cmp >> $pp_wrkdir/scripts/postremove + echo : >> $pp_wrkdir/scripts/postremove + fi + done + if test "`echo $pp_wrkdir/scripts/*`" != "$pp_wrkdir/scripts/*"; then + # write scripts archive, scripts are mode 0755 uid/gid 0/0 + # resetting the owner and mode is not strictly required + ( + cd $pp_wrkdir/scripts || pp_error "Can't cd to $pp_wrkdir/scripts" + rm -f $pp_wrkdir/tmp.files.scripts + for s in *; do + echo "f 0755 0 0 - ./$s" >>$pp_wrkdir/tmp.files.scripts + done + find . -type f | /usr/bin/cpio -o | pp_macos_rewrite_cpio $pp_wrkdir/tmp.files.scripts | gzip -9f -c > $bundledir/Scripts + ) + fi + + # Write PackageInfo file + cat <<-. >$bundledir/PackageInfo + <?xml version="1.0" encoding="UTF-8"?> + <pkg-info format-version="2" identifier="${pp_macos_bundle_id}" version="$version" install-location="/" relocatable="false" overwrite-permissions="true" followSymLinks="true" auth="root"> + <payload installKBytes="$size" numberOfFiles="$numfiles"/> +. + if test -s $bundledir/Scripts; then + echo " <scripts>" >>$bundledir/PackageInfo + for s in preflight postflight preinstall postinstall preupgrade postupgrade; do + if test -s "$pp_wrkdir/scripts/$s"; then + echo " <$s file=\"$s\"/>" >>$bundledir/PackageInfo + fi + done + echo " </scripts>" >>$bundledir/PackageInfo + fi + cat <<-. >>$bundledir/PackageInfo + </pkg-info> +. + + . $pp_wrkdir/%fixup + + # Create the bill-of-materials (Bom) + cat $filelists | pp_macos_files_bom | sort | + pp_macos_bom_fix_parents > $pp_wrkdir/tmp.bomls + pp_macos_mkbom $pp_wrkdir/tmp.bomls $bundledir/Bom + + # Create the cpio payload + ( + cd $pp_destdir || pp_error "Can't cd to $pp_destdir" + awk '{ print "." $6 }' $filelists | sed 's:/$::' | sort | /usr/bin/cpio -o | pp_macos_rewrite_cpio $filelists | gzip -9f -c > $bundledir/Payload + ) + awk '{print $6}' $filelists > $name.files + + # Copy installer plugins if any + if test -n "$pp_macos_installer_plugin"; then + if test ! -f "$pp_macos_installer_plugin/InstallerSections.plist"; then + pp_error "Missing InstallerSections.plist file in $pp_macos_installer_plugin" + fi + mkdir -p $pkgdir/Plugins + cp -R "$pp_macos_installer_plugin"/* $pkgdir/Plugins + fi + + test -d $pp_wrkdir/bom_stage && $pp_macos_sudo rm -rf $pp_wrkdir/bom_stage + + # Create the flat package with xar (like pkgutil --flatten does) + # Note that --distribution is only supported by macOS 10.6 and above + xar_flags="--compression=bzip2 --no-compress Scripts --no-compress Payload" + case $mac_version in + "10.5"*) ;; + *) xar_flags="$xar_flags --distribution";; + esac + (cd $pkgdir && /usr/bin/xar $xar_flags -cf "../$pkgfile" *) + + echo "version=$version" > $name.uninstall +} + +pp_backend_macos_cleanup () { + : +} + +pp_backend_macos_names () { + case "$pp_macos_pkg_type" in + bundle) echo ${name}.pkg;; + flat) echo ${name}-${version}.pkg;; + *) pp_error "unsupported package type $pp_macos_pkg_type";; + esac +} + +pp_backend_macos_install_script () { + echo '#!/bin/sh' + typeset pkgname platform + + pkgname="`pp_backend_macos_names`" + platform="`pp_backend_macos_probe`" + pp_install_script_common + + cat <<. + 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 + vol=/Volumes/pp\$\$ + pkg=\$vol/${name}-${version}.pkg + hdiutil attach -readonly -mountpoint \$vol \ + \${PP_PKGDESTDIR:-.}/"$pkgname" + trap "hdiutil detach \$vol" 0 + installer -pkginfo -pkg \$pkg + installer -verbose -pkg \$pkg -target / + ;; + uninstall) + test \$# -ge 1 || usage \$op + # XXX + echo "Uninstall not implemented" >&2 + exit 1;; + start|stop) + test \$# -ge 1 || usage \$op + ec=0 + for svc + do + # XXX + echo "\${op} not implemented" >&2 + ec=1 + done + exit \$ec + ;; + print-platform) + echo "$platform" + ;; + *) + usage;; + esac +. +} + +pp_backend_macos_init_svc_vars () { + pp_macos_start_services_after_install=true + pp_macos_service_name= + pp_macos_default_service_id_prefix="com.quest.rc." + pp_macos_service_id= + pp_macos_service_user= + pp_macos_service_group= + pp_macos_service_initgroups= + pp_macos_service_umask= + pp_macos_service_cwd= + pp_macos_service_nice= + pp_macos_svc_plist_file= +} + +pp_macos_launchd_plist () { + typeset svc svc_id + + svc="$1" + svc_id="$2" + + set -- $cmd + + if [ -n "$pp_macos_svc_plist_file" ]; then + echo "## Launchd plist file already defined at $pp_macos_svc_plist_file" + return + fi + + echo "## Generating the launchd plist file for $svc" + pp_macos_svc_plist_file="$pp_wrkdir/$svc.plist" + cat <<-. > $pp_macos_svc_plist_file + <?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"> + <dict> + <key>Label</key> + <string>$svc_id</string> + <key>ProgramArguments</key> + <array> +. + while test $# != 0; do + printf " <string>$1</string>\n" >> $pp_macos_svc_plist_file + shift + done + cat <<-. >> $pp_macos_svc_plist_file + </array> + <key>KeepAlive</key> + <true/> +. + if test -n "$pp_macos_service_user"; then + printf " <key>UserName</key>\n" >> $pp_macos_svc_plist_file + printf " <string>$pp_macos_service_user</string>\n" >> $pp_macos_svc_plist_file + fi + if test -n "$pp_macos_service_group"; then + printf " <key>GroupName</key>\n" >> $pp_macos_svc_plist_file + printf " <string>$pp_macos_service_group</string>\n" >> $pp_macos_svc_plist_file + fi + if test -n "$pp_macos_service_initgroups"; then + printf " <key>InitGroups</key>\n" >> $pp_macos_svc_plist_file + printf " <string>$pp_macos_service_initgroups</string>\n" >> $pp_macos_svc_plist_file + fi + if test -n "$pp_macos_service_umask"; then + printf " <key>Umask</key>\n" >> $pp_macos_svc_plist_file + printf " <string>$pp_macos_service_umask</string>\n" >> $pp_macos_svc_plist_file + fi + if test -n "$pp_macos_service_cwd"; then + printf " <key>WorkingDirectory</key>\n" >> $pp_macos_svc_plist_file + printf " <string>$pp_macos_service_cwd</string>\n" >> $pp_macos_svc_plist_file + fi + if test -n "$pp_macos_service_nice"; then + printf " <key>Nice</key>\n" >> $pp_macos_svc_plist_file + printf " <string>$pp_macos_service_nice</string>\n" >> $pp_macos_svc_plist_file + fi + cat <<-. >> $pp_macos_svc_plist_file + </dict> + </plist> +. +} + +pp_macos_add_service () { + typeset svc svc_id plist_file plist_dir + + pp_load_service_vars "$1" + svc=${pp_macos_service_name:-$1} + svc_id=${pp_macos_service_id:-$pp_macos_default_service_id_prefix$svc} + + #-- create a plist file for svc + pp_macos_launchd_plist "$svc" "$svc_id" + + #-- copy the plist file into place and add to %files + plist_dir="/Library/LaunchDaemons" + plist_file="$plist_dir/$svc_id.plist" + mkdir -p "$pp_destdir/$plist_dir" + cp "$pp_macos_svc_plist_file" "$pp_destdir/$plist_file" + pp_add_file_if_missing "$plist_file" + + #-- add code to start the service on install & upgrade + ${pp_macos_start_services_after_install} && <<-. >> $pp_wrkdir/%post.$svc + # start service '$svc' automatically after install + launchctl load "$plist_file" +. + ${pp_macos_start_services_after_install} && <<-. >> $pp_wrkdir/%postup.$svc + # start service '$svc' automatically after upgrade + # This is necessary if the service is new since the previous version. + # XXX: Does launchd automatically reload an service if its binary + # is replaced? + launchctl load "$plist_file" +. +} + +pp_backend_macos_probe () { + typeset name vers arch + case `sw_vers -productName` in + "macOS") name="macos";; + "Mac OS X") name="macos";; + *) name="unknown";; + esac + vers=`sw_vers -productVersion | awk -F. '{ printf "%d%02d\n", $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_backend_macos_function () { + case "$1" in + _pp_macos_search_unused) cat<<'.';; + # Find an unused value in the given path + # args: path attribute minid [maxid] + pp_tmp_val=$3 + while :; do + test $pp_tmp_val -ge ${4:-999999} && return 1 + /usr/bin/dscl . -search "$1" "$2" $pp_tmp_val | + grep . > /dev/null || break + pp_tmp_val=`expr $pp_tmp_val + 1` + done + echo $pp_tmp_val +. + pp_mkgroup:depends) echo _pp_macos_search_unused;; + pp_mkgroup) cat<<'.';; + set -e + /usr/bin/dscl . -read /Groups/"$1" >/dev/null 2>&1 && return + pp_tmp_gid=`_pp_macos_search_unused /Groups PrimaryGroupID 100` + /usr/bin/dscl . -create /Groups/"$1" + /usr/bin/dscl . -create /Groups/"$1" PrimaryGroupID $pp_tmp_gid + /usr/bin/dscl . -create /Groups/"$1" RealName "Group $1" + /usr/bin/dscl . -create /Groups/"$1" GroupMembership "" + /usr/bin/dscl . -create /Groups/"$1" Password '*' +. + pp_mkuser:depends) echo pp_mkgroup _pp_macos_search_unused;; + pp_mkuser) cat<<'.';; + set -e + /usr/bin/dscl . -read /Users/"$1" >/dev/null 2>&1 && return + pp_tmp_uid=`_pp_macos_search_unused /Users UniqueID 100` + pp_mkgroup "${2:-$1}" + pp_tmp_gid=`/usr/bin/dscl . -read /Groups/"${2:-$1}" \ + PrimaryGroupID | awk '{print $2}'` + /usr/bin/dscl . -create /Users/"$1" + /usr/bin/dscl . -create /Users/"$1" PrimaryGroupID $pp_tmp_gid + /usr/bin/dscl . -create /Users/"$1" NFSHomeDirectory \ + "${3:-/var/empty}" + /usr/bin/dscl . -create /Users/"$1" UserShell \ + "${4:-/usr/bin/false}" + /usr/bin/dscl . -create /Users/"$1" RealName "$1" + /usr/bin/dscl . -create /Users/"$1" UniqueID $pp_tmp_uid + /usr/bin/dscl . -create /Users/"$1" Password '*' +. + pp_havelib) cat<<'.';; + # (use otool -L to find dependent libraries) + for pp_tmp_dir in `echo "${3:+$3:}/usr/local/lib:/lib:/usr/lib" | + tr : ' '`; do + test -r "$pp_tmp_dir/lib$1{$2:+.$2}.dylib" && return 0 + done + return 1 +. + *) false;; + esac +} + +pp_platforms="$pp_platforms inst" + +pp_backend_inst_detect () { + case "$1" in + IRIX*) return 0;; + *) return 1;; + esac +} + +pp_backend_inst_init () { + pp_readlink_fn=pp_ls_readlink +} + +pp_backend_inst_create_idb() +{ + typeset t m o g f p st + + while read t m o g f p st; do + if test x"$o" = x"-"; then + o="root" + fi + if test x"$g" = x"-"; then + g="sys" + fi + case "$t" in + f) test x"$m" = x"-" && m=444 + echo "f 0$m $o $g $p $p $name.sw.base" + ;; + d) test x"$m" = x"-" && m=555 + echo "d 0$m $o $g $p $p $name.sw.base" + ;; + 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 "l 0$m $o $g $p $p $name.sw.base symval($st)" + ;; + esac + done +} + +pp_backend_inst_create_spec() +{ + echo "product $name" + echo " id \"${summary}. Version: ${version}\"" + echo " image sw" + echo " id \"Software\"" + echo " version $version" + echo " order 9999" + echo " subsys base" + echo " id \"Base Software\"" + echo " replaces self" + echo " exp $name.sw.base" + echo " endsubsys" + echo " endimage" + echo "endproduct" +} + +pp_backend_inst () { + curdir=`pwd` + + cd "$pp_opt_wrkdir" + + # initialize + pp_inst_tardist=tardist + pp_inst_spec=${name}.spec + pp_inst_idb=${name}.idb + + rm -rf $pp_inst_tardist $pp_inst_spec $pp_inst_idb + mkdir -p $pp_inst_tardist + + # Create idb file + (for _cmp in $pp_components; do + cat %files.$_cmp | sort +4u -6 | pp_backend_inst_create_idb + done) >> $pp_inst_idb + + pp_backend_inst_create_spec >> $pp_inst_spec + + # Generate tardist + gendist -verbose -all -root / -source $pp_opt_destdir -idb $pp_inst_idb -spec $pp_inst_spec -dist $pp_inst_tardist $name + tar -cvf `pp_backend_inst_names` $pp_inst_tardist + + cd "$curdir" +} + +pp_backend_inst_cleanup () { + : +} + +pp_backend_inst_names () { + echo ${name}-${version}.tardist +} + +pp_backend_inst_install_script () { + : +} + +pp_backend_inst_function () { + echo false +} + +pp_backend_inst_init_svc_vars () { + : +} + +pp_backend_inst_probe () { + cpu=`hinv|sed -n '/^CPU/{s/000 /k /;s/^CPU: //;s/ Process.*//;s/^MIPS //;p;q;}'|tr A-Z a-z` + echo irix`uname -r`-$cpu +} + +pp_backend_inst_vas_platforms () { + echo "irix-65" +} + +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 +} + +pp_backend_null_vas_platforms () { +: +} + +pp_platforms="$pp_platforms bsd" + +pp_bsd_munge_text () { + # Insert a leading space on each line, replace blank lines with a + #space followed by a full-stop. + test -z "$1" && pp_die "pp_bsd_munge_text requires a parameter" + echo ${1} | sed "s,^\(.*\)$, \1, " | sed "s,^[ \t]*$, .,g" +} + +pp_backend_bsd_detect () { + test x"$1" = x"FreeBSD" -o x"$1" = x"DragonFly" +} + +pp_backend_bsd_init () { + + # Get the OS revision + pp_bsd_detect_os + + # Get the arch (i386/x86_64) + pp_bsd_detect_arch + + pp_bsd_name= + pp_bsd_version= + pp_bsd_origin= + pp_bsd_comment= + pp_bsd_arch= + pp_bsd_abi= + pp_bsd_www= + pp_bsd_maintainer= + pp_bsd_prefix="/usr/local/" + pp_bsd_desc= + pp_bsd_message= + + # FreeBSD uses package.txz, DragonFly uses package.pkg. + if [ "$pp_bsd_os" = "DragonFly" ]; then + pp_bsd_pkg_sfx=pkg + else + pp_bsd_pkg_sfx=txz + fi + + # pp_bsd_category must be in array format comma separated + # pp_bsd_category=[security,network] + pp_bsd_category= + + # pp_bsd_licenselogic can be one of the following: single, and, or unset + pp_bsd_licenselogic= + + # pp_bsd_licenses must be in array format comma separated + # pp_bsd_licenses=[GPLv2,MIT] + pp_bsd_licenses= + + # pp_bsd_annotations. These can be any key: value pair + # key must be separated by a : + # keyvalue pairs must be comma separated + # pp_bsd_annotations="repo_type: binary, somekey: somevalue" + # since all packages created by PolyPackage will be of type binary + # let's just set it now. + pp_bsd_annotations="repo_type: binary" + + pp_bsd_dbg_pkgname="debug" + pp_bsd_dev_pkgname="devel" + pp_bsd_doc_pkgname="doc" + + # Make sure any programs we require are installed + pp_bsd_check_required_programs + +} + +pp_bsd_cmp_full_name () { + typeset prefix + prefix="${pp_bsd_name:-$name}" + case "$1" in + run) echo "${prefix}" ;; + dbg) echo "${prefix}-${pp_bsd_dbg_pkgname}";; + dev) echo "${prefix}-${pp_bsd_dev_pkgname}";; + doc) echo "${prefix}-${pp_bsd_doc_pkgname}";; + *) pp_error "unknown component '$1'"; + esac +} + +pp_bsd_check_required_programs () { + local p needed notfound ok + needed= notfound= + + # list of programs FreeBSD needs in order to create a binary package + for prog in ${pp_bsd_required_programs:-"pkg"} + do + if command -v $prog 2>&1 > /dev/null; then + pp_debug "$prog: found" + else + pp_debug "$prog: not found" + case "$prog" in + pkg) p=pkg;; + *) pp_die "Unexpected pkg tool $prog";; + esac + notfound="$notfound $prod" + 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_bsd_detect_os () { + typeset revision + + pp_bsd_os=`uname -s` + revision=`uname -r` + pp_bsd_os_rev=`echo $revision | awk -F '-' '{print $1}'` +} + +pp_bsd_detect_arch() { + pp_bsd_platform="`uname -m`" + case $pp_bsd_platform in + amd64|x86_64) pp_bsd_platform_std=x86_64;; + i386) pp_bsd_platform_std=i386;; + *) pp_bsd_platform_std=unknown;; + esac +} + +pp_bsd_label () { + local label arg + label="$1"; shift + for arg + do + test -z "$arg" || echo "$label: $arg" + done +} + +pp_bsd_make_annotations () { + + test -z $1 && pp_die "pp_bsd_make_annotations requires a parameter" + manifest=$1 + + # Add annotations. These can be any key: value pair + # key must be separated by a : + # key:value pairs must be comma separated. + if test -n "$pp_bsd_annotations"; then + pp_debug "Processing annotations:" + pp_bsd_label "annotations" "{" >> $manifest + + SAVEIFS=$IFS + IFS=, + for annotate in $pp_bsd_annotations; do + # Remove any spaces at the start of the line + annotate=`echo $annotate | sed 's/^ *//'` + pp_debug " $annotate" + echo " $annotate" >> $manifest + done + IFS=$SAVEIFS + echo "}" >> $manifest + fi +} + +pp_bsd_make_depends() { + typeset package origin version + cmp=$1 + manifest=$2 + + if test -s $pp_wrkdir/%depend.${cmp}; then + echo "deps: {" >> $manifest + cat $pp_wrkdir/%depend.${cmp} | while read package origin version; do + if test x != x$package; then + pp_debug "Processing dependency: $package" + if test x != x$origin -a x != x$version; then + pp_debug " $package: {origin: \"$origin\", version: \"$version\"}" + echo " $package: {origin: \"$origin\", version: \"$version\"}" >> $manifest + else + pp_warn "Dependency $package is missing origin or version or both" + fi + fi + done + echo "}" >> $manifest + fi +} + +pp_bsd_make_messages () { + test -z $1 && pp_die "pp_bsd_make_messages requires a parameter" + manifest=$1 + + pp_debug "Processing messages" + + # Empty messages: [ ] is OK in the manifest + pp_bsd_label "messages" "[" >> $manifest + # Look for a single message in the variable pp_bsd_message + if test -n "$pp_bsd_message"; then + echo " { message: \"`pp_bsd_munge_text "$pp_bsd_message"`\" }," >> $manifest + fi + local a=1 + # Look for messages in the variables pp_bsd_message_[1..n] + var="pp_bsd_messages_1" + while [ -n "${!var}" ]; do + echo " { message: \"`pp_bsd_munge_text "${!var}"`\" }," >> $manifest + a=`expr $a + 1` + var="pp_bsd_messages_$a" + done + echo "]" >> $manifest +} + +pp_bsd_make_manifest() { + local cmp manifest + + cmp="$1" + manifest="$2" + + package_name=`pp_bsd_cmp_full_name $cmp` + + # Required for pkg +MANIFEST + cat <<-. >> $manifest + name: "${package_name}" + version: "${pp_bsd_version:-$version}" + origin: "${pp_bsd_origin}" + www: "${pp_bsd_www}" + desc: "`pp_bsd_munge_text "${pp_bsd_desc:-$description}"`" + comment: "${pp_bsd_comment:-$summary}" + maintainer: "${pp_bsd_maintainer}" + prefix: "${pp_bsd_prefix}" +. + + # Optional, so if they are not included in the pkg-product.pp file then do not create the label + pp_bsd_label "categories" "${pp_bsd_categories}" >> $manifest + pp_bsd_label "arch" "${pp_bsd_arch}" >> $manifest + pp_bsd_label "abi" "${pp_bsd_abi}" >> $manifest + pp_bsd_label "licenselogic" "${pp_bsd_licenselogic}" >> $manifest + pp_bsd_label "licenses" "${pp_bsd_licenses}" >> $manifest + + pp_bsd_make_annotations $manifest + pp_bsd_make_depends $cmp $manifest + + pp_bsd_make_messages $manifest +} + +pp_bsd_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_bsd_make_data() { + # t = file type + # m = file mode + # o = file owner + # g = file group + # f = ? + # p = file path + # st = file link + # + # EXAMPLE: f 755 root httpd v /usr/bin/hello goodbye + # -> /usr/bin/hello: {uname: root, gname: httpd, perm: 755 } goodbye + typeset _l t m o g f p st datadir + cmp=$1 + datadir=$pp_wrkdir/`pp_bsd_cmp_full_name $cmp` + local path + + outfilelist="$pp_wrkdir/files.list.$cmp" + outdirslist="$pp_wrkdir/dirs.list.$cmp" + + pp_debug "Processing $pp_wrkdir/%file.${cmp}" + + echo "files: {" > $outfilelist + echo "directories: {" > $outdirslist + + cat $pp_wrkdir/%files.${cmp} | while read t m o g f p st; do + test x"$o" = x"-" && o="${pp_bsd_defattr_uid:-root}" + test x"$g" = x"-" && g="${pp_bsd_defattr_gid:-wheel}" + if test x"$m" = x"-"; then + case "$t" in + d) m=755;; + f) m=644;; + esac + fi + path=$p + case "$t" in + f) # Files + case "$f" in + *v*) + # For now just skip the file if it is volatile, we + # will need to remove it in the pre uninstall script + pp_warn "file $path was marked as volatile, skipping" + ;; + *) + # If the directory doesn't exist where we are going to copy this file, then create it first + if [ ! -d `dirname "$datadir$path"` ]; then + pp_debug "creating directory `dirname "$datadir$path"`" + mkdir -p `dirname "$datadir$path"` + fi + + pp_debug "install -D $datadir -o $o -g $g -m ${m} -v $pp_destdir$p $datadir$path" + pp_bsd_fakeroot install -D $datadir -o $o -g $g -m ${m} -v $pp_destdir$p $datadir$path + echo " \"$path\": \"-\", \"$path\": {uname: $o, gname: $g, perm: ${m}}" >> $outfilelist + ;; + esac + ;; + d) # Directories + pp_debug "install -D $datadir -o $o -g $g -m ${m} -d -v $datadir$path"; + pp_bsd_fakeroot install -D $datadir -o $o -g $g -m ${m} -d -v $datadir$path; + echo " \"$path\": \"-\", \"$path\": {uname: $o, gname: $g, perm: ${m}}" >> $outdirslist; + ;; + s) # Symlinks + pp_debug "Found symlink: $datadir$path"; + # Remove leading / + rel_p=`echo $p | sed s,^/,,` + (cd $datadir; ln -sf $st $rel_p); + # Do we care if the file doesn't exist? Just symnlink it regardless and throw a warning? This will be important in the case + # where we depend on other packages to be installed and will be using the libs from that package. + if [ ! -e "$datadir$path" ]; then + pp_warn "$datadir$path does not exist" + fi + echo " \"$path\": \"$st\"" >> $outfilelist; + ;; + *) pp_error "Unsupported data file type: %t";; + esac + done + + echo "}" >> $outfilelist + echo "}" >> $outdirslist + cat $outfilelist >> $manifest + cat $outdirslist >> $manifest + + pp_debug "Finished processing $pp_wrkdir/%file.${cmp}" +} + +pp_bsd_makebsd() { + typeset cmp + typeset package_build_dir + local manifest postinstall preinstall preuninstall postuninstall preupgrade postupgrade + + cmp="$1" + + if test -z "$pp_bsd_platform"; then + pp_error "Unknown BSD architecture" + return 1 + fi + + _subname=`pp_bsd_cmp_full_name $cmp` + package_build_dir=$pp_wrkdir/$_subname + + manifest="$package_build_dir/+MANIFEST" + postinstall="$package_build_dir/+POST_INSTALL" + preinstall="$package_build_dir/+PRE_INSTALL" + preuninstall="$package_build_dir/+PRE_DEINSTALL" + postuninstall="$package_build_dir/+POST_DEINSTALL" + preupgrade="$package_build_dir/+PRE_UPGRADE" + postupgrade="$package_build_dir/+POST_UPGRADE" + + # Create package dir + mkdir -p $package_build_dir + + pp_bsd_make_manifest $cmp $manifest + pp_bsd_make_data $cmp + + pp_debug "Processing pre/post install scripts" + + if test -s $pp_wrkdir/%pre.$cmp; then + pp_debug "Found %pre.$cmp" + { + cat "$pp_wrkdir/%pre.$cmp" + } > $preinstall + pp_debug "Created $preinstall" + fi + + if test -s $pp_wrkdir/%post.$cmp; then + pp_debug "Found %post.$cmp" + { + echo "# Post install script for " + cat "$pp_wrkdir/%post.$cmp" + } > $postinstall + pp_debug "Created $postinstall" + fi + + pp_debug "Processing pre/post uninstall scripts" + + if test -s $pp_wrkdir/%preun.$cmp; then + pp_debug "Found %preun.$cmp" + { + echo "# Pre uninstall script for ${pp_bsd_name:-$name}" + cat "$pp_wrkdir/%preun.$cmp" + } > $preuninstall + pp_debug "Created pkg $preuninstall" + fi + + if test -s $pp_wrkdir/%postun.$cmp; then + pp_debug "Found %postun.$cmp" + { + echo "# Post uninstall script for ${pp_bsd_name:-$name}" + cat "$pp_wrkdir/%postun.$cmp" + } > $postuninstall + pp_debug "Created $postuninstall" + fi + + if test -s $pp_wrkdir/%preup.$cmp; then + pp_debug "Found %preup.$cmp" + { + echo "# Pre upgrade script for ${pp_bsd_name:-$name}" + cat "$pp_wrkdir/%preup.$cmp" + } > $preupgrade + pp_debug "Created pkg $preupgrade" + fi + + if test -s $pp_wrkdir/%postup.$cmp; then + pp_debug "Found %postup.$cmp" + { + echo "# Post upgrade script for ${pp_bsd_name:-$name}" + cat "$pp_wrkdir/%postup.$cmp" + } > $postupgrade + pp_debug "Created $postupgrade" + fi +} + +pp_backend_bsd() { + #get-files-dir-entries + #create-manifest + #create-preuninstall + #create-postinstall + #create-package + # + pp_bsd_handle_services + + for cmp in $pp_components + do + _subname=`pp_bsd_cmp_full_name $cmp` + pp_debug "Generating packaging specific files for $_subname" + pp_bsd_makebsd $cmp + done + + # call this to fixup any files before creating the actual packages + . $pp_wrkdir/%fixup + + for cmp in $pp_components + do + _subname=`pp_bsd_cmp_full_name $cmp` + package_build_dir=$pp_wrkdir/$_subname + # Build the actual packages now + pp_debug "Building FreeBSD $_subname" + pp_debug "Running package create command: pkg create -m $package_build_dir -r $pp_wrkdir/`pp_bsd_cmp_full_name $cmp` -o $pp_wrkdir" + pp_bsd_fakeroot pkg create -m $package_build_dir -r $pp_wrkdir/`pp_bsd_cmp_full_name $cmp` -o $pp_wrkdir -v + done + +} + +pp_bsd_name () { + typeset cmp="${1:-run}" + echo `pp_bsd_cmp_full_name $cmp`"-${pp_bsd_version:-$version}.${pp_bsd_pkg_sfx}" +} + +pp_backend_bsd_names () { + for cmp in $pp_components; do + echo `pp_bsd_cmp_full_name $cmp`"-${pp_bsd_version:-$version}.${pp_bsd_pkg_sfx}" + done +} + +pp_backend_bsd_cleanup () { + : +} + +pp_backend_bsd_probe () { + echo "${pp_bsd_os}-${pp_bsd_platform_std}" + echo "${pp_bsd_os}${pp_bsd_os_rev}-${pp_bsd_platform_std}" +} + + +pp_backend_bsd_vas_platforms() { + case "${pp_bsd_platform_std}" in + x86_64) echo "FreeBSD-x86_64.${pp_bsd_pkg_sfx} FreeBSD-i386.${pp_bsd_pkg_sfx}";; + i386) echo "FreeBSD-i386.${pp_bsd_pkg_sfx}";; + *) pp_die "unknown architecture $pp_bsd_platform_std";; + esac +} + + +pp_backend_bsd_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_bsd_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_bsd_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 + pkg add \`cmp_to_pathname "\$@"\` + ;; + uninstall) + test \$# -ge 1 || usage \$op + pkg remove \`cmp_to_pkgname "\$@"\`; : + ;; + start|stop) + test \$# -ge 1 || usage \$op + ec=0 + for svc + do + /etc/rc.d/\$svc \$op || ec=1 + done + exit \$ec + ;; + print-platform) + test \$# -eq 0 || usage \$op + echo "${pp_bsd_os}-${pp_bsd_platform}" + echo '`pp_backend_bsd_probe`' + ;; + *) + usage + ;; + esac +. +} +pp_backend_bsd_init_svc_vars () { + svc_process_regex="${pp_bsd_svc_process_regex}" + svc_description=$summary + svc_init_prefix="${pp_bsd_prefix}" + svc_init_filename="${pp_bsd_svc_init_filename}" # == $svc + svc_init_filepath="${pp_bsd_svc_init_filepath}" # == $pp_bsd_prefix/etc/rc.d/ by default + + bsd_svc_before="${pp_bsd_svc_before}" + bsd_svc_require="${pp_bsd_svc_require}" + bsd_svc_keyword="${pp_bsd_svc_keyword}" + +} + +pp_bsd_service_make_init_info() { + local svc=$1 + local out=$2 + cat <<-. >$out + #!/bin/sh + # + # FreeBSD Script Header Detail + # + # PROVIDE: $svc +. + + if [ ! -z "$bsd_svc_before" ]; then + cat <<-. >>$out + # BEFORE: $bsd_svc_before +. + fi + + if [ ! -z "$bsd_svc_require" ]; then + cat <<-. >>$out + # REQUIRE: $bsd_svc_require +. + fi + + if [ ! -z "$bsd_svc_keyword" ]; then + cat <<-. >>$out + # KEYWORD: $bsd_svc_keyword +. + fi + + cat <<-'.' >>$out + ### END INIT INFO + +. + +} + +pp_bsd_service_make_init_set_vars() { + local svc=$1 + local out=$2 + + svc_command="$cmd" + svc_pre_command="${pp_bsd_svc_pre_command}" + svc_pre_command_args="${pp_bsd_svc_pre_command_args}" + + local run_command="${svc_pre_command:-$svc_command}" + local run_pre_command_args="${svc_pre_command:+"${svc_pre_command_args}"}" + local run_post_command_args="${svc_command:+"${svc_command_args}"}" + local run_post_command_without_pre_command="${svc_pre_command:+"$svc_command"}" + local run_post_command_with_args="${run_post_command_without_pre_command}${run_post_command_args:+" $run_post_command_args"}" + local run_command_args="${run_pre_command_args:+"$run_pre_command_args"}${run_post_command_with_args:+" $run_post_command_with_args"}" + + # https://www.freebsd.org/cgi/man.cgi?query=rc.subr + cat <<-. >>$out + # FreeBSD rc subroutines + . /etc/rc.subr + + # 0: Not running. + # 1: Running normally + # 2: Running, but no PID file. + # 3: Running, but PID file doesn't match running processes. + # If the PID file is found but no process, the file is removed and 0 is returned. + DAEMON_RUNNING=0 + + name="$svc" + desc="${svc_description:-\$name}" + + start_cmd="\${name}_start" + status_cmd="\${name}_status" + stop_cmd="\${name}_stop" + + # Loads any variables set in /etc/rc.conf.d/\$name + load_rc_config \$name + + : \${${svc}_enable:="Yes"} + : \${${svc}_pidfile:="${pidfile:-/var/run/\${name\}.pid}"} + : \${${svc}_args:="$run_command_args"} + : \${${svc}_cmd:="$run_command"} + + # Regex used in the pp_check_daemon_running ps check to find our running processe(s) + # If it's set in /etc/rc.conf.d/\$name this will be used first + # then check if pp_bsd_svc_process_regex is set, finally set to the \${name}_cmd + # When set to \${name}_cmd pp_check_daemon_running will only find the parent process pid + : \${${svc}_process_regex:="${pp_bsd_svc_process_regex:-${cmd}}"} + + # For additional information about the rc.subr see: + # https://www.freebsd.org/cgi/man.cgi?query=rc.subr + rcvar="\${name}_enable" + + pidfile=\${${svc}_pidfile} + + command="\$${svc}_cmd" + command_args="\$${svc}_args" + +. + +} + +pp_bsd_service_make_init_body() { + local svc=$1 + local out=$2 + + cat<<-'.' >>$out + pp_exec_cmd() { (eval $command $command_args) } + + pp_success_msg () { echo ${1:+"$*:"} OK; } + pp_failure_msg () { echo ${1:+"$*:"} FAIL; } + pp_warning_msg () { echo ${1:+"$*:"} WARNING; } + + #-- prints a status message + pp_msg () { echo -n "$*: "; } + + # Kills process $1. + # First a sigterm, then wait up to 10 seconds + # before issuing a sig kill. + pp_signal () { + # Kill the processes the nice way first + if [ -z "$1" ]; then + # No pid file. Use the list from pp_check_daemon_running + kill $PROCESSES 2>/dev/null + else + kill $1 2>/dev/null + fi + count=1 + + #Check to make sure the processes died, if not kill them the hard way + while [ $count -le 10 ]; do + sleep 1 + pp_check_daemon_running + if [ $DAEMON_RUNNING -eq 0 ]; then + break; + fi + if [ $count -eq 1 ]; then + # We tried killing the pid associated to the pidfile, now try the ones we found from pp_check_daemon_running + kill $PROCESSES 2>/dev/null + fi + count=`expr $count + 1` + done + # Check one more time to make sure we got them all + if [ $DAEMON_RUNNING -ne 0 ]; then + # These guys don't want to go down the nice way, now just kill them + kill -9 $PROCESSES 2>/dev/null + fi + # make sure to remove the pidfile + rm -f $pidfile + } + + # Check to see if the daemon process is running + # Sets the PROCESSES global variable with all pids that match + # ${name}_process_regex + # Sets global variable DAEMON_RUNNING to one of the following: + # 0: Not Running + # 1: Running normally + # 2: Running, but no PID file + # 3: Running, but PID file doesn't match running processes. + # + pp_check_daemon_running() + { + DAEMON_RUNNING=0 +. + cat<<-. >>$out + + PROCESSES="\`eval ps -axo pid,args | grep "\${${svc}_process_regex}" | grep -v grep | awk '{print \$1}'\`" + +. + cat<<-'.' >>$out + if [ -f $pidfile ]; then + if [ ! -z "$PROCESSES" ]; then + PARENT_PID=`cat $pidfile 2>/dev/null` + PPROCESS=`echo $PROCESSES | grep "${PARENT_PID:-"NOPID"}"` + if [ $? -eq 0 ]; then + DAEMON_RUNNING=1 + else + DAEMON_RUNNING=3 + fi + else + rm -r $pidfile + fi + else + if [ ! -z "$PROCESSES" ]; then + DAEMON_RUNNING=2 + fi + fi + } +. + cat <<-. >>$out + + # starts the service + ${svc}_start() +. + cat <<-'.' >>$out + { + pp_msg "Starting ${desc}" + pp_check_daemon_running + + if [ $DAEMON_RUNNING -eq 0 ]; then + pp_exec_cmd + RETVAL=$? + if [ $RETVAL -eq 0 ]; then + pp_success_msg + else + pp_failure_msg "cannot start" + fi + else + if [ $DAEMON_RUNNING -eq 1 ]; then + pp_success_msg "${name} appears to be running already" + else + pp_warning_msg "${name} is already running but without a pid file" + fi + fi + } + +. + + cat <<-. >>$out + # stops the service + ${svc}_stop() +. + + cat <<-'.' >>$out + { + pp_msg "Stopping ${desc}" + pp_check_daemon_running + + if [ $DAEMON_RUNNING -ne 0 ]; then + pp_signal `cat $pidfile 2>/dev/null` + if [ -n "$pidfile" ]; then + loop_cnt=1 + while [ -e ${pidfile} ]; do + sleep 1 + loop_cnt=`expr $loop_cnt + 1` + if [ $loop_cnt -eq 10 ]; then + break + fi + done + fi + rm -f $pidfile + + pp_success_msg + else + pp_failure_msg + echo -n "$desc does not appear to be running." + echo + fi + } +. + + cat <<-. >>$out + # prints information about the service status + # returns: + # 0=running + # 1=Not running + # 2=Running without pidfile + # 3=Running with pid that doesn't match pidfile + ${svc}_status() +. + + cat <<-'.' >>$out + { + pp_msg "Checking ${desc}" + pp_check_daemon_running + if [ $DAEMON_RUNNING -eq 1 ]; then + pp_success_msg "PID $PARENT_PID: running" + return 0 + else + if [ $DAEMON_RUNNING -eq 0 ]; then + pp_failure_msg "not running" + return 1 + elif [ $DAEMON_RUNNING -eq 2 ]; then + pp_warning_msg "running without a pid file" + return 2 + else + pp_warning_msg "running but pid file doesn't match running processe()" + return 3 + fi + fi + } + + run_rc_command "$1" +. +} + +pp_bsd_service_make_init_script () { + local svc=${svc_init_filename:-$1} + local script="${svc_init_filepath:-"${svc_init_prefix}/etc/rc.d"}/$svc" + script=`echo $script | sed 's://*:/:g'` + local out=$pp_destdir$script + + pp_add_file_if_missing $script run 755 || return 0 + + pp_bsd_service_make_init_info "$svc" "$out" + pp_bsd_service_make_init_set_vars "$svc" "$out" + pp_bsd_service_make_init_body "$svc" "$out" + + chmod 755 $out + +} + +pp_bsd_handle_services () { + if test -n "$pp_services"; then + for svc in $pp_services; do + pp_load_service_vars $svc + # Append some code to %post to install the svc TODO: Figure out why/what + pp_bsd_service_make_init_script $svc + # prepend some code to %preun to uninstall svc TODO: Figure out why/what + done + fi +} +pp_backend_bsd_function() { + case "$1" in + pp_mkgroup) cat<<'.';; + /usr/sbin/pw group show "$1" 2>/dev/null && return 0 + /usr/sbin/pw group add "$1" +. + pp_mkuser:depends) echo pp_mkgroup;; + pp_mkuser) cat<<'.';; + #Check if user exists + /usr/sbin/pw user show "$1" 2>/dev/null && return 0 + pp_mkgroup "${2:-$1}" || return 1 + echo "Creating user $1" + /usr/sbin/pw user add \ + -n "$1" \ + -d "${3:-/nonexistent}" \ + -g "${2:-$1}" \ + -s "${4:-/bin/false}" +. + pp_havelib) cat<<'.';; + for pp_tmp_dir in `echo "/usr/local/lib:/usr/lib:/lib${3:+:$3}" | tr : ' '`; do + test -r "$pp_tmp_dir/lib$1.so{$2:+.$2}" && return 0 + done + return 1 +. + *) false;; + esac +} +pp_systemd_make_service_file() { + local svc f + + if [ "${pp_systemd_disabled:-false}" = "true" ]; then + return + fi + + svc="$1" + f="${pp_systemd_service_dir:-/opt/quest/libexec/vas}/$svc.service" + pp_add_file_if_missing $f run 644 v || return 0 + + cat <<. >$pp_destdir$f + +[Unit] +Description=${pp_systemd_service_description:-"systemd service file for $svc"} +${pp_systemd_service_man:+"Documentation=$pp_systemd_service_man"} +${pp_systemd_service_documentation:+"Documentation=$pp_systemd_service_documentation"} +${pp_systemd_service_requires:+"Requires=$pp_systemd_service_requires"} +After=${pp_systemd_service_after:-"syslog.target network.target auditd.service"} +${pp_systemd_service_before:+"Before=$pp_systemd_service_before"} +${pp_systemd_service_wants:+"Wants=$pp_systemd_service_wants"} +${pp_systemd_service_conflicts:+"Conflicts=$pp_systemd_service_conflicts"} + +[Service] +ExecStart=${pp_systemd_service_exec:-"/opt/quest/sbin/$svc"} ${pp_systemd_service_exec_args} +KillMode=${pp_systemd_service_killmode:-process} +Type=${pp_systemd_service_type:-forking} +${pp_systemd_service_pidfile:+"PIDFile=$pp_systemd_service_pidfile"} + +[Install] +WantedBy=${pp_systemd_system_target:-"multi-user.target"} +. +} + +pp_systemd_service_init_common () { + cat <<. + + _pp_systemd_init () { + systemd_service_dir=${pp_systemd_service_dir:-/opt/quest/libexec/vas} + systemd_target=${pp_systemd_system_target:-"multi-user.target"} + systemd_target_wants="\${systemd_target}.wants" + + pkg_config_cmd=${pp_systemd_pkg_config_cmd:-"\$(command -v pkg-config)"} + systemctl_cmd=${pp_systemd_systemctl_cmd:-"\$(command -v systemctl)"} + + # See if pkg-config is installed to get the default locations for this OS, if not installed then just use what we hard code. + # So far works on Debian 8, OpenSuse12.3, Ubuntu 16.04, RHEL 7.3 + # See systemd wiki for more OS interactions https://en.wikipedia.org/wiki/Systemd + if [ -x "\$pkg_config_cmd" ]; then + systemd_system_unit_dir="\$(pkg-config systemd --variable=systemdsystemunitdir)" + systemd_system_conf_dir="\$(pkg-config systemd --variable=systemdsystemconfdir)" + fi + + #if pkg-config does not exist or if the \$pkg_config_cmd command returns nothing + if test -z "\$systemd_system_unit_dir"; then + systemdsystemunitdirs="/lib/systemd/system /usr/lib/systemd/system" + for dir in \$systemdsystemunitdirs; do + if [ -d "\$dir/\$systemd_target_wants" ]; then + systemd_system_unit_dir="\$dir" + break + fi + done + fi + + # In the case where \$systemd_system_conf_dir is empty hard code the path + if test -z "\$systemd_system_conf_dir"; then + systemd_system_conf_dir="/etc/systemd/system" + fi + + # if the \$svc.pp file defines the systemd unit dir then use it. + ${pp_systemd_system_unit_dir:+"# systemd_system_unit_dir defined by variable pp_systemd_system_unit_dir from the \$svc.pp file"} + systemd_system_unit_dir="${pp_systemd_system_unit_dir:-"\$systemd_system_unit_dir"}" + + # if the \$svc.pp file defines the systemd conf dir then use it. + ${pp_systemd_system_conf_dir:+"# systemd_system_conf_dir defined by variable pp_systemd_system_conf_dir from the \$svc.pp file"} + systemd_system_conf_dir="${pp_systemd_system_conf_dir:-"\$systemd_system_conf_dir"}" + } +. +} + +pp_systemd_service_install_common () { + if [ "${pp_systemd_disabled:-false}" = "true" ]; then + cat<<'.' + + # systemd support disabled + _pp_systemd_init () { + return + } + + _pp_systemd_install () { + return + } + + _pp_systemd_enable () { + return + } +. + return + fi + + pp_systemd_service_init_common + + cat<<'.' + + _pp_systemd_install () { + local svc="$1" + + # If $systemctl_cmd is not set, then call _pp_systemd_init. If still not + # set, we do not know where the systemctl command is so do nothing; + # systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + if test -x "$systemctl_cmd" && test -d "$systemd_system_conf_dir/$systemd_target_wants"; then + # If our service file still exists (upgrade) remove the link/file and systemctl + # will recreate it if/when we enable the $svc service. + rm -f "$systemd_system_conf_dir/$systemd_target_wants/$svc.service" + + # Copy the $svc.service file to the correct systemd_system_unit_dir location + if [ "x$systemd_service_dir" != "x$systemd_system_unit_dir" ]; then + cp -f "$systemd_service_dir/$svc.service" "$systemd_system_unit_dir/$svc.service" + chmod 644 "$systemd_system_unit_dir/$svc.service" + fi + fi + } + + _pp_systemd_enable () { + local svc="$1" + local RUNNING + + # If $systemctl_cmd is not set, then call _pp_systemd_init. If still not + # set, we do not know where the systemctl command is so do nothing; + # systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + if test -x "$systemctl_cmd" && test -f "$systemd_system_unit_dir/$svc.service"; then + # stop the daemon using the old init script before enabling systemd for the service + # we do this so we do not "orphan" the process. Because init started it and if we enable systemd + # it will not know about this process and will not be able to stop it. + if [ -x "/etc/init.d/$svc" ]; then + output="$(/etc/init.d/$svc status 2>&1)" + RUNNING=$? + if [ $RUNNING -eq 0 ]; then + case "$output" in + *"not running"*) + # systemd is reporting the status (compatibility package is installed) + RUNNING=1 + ;; + *) # it is really running + /etc/init.d/$svc stop > /dev/null 2>&1 + ;; + esac + fi + else + RUNNING=1 + fi + + # Enable the $svc.service + $systemctl_cmd daemon-reload >/dev/null 2>&1 + $systemctl_cmd enable $svc.service >/dev/null 2>&1 + + # Now that the service has been enabled, start it again if it was running before. + if [ $RUNNING -eq 0 ]; then + /etc/init.d/$svc start > /dev/null 2>&1 + fi + fi + } +. +} + +pp_systemd_service_remove_common () { + if [ "${pp_systemd_disabled:-false}" = "true" ]; then + cat<<'.' + + # systemd support disabled + _pp_systemd_init () { + return + } + + _pp_systemd_disable () { + return + } + + _pp_systemd_remove () { + return + } +. + return + fi + + pp_systemd_service_init_common + + cat<<'.' + + _pp_systemd_disable () { + local svc="$1" + + # If $systemctl_cmd is not set, then call _pp_systemd_init. + # If still not set, we do not know where the systemctl command + # is so do nothing; systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + systemd_service_file="$systemd_system_conf_dir/$systemd_target_wants/$svc.service" + + # Remove systemd symlink (enabled) unit service file + if test -e $systemd_service_file; then + # Disable the $svc service + if test -x "$systemctl_cmd"; then + $systemctl_cmd disable $svc.service > /dev/null 2>&1 + else + # For some reason systemctl is not install but our service file exists + # Just delete the symlink then + rm -f "$systemd_service_file" + fi + fi + } + + _pp_systemd_remove () { + local svc="$1" + + # If $systemctl_cmd is not set, then call _pp_systemd_init. + # If still not set, we do not know where the systemctl command + # is so do nothing; systemd must not be on this system. + if test -z "$systemctl_cmd"; then + _pp_systemd_init + fi + + # Remove the systemd unit service file + if [ "x$systemd_service_dir" != "x$systemd_system_unit_dir" ]; then + rm -f "$systemd_system_unit_dir/$svc.service" + fi + + if test -x "$systemctl_cmd"; then + $systemctl_cmd daemon-reload + $systemctl_cmd reset-failed $svc.service >/dev/null 2>&1 || true + fi + } +. +} + + +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+"$@"} |