pacman-key: use our option parser

The pacman-key script is complicated enough to warrent usage of the
parse_options script.  This is especially helpful in dealing with
all the configuration file override flags as the no longer need to
be specified first.  It also allows us to do the right thing early
with --help/--version and no option cases cleanly. This change also
makde the check for root privileges only occur on operations where
they are needed.

This patch is inspired by and supercedes some patches submitted by
Denis A. Altoé Falqueto and Ivan Kanakarakis who were altering the
previous option handling in an attempt to deal with the above issues.

Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
Allan McRae 2011-07-06 03:05:08 +10:00
parent dad96ccce2
commit 7d205a70a2

View file

@ -26,20 +26,30 @@ export TEXTDOMAINDIR='@localedir@'
myver="@PACKAGE_VERSION@" myver="@PACKAGE_VERSION@"
# Options
ADD=0
ADVANCED=0
DELETE=0
EXPORT=0
FINGER=0
LIST=0
RECEIVE=0
RELOAD=0
TRUST=0
UPDATEDB=0
m4_include(library/output_format.sh) m4_include(library/output_format.sh)
m4_include(library/parse_options.sh)
usage() { usage() {
printf "pacman-key (pacman) %s\n" ${myver} printf "pacman-key (pacman) %s\n" ${myver}
echo echo
printf "$(gettext "Usage: %s [options] <command> [arguments]")\n" $(basename $0) printf "$(gettext "Usage: %s [options]")\n" $(basename $0)
echo echo
printf "$(gettext "Manage pacman\'s list of trusted keys")\n" printf "$(gettext "Manage pacman\'s list of trusted keys")\n"
echo echo
echo "$(gettext "Options must be placed before commands. The available options are:")" echo "$(gettext "Options:")"
printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$CONFIG"
printf "$(gettext " --gpgdir Set an alternate directory for gnupg (instead of '%s')")\n" "$PACMAN_KEYRING_DIR"
echo
echo "$(gettext "The available commands are:")"
echo "$(gettext " -a, --add [<file(s)>] Add the specified keys (empty for stdin)")" echo "$(gettext " -a, --add [<file(s)>] Add the specified keys (empty for stdin)")"
echo "$(gettext " -d, --del <keyid(s)> Remove the specified keyids")" echo "$(gettext " -d, --del <keyid(s)> Remove the specified keyids")"
echo "$(gettext " -e, --export <keyid(s)> Export the specified keyids")" echo "$(gettext " -e, --export <keyid(s)> Export the specified keyids")"
@ -51,8 +61,11 @@ usage() {
echo "$(gettext " -u, --updatedb Update the trustdb of pacman")" echo "$(gettext " -u, --updatedb Update the trustdb of pacman")"
echo "$(gettext " -V, --version Show program version")" echo "$(gettext " -V, --version Show program version")"
echo "$(gettext " --adv <params> Use pacman's keyring with advanced gpg commands")" echo "$(gettext " --adv <params> Use pacman's keyring with advanced gpg commands")"
printf "$(gettext " --reload Reload the default keys")" echo "$(gettext " --config <file> Use an alternate config file")"
echo printf "$(gettext " (instead of '%s')")\n" "@sysconfdir@/pacman.conf"
echo "$(gettext " --gpgdir <dir> Set an alternate directory for gnupg")"
printf "$(gettext " (instead of '%s')")\n" "@sysconfdir@/pacman.d/gnupg"
echo "$(gettext " --reload Reload the default keys")"
} }
version() { version() {
@ -198,116 +211,108 @@ if ! type gettext &>/dev/null; then
} }
fi fi
if [[ $1 != "--version" && $1 != "-V" && $1 != "--help" && $1 != "-h" && $1 != "" ]]; then OPT_SHORT="a::d:e:f::hlr:t:uV"
if type -p gpg >/dev/null 2>&1 = 1; then OPT_LONG="add::,adv:,config:,del:,export:,finger::,gpgdir:,help,list"
error "$(gettext "gnupg does not seem to be installed.")" OPT_LONG+=",receive:,reload,trust:,updatedb,version"
msg2 "$(gettext "pacman-key requires gnupg for most operations.")" if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then
exit 1 echo; usage; exit 1 # E_INVALID_OPTION;
elif (( EUID != 0 )); then
error "$(gettext "pacman-key needs to be run as root.")"
exit 1
fi fi
eval set -- "$OPT_TEMP"
unset OPT_SHORT OPT_LONG OPT_TEMP
if [[ $1 == "--" ]]; then
usage;
exit 0;
fi fi
# Parse global options while true; do
CONFIG="@sysconfdir@/pacman.conf"
PACMAN_KEYRING_DIR="@sysconfdir@/pacman.d/gnupg"
while [[ $1 =~ ^--(config|gpgdir)$ ]]; do
case "$1" in case "$1" in
--config) shift; CONFIG="$1" ;; -a|--add) ADD=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYFILES=($1) ;;
--gpgdir) shift; PACMAN_KEYRING_DIR="$1" ;; --adv) ADVANCED=1; shift; ARGUMENTS=($1) ;;
--config) shift; CONFIG=$1 ;;
-d|--del) DELETE=1; shift; KEYIDS=($1) ;;
-e|--export) EXPORT=1; shift; KEYIDS=($1) ;;
-f|--finger) FINGER=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;;
--gpgdir) shift; PACMAN_KEYRING_DIR=$1 ;;
-l|--list) LIST=1 ;;
-r|--receive) RECEIVE=1; shift; KEYSERVER="${1[0]}"; KEYIDS=("${1[@]:1}") ;;
--reload) RELOAD=1 ;;
-t|--trust) TRUST=1; shift; KEYIDS=($1) ;;
-u|--updatedb) UPDATEDB=1 ;;
-h|--help) usage; exit 0 ;;
-V|--version) version; exit 0 ;;
--) OPT_IND=0; shift; break;;
*) usage; exit 1 ;;
esac esac
shift shift
done done
if [[ ! -r "${CONFIG}" ]]; then
error "$(gettext "%s not found.")" "$CONFIG" if ! type -p gpg >/dev/null; then
error "$(gettext "Cannot find the %s binary required for all %s operations.")" "gpg" "pacman-key"
exit 1 exit 1
fi fi
# Read GPGDIR from $CONFIG. if (( (ADD || ADVANCED || DELETE || RECEIVE || RELOAD || TRUST || UPDATEDB) && EUID != 0 )); then
if [[ GPGDIR=$(get_from "$CONFIG" "GPGDir") == 0 ]]; then error "$(gettext "%s needs to be run as root for this operation.")" "pacman-key"
exit 1
fi
CONFIG=${CONFIG:-@sysconfdir@/pacman.conf}
if [[ ! -r "${CONFIG}" ]]; then
error "$(gettext "%s configuation file '%s' not found.")" "pacman" "$CONFIG"
exit 1
fi
# Get GPGDIR from pacman.conf iff not specified on command line
if [[ -z PACMAN_KEYRING_DIR && GPGDIR=$(get_from "$CONFIG" "GPGDir") == 0 ]]; then
PACMAN_KEYRING_DIR="${GPGDIR}" PACMAN_KEYRING_DIR="${GPGDIR}"
fi fi
GPG_PACMAN="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning" PACMAN_KEYRING_DIR=${PACMAN_KEYRING_DIR:-@sysconfdir@/pacman.d/gnupg}
# Try to create $PACMAN_KEYRING_DIR if non-existent # Try to create $PACMAN_KEYRING_DIR if non-existent
# Check for simple existence rather than for a directory as someone may want # Check for simple existence rather than for a directory as someone may want
# to use a symlink here # to use a symlink here
[[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir -p -m 755 "${PACMAN_KEYRING_DIR}" [[ -e ${PACMAN_KEYRING_DIR} ]] || mkdir -p -m 755 "${PACMAN_KEYRING_DIR}"
# Parse and execute command GPG_PACMAN="gpg --homedir ${PACMAN_KEYRING_DIR} --no-permission-warning"
command="$1"
if [[ -z "${command}" ]]; then
usage
exit 1
fi
shift
case "${command}" in
-a|--add) (( ADD )) && ${GPG_PACMAN} --quiet --batch --import "${KEYFILES[@]}"
# If there is no extra parameter, gpg will read stdin (( DELETE )) && ${GPG_PACMAN} --quiet --batch --delete-key --yes "${KEYIDS[@]}"
${GPG_PACMAN} --quiet --batch --import "$@" (( EXPORT )) && ${GPG_PACMAN} --armor --export "${KEYIDS[@]}"
;; (( FINGER )) && ${GPG_PACMAN} --batch --fingerprint "${KEYIDS[@]}"
-d|--del) (( LIST )) && ${GPG_PACMAN} --batch --list-sigs "${KEYIDS[@]}"
if (( $# == 0 )); then (( RELOAD )) && reload_keyring
error "$(gettext "You need to specify at least one key identifier")" (( UPDATEDB )) && ${GPG_PACMAN} --batch --check-trustdb
exit 1
if (( ADVANCED )); then
msg "$(gettext "Executing: %s %s")" "${GPG_PACMAN}" "${ARGUMENTS[@]}"
${GPG_PACMAN} "${ARGUMENTS[@]}" || ret=$?
exit $ret
fi fi
${GPG_PACMAN} --quiet --batch --delete-key --yes "$@"
;; if (( RECEIVE )); then
-u|--updatedb) if [[ -z ${KEYIDS[@]} ]]; then
${GPG_PACMAN} --batch --check-trustdb
;;
--reload)
reload_keyring
;;
-l|--list)
${GPG_PACMAN} --batch --list-sigs "$@"
;;
-f|--finger)
${GPG_PACMAN} --batch --fingerprint "$@"
;;
-e|--export)
${GPG_PACMAN} --armor --export "$@"
;;
-r|--receive)
if (( $# < 2 )); then
error "$(gettext "You need to specify the keyserver and at least one key identifier")" error "$(gettext "You need to specify the keyserver and at least one key identifier")"
exit 1 exit 1
fi fi
keyserver="$1" ${GPG_PACMAN} --keyserver "$KEYSERVER" --recv-keys "${KEYIDS[@]}"
shift
${GPG_PACMAN} --keyserver "${keyserver}" --recv-keys "$@"
;;
-t|--trust)
if (( $# == 0 )); then
error "$(gettext "You need to specify at least one key identifier")"
exit 1
fi fi
while (( $# > 0 )); do
if (( TRUST )); then
for key in ${KEYIDS[@]}; do
# Verify if the key exists in pacman's keyring # Verify if the key exists in pacman's keyring
if ${GPG_PACMAN} --list-keys "$1" > /dev/null 2>&1; then if ${GPG_PACMAN} --list-keys "$key" > /dev/null 2>&1; then
${GPG_PACMAN} --edit-key "$1" ${GPG_PACMAN} --edit-key "$key"
else else
error "$(gettext "The key identified by %s doesn't exist")" "$1" error "$(gettext "The key identified by %s does not exist")" "$key"
exit 1 exit 1
fi fi
shift shift
done done
;; fi
--adv)
msg "$(gettext "Executing: %s ")$*" "${GPG_PACMAN}"
${GPG_PACMAN} "$@" || ret=$?
exit $ret
;;
-h|--help)
usage; exit 0 ;;
-V|--version)
version; exit 0 ;;
*)
error "$(gettext "Unknown command:") $command"
usage; exit 1 ;;
esac
# vim: set ts=2 sw=2 noet: # vim: set ts=2 sw=2 noet: