#!/bin/sh -e
#
# (C) Copyright 2015-2018 Axis Communications AB, LUND, SWEDEN
. /usr/lib/addon-common
usage() {
local script_name=${0##*/}
echo "This script is used for listing installed add-ons packages.
Usage:
--------------
$script_name List all add-ons and their information(*)
$script_name -i <appname> - List specified add-on's information(*)
$script_name -<option(s)>
Options:
---------------
-n list all addons
-c version
-v version name
-a add-on nice name
-m maintainer nice name
-l license
-s signature status
-w main webpage
-t status of the add-on
Information(*):
---------------
addon-name Name of the add-on.
name Nice name of add-on.
maintainer-name Maintainer nice name.
version Version of the add-on.
version-name Version name of the add-on.
license The licenses in use.
signature Tells if the add-on is signed or not.
webpage The mainpage.
status Status of an add-on.
generation Current add-on generation.
"
exit $1
}
get_status() {
# Get status from an add-on. This function is called locally in this
# script with the output from OPKG list which means that it will only
# be called with add-on names of add-ons which OPKG considers to be
# installed, in line with the behaviour of addon-list as a whole the
# use case of an empty parameter will NOT be considered erroneous but
# instead result in a non-existent output and a graceful return.
# Arguments
# $1: an installed Add-on as listed by OPKG-list on the format
# "name blank - version"
local status
# Disregard error return value from "systemctl is-active" if addon is not
# running or not installed. The printed text will be correct.
status=$(systemctl is-active ${1%%[[:blank:]]*}.service || :)
# All add-ons that are stopped (without error) shall be reported as
# inactive. Handle that systemctl reports "non-activated" add-ons as
# "unknown", not inactive.
[ "$status" != unknown ] || status=inactive
eval $2=\$status
}
get_manifest_element_data() {
# Parse and extract an element from manifest
# $1 - Element path
# $2 - Variable that will be assigned with the element data
# $3 - Optional boolean variable to mark if optional manifest element
[ $# -ge 2 ] && [ "$1" ] && [ "$2" ] || {
syslog_err "addon-info" "get_manifest_element_data: Missing argument"
exit 1
}
local _result _opt=true
# If optional variable true, we should not set an error for empty result
[ $# -eq 3 ] && [ $3 ] || _opt=false
_result="$(xmllint --xpath "string(/$1)" $MANIFEST_FILE 2>/dev/null)" ||
fail_errorcode $ERR_MANIFEST "Error when parsing manifest"
[ "$_result" ] || [ $_opt = true ] || {
syslog_err "addon-info" "get_manifest_element_data: Could not find element $1"
exit 1
}
eval $2=\$_result
}
escape_delimiter_character() {
# To separate delimiter ' ^ ' from any other use in free typing strings all
# characters '^' are escaped with character '~'
# The same variable may be used for unescaped and escaped string
# $1 - Variable with unescaped string
# $2 - Variable that will be assigned with escaped string
[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] || {
syslog_err "addon-info" "escape_delimiter_character: Missing argument"
exit 1
}
local continue_iter=false delimiter="^" _remain="$1" _escaped=
[ "${1#*$delimiter}" = "$1" ] || continue_iter=true
while [ $continue_iter = true ]; do
case $_remain in
*$delimiter*)
_escaped=$_escaped${_remain%%$delimiter*}"~^"
_remain=${_remain#*$delimiter}
;
*)
continue_iter=false
;
esac
done
eval $2=\$_escaped\$_remain
}
get_manifest_major() {
# Get the manifest major version from the Manifest file
# $1 - Variable that will be assigned with manifest major.
[ $# -eq 1 ] && [ "$1" ] || {
syslog_err "addon-info" "get_manifest_major: Missing argument"
exit 1
}
local major
get_manifest_element_data /Manifest/@Major major
eval $1=\$major
}
get_license() {
# Get the license name from the Manifest file
# $1 - Variable that will be assigned with the license name
[ $# -eq 1 ] && [ "$1" ] || {
syslog_err "addon-info" "get_license: Missing argument"
exit 1
}
local license_name
get_manifest_element_data "/Manifest/License/text()" license_name
escape_delimiter_character "$license_name" license_name
eval $1=\$license_name
}
get_version_name() {
# Get the version name from the Manifest file
# $1 - Variable with manifest major version.
# $2 - Variable that will be assigned with version name.
[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] || {
syslog_err "addon-info" "get_version_name: Missing argument"
exit 1
}
local version_name
if [ $1 -ge 2 ]; then
local version version_info
get_manifest_element_data "/Manifest/PackageInfo/Version/text()" version
get_manifest_element_data /Manifest/PackageInfo/Version/@Info version_info true
[ $version ] || {
syslog_err "addon-info" "get_version_name: Could not get version"
exit 1
}
[ -z $version_info ] && version_name=$version ||
version_name="$version $version_info"
elif [ $1 -eq 1 ]; then
get_manifest_element_data /Manifest/PackageInfo/Version/@Name version_name
else
syslog_err "addon-info" "get_version_name: Incorrect manifest version"
exit 1
fi
escape_delimiter_character "$version_name" version_name
eval $2=\$version_name
}
get_nice_name() {
# Get the nice add-on name from the Manifest file
# $1 - Variable that will be assigned with nice name.
[ $# -eq 1 ] && [ "$1" ] || {
syslog_err "addon-info" "get_nice_name: Missing argument"
exit 1
}
local nice_name
get_manifest_element_data Manifest/PackageInfo/Name/@NiceName nice_name
escape_delimiter_character "$nice_name" nice_name
eval $1=\$nice_name
}
get_nice_maintainer() {
# Get the nice add-on maintainer name from the Manifest file
# $1 - Variable that will be assigned with nice maintainer name.
[ $# -eq 1 ] && [ "$1" ] || {
syslog_err "addon-info" "get_nice_maintainer: Missing argument"
exit 1
}
local nice_maintainer
get_manifest_element_data /Manifest/PackageInfo/Maintainer/@NiceName nice_maintainer
escape_delimiter_character "$nice_maintainer" nice_maintainer
eval $1=\$nice_maintainer
}
get_signed_state()
{
#Check whether an addon has been signed
# Arguments:
# $1 - pkg to check for signed state
local signed eof=
while [ -z "$eof" ]; do
read LINE || eof=true ## detect eof, but have a last round
[ "$LINE" = "${1%%[[:blank:]]*}" ] && signed=unsigned && break ||
signed=signed
done</etc/opkg/addon/addonunsigned
echo $signed
}
get_mainwebpage_info() {
# Get the mainwebpage info from the Manifest file
# $1 - Variable that will be assigned with main webpage
# $2 - The package name, used for the main-webpage path construction
[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] || {
syslog_err "addon-info" "get_mainwebpage_info: Missing arguments"
exit 1
}
local webpage_name
get_manifest_element_data "/Manifest/Supplies/WebContent/MainPage/text()" webpage_name true
[ "$webpage_name" ] && webpage_name=local/$2/$webpage_name ||
webpage_name=none
eval $1=\$webpage_name
}
# Addon name will be assigned if -i used used
addon_name=
addon_attr=
while getopts hi:namcvlswt opt; do
case $opt in
h)
# Print usage
usage 0
;
i)
addon_name=$OPTARG
;
n)
addon_attr="$addon_attr addons"
;
a)
addon_attr="$addon_attr name"
;
m)
addon_attr="$addon_attr maintainer"
;
c)
addon_attr="$addon_attr version"
;
v)
addon_attr="$addon_attr vername"
;
l)
addon_attr="$addon_attr license"
;
s)
addon_attr="$addon_attr signed"
;
w)
addon_attr="$addon_attr webpage"
;
t)
addon_attr="$addon_attr status"
;
\?)
# Print usage with error
usage 1
;
esac
done
shift $(($OPTIND - 1))
if [ "$addon_name" ]; then
is_package_name_valid "$addon_name" result ||
fail_errorcode $ERR_INVALID_PKG_NAME "Failed to validate package name: $addon_name"
[ $result -eq $TRUE ] || fail_errorcode $ERR_INVALID_PKG_NAME "Package name $addon_name contains illegal characters only " "[a-z0-9.+-] is allowed"
fi
# If -i is used only that addon will be listed
# If no options are specified then all addons will be listed.
list_addon=$($OPKG list-installed $addon_name) || {
syslog_err "addon-info: Failed to list installed add-ons"
exit 1
}
oldIFS=$IFS
newlineIFS='
'
IFS=$newlineIFS
for pkg in $list_addon; do
# Change delimiter to " ^ "
pkg="${pkg%% *} ^ ${pkg##* }"
_signed=$(get_signed_state $pkg)
MANIFEST_FILE=$MANIFEST_PATH/${pkg%%[[:blank:]]*}_manifest.xml
[ -f $MANIFEST_FILE ] || {
syslog_err "addon-info: Manifest file not found"
exit 1
}
[ -r $MANIFEST_FILE ] || {
syslog_err "addon-info: Manifest file not readable"
exit 1
}
get_manifest_major _manifest_major
get_license _license_name
get_version_name $_manifest_major _version_name
[ $_manifest_major -ne 2 ] || {
get_nice_name _nice_name
get_nice_maintainer _nice_maintainer
}
get_status $pkg _status
get_mainwebpage_info _webpage_name ${pkg%%[[:blank:]]*}
if [ "$addon_attr" ]; then
# Reset the IFS to default value
IFS=$oldIFS
addon_attr_list="${pkg%%[[:blank:]]*}"
[ "$addon_attr" = addons ] || {
for attr in $addon_attr; do
case $attr in
addons)
continue
;
version)
addon_attr_list="$addon_attr_list ^ ${pkg##*[[:blank:]]}"
;
name)
[ $_manifest_major -ne 2 ] ||
addon_attr_list="$addon_attr_list ^ $_nice_name"
;
maintainer)
[ $_manifest_major -ne 2 ] ||
addon_attr_list="$addon_attr_list ^ $_nice_maintainer"
;
vername)
addon_attr_list="$addon_attr_list ^ $_version_name"
;
license)
addon_attr_list="$addon_attr_list ^ $_license_name"
;
signed)
addon_attr_list="$addon_attr_list ^ $_signed"
;
webpage)
addon_attr_list="$addon_attr_list ^ $_webpage_name"
;
status)
addon_attr_list="$addon_attr_list ^ $_status"
;
esac
done
}
# Restore the IFS to previus value
IFS=$newlineIFS
# Print out the filtered attributes
echo $addon_attr_list
elif [ $_manifest_major -ge 2 ]; then
echo $pkg ^ $_version_name ^ $_license_name ^ $_signed ^ $_webpage_name ^ $_status ^ 3 ^ $_nice_name ^ $_nice_maintainer
else
echo $pkg ^ $_version_name ^ $_license_name ^ $_signed ^ $_webpage_name ^ $_status ^ 3
fi
done