summaryrefslogtreecommitdiff
path: root/src/pkgbuild-check-nonfree
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkgbuild-check-nonfree')
-rwxr-xr-xsrc/pkgbuild-check-nonfree309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/pkgbuild-check-nonfree b/src/pkgbuild-check-nonfree
new file mode 100755
index 0000000..67f07bc
--- /dev/null
+++ b/src/pkgbuild-check-nonfree
@@ -0,0 +1,309 @@
+#!/usr/bin/env bash
+# -*- tab-width: 4 ; sh-basic-offset: 4 -*-
+# pkgbuild-check-nonfree
+
+# Copyright (C) 2011 Joseph Graham (Xylon) <joe@t67.eu>
+# Copyright (C) 2010-2011 Joshua Ismael Haase Hernández (xihh) <hahj87@gmail.com>
+# Copyright (C) 2010-2012 Nicolás Reynolds <fauno@parabola.nu>
+# Copyright (C) 2012-2013 Luke Shumaker <lukeshu@sbcglobal.net>
+#
+# License: GNU GPLv3+
+#
+# This file is part of Parabola.
+#
+# Parabola is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Parabola is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Parabola. If not, see <http://www.gnu.org/licenses/>.
+
+# I appologize that this program got *huge*.
+# It's not complicated, just long.
+
+. "$(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 (add them for combinations):"
+ print " 0: Everything OK, no freedom issues"
+ print " 1: Ran with error"
+ 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 '-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() {
+ # Parse flags
+ local cache=false
+ local asroot=false
+ local v=1
+ while getopts 'cfqvh' arg; do
+ case "$arg" in
+ c) cache=true;;
+ f) asroot=true;;
+ q) v=0;;
+ v) v=2;;
+ h) usage; return $_E_OK;;
+ *) usage >&2; return $_E_ERROR;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+ if [[ $# -lt 1 ]]; then
+ pkgbuilds=("`pwd`/PKGBUILD")
+ else
+ 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
+
+ # 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
+
+ # Do the work
+ declare -i ret=0
+ local pkgbuild
+ for pkgbuild in "${pkgbuilds[@]}"; do
+ 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 "$@"