#!/bin/sh
##############################################################################
#
# FILE NAME : install-package.sh
#
# DESCRIPTION: Application package installation script to be run on TARGET
#
# ----------------------------------------------------------------------------
# Copyright (C) 2008-2019, Axis Communications AB, LUND, SWEDEN
##############################################################################
INSTALLDIR=/usr/local/packages
ADPPACKCFG=package.conf
ADPPACKPARAMCFG=param.conf
DEFRUNLEVELSSTART=3
DEFRUNLEVELSSTOP="0 1 2 4 5 6"
PHC="parhandclient --nocgi --nolog"
LIMITED_POSTINSTALL=no
information() {
printf "%s\n" "$*" >&1
}
warning() {
printf "%s\n" "$*" >&2
}
error() {
warning "$*\n"
[ "$is_reinstall" ] || uninstall
exit 1
}
. /usr/html/axis-cgi/lib/acap_handle_files.sh
. /usr/html/axis-cgi/lib/preserve.sh
__pkgconf_unset(){
unset \
APPGRP APPID APPMAJORVERSION APPMINORVERSION APPNAME APPOPTS APPTYPE \
APPUSR LICENSENAME LICENSEPAGE LUAFILES LUAFILESENCRYPTED MENUNAME OTHERFILES \
PACKAGENAME POSTINSTALLSCRIPT PREUPGRADESCRIPT REQEMBDEVVERSION \
SETTINGSPAGEFILE SETTINGSPAGETEXT STARTMODE VENDOR VENDORHOMEPAGELINK
}
__pkgconf_unset
[ -r $ADPPACKCFG ] || {
warning "Failed to read $ADPPACKCFG"
exit 1
}
. ./$ADPPACKCFG || {
warning "Failed to source $ADPPACKCFG"
exit 1
}
[ "$DIRNAME" ] || DIRNAME=$APPNAME
[ "$DIRNAME" ] || {
warning "Failed to read DIRNAME"
exit 1
}
if [ "$APPTYPE" = lua ]; then
DIRNAME=${APPNAME%.*}
XMLCONFFILE=$INSTALLDIR/$DIRNAME/$APPNAME
APPNAME=$DIRNAME
APPUSR=ruleengined
APPGRP=ruleengined
fi
ETC_HTTPD_CONF=/etc/apache2
ETC_VHOSTS_ALL=$ETC_HTTPD_CONF/conf.d/vhosts/all
ACAP_DOC_ROOT=/usr/html/local
ETC_TRANSFER_CONF=$ETC_HTTPD_CONF/transfer
ETC_MIME_CONF=$ETC_HTTPD_CONF/mime
ABSAPPNAME=$INSTALLDIR/$DIRNAME/$APPNAME
PKG_CONFDIR=$INSTALLDIR/$DIRNAME/conf
RUNSTATE_CONF=$PKG_CONFDIR/runstate.conf
GROUPNAME=$(r=${APPNAME#?};f=${APPNAME%$r};echo $(echo $f | tr [:lower:] [:upper:])$r)
ETC_DYN=/etc/dynamic
ETC_DYN_APP_CONF=$ETC_DYN/$APPNAME.conf
PKG_ETC_DYN_APP_CONF=$PKG_CONFDIR/$APPNAME.conf
ETC_DYN_PARAM=$ETC_DYN/param
ETC_DYN_PARAM_APP_CONF=$ETC_DYN_PARAM/$APPNAME.conf
PKG_ETC_DYN_PARAM_APP_CONF=$PKG_CONFDIR/param_$APPNAME.conf
WEB_DIR=/usr/html/local
DBUS_DIR=/etc/dbus-1/system.d
DBUS_FILE=$DBUS_DIR/$APPNAME.conf
PKG_DBUS_FILE=$PKG_CONFDIR/dbus_$APPNAME.conf
DATA_DIR=$INSTALLDIR/$DIRNAME/localdata
BAK_DIR=$INSTALLDIR/$DIRNAME/configuration.bak
HTTP_VAR_RUN=/var/run/http
HTTPD_CONF_LOCAL=httpd.conf.local.$APPNAME
HTTPD_MIME_LOCAL=mime.types.local.$APPNAME
ETC_INIT_D_APPNAME=/etc/init.d/sdk$APPNAME
PKG_ETC_INIT_D_APPNAME=$PKG_CONFDIR/sdk$APPNAME
SYSTEMD_SERVICE_FILENAME=sdk$APPNAME.service
ETC_SYSTEMD_DIR=/etc/systemd/system
ETC_SYSTEMD_APPNAME=$ETC_SYSTEMD_DIR/$SYSTEMD_SERVICE_FILENAME
PREUPGRADE_SERVICE=preupgrade$APPNAME
PREUPGRADE_SERVICE_FILENAME=$PREUPGRADE_SERVICE.service
PREUPGRADE_LOG=$INSTALLDIR/$APPNAME/preupgrade.log
POSTINSTALL_SERVICE=postinstall$APPNAME
POSTINSTALL_SERVICE_FILENAME=$POSTINSTALL_SERVICE.service
POSTINSTALL_LOG=$INSTALLDIR/$APPNAME/postinstall.log
LOGINFOAPPNAME="logger -p INFO -t $APPNAME[0]"
create_initscript() {
local respawn=$1
cat <<-EOF > $PKG_ETC_INIT_D_APPNAME.tmp
#! /bin/sh -e
. /etc/init.d/functions.sh
trap 'end \$?' EXIT
sdkkillall() {
local appname pid thispid binexe
[ "\$1" ] && [ "\$2" ] || return 2
appname=\${2##*/}
pid=\$(pidof \$appname) || return 0
if [ "\$pid" ]; then
for thispid in \$pid ; do
binexe=\$(readlink /proc/\${thispid}/exe) || return 1
if eval \$(echo -n "\$binexe" | grep -q "\$INSTALLDIR" ) ; then
[ "\$1" = 0 ] ||
$LOGINFOAPPNAME "$0: kill -\$1 \$thispid" || :
kill -\$1 \$thispid || return 1
fi
done
fi
}
start_d() {
elflibcheck.sh $ABSAPPNAME || {
$LOGINFOAPPNAME "elflibcheck failed $APPNAME"
return 1
}
start-package-allowed.sh $ABSAPPNAME > /dev/null 2>&1 || {
return 1
}
$LOGINFOAPPNAME "starting $APPNAME"
/sbin/start-stop-daemon --start --background \
-c $APPUSR:$APPGRP --exec \
"$ABSAPPNAME" -- $APPOPTS || {
$LOGINFOAPPNAME "start-stop-daemon \
\"$ABSAPPNAME\" $APPOPTS failed!" || {
return 1
}
}
EOF
if [ "$respawn" ]; then
cat <<-EOF >> $PKG_ETC_INIT_D_APPNAME.tmp
respawn-on-n -c $APPUSR -g $APPGRP "$ABSAPPNAME" $APPOPTS ||
$LOGINFOAPPNAME "respawn-on-n -c $APPUSR -g $APPGRP \"$ABSAPPNAME\" $APPOPTS failed!" || :
EOF
fi
cat <<-EOF >> $PKG_ETC_INIT_D_APPNAME.tmp
}
stop_d() {
EOF
if [ "$respawn" ]; then
cat <<-EOF >> $PKG_ETC_INIT_D_APPNAME.tmp
respawn-off "$ABSAPPNAME" $APPOPTS ||
$LOGINFOAPPNAME "respawn-off \"$ABSAPPNAME\" $APPOPTS failed!" || :
EOF
fi
cat <<-EOF >> $PKG_ETC_INIT_D_APPNAME.tmp
$LOGINFOAPPNAME "stopping $APPNAME"
stop_daemon $ABSAPPNAME ||
$LOGINFOAPPNAME "stop_daemon $APPNAME failed"
! sdkkillall 0 $ABSAPPNAME ||
sdkkillall SIGKILL $ABSAPPNAME || :
}
case \$1 in
start)
begin "Starting $APPNAME"
start_d
;
stop)
begin "Stopping $APPNAME"
stop_d
;
restart)
begin "Restarting $APPNAME"
stop_d ; start_d
;
*)
error "Usage: \$0 start|stop|restart"
;
esac
EOF
chmod 755 $PKG_ETC_INIT_D_APPNAME.tmp ||
error "Failed to chmod $PKG_ETC_INIT_D_APPNAME.tmp."
fsynced_write_or_cleanup $PKG_ETC_INIT_D_APPNAME.tmp $PKG_ETC_INIT_D_APPNAME
}
create_lua_service() {
luaappname=${APPNAME%.*}
if [ $STARTMODE = auto ]; then
startcmd=start
else
startcmd=add
fi
cat <<-EOF > $ETC_SYSTEMD_APPNAME.tmp
[Unit]
Description=$luaappname
After=ruleengined.service
Requires=ruleengined.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/rc-ruleengine-acap $startcmd $luaappname
ExecStop=/usr/libexec/rc-ruleengine-acap remove $luaappname
EOF
chmod 644 $ETC_SYSTEMD_APPNAME.tmp ||
error "Failed to chmod $ETC_SYSTEMD_APPNAME.tmp."
chown root:root $ETC_SYSTEMD_APPNAME.tmp ||
error "Failed to chown $ETC_SYSTEMD_APPNAME.tmp."
fsynced_write_or_cleanup $ETC_SYSTEMD_APPNAME.tmp $ETC_SYSTEMD_APPNAME
}
create_initwrap_service() {
local respawn=$1
cat <<-EOF > $ETC_SYSTEMD_APPNAME.tmp
[Unit]
Description=$APPNAME
After=acap-pre.target
Requires=acap-pre.target
EOF
if [ "$respawn" ]; then
cat <<-EOF >> $ETC_SYSTEMD_APPNAME.tmp
After=respawnd.service
Requires=respawnd.service
EOF
fi
cat <<-EOF >> $ETC_SYSTEMD_APPNAME.tmp
[Service]
Slice=extension-acap.slice
Type=oneshot
RemainAfterExit=yes
ExecStart=$ETC_INIT_D_APPNAME start
ExecStop=$ETC_INIT_D_APPNAME stop
[Install]
WantedBy=acap.target
EOF
chmod 644 $ETC_SYSTEMD_APPNAME.tmp ||
error "Failed to chmod $ETC_SYSTEMD_APPNAME.tmp."
chown root:root $ETC_SYSTEMD_APPNAME.tmp ||
error "Failed to chown $ETC_SYSTEMD_APPNAME.tmp."
fsynced_write_or_cleanup $ETC_SYSTEMD_APPNAME.tmp $ETC_SYSTEMD_APPNAME
}
setup_legacy_webserver_config() {
local line transfer_conf transfer_link mime_conf mime_link
if [ -r "$HTTPD_CONF_LOCAL" ]; then
transfer_conf=$PKG_CONFDIR/$HTTPD_CONF_LOCAL
transfer_link=$ETC_TRANSFER_CONF/legacy_transfer_$APPNAME.conf
if [ -h $transfer_link ]; then
rm -f $transfer_link || error "Failed to remove link: $transfer_link"
fi
echo "# $APPNAME config" > $transfer_conf.tmp
while read -r line; do
case $line in
Transfer[[:blank:]]*)
transfer=${line#Transfer[[:blank:]]}
echo "TransferProxy $transfer"
;
TransferMethod[[:blank:]]*)
transfer=${line#TransferMethod[[:blank:]]}
echo "TransferMethodProxy $transfer"
;
esac
done < "$HTTPD_CONF_LOCAL" > $transfer_conf.tmp
chmod 644 $transfer_conf.tmp
chown www:www $transfer_conf.tmp
fsynced_write_or_cleanup $transfer_conf.tmp $transfer_conf
ln -sf $transfer_conf $transfer_link ||
error "Failed to create link: $transfer_link"
chown -h www:www $transfer_link
fi
if [ -r "$HTTPD_MIME_LOCAL" ]; then
mime_conf=$PKG_CONFDIR/$HTTPD_MIME_LOCAL
mime_link=$ETC_MIME_CONF/legacy_mime_$APPNAME.conf
if [ -h $mime_link ]; then
rm -f $mime_link || error "Failed to remove link: $mime_link"
fi
echo "# $APPNAME types" > $mime_conf.tmp
while read -r line; do
[ -z "$line" ] || printf "AddType $line\n"
done < "$HTTPD_MIME_LOCAL" > $mime_conf.tmp
chmod 644 $mime_conf.tmp
chown www:www $mime_conf.tmp
fsynced_write_or_cleanup $mime_conf.tmp $mime_conf
ln -sf $mime_conf $mime_link ||
error "Failed to create link: $mime_link"
chown -h www:www $mime_link
fi
}
create_config_links() {
local tmp_file owner cgi_path cgi_path_dir cgi_path_file lic_file
local chown_lic_file=no
local path_validation_expr='^\(/\([-./_~]\|[[:alnum:]]\|%[[:xdigit:]]\{2\}\)\+[^/]\)*$'
if [ "$APPTYPE" != lua ] && [ ! -h $ETC_INIT_D_APPNAME ]; then
ln -sf $PKG_ETC_INIT_D_APPNAME $ETC_INIT_D_APPNAME ||
error "Failed to create link: $ETC_INIT_D_APPNAME"
fi
if [ ! -h $WEB_DIR/$APPNAME ] && [ -d $INSTALLDIR/$DIRNAME/html ]; then
ln -sfn $INSTALLDIR/$DIRNAME/html $WEB_DIR/$APPNAME ||
error "Failed to create link: $WEB_DIR/$APPNAME"
fi
setup_legacy_webserver_config
if [ "$HTTPCGIPATHS" ]; then
if [ ! -r $HTTPCGIPATHS ]; then
error "Failed to read $HTTPCGIPATHS, file is read protected"
fi
tmp_file=$PKG_CONFDIR/$HTTPCGIPATHS.tmp
while read owner cgi_path; do
[ "$cgi_path" ] || continue
printf "%s" "$cgi_path" | grep -q $path_validation_expr ||
error "Failed to verify path: $cgi_path"
echo "TransferMethodProxy /local/$APPNAME$cgi_path /var/run/http/$APPNAME/http"
done<$HTTPCGIPATHS>$tmp_file
chmod 644 $tmp_file || error "Failed to chmod: $tmp_file"
fsynced_write_or_cleanup $tmp_file $PKG_CONFDIR/$HTTPCGIPATHS
ln -sf $PKG_CONFDIR/$HTTPCGIPATHS $ETC_TRANSFER_CONF/transfer_$APPNAME.conf ||
error "Failed to create link: $ETC_TRANSFER_CONF/transfer_$APPNAME.conf"
while read owner cgi_path; do
[ "$cgi_path" ] || continue
case $owner in
administrator)
owner=admin
;
operator|viewer)
;
*)
error "Not a vaild owner: $owner"
;
esac
cgi_path_dir=$INSTALLDIR/$DIRNAME/html/$(dirname $cgi_path) ||
error "Failed to dirname: $cgi_path"
cgi_path_file=$cgi_path_dir/$(basename $cgi_path) ||
error "Failed to basename: $cgi_path"
mkdir -p $cgi_path_dir ||
error "Failed to mkdir: $cgi_path_dir"
find $cgi_path_dir -type d | xargs chown sdk:sdk ||
error "Failed to chown: $cgi_path_dir"
>$cgi_path_file.tmp ||
error "Failed to create: $cgi_path_file.tmp"
chgrp $owner $cgi_path_file.tmp ||
error "Failed to chgrp: $owner $cgi_path_file.tmp"
chmod 0750 $cgi_path_file.tmp ||
error "Failed to chmod: $cgi_path_file.tmp"
fsynced_write_or_cleanup $cgi_path_file.tmp $cgi_path_file
done<$HTTPCGIPATHS
fi
if [ "$LICENSENAME" ] && [ -d $INSTALLDIR/$DIRNAME/html ]; then
lic_file=$INSTALLDIR/$DIRNAME/LICENSE
[ -r $lic_file ] ||
error "No LICENSE file for $DIRNAME"
chown_lic_file=yes
chmod 0640 $lic_file ||
error "Failed to set file permissions for the LICENSE file"
ln -sf $lic_file $INSTALLDIR/$DIRNAME/html/LICENSE >/dev/null 2>&1 ||
error "Failed to expose license - could not create symlink"
fi
if [ -d $INSTALLDIR/$DIRNAME/html ]; then
for dir in $(find $INSTALLDIR/$DIRNAME/html -type d); do
chmod 751 $dir || error "Failed to set permissions html"
done
install_urls $APPNAME $INSTALLDIR/$DIRNAME/html ||
error "Failed to create install urls"
chown $APPUSR:www $INSTALLDIR/$DIRNAME/html ||
error "Failed to change ownership html"
fi
if [ "$chown_lic_file" = yes ]; then
chown $APPUSR:www $lic_file ||
error "Failed to set ownership of the LICENSE file for $DIRNAME"
fi
if [ ! -h $ETC_DYN_APP_CONF ] && [ -r $PKG_ETC_DYN_APP_CONF ]; then
ln -sf $PKG_ETC_DYN_APP_CONF $ETC_DYN_APP_CONF ||
error "Failed to create link: $ETC_DYN_APP_CONF"
fi
if [ ! -h $ETC_DYN_PARAM_APP_CONF ] &&
[ -r $PKG_ETC_DYN_PARAM_APP_CONF ]; then
ln -sf $PKG_ETC_DYN_PARAM_APP_CONF $ETC_DYN_PARAM_APP_CONF ||
error "Failed to create link: $ETC_DYN_PARAM_APP_CONF"
fi
if [ "$APPTYPE" != lua ] && [ ! -h $DBUS_FILE ]; then
ln -sf $PKG_DBUS_FILE $DBUS_FILE ||
error "Failed to create link: $DBUS_FILE"
fi
}
reload_configs() {
dbus-send --system --type=method_call --dest=org.freedesktop.DBus / \
org.freedesktop.DBus.ReloadConfig ||
error "Failed to reload DBus configuration."
if [ -r "$ETC_DYN_PARAM_APP_CONF" ]; then
$PHC readgroupfile $ETC_DYN_PARAM_APP_CONF ||
error "Failed to read group file ($ETC_DYN_PARAM_APP_CONF)."
fi
}
set_up_certificates() {
if [ "$CERTSETNAME" ]; then
case $CERTSETACTOR in
client|server)
;
*)
error "Failed to create certificate set: CERTSETACTOR"\
"should be 'client' or 'server'"
;
esac
[ "$CERTSETPROTOCOL" ] ||
error "Failed to create certificate set: empty CERTSETPROTOCOL"
gdbus call -y -d com.axis.PolicyKitCert \
-o /com/axis/PolicyKitCert \
-m com.axis.PolicyKitCert.CertSetCreate \
"$CERTSETNAME" "$APPNAME" "$CERTSETACTOR" \
"$CERTSETPROTOCOL" $(id -u $APPUSR) ||
error "Failed to create certificate set"
fi
}
clean_up_certificates() {
if [ "$CERTSETNAME" ]; then
local _continue=ok
case $CERTSETACTOR in
client|server)
;
*)
_continue=
warning "Failed to clean up certificate set: CERTSETACTOR"\
"should be 'client' or 'server'"
;
esac
[ "$CERTSETPROTOCOL" ] || {
_continue=
warning "Failed to delete certificate sets: empty CERTSETPROTOCOL"
}
[ -z "$_continue" ] ||
gdbus call -y -d com.axis.PolicyKitCert \
-o /com/axis/PolicyKitCert \
-m com.axis.PolicyKitCert.CertSetDeleteAll \
"$APPNAME" "$CERTSETACTOR" "$CERTSETPROTOCOL" ||
error "Failed to delete certificate sets"
fi
}
binary_specific_install() {
local line entry type param
chmod 755 $ABSAPPNAME || error "Failed to change permissions on $ABSAPPNAME"
case $STARTMODE in
once|never)
create_initscript
;
respawn)
create_initscript respawn
;
esac
create_initwrap_service respawn
if [ "$is_reinstall" != yes ]; then
mkdir -p $DATA_DIR || error "Failed to create dir $DATA_DIR"
chown $APPUSR:$APPGRP $DATA_DIR ||
error "Failed to set file ownership on $DATA_DIR."
mkdir -p $ETC_DYN_PARAM || error "Failed to create dir $ETC_DYN_PARAM"
mkdir -p $ETC_DYN || error "Failed to create dir $ETC_DYN"
cat <<-EOF > $PKG_ETC_DYN_PARAM_APP_CONF.tmp
group $GROUPNAME {
parser = Standard2parser
file = "$ETC_DYN_APP_CONF"
dbus = "--system --dest=com.axis.Param.$APPNAME /com/axis/Param/$APPNAME com.axis.Param.ChangeNotification string:'\$NAME' string:'\$VALUE'"
accessControl = "admin:3;$APPGRP:3;operator:1;viewer:1"
EOF
echo "[$GROUPNAME]" > $PKG_ETC_DYN_APP_CONF.tmp
if [ -r $ADPPACKPARAMCFG ]; then
while read -r line; do
entry=$(echo $line | sed -rne 's/^[[:space:]]*([[:alnum:]]*)[[:space:]]*=[[:space:]]*"?([^"]*)"?.*/\1="\2"/p')
if [ "$entry" ]; then
type=$(echo $line | sed -rne 's/.*type[[:space:]]*=[[:space:]]*"([^"]*)"[[:space:]]*$/\1/p')
[ "$type" ] || type=string
param=${entry%%=*}
cat <<-EOF >> $PKG_ETC_DYN_PARAM_APP_CONF.tmp
param $param {
mount = "Standard2{$GROUPNAME}{$param}"
type = "$type"
}
EOF
echo $entry >> $PKG_ETC_DYN_APP_CONF.tmp
fi
done < $ADPPACKPARAMCFG
fi
echo "}" >> $PKG_ETC_DYN_PARAM_APP_CONF.tmp
chown $APPUSR:$APPGRP $PKG_ETC_DYN_APP_CONF.tmp ||
error "Failed to chown on $PKG_ETC_DYN_APP_CONF.tmp."
chown $APPUSR:$APPGRP $PKG_ETC_DYN_PARAM_APP_CONF.tmp ||
error "Failed to chown on $PKG_ETC_DYN_PARAM_APP_CONF.tmp."
fsynced_write_or_cleanup $PKG_ETC_DYN_APP_CONF.tmp $PKG_ETC_DYN_APP_CONF
fsynced_write_or_cleanup $PKG_ETC_DYN_PARAM_APP_CONF.tmp $PKG_ETC_DYN_PARAM_APP_CONF
cat <<-EOF > $PKG_DBUS_FILE.tmp
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Only root or user $APPUSR can own the $APPNAME service. -->
<policy user="$APPUSR">
<allow own="com.axis.Param.$APPNAME"/>
<allow send_destination="com.axis.Param.$APPNAME"/>
<allow receive_sender="com.axis.Param.$APPNAME"/>
</policy>
<policy user="root">
<allow own="com.axis.Param.$APPNAME"/>
<allow send_destination="com.axis.Param.$APPNAME"/>
<allow receive_sender="com.axis.Param.$APPNAME"/>
</policy>
<policy context="default">
<allow send_destination="com.axis.Param.$APPNAME"/>
<allow receive_sender="com.axis.Param.$APPNAME"/>
</policy>
</busconfig>
EOF
chmod 644 $PKG_DBUS_FILE.tmp || error "Failed to chmod on $PKG_DBUS_FIL.tmp"
fsynced_write_or_cleanup $PKG_DBUS_FILE.tmp $PKG_DBUS_FILE
fi
}
add_file_to_url_conf() {
local url_conf_file url_group url_file url_base_file
[ $# -eq 2 ] || error "Wrong number of arguments"
[ "$1" ] && url_conf_file=$1 || error "Configuration file not specified"
[ "$2" ] && url_file=$2 || error "Failed to read file (file not found)"
unset IFS
# This function will always be called with the path to a directory first
# and then additional calls are made with the paths to the files in the
# directory. We simply ignore the directories.
[ ! -d $url_file ] || return 0
url_group=$(stat -c "%G" $url_file)
[ "$url_group" = 'admin' ] || [ "$url_group" = 'operator' ] || \
[ "$url_group" = 'viewer' ] || url_group='admin'
url_base_file=$(basename $url_file)
echo " <Files \"$url_base_file\">
Require axis-group $url_group
" >> $url_conf_file || error "Failed add config for '$url_base_file' in '$url_conf_file'"
[ "$url_file" != "$INSTALLDIR/$DIRNAME/html/LICENSE" ] || \
echo " Header set Content-Type \"text/plain; charset=utf-8\"
" >> $url_conf_file || error "Failed add Content-Type config for '$url_base_file' in '$url_conf_file'"
echo "</Files>" >> $url_conf_file || error "Failed end config for '$url_base_file' in '$url_conf_file'"
cmd="chmod g+r $url_file"
$cmd || warning "'$cmd' failed"
cmd="chgrp www $url_file"
$cmd || warning "'$cmd' failed"
}
gen_url_conf() {
local url_conf_file dir files file
[ $# -eq 2 ] || error "Wrong number of arguments"
[ "$1" ] && url_conf_file=$1 ||
error "Failed to complete, missing argument url_conf_file"
[ "$2" ] && dir=$2 || error "Failed to complete, missing argument dir"
files=$(ls -A $dir)
if [ "$files" ]; then
for file in $files; do
add_file_to_url_conf $url_conf_file $dir/$file
done
fi
}
install_urls() {
local acap_name dir dirs subdir url_conf_tmpfile url_conf_file url_dir
[ $# -eq 2 ] || error "Wrong number of arguments"
[ "$1" ] && acap_name=$1 || error "Failed to complete, missing argument acap_name"
[ "$2" ] && dir=$2 || error "Failed to complete, missing argument dir"
url_conf_tmpfile=$ETC_VHOSTS_ALL/urls_$acap_name.conf.tmp
url_conf_file=$ETC_VHOSTS_ALL/urls_$acap_name.conf
rm -f $url_conf_file 1>/dev/null 2>&1
rm -f $url_conf_tmpfile 1>/dev/null 2>&1
dirs=$(find $dir -type d)
for subdir in $dirs; do
if [ "$dir" = "$subdir" ]; then
url_dir=$ACAP_DOC_ROOT/$acap_name
else
url_dir=$ACAP_DOC_ROOT/$acap_name/$(basename $subdir)
fi
echo "<Directory \"$url_dir\">" >> \
$url_conf_tmpfile ||
error "Failed to write begining to '$url_conf_tmpfile'"
gen_url_conf $url_conf_tmpfile $subdir
echo "</Directory>" >> $url_conf_tmpfile ||
error "Failed to write end to '$url_conf_tmpfile'"
done
fsynced_write_or_cleanup $url_conf_tmpfile $url_conf_file
}
install() {
local dir=
if [ "$is_reinstall" != yes ]; then
information "Installing $APPNAME in $INSTALLDIR/$DIRNAME"
else
information "Re-installing $APPNAME in $INSTALLDIR/$DIRNAME"
[ ! -d "$BAK_DIR" ] || rm -rf $BAK_DIR
fi
handle_eventdecl -d $INSTALLDIR/$DIRNAME/declarations -n $APPNAME -a ||
error "Failed to handle_eventdecl illegal declaration template"
mkdir -p $PKG_CONFDIR || error "Failed to mkdir -p $PKG_CONFDIR"
chmod 755 $PKG_CONFDIR || error "Failed to change permissions on $PKG_CONFDIR"
if [ "$is_reinstall" != yes ]; then
echo ENABLED=no > $RUNSTATE_CONF.tmp || error "Failed to write to $RUNSTATE_CONF.tmp"
chmod 644 $RUNSTATE_CONF.tmp || error "Failed to change permissions on $RUNSTATE_CONF.tmp"
fsynced_write_or_cleanup $RUNSTATE_CONF.tmp $RUNSTATE_CONF
fi
chown -Rh $APPUSR:admin $INSTALLDIR/$DIRNAME ||
error "Failed to chown -R $APPUSR:admin '$INSTALLDIR/$DIRNAME'"
if [ "$HTTPCGIPATHS" ] || [ "$LICENSENAME" ] && [ ! -d $INSTALLDIR/$DIRNAME/html ]; then
mkdir -p $INSTALLDIR/$DIRNAME/html ||
error "Failed to create directory: $INSTALLDIR/$DIRNAME/html"
fi
if [ "$APPTYPE" != lua ]; then
binary_specific_install
else
create_lua_service
fi
if [ -d "$BAK_DIR" ]; then
if __restore_app $INSTALLDIR/$DIRNAME $BAK_DIR; then
information "Restored config for '$APPNAME'"
else
warning "Failed to restore config for '$APPNAME'"
fi
rm -rf "$BAK_DIR"
fi
chmod 644 $INSTALLDIR/$DIRNAME/$ADPPACKCFG || {
warning "Failed to make $ADPPACKCFG readable for $APPNAME"
}
}
create_preupgrade_service() {
information "Preupgrade script $2 executed as user $1"
printf "\
[Unit]
Description=%s
[Service]
User=%s
Type=oneshot
ExecStart=/bin/sh %s
WorkingDirectory=%s/%s
" $PREUPGRADE_SERVICE $1 $2 $INSTALLDIR $APPNAME > $ETC_SYSTEMD_DIR/$PREUPGRADE_SERVICE_FILENAME
}
remove_preupgrade_service() {
rm $ETC_SYSTEMD_DIR/$PREUPGRADE_SERVICE_FILENAME ||
warning "Failed to remove $ETC_SYSTEMD_DIR/$PREUPGRADE_SERVICE_FILENAME"
}
run_pre_upgrade() {
[ $# -eq 1 ] || {
warning "Missing argument to perform preupgrade. Aborting"
return 0
}
[ -r $1 ] || {
warning "Failed to read the preupgrade script provided by $APPNAME"
return 0
}
information "Executing preupgrade script"
create_preupgrade_service $APPUSR $1
systemctl start $PREUPGRADE_SERVICE >/dev/null 2>&1 || {
warning "Preupgrade script provided by $APPNAME returned error code $?"
systemctl reset-failed $PREUPGRADE_SERVICE > /dev/null 2>&1 ||
warning "Failed to reset failed service $PREUPGRADE_SERVICE with error code $?"
}
remove_preupgrade_service
}
create_postinstall_service() {
information "Run $APPNAME/$POSTINSTALLSCRIPT as $1"
printf "\
[Unit]
Description=%s
[Service]
User=%s
Type=oneshot
ExecStart=/bin/sh %s/%s/%s
WorkingDirectory=%s/%s
" $POSTINSTALL_SERVICE $1 $INSTALLDIR $APPNAME $POSTINSTALLSCRIPT $INSTALLDIR $APPNAME > $ETC_SYSTEMD_DIR/$POSTINSTALL_SERVICE_FILENAME
}
remove_postinstall_service() {
rm $ETC_SYSTEMD_DIR/$POSTINSTALL_SERVICE_FILENAME ||
warning "Failed to remove $ETC_SYSTEMD_DIR/$POSTINSTALL_SERVICE_FILENAME"
}
run_post_install() {
[ "$POSTINSTALLSCRIPT" ] || return 0
[ -r "$POSTINSTALLSCRIPT" ] || {
warning "Failed to read $POSTINSTALLSCRIPT"
return 0
}
information "Run $PACKAGENAME post install script $POSTINSTALLSCRIPT"
if [ $LIMITED_POSTINSTALL = yes ]; then
create_postinstall_service $APPUSR
else
create_postinstall_service root
fi
systemctl --quiet status $POSTINSTALL_SERVICE >/dev/null 2>&1 ||
[ $? != 4 ] || systemctl --quiet daemon-reload >/dev/null 2>&1
systemctl start $POSTINSTALL_SERVICE >/dev/null 2>&1 || {
warning "Failed to run $POSTINSTALLSCRIPT"
systemctl reset-failed $POSTINSTALL_SERVICE > /dev/null 2>&1 ||
warning "Failed to reset failed service $POSTINSTALL_SERVICE with error code $?"
}
remove_postinstall_service
chmod 644 $INSTALLDIR/$DIRNAME/$ADPPACKCFG || {
warning "Failed to make $ADPPACKCFG readable for $APPNAME"
}
}
binary_specific_uninstall() {
rm -f $ETC_TRANSFER_CONF/transfer_$APPNAME.conf
rm -f $ETC_TRANSFER_CONF/legacy_transfer_$APPNAME.conf
rm -f $ETC_MIME_CONF/legacy_mime_$APPNAME.conf
rm -rf $HTTP_VAR_RUN/$APPNAME
rm -f $ETC_DYN_PARAM_APP_CONF
rm -f $ETC_DYN_APP_CONF
$PHC deletegroup $GROUPNAME >/dev/null 2>&1 || :
}
remove_package_dir() {
rm -rf $INSTALLDIR/$DIRNAME
}
read_enabled() {
local enb=no var= val= IFS==
if [ -r $RUNSTATE_CONF ]; then
while read var val; do
case $var in
ENABLED)
eval enb=$val
;
*)
$log_info "unknown runstate $var for $APPNAME"
;
esac
done < $RUNSTATE_CONF
else
$log_info "no runstate for $APPNAME"
fi
echo $enb
}
keep_runstate() {
# first check that this acap uses systemd
[ -r $ETC_SYSTEMD_APPNAME ] || return 0
enabled=$(read_enabled)
if [ $STARTMODE != never ] && [ $enabled = yes ]; then
systemctl enable $SYSTEMD_SERVICE_FILENAME ||
warning "Failed to enable $SYSTEMD_SERVICE_FILENAME"
fi
if [ $STARTMODE = never ] && [ $enabled = yes ]; then
echo ENABLED=no >$RUNSTATE_CONF ||
warning "Failed to set runstate for $RUNSTATE_CONF"
fi
}
uninstall() {
local runlevel
[ "$APPTYPE" = lua ] || binary_specific_uninstall
handle_eventdecl -d $INSTALLDIR/$DIRNAME/declarations -n $APPNAME -r
rm -rf $WEB_DIR/$APPNAME
if [ "$APPTYPE" != lua ]; then
rm -f $ETC_INIT_D_APPNAME
fi
rm -f $ETC_SYSTEMD_APPNAME
rm -f $DBUS_FILE
}
case $2 in
yes)
information "Limited access rights for $APPNAME"
LIMITED_POSTINSTALL=yes
;
*)
esac
case $1 in
backup)
backup
;
preupgrade)
run_pre_upgrade $2
information "$APPNAME has been successfully pre upgraded (OK)"
;
install)
install
create_config_links
set_up_certificates
reload_configs
run_post_install
information "$APPNAME has been successfully installed (OK)"
;
reinstall|reinstall-forced)
is_reinstall=yes
install
keep_runstate
create_config_links
set_up_certificates
reload_configs
run_post_install
information "$APPNAME has been successfully re-installed (OK)"
;
uninstall)
clean_up_certificates
uninstall
remove_package_dir
reload_configs
;
*)
information "usage: $0 backup|preupgrade|install|reinstall|uninstall"
exit 1
;
esac