summaryrefslogtreecommitdiff
path: root/src/pkgbuild-check-nonfree
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkgbuild-check-nonfree')
-rwxr-xr-xsrc/pkgbuild-check-nonfree301
1 files changed, 244 insertions, 57 deletions
diff --git a/src/pkgbuild-check-nonfree b/src/pkgbuild-check-nonfree
index 1cc0d9b..18fac91 100755
--- a/src/pkgbuild-check-nonfree
+++ b/src/pkgbuild-check-nonfree
@@ -1,9 +1,11 @@
#!/usr/bin/env bash
+# -*- tab-width: 4 ; sh-basic-offset: 4 -*-
# pkgbuild-check-nonfree
# Copyright 2010 Haase Hernández
# Copyright 2010 Joseph Graham
# Copyright 2010 Joshua Ismael
+# Copyright 2010 Nicolás Reynolds
# Copyright 2012-2013 Luke Shumaker
#
# This file is part of Parabola.
@@ -21,80 +23,61 @@
# You should have received a copy of the GNU General Public License
# along with Parabola. If not, see <http://www.gnu.org/licenses/>.
-. libremessages
-. libreblacklist
-. $(librelib conf)
-
-# Usage: check_deps $pkgbuild
-# Check whether a PKGBUILD package depends on non-free packages
-check_deps() (
- # Note that we use () instead of {} for this function; so that variables
- # from the PKBUILD don't bubble up
- local pkgbuild=$1
- load_PKGBUILD "$pkgbuild"
- if [[ -z "$pkgname" ]]; then
- exit 1 # not a PKGBUILD
- fi
+# I appologize that this program got *huge*.
+# It's not complicated, just long.
- msg2 'Looking for unfree dependencies of %s %s' "${pkgbase:-${pkgname[0]}}" "$(get_full_version)"
-
- local pkgs=(
- # packages being built
- "${pkgname[@]}"
- # depends
- "${depends[@]}" "${makedepends[@]}" "${checkdepends[@]}" "${optdepends[@]%%:*}"
- # mksource depends
- "${mkdepends[@]}"
- )
- local ret=0
- for pkg in "${pkgs[@]}"; do
- local line="$(blacklist-cat|blacklist-lookup "$pkg")"
- local rep="$(blacklist-get-rep <<<"$line")"
- if [[ -z $line ]]; then
- # not mentioned in blacklist; free
- plain '%s: not blacklisted' "$pkg"
- continue
- elif [[ -z $rep ]]; then
- # non-free with no replacement
- plain '%s: blacklisted' "$pkg"
- ret=1
- else
- # non-free with free replacement
- if [[ "$rep" == "$pkg" ]]; then
- plain '%s: repackaged with the same name' "$pkg"
- else
- plain '%s: replaced by %s' "$pkg" "$rep"
- fi
- fi
- done
- return $ret
-)
+. $(librelib messages)
+. $(librelib conf)
+. $(librelib blacklist)
usage() {
print "Usage: %s [OPTIONS] [PKGBUILD1 PKGBUILD2 ...]" "${0##*/}"
+ print "Analyzes a PKGBUILD for freedom issues"
echo
prose 'If no PKGBUILD is specified, `./PKGBUILD` is implied.'
echo
- print "Exit status:"
+ print "Exit status (add them for combinations):"
print " 0: Everything OK, no freedom issues"
print " 1: Ran with error"
- print " 15: Depends on non-free packages"
+ print "Warning-level freedom issues:"
+ print " 2: Uses unrecognized licenses, check them"
+ print " 4: Uses GPL-incompatible licenses"
+ print "Error-level freedom issues:"
+ print " 8: Uses known unacceptable licenses"
+ print " 16: Has nonfree dependencies"
+ print " 32: Is a known nonfree package"
echo
print "Options:"
- flag '-c' 'Use the cached blacklist, do not try downloading.'
+ flag '-c' 'Use the cached blacklist, do not try downloading'
flag '-f' 'Allow running as root user'
+ echo
+ flag '-q' 'Be quiet'
+ flag '-v' 'Be verbose'
+ echo
flag '-h' 'Show this message'
}
+# Make sure these match pkgbuild-summarize-nonfree
+declare -ri _E_OK=0
+declare -ri _E_ERROR=1
+declare -ri _E_LIC_UNKNOWN=2
+declare -ri _E_LIC_NOGPL=4
+declare -ri _E_LIC_NONFREE=8
+declare -ri _E_DEP_NONFREE=16
+declare -ri _E_PKG_NONFREE=32
main() {
- local asroot=false
+ # Parse flags
local cache=false
- while getopts 'cfh' arg; do
+ local asroot=false
+ local v=1
+ while getopts 'cfqvh' arg; do
case "$arg" in
c) cache=true;;
f) asroot=true;;
- h) usage; return 0;;
- *) usage; return 1;;
+ q) v=0;;
+ v) v=2;;
+ h) usage; return $_E_OK;;
+ *) usage >&2; return $_E_ERROR;;
esac
done
shift $(($OPTIND - 1))
@@ -104,18 +87,222 @@ main() {
pkgbuilds=("$@")
fi
+ # Do a check to see if we are running as root
if [[ -w / ]] && ! $asroot; then
error "Run as normal user, or use the -f option to run as root."
return 1
fi
- $cache || blacklist-update || return 1
+ # Adjust the verbosity
+ if [[ $v == 0 ]]; then
+ error() { :; }
+ warning() { :; }
+ plain() { :; }
+ info() { :; }
+ elif [[ $v == 1 ]]; then
+ info() { :; }
+ elif [[ $v == 2 ]]; then
+ info() { plain "$@"; }
+ fi
+
+ # Update the blacklist
+ $cache || blacklist-update || return $_E_ERROR
- local ret=0
+ # Do the work
+ declare -i ret=0
+ local pkgbuild
for pkgbuild in "${pkgbuilds[@]}"; do
- check_deps "$pkgbuild" || ret=15
+ pkgbuild_check "$pkgbuild" || ret=$(($ret|$?))
done
return $ret
}
+# Helper functions #############################################################
+# These should maybe be moved into lib/conf.sh
+
+# Usage: var="$(pkgbuild_get_pkg_str ${pkgname} ${varname})"
+# Gets a package-level string for a split-package
+pkgbuild_get_pkg_str() {
+ [[ $# == 2 ]] || panic 'malformed call to pkgbuild_get_pkg_str'
+ local pkg=$1
+ local var=$2
+
+ local indirect=${!var}
+ eval $(declare -f package_$pkg | sed -rn "s/^\s*${var}(\+?=)/indirect\1/p")
+ printf '%s' "${indirect}"
+}
+# Usage: eval $(pkgbuild_get_pkg_ary ${pkgname} ${varname} [$variable_name_to_set])
+# Gets a package-level array for a split-package
+pkgbuild_get_pkg_ary() {
+ [[ $# == 2 ]] || [[ $# == 3 ]] || panic 'malformed call to pkgbuild_get_pkg_ary'
+ local pkg=$1
+ local var=$2
+ local out="${3:-$var}"
+
+ local ary="${var}[@]"
+ local indirect=("${!ary}")
+ eval $(declare -f package_$pkg | sed -rn "s/^\s*${var}(\+?=)/indirect\1/p")
+ declare -p indirect|sed "s/ indirect=/ ${out}=/"
+}
+
+# Checker functions ############################################################
+
+# Usage: check_lic "${licence}"
+# Check a license name to see if it is OK
+check_lic() {
+ [[ $# == 1 ]] || panic 'malformed call to check_license'
+ local license=$1
+
+ info 'Checking license: %s' "$license"
+
+ if [[ -e "/usr/share/licenses/common/$license" ]]; then
+ return $_E_OK
+ else
+ case "${license#custom:}" in
+ WTFPL)
+ # accept as common, I think it should be in the licenses package
+ return $_E_OK;;
+ BSD1|BSD2|BSD3|MIT|X11)
+ # accept these as common; they can't be included in the
+ # 'licenses' package because some text must be customized
+ return $_E_OK;;
+ BSD4)
+ warning "The 4-clause BSD license is free but has practical problems."
+ return $_E_LIC_NOGPL;;
+ BSD)
+ warning "License 'BSD' is ambiguous, use 'BSD{1..4}' to specify the number of clauses."
+ return $_E_LIC_UNKNOWN;;
+ JSON)
+ error "License '%s' is a known non-free license." "$license"
+ return $_E_LIC_NONFREE;;
+ *)
+ warning "License '%s' is not a common (recognized) license." "$license"
+ return $_E_LIC_UNKNOWN;;
+ esac
+ fi
+ panic 'code should never be reached'
+}
+
+# Usage: check_dep "${dependency}"
+# Checks for ${dependency} in the blacklist
+check_dep() {
+ [[ $# == 1 ]] || panic 'malformed call to check_dep'
+ local pkg=$1
+
+ local line="$(blacklist-cat|blacklist-lookup "$pkg")"
+ local rep="$(blacklist-get-rep <<<"$line")"
+ if [[ -z $line ]]; then
+ # not mentioned in blacklist; free
+ info '%s: not blacklisted' "$pkg"
+ return $_E_OK
+ elif [[ -z $rep ]]; then
+ # non-free with no replacement
+ plain '%s: blacklisted' "$pkg"
+ return $_E_DEP_NONFREE
+ else
+ # non-free with free replacement
+ if [[ "$rep" == "$pkg" ]]; then
+ info '%s: repackaged with the same name' "$pkg"
+ else
+ info '%s: replaced by %s' "$pkg" "$rep"
+ fi
+ return $_E_OK
+ fi
+ panic 'code should never be reached'
+}
+
+# Usage: check_pkg "${pkgname}"
+# Checks for ${pkgname} in the blacklist
+check_pkg() {
+ [[ $# == 1 ]] || panic 'malformed call to check_pkg'
+ check_dep "$@"
+ case $? in
+ $_E_OK)
+ return $_E_OK;;
+ $_E_DEP_NONFREE)
+ return $_E_PKG_NONFREE;;
+ *)
+ panic 'unexpected return code from check_dep';;
+ esac
+ panic 'code should never be reached'
+}
+
+# Usage: pkgbuild_ckec $pkgbuild
+# Check whether a PKGBUILD has any issues (using the above)
+pkgbuild_check() (
+ [[ $# == 1 ]] || panic 'malformed call to pkgbuild_check'
+ local pkgbuild=$1
+
+ load_PKGBUILD "$pkgbuild"
+ if [[ -z $pkgname ]]; then
+ return $_E_ERROR # not a PKGBUILD
+ fi
+
+ declare -i ret=0 # the return status
+ local dep lic # iterators for us in `for` loops
+ local ck_deps ck_lics # lists of deps and licenses that have been checked
+
+ if [[ ${#pkgname[@]} == 1 ]]; then
+ msg2 'Inspecting package pkgname=%q (%s)' "$pkgname" "$(get_full_version)"
+ else
+ msg2 'Inspecting split package pkgbase=%q (%s)' "${pkgbase:-${pkgname[0]}}" "$(get_full_version)"
+ fi
+
+ # Check if this is blacklisted
+ check_pkg "${pkgbase:-${pkgname[0]}}" || ret=$(($ret|$?))
+ # Check if dependencies are blacklisted
+ for dep in "${depends[@]}" "${makedepends[@]}" "${checkdepends[@]}" \
+ "${optdepends[@]%%:*}" "${mkdepends[@]}"
+ do
+ check_dep "$dep" || ret=$(($ret|$?))
+ ck_deps+=("$dep")
+ done
+ # Check the licenses
+ for lic in "${license[@]}"; do
+ check_lic "$lic" || ret=$(($ret|$?))
+ ck_lics+=("$lic")
+ done
+
+ if [[ ${#pkgname[@]} == 1 ]]; then
+ # Non-split package
+ # Make sure a license is set
+ if [[ ${#ck_lics[@]} == 0 ]]; then
+ error "The license array is empty"
+ ret=$(($ret|$_E_ERROR))
+ fi
+ else
+ # Split package
+ # Check the individual split packages
+ local _pkgname _license _depends _optdepends
+ for _pkgname in "${pkgname[@]}"; do
+ msg2 'Inspecting split package pkgname=%q (%s)' "$_pkgname" "$(get_full_version "$_pkgname")"
+ eval $(pkgbuild_get_pkg_ary "$_pkgname" license _license)
+ eval $(pkgbuild_get_pkg_ary "$_pkgname" depends _depends)
+ eval $(pkgbuild_get_pkg_ary "$_pkgname" optdepends _optdepends)
+
+ # Check if this is blacklisted
+ check_pkg "$_pkgname" || ret=$(($ret|$?))
+ # Check if dependencies are blacklisted
+ for dep in "${_depends[@]}" "${_optdepends[@]%%:*}"; do
+ if ! in_array "$dep" "${ck_deps[@]}"; then
+ check_dep "$dep" || ret=$(($ret|$?))
+ fi
+ done
+ # Check the licenses
+ for lic in "${_license[@]}"; do
+ if ! in_array "$lic" "${ck_lics[@]}"; then
+ check_lic "$lic" || ret=$(($ret|$?))
+ fi
+ done
+
+ if [[ ${#_license[@]} == 0 ]]; then
+ error "The license array is empty"
+ ret=$(($ret|$_E_ERROR))
+ fi
+ done
+ fi
+
+ return $ret
+)
+
main "$@"