sudo/scripts/pp

9142 lines
258 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
# Copyright 2024 One Identity LLC. ALL RIGHTS RESERVED
pp_revision="20240518"
# 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_is_version_greater () {
smaller_version="$(echo -e "$1\n$2" | sort -V | head -1)"
test x"$smaller_version" = x"$1"
}
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 *,missingok,*) _flags="${_flags}m";; 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
for fileset in ${pp_aix_deprecated_filesets}; do
echo "$fileset"
done >$user_wrkdir/$pp_aix_bff_name.$ex.namelist
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";;
*m*) _l="%config(missingok) $_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 m || 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 m || 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/&/&amp;/g;s/</\&lt;/g;s/>/\&gt;/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=
# Newer "pkg" (>=1.17.0) generates package.pkg, before that package.txz.
if pp_is_version_greater 1.17.0 "$(pkg --version)"; 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_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=0
# 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
fi
# If the service is not running according to its sysv script (eg. systemd service
# is not using a pidfile the sysv script needs), or its sysv script is not present any more,
# check how systemd thinks.
# We also try to restart the service in case something went wrong with it.
if $systemctl_cmd is-active "$svc" >/dev/null 2>&1 || $systemctl_cmd is-failed "$svc" >/dev/null 2>&1; then
$systemctl_cmd stop "$svc" >/dev/null 2>&1
RUNNING=0
fi
# Enable the $svc.service
$systemctl_cmd daemon-reload >/dev/null 2>&1
# We do not need the init.d script any more, and it causes problems on SLES
# where systemd sysv compatibility is enforced and broken on default installs
rm -f "/etc/init.d/$svc"
$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
$systemctl_cmd start $svc.service >/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
$systemctl_cmd stop $svc.service > /dev/null 2>&1
# 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+"$@"}