[pacman-dev] [PATCH] pacman-key: better handling of options and supressing gpg output

Denis A. Altoé Falqueto denisfalqueto at gmail.com
Fri Apr 1 19:41:16 EDT 2011


The option --trust was changed to --edit-key, for better alignment
with the underlying --edit-key of gnupg.

The options --config and --gpgdir were not being handled correctly.
They would not work if were not used as first arguments always.
Now the handling is more flexible.

The use of gpg for verification purposes was leaking inconvenient
messages to the output, so they were quieted with --quiet,
1>/dev/null and 2>&1.

The check for existence of gpg and if user is root was
put in a function and called just when needed.

Signed-off-by: Denis A. Altoé Falqueto <denisfalqueto at gmail.com>
---
This patch is a remake of this one: http://mailman.archlinux.org/pipermail/pacman-dev/2011-February/012457.html. 
It is adapted for master branch. I've applied some suggestions from other emails regarding
that implementation, like a function to check if gpg exists and if user is root. It is called
just if an operation needs to check it, avoiding a special casing for -h or -v.

 doc/pacman-key.8.txt     |    4 +-
 scripts/pacman-key.sh.in |  137 ++++++++++++++++++++++++++++++----------------
 2 files changed, 92 insertions(+), 49 deletions(-)

diff --git a/doc/pacman-key.8.txt b/doc/pacman-key.8.txt
index 8a08480..e806b81 100644
--- a/doc/pacman-key.8.txt
+++ b/doc/pacman-key.8.txt
@@ -68,8 +68,8 @@ Commands
 *\--reload*::
 	Reloads the keys from the keyring package.
 
-*-t, \--trust* keyid::
-	Set the trust level of the given key.
+*-t*, *\--edit-key* 'keyid ...'::
+	Edit trust properties for the given keys
 
 *-u, \--updatedb*::
 	Equivalent to \--check-trustdb in GnuPG.
diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in
index 89e52fc..2b19611 100644
--- a/scripts/pacman-key.sh.in
+++ b/scripts/pacman-key.sh.in
@@ -66,7 +66,7 @@ usage() {
 	echo "$(gettext "  -h, --help                This help")"
 	echo "$(gettext "  -l, --list                List keys")"
 	echo "$(gettext "  -r, --receive <keyserver> <keyid(s)> Fetch the specified keyids")"
-	echo "$(gettext "  -t, --trust <keyid(s)>    Set the trust level of the given keyids")"
+	echo "$(gettext "  -t, --edit-key <keyid> ... edit trust properties for the given keys")"
 	echo "$(gettext "  -u, --updatedb            Update the trustdb of pacman")"
 	echo "$(gettext "  -V, --version             Show program version")"
 	echo "$(gettext "  --adv <params>            Use pacman's keyring with advanced gpg commands")"
@@ -110,7 +110,7 @@ reload_keyring() {
 	# Verify signatures of related files, if they exist
 	if [[ -r "${ADDED_KEYS}" ]]; then
 		msg "$(gettext "Verifying official keys file signature...")"
-		if ! ${GPG_PACMAN} --quiet --batch --verify "${ADDED_KEYS}.sig" 1>/dev/null; then
+		if ! ${GPG_PACMAN} --verify "${ADDED_KEYS}.sig" &>/dev/null; then
 			error "$(gettext "The signature of file %s is not valid.")" "${ADDED_KEYS}"
 			exit 1
 		fi
@@ -118,7 +118,7 @@ reload_keyring() {
 
 	if [[ -r "${DEPRECATED_KEYS}" ]]; then
 		msg "$(gettext "Verifying deprecated keys file signature...")"
-		if ! ${GPG_PACMAN} --quiet --batch --verify "${DEPRECATED_KEYS}.sig" 1>/dev/null; then
+		if ! ${GPG_PACMAN} --verify "${DEPRECATED_KEYS}.sig" &>/dev/null; then
 			error "$(gettext "The signature of file %s is not valid.")" "${DEPRECATED_KEYS}"
 			exit 1
 		fi
@@ -126,7 +126,7 @@ reload_keyring() {
 
 	if [[ -r "${REMOVED_KEYS}" ]]; then
 		msg "$(gettext "Verifying deleted keys file signature...")"
-		if ! ${GPG_PACMAN} --quiet --batch --verify "${REMOVED_KEYS}.sig"; then
+		if ! ${GPG_PACMAN} --verify "${REMOVED_KEYS}.sig" &>/dev/null; then
 			error "$(gettext "The signature of file %s is not valid.")" "${REMOVED_KEYS}"
 			exit 1
 		fi
@@ -204,14 +204,8 @@ reload_keyring() {
 	${GPG_PACMAN} --batch --check-trustdb
 }
 
-# PROGRAM START
-if ! type gettext &>/dev/null; then
-	gettext() {
-		echo "$@"
-	}
-fi
-
-if [[ $1 != "--version" && $1 != "-V" && $1 != "--help" && $1 != "-h" && $1 != "" ]]; then
+# Checks if gpg exists and user is root
+function check_environment() {
 	if type -p gpg >/dev/null 2>&1 = 1; then
 		error "$(gettext "gnupg does not seem to be installed.")"
 		msg2 "$(gettext "pacman-key requires gnupg for most operations.")"
@@ -220,17 +214,49 @@ if [[ $1 != "--version" && $1 != "-V" && $1 != "--help" && $1 != "-h" && $1 != "
 		error "$(gettext "pacman-key needs to be run as root.")"
 		exit 1
 	fi
+}
+
+# PROGRAM START
+if ! type gettext &>/dev/null; then
+	gettext() {
+		echo "$@"
+	}
 fi
 
-# Parse global options
+# Iterate over the parameters to get --config and --gpgdir
+# The other parameters will be filtered to another array,
+# so --config and --gpgdir don't interfere with other options.
 CONFIG="@sysconfdir@/pacman.conf"
-PACMAN_KEYRING_DIR="@sysconfdir@/pacman.d/gnupg"
-while [[ $1 =~ ^--(config|gpgdir)$ ]]; do
-	case "$1" in
-		--config) shift; CONFIG="$1" ;;
-		--gpgdir) shift; PACMAN_KEYRING_DIR="$1" ;;
+declare -a PARAMS
+GPGDIR=""
+isconfig=0
+isgpgdir=0
+for arg in "$@"; do
+	if (( isconfig )); then
+		isconfig=0
+		CONFIG="$arg"
+		if [[ ! -f "$CONFIG" ]]; then
+			error "$(gettext "The configuration file is not a valid file.")"
+			usage
+			exit 1
+		fi
+		continue
+	fi
+	if (( isgpgdir )); then
+		isgpgdir=0
+		GPGDIR="$arg"
+		if [[ ! -d "$GPGDIR" ]]; then
+			error "$(gettext "The home directory for GnuPG is not valid.")"
+			usage
+			exit 1
+		fi
+		continue
+	fi
+	case "$arg" in
+		--config) isconfig=1;;
+		--gpgdir) isgpgdir=1;;
+		*) PARAMS[${#PARAMS[@]}]="$arg"
 	esac
-	shift
 done
 
 if [[ ! -r "${CONFIG}" ]]; then
@@ -239,11 +265,13 @@ if [[ ! -r "${CONFIG}" ]]; then
 fi
 
 # Read GPGDIR from $CONFIG.
-# The pattern is: any spaces or tabs, GPGDir, any spaces or tabs, equal sign
-# and the rest of the line. The string is splitted after the first occurrence of =
-if [[ GPGDIR=$(find_config "GPGDir") == 0 ]]; then
-	PACMAN_KEYRING_DIR="${GPGDIR}"
-fi
+# The precedence for GPGDIR is:
+# 1st: command line
+# 2nd: pacman.conf
+# 3rd: default value
+[[ -z "$GPGDIR" ]] && GPGDIR=$(find_config "GPGDir")
+[[ -z "$GPGDIR" ]] && GPGDIR="@sysconfdir@/pacman.d/gnupg"
+PACMAN_KEYRING_DIR="${GPGDIR}"
 GPG_PACMAN="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning"
 
 # Try to create $PACMAN_KEYRING_DIR if non-existent
@@ -252,74 +280,89 @@ GPG_PACMAN="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning"
 [[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir -p -m 755 "${PACMAN_KEYRING_DIR}"
 
 # Parse and execute command
-command="$1"
+command="${PARAMS[0]}"
 if [[ -z "${command}" ]]; then
 	usage
 	exit 1
 fi
-shift
+unset PARAMS[0]
 
 case "${command}" in
 	-a|--add)
+		check_environment
 		# If there is no extra parameter, gpg will read stdin
-		${GPG_PACMAN} --quiet --batch --import "$@"
+		${GPG_PACMAN} --quiet --batch --import "${PARAMS[@]}"
 		;;
 	-d|--del)
-		if (( $# == 0 )); then
+		check_environment
+		if (( ${#PARAMS[@]} == 0 )); then
 			error "$(gettext "You need to specify at least one key identifier")"
 			exit 1
 		fi
-		${GPG_PACMAN} --quiet --batch --delete-key --yes "$@"
+		${GPG_PACMAN} --quiet --batch --delete-key --yes "${PARAMS[@]}"
 		;;
 	-u|--updatedb)
+		check_environment
 		${GPG_PACMAN} --batch --check-trustdb
 		;;
 	--reload)
+		check_environment
 		reload_keyring
 		;;
 	-l|--list)
-		${GPG_PACMAN} --batch --list-sigs "$@"
+		check_environment
+		${GPG_PACMAN} --list-sigs "${PARAMS[@]}"
 		;;
 	-f|--finger)
-		${GPG_PACMAN} --batch --fingerprint "$@"
+		check_environment
+		${GPG_PACMAN} --fingerprint "${PARAMS[@]}"
 		;;
 	-e|--export)
-		${GPG_PACMAN} --armor --export "$@"
+		check_environment
+		${GPG_PACMAN} --armor --export "${PARAMS[@]}"
 		;;
 	-r|--receive)
-		if (( $# < 2 )); then
+		check_environment
+		if (( ${#PARAMS[@]} < 2 )); then
 			error "$(gettext "You need to specify the keyserver and at least one key identifier")"
 			exit 1
 		fi
-		keyserver="$1"
-		shift
-		${GPG_PACMAN} --keyserver "${keyserver}" --recv-keys "$@"
+		keyserver="${PARAMS[1]}"
+		unset PARAMS[1]
+		${GPG_PACMAN} --keyserver "${keyserver}" --recv-keys "${PARAMS[@]}"
 		;;
-	-t|--trust)
-		if (( $# == 0 )); then
+	-t|--edit-key)
+		check_environment
+		if (( ${#PARAMS[@]} == 0 )); then
 			error "$(gettext "You need to specify at least one key identifier")"
+			usage
 			exit 1
 		fi
-		while (( $# > 0 )); do
-			# Verify if the key exists in pacman's keyring
-			if ${GPG_PACMAN} --list-keys "$1" > /dev/null 2>&1; then
-				${GPG_PACMAN} --edit-key "$1"
-			else
-				error "$(gettext "The key identified by %s doesn't exist")" "$1"
-				exit 1
+		for key in "${PARAMS[@]}"; do
+			if [[ -n "$key" ]]; then
+				# Verify if the key exists in pacman's keyring
+				if ${GPG_PACMAN} --list-keys "$key" &>/dev/null; then
+					${GPG_PACMAN} --edit-key "$key"
+				else
+					error "$(gettext "The key identified by %s doesn't exist")" "$key"
+					exit 1
+				fi
 			fi
-			shift
 		done
 		;;
 	--adv)
+		check_environment
 		msg "$(gettext "Executing: %s ")$*" "${GPG_PACMAN}"
-		${GPG_PACMAN} "$@" || ret=$?
+		${GPG_PACMAN} "${PARAMS[@]}" || ret=$?
 		exit $ret
 		;;
 	-h|--help)
 		usage; exit 0 ;;
 	-V|--version)
 		version; exit 0 ;;
+	# Parameters already handled
+	--config) shift ;;
+	--gpgdir) shift ;;
 	*)
 		usage; exit 1 ;;
 esac
-- 
1.7.4.2



More information about the pacman-dev mailing list