#! /bin/bash
#
# -- pine-gpg-filter-0.70, 2006-07-08; Martin A. Brown <martin@linux-ip.net>
#
# -- released under the GPL
#
# -- A pine filter which can handle multiple GPG roles.
#
# -- ChangeLog
#
#    0.70 2006-07-08; -MAB
#         adding --autoid option; improving documentation
#    0.62 2006-07-07; -MAB
#         fixing silly "packaging" bug
#    0.61 2006-07-07; -MAB
#         fixing documentation bug
#    0.6  2006-07-07; -MAB
#         wrote quite a bit of introductory (README) documentation
#    0.5  2006-07-06; -MAB
#         version bump just before attempting autoid work
#    0.4  2006-07-05; -MAB
#         oops!  Forgot that it's supposed to be "clearsign"; fixed
#         added logic switches so that it can be called by many names
#    0.3  2006-07-04; -MAB
#         improved documentation (long_usage)
#         verify functionality needs to use "tee", "mkfifo"
#         functionizing verify, encrypt, sign and so forth
#    0.2  2006-07-04; -MAB
#         fixed quoting issues for "$PGF_COMMENT"
#         shorter default comment string
#         put recipient existence check in correct place (--encrypt only)
#         allow user to specify the (--quiet) option
#    0.1  2006-07-04; -MAB
#         initial version; great U.S. Independence Day activity
#
# -- Contributors
#
#    Mike Pomraning <mjp@pilcrow.madison.wi.us>;  MJP supplied an
#    explanation for file pointer behaviour upon child process exit.
#    In short, a program (e.g., shell) has no way of knowing where a
#    child process has left the file pointer, if the child process
#    simply exits.  For ramifications, see --autoid code.
#
# -- BUGS/TODO
#
#

# -- script global variables
#
VERBOSE="${PGF_VERBOSE:-0}"
INFORM=1
NOTICE=2
DEBUG=3

STDOUT=1
STDERR=2

VERSION=0.70
NAME=pine-gpg-filter
PGF_URL="http://linux-ip.net/sw/pine-gpg-filter/"

REQUIRED_UTILITIES="gpg mkfifo rm tee"

# -- remove these from our environment for sanity
#
unset GPG_OPT_LU            \
      GPG_OPT_RECIPIENTS    \
      PGF_RECIPIENTS        \
      PGF_MODE              \
      PGF_TO_SELF

# -- set up some global defaults, but allow for environment variables
#
 : "${PGF_COMMENT:=pgf-$VERSION ($PGF_URL)}"
 : "${PGF_STATLINES:=multi}"

# -- and set up some internal flags for the different primary actions
#
unset C S E V D
C="--clearsign"
S="--sign"
E="--encrypt"
D="--decrypt"
V="--verify"

# -- my favorite shell functions (and their offspring)
#
# - - - - - - - - - 
  gripe () {
# - - - - - - - - - 
#
  local descriptor=$1   && shift
  printf -- "%s\n" "$@" >&${!descriptor}
}

abort  () { gripe STDERR "$@"; exit 1;     }

inform () { test "$VERBOSE" -ge "$INFORM" && gripe STDERR "I: $@"; }
notice () { test "$VERBOSE" -ge "$NOTICE" && gripe STDERR "N: $@"; }
debug  () { test "$VERBOSE" -ge "$DEBUG"  && gripe STDERR "D: $@"; }

# -- create logger as a shell function
#
logger () { command logger -i -t "${0##*/}[$$]" -p daemon.err -- "$@" ; }

# - - - - - - - - - - -
  version  () {
# - - - - - - - - - - -
#
  gripe STDOUT "${0##*/}-${VERSION}"
  exit 0
}

# - - - - - - - - - - -
  usage  () {
# - - - - - - - - - - -
#
  local descriptor=$1   && shift
  cat >&${!descriptor} <<-EOUSAGE
Usage: ${NAME} [ options ] [ <recipient> ... ]

Options (defaults marked, or in parentheses):
  -h, --help                  Print out this handy help screen.
  -L, --long-usage            Provide help and some more hints.
  -q, --quiet                 Reset verbosity to none.
  -v, --verbose               Increase verbosity, can be used multiple times.
  -V, --version               Print version information.
  -c, --clearsign             Ask GPG to clearsign the input.
  -e, --encrypt               Ask GPG to encrypt the input.
  -s, --sign                  Ask GPG to sign the input.
  -d, --decrypt               Ask GPG to decrypt the input.
  -y, --verify                Ask GPG to verify the input.
  -o, --one-line              Compress multiline status output from GPG.
  -m, --multi-line            Allow all of the status output from GPG.
  -t, --to-self               Also encrypt-to-self (ignored if not needed).
  -n, --no-comment            Suppress any comment string.
  -C, --comment     <string>  Override the default comment string.
  -D, --datafile    <file>    Use pine-provided _DATAFILE_ as temporary FIFO.
  -R, --resultfile  <file>    Pine reports command output via _RESULTFILE_.
  -l, --local-user  <key_id>  Specify a local username.
  -a, --autoid                Determine <key_id> (role) from From: line.
      --build-symlinks        Install pgf-* and pgfa-* symlinks.

EOUSAGE
}

# - - - - - - - - - - -
  short_usage  () {
# - - - - - - - - - - -
#
  local descriptor="${1:-STDOUT}"  && shift
  usage $descriptor
  test "$#" -gt 0 && abort "$@"
  exit 0
}

# - - - - - - - - - - -
  long_usage  () {
# - - - - - - - - - - -
#
  local descriptor="${1:-STDOUT}"  && shift
  usage $descriptor
  cat >&${!descriptor} <<-EOUSAGE
${NAME}-${VERSION} README

Description
===========
${NAME} (pgf) is almost a clone of pinepg [0].  It, however,
adds the capability for specifying which user ID (or IDs) to use for
the encryption or signing.  It does absolutely no passphrase
caching.  If you need (want) passphrase caching, look into
gpg-agent, available in the "gnupg2" package, e.g., gnupg-1.9.21 as
of 2006-07-04.

This utility is intended to allow the pine user to be able to take
advantage of multiple separate roles and keys for each of those
roles within pine.  Other pine and GnuPG integration (i.e.,
pgp4pine, pinepg) utilities do not allow for selection of user ID
for a particular encryption or signing request.


Required Option(s)
==================
At least one of these first options is required.  The sign and
encrypt options may be combined, but no other combination is
possible.  If multiple options are specified in incompatible
combinations, the last one "wins".

 --clearsign (-c)       Have GPG clearsign the message.  This is what
                        most people mean when they talk about "signed"
                        email messages.
 --encrypt (-e)         Have GPG encrypt the message.  When using
                        this option, you must specify recipient
                        addresses, as well.
 --sign (-s)            Have GPG sign the message (use with encrypt).
 --decrypt (-d)         Have GPG decrypt the message.
 --verify (-v)          Have GPG verify the message.


Behaviour modifying options
===========================

 --to-self (-t)         This option asks GPG to employ the encrypt-to-self
                        option, where self is defined as the local
                        user <key_id> specified with the -L option.
                        (This option is simply ignored if not needed.)
 --one-line (-o)        Only print out one line of the status generated
                        by GnuPG on the STDERR (_RESULTFILE_).
 --multi-line (-m)      Produce all of the usual GnuPG status output.
 --no-comment (-n)      Suppress the default comment string.
 --comment (-C)         Override the default comment string. Default is
                        $PGF_COMMENT
 --resultfile (-R)      Pine returns the filter's STDERR via the
                        _RESULTFILE_  See Examples.
 --datafile (-D)        Pine provides a session-unique filename called
                        We use it as a FIFO.  _DATAFILE_ (cf. Examples).
 --local-user (-l)      Select a specific local key identifier.  With this
                        option, you may specify a non-default key on
                        your GPG keyring.  The <key_id> may be an
                        email address or the actual key ID itself.
 --autoid (-a)          Select a specific local key identifier by parsing
                        the From: header line.  Requires the use of
                        Pine's _INCLUDEALLHDRS_ directive.  See Examples.

Special options
===============

 --build-symlinks       This will install all of the compatibility symlinks
                        for the pine-gpg-filter program.  You must have
                        write permissions on the directory in question in
                        order to use this option.

Prerequisites
=============
You must have a working GnuPG installation.  If you are using these
scripts for integration with your pine MUA and you have only a
single GPG identity (one secret key), you may wish to consider the
GnuPG option (check ~/.gnupg/options or ~/.gnupg/gpg.conf in newer
versions) known as "encrypt-to".  The encrypt-to option allows you
to specify a key identifier which will be added to the recipient
list for any encryption.

Although not strictly a prerequisite, you may find that the
passphrase caching offered by gpg-agent (included in SuSE's gpg2
package) will save some keystrokes when used with this filter, which
performs none of its own caching.


Notes on sending-filters and display-filters
============================================
all scripts:  All of the scripts can make use of the _RESULTFILE_
  token as either a sending-filter or a display-filter.  The
  _RESULTFILE_ is used to store output like "gpg: Good signature..."
  while the filter itself is running.

  I recommend invoking each of the utilities with the "--resultfile
  _RESULTFILE_" option (see Examples, below).  Pine will pause and
  display the STDERR output from GPG, which has ended up in the
  _RESULTFILE_.  This option is, perhaps, less important when used
  on the sending-filters.

  If you are absolutely sure you want to bypass the confirmations
  of successful decryption or verification, you may omit the "-R
  _RESULTFILE_" (in which case, the output will go to the terminal
  "behind" pine's curses interface) or you may specify "-R
  /dev/null" to obliterate the output.  (Not recommended.)

  I would encourage the use of "--resultfile _RESULTFILE_", because
  the user will then receive feedback from GPG regarding the
  signature (or encryption).

*-verify:  The *-verify command requires the use of a temporary
  file (it uses a FIFO) in order to both output the text of the
  message and validate the signature.  Thus, not supplying the
  --datafile _DATAFILE_ option when using the *-verify commands is
  an error.
  
*-encrypt, *-sign-encrypt:  Any use of the encryption command
  requires at least one recipient.  If there is no recipient, then
  the command will fail.  Pine will provide the recipient list,
  including Cc and Bcc (careful!), to the filters as command line
  arguments.  By using the _RECIPIENTS_ token in the sending-filter,
  you are asking pine to provide these addresses.


Simplest usage
==============
With the exception of the incorrect path, the below examples are the
minimum configuration set for using the ${NAME} tools.  (Note,
that these pinerc entries are line broken for readability.)

display-filters=_LEADING("-----BEGIN PGP MESSAGE-----")_ \\
                    /path/to/pgf-decrypt -R _RESULTFILE_,
	_LEADING("-----BEGIN PGP SIGNED MESSAGE-----")_  \\
                    /path/to/pgf-verify -D _DATAFILE_ -R _RESULTFILE_

sending-filters=/path/to/pgf-clearsign -R _RESULTFILE_
	/path/to/pgf-sign-encrypt -R _RESULTFILE_ _RECIPIENTS_


Compatibility names
===================
In order to make the utility easier to use, there are several ways
to call it without requiring long options.  Here are the names and
the indicated behaviour:

       option             compat           autoid compat
   ================   ================   =================
   --clearsign        pgf-clearsign      pgfa-clearsign
   --encrypt          pgf-encrypt        pgfa-encrypt
   --sign --encrypt   pgf-sign-encrypt   pgfa-sign-encrypt
   --sign             pgf-sign           pgfa-sign
   --decrypt          pgf-decrypt        pgfa-decrypt (N.B.)
   --verify           pgf-verify         pgfa-verify (N.B.)

N.B., for symmetry, the pgfa-decrypt and pgfa-verify compatibility
symlinks are installed, although there is little sense to a pine
filter which selects an identity for receiving a message.  Why?
Because GPG simply attempts to decrypt (or verify) the message with
the key used for encryption.  In these invocations, the autoid
component is simply ignored.

See also Examples, below.


Examples
========
Here are several examples of how to configure your pine filters:

  
0: /path/to/pgf-sign-encrypt --resultfile _RESULTFILE_ _RECIPIENTS_
0: /path/to/pgf-sign-encrypt -r _RESULTFILE_ _RECIPIENTS_

   The above will select the primary GPG key ID to use for signing
   and encrypting the message.  These two are exactly the same, one
   uses the long command line options, and the other uses the short
   command line options.

1: /path/to/pgf-sign-encrypt -tl 0x2486302b -R _RESULTFILE_ _RECIPIENTS_
1: /path/to/pgf-sign-encrypt --to-self --local-user 0x2486302b \\
     --resultfile _RESULTFILE_ _RECIPIENTS_

   In these examples, we are specifying the key identifier
   (0x0x2486302b) we wish to use when encrypting.  The --to-self
   (-t) option instructs GPG to encrypt the message not only to the
   _RECIPIENTS_, but also to the key 0x2486302b.

   Because there may be multiple _RECIPIENTS_, this should be the
   last parameter on the command line.

2: /path/to/pgf-clearsign -l frank@cheese-shop.net -R _RESULTFILE_
2: /path/to/pgf-clearsign --local-user frank@cheese-shop.net \\
     --resultfile _RESULTFILE_

   In this case, we are asking GPG to use the key for address
   frank@cheese-shop.net.

3: /path/to/pgf-clearsign -C "Organization Name" -R _RESULTFILE_

   We do not specify a key ID here, so the default GPG user will be
   selected.  The --comment (-C) option allows you to alter the
   string sent in the body of the GPG signature (in this case, or
   the header of the encrypted message in the case of encryption).

4: /path/to/pgf-sign-encrypt -nR _RESULTFILE_ _RECIPIENTS_

   Maybe you don't like the advertisement for pine-gpg-filter in the
   clearsign text of your messages.  Suppress the comment string
   by using the --no-comment (-n) option.

5: /path/to/pgf-verify -R _RESULTFILE_ -D _DATAFILE_
5: /path/to/pgf-verify --resultfile _RESULTFILE_ --datafile _DATAFILE_

   The verify functionality requires a temporary file.  If you do
   not supply the "--datafile _DATAFILE_", $NAME cannot
   validate the signature on the message, and must abort.

6: /path/to/pgfa-sign-encrypt _INCLUDEALLHDRS_ -R _RESULTFILE_ _RECIPIENTS_

   This is the calling method for using the automatic identity
   selection of this utility.

7: /path/to/pgfa-clearsign _INCLUDEALLHDRS_ -R _RESULTFILE_

   To select one of your identities automatically for any
   clearsigning, this invocation should suffice.


Similar applications
====================

 [0] http://quantumlab.net/pine_privacy_guard/     pinepg
 [1] http://hany.sk/~hany/software/pinepgp/        pinepgp
 [2] http://user.cs.tu-berlin.de/~gator/pgp4pine/  PGP4Pine (PAPP) 
 [3] http://dougbarton.net/FreeBSD/Downloads/      Pine PGP Filters 
 [4] http://pgpenvelope.sourceforge.net/           pgpenvelope

EOUSAGE

exit 0

}

# - - - - - - - - - - -
  parse_options () {
# - - - - - - - - - - -
#
  command getopt                    \
    --unquoted                      \
    --name "${0##*/}"               \
    --options "${OPTIONS}"          \
    --longoptions "${LONGOPTIONS}"  \
    -- "$@"
}

# - - - - - - - - - - -
  verify_support  () {
# - - - - - - - - - - -
#
# -- all we want to do is make sure that all of our support
# programs exist.
#
  local program
  local programs="$@"
  local N
  local ok=0           # -- return 0, if everything is OK!
  
  for program in $programs; do
    N=$( which "$program" 2>/dev/null )
    if test -z "$N"; then
      ok=1
      gripe STDERR "Could not locate necessary support program:  $program"
    fi
  done
  return $ok
}

# - - - - - - - - - - -
  pgf_build_symlinks () {
# - - - - - - - - - - -
#
# -- cd to the current working directory of the binary, and
#    add missing symlinks
#

  cd "${0%/*}"    || abort "Could not chdir to ${0%/*}"

  gripe STDOUT "chdir to ${0%/*} successful, making symlinks."

  for f in pgf{a,}-{sign,sign-encrypt,encrypt,clearsign,decrypt,verify} ; do

    if test -L "$f" ; then

      gripe STDERR "Skipping symlink $f, already exists."
      continue

    fi

    ln -sv "${0##*/}" "$f" \
      || abort "Error creating symlink $f."

  done

  exit 0

}

# - - - - - - - - - - -
  one_line_check  () {
# - - - - - - - - - - -
#
# -- test to see if the user wants (only) one-line status messages
#
  test -z "$PGF_RESULTFILE"                 && return
  test    "$PGF_RESULTFILE" = "/dev/null"   && return
  test    "$PGF_RESULTFILE" = "/dev/stderr" && return
  test    "$PGF_STATLINES"  = "multi"       && return

  LINE="$( tail -1 $PGF_RESULTFILE )"

  printf "%s\n" "$LINE" > "$PGF_RESULTFILE"

}

# - - - - - - - - - - -
  pgf_autoid () {
# - - - - - - - - - - -
#
# -- check to see if we were called in decrypt or verify mode, in
#    which case, just skip the autoid portion--it's not relevant
#
# -- reads input from STDIN, setting global variable PGF_LOCAL_USER
#    and leaves the file pointer (we're reading from a pipe) at the
#    end of the headers.
#
# -- In the event that we have been called from one of pine's
#    sending-filters, we attempt to determine if we have been called
#    incorrectly (without _INCLUDEALLHDRS_) and abort accordingly.
#

  test "$PGF_MODE" == "D" -o "$PGF_MODE" == "V"   && return

  while read line ; do
  
    # -- Try to detect if we have been fed a message without the
    #      _INCLUDEALLHDRS_ directive; gotta abort.
    #
    test "${line%%^M}" == "${line}" \
      || abort "--autoid called without _INCLUDEALLHDRS_"
  
    # -- Detect end of headers, PCRE equivalent would be  m/^\r$/
    #
    test -z "$line" -o "$line" == "^M" && break
  
    # -- See if we are on the From: line
    #
    if test "From:" == "${line:0:5}" ; then
  
      # -- We have found a From line!  Extract the address.
      #    Rather, disgustingly, we have to chop off the carriage
      #    return at the end of the line.
      #
      t="${line%*>
}"
      PGF_LOCAL_USER="${t##*<}"
  
    fi
  
  done
}

# - - - - - - - - - - -
  pgf_catchall () {
# - - - - - - - - - - -
#
# -- call the GnuPG utility for any general purpose
#
  gpg $GPG_OPT_ACTION "$PGF_COMMENT" $GPG_OPT_LU

  EC=$?

  one_line_check

  exit $EC

}

# - - - - - - - - - - -
  pgf_encrypt  () {
# - - - - - - - - - - -
#
# -- call the GnuPG utility to encrypt (and maybe sign) the message on STDIN
#

  # -- we have to have recipients, or else there's no work to do,
  #    and this has to be an error.
  #
  test -n "$PGF_RECIPIENTS" \
    || abort "No recipient address(es) specified."
  
  gpg $GPG_OPT_ACTION "$PGF_COMMENT" $GPG_OPT_LU $GPG_OPT_RECIPS ;

  EC=$?

  one_line_check

  exit $EC

}

# - - - - - - - - - - -
  pgf_verify  () {
# - - - - - - - - - - -
#
# -- call the GnuPG utility to verify the message on STDIN
#
  rm -f "$PGF_FIFO" \
    || abort "Could not remove $PGF_FIFO (_DATAFILE_) prior to mkfifo."

  mkfifo --mode 0700 "$PGF_FIFO" \
    || abort "Could not create FIFO $PGF_FIFO for verify option."

  # -- very ugly; have to put gpg in the background, reading
  #    from a FIFO while we use "tee" to drop the data into
  #    the FIFO and spit to STDOUT, for the user to read the
  #    message.
  #
  gpg $GPG_OPT_ACTION "$PGF_COMMENT" $GPG_OPT_LU < "$PGF_FIFO" &

  GPG_PID=$!

  tee "$PGF_FIFO"

  wait $GPG_PID

  EC=$?

  one_line_check

  exit $EC

}

# -- check to make sure that we have a few key utilities before
#    launching off the command line processing
#
verify_support which \
  || abort "${0##*/}: Cannot proceed without \"which\" utility, quitting."

verify_support getopt \
  || abort "${0##*/}: Cannot process command line options, quitting."

# - - - - - - - - - - -
# main () {
# - - - - - - - - - - -
#
# -- normalize the command-line options
#
OPTIONS="vqhLVcesdytmonC:R:D:l:a"
LONGOPTIONS="verbose,quiet,help,long-usage,version"
LONGOPTIONS="$LONGOPTIONS,clearsign,encrypt,sign,decrypt,verify,to-self"
LONGOPTIONS="$LONGOPTIONS,no-comment,comment:,datafile:,resultfile:"
LONGOPTIONS="$LONGOPTIONS,multi-line,one-line,local-user:,autoid"
LONGOPTIONS="$LONGOPTIONS,build-symlinks"

# -- calling parse_options twice seems silly.  It is.  It allows, us
#    however, to control the error reporting to the user a bit more
#    carefully.  All the OCD kids are doing it.
#
parse_options "$@" >/dev/null \
  || abort "Try \"${0##*/} --help\" for more information."

set -- $( parse_options "$@" )

# -- Bump up verbosity a notch if we are connected to a terminal;
#    generally, users like to know a bit more of what's going on...
#
tty --silent         && let VERBOSE=VERBOSE+1

# -- examples of options/arguments should look like this now:
# 
while test "$#" -gt "0" ; do
   case "$1" in

      -h | --h*    ) short_usage                              ;;
      -L | --long* ) long_usage                               ;;
      -V | --vers* ) version                                  ;;
      -v | --verb* ) let VERBOSE=VERBOSE+1                    ;;
      -q | --q*    ) VERBOSE=0 ; PGF_QUIET="--quiet"          ;;

      -s | --s*    ) PGF_MODE="S ${PGF_MODE}"                 ;;
      -e | --e*    ) PGF_MODE="${PGF_MODE} E"                 ;;
      -c | --clea* ) PGF_MODE="${PGF_MODE} E"                 ;;
      -d | --decr* ) PGF_MODE="D"                             ;;
      -y | --veri* ) PGF_MODE="V"                             ;;
      -a | --a*    ) PGF_AUTOID="true"      && shift          ;;
      -l | --loca* ) PGF_LOCAL_USER="$2"    && shift          ;;
      -t | --t*    ) PGF_TO_SELF="true"                       ;;

      -m | --m*    ) PGF_STATLINES="multi"  && shift          ;;
      -o | --o*    ) PGF_STATLINES="one"    && shift          ;;
      -n | --n*    ) PGF_NOCOMMENT="true"   && shift          ;;
      -C | --comm* ) PGF_COMMENT="$2"       && shift          ;;
      -D | --d*    ) PGF_FIFO="$2"          && shift          ;;
      -R | --r*    ) PGF_RESULTFILE="$2"    && shift          ;;

      # -- one-shot, or unusual options
      #
      --build-symlinks ) pgf_build_symlinks                   ;;

             --    ) shift                  && break          ;;
             -*    ) short_usage STDERR "Unknown option: $1"  ;;

   esac
   shift
done

# -- Short names override options; symlinks and behaviour switching
#    based on the invocation name allow us to provide shorter
#    commands with fewer options for the user.
# -- If the user insists on typing command lines that are a mile long,
#    s/he is free to use the primary script name $NAME
#
case ${0##*/} in
     
  *-sign-encrypt ) PGF_MODE="S E"     ;;
  *-sign         ) PGF_MODE="S"       ;;
  *-clearsign    ) PGF_MODE="C"       ;;
  *-encrypt      ) PGF_MODE="E"       ;;
  *-decrypt      ) PGF_MODE="D"       ;;
  *-verify       ) PGF_MODE="V"       ;;
  *              ) :                  ;;  # -- not strictly required

esac

case ${0##*/} in

  pgfa-*         ) PGF_AUTOID="true"  ;;
  pgf-*          ) unset PGF_AUTOID   ;;
  *              ) :                  ;;  # -- not strictly required

esac

# -- all remaining arguments are taken to be recipient addresses
#
PGF_RECIPIENTS="$@"

verify_support $REQUIRED_UTILITIES \
  || abort "${0##*/}: Missing utilities, cannot continue, quitting."

test -n "$PGF_MODE" \
  || short_usage STDERR "At least one mode must be specified (e.g., clearsign)."

test -n "$PGF_AUTOID" -a -n "$PGF_LOCAL_USER" \
  && short_usage "--autoid (-a) and --local-user (-l) are conflicting options."

# -- actions taken after sanity checking

# -- If we have been called with PGF_AUTOID, then get started!
#
if test -n "$PGF_AUTOID" ; then

  PGF_LOCAL_USER=""

  pgf_autoid

  test "$PGF_LOCAL_USER" == "" \
    && abort "Automatic identification of user failed; please report bug."

fi

# -- iterate over the list of recipients and add them to the list
#    of addresses to which to encrypt the message
#
for RECIP in $PGF_RECIPIENTS ; do

  GPG_OPT_RECIPS="$GPG_OPT_RECIPS --recipient $RECIP"

done

# -- find out if the user specified an alternate email address and
#    specify that user ID for the following commands.  This is not necessary
#    for the --decrypt and --verify options but GnuPG-1.4.x simply ignores
#    the extraneous option.
#
if test -n "$PGF_LOCAL_USER" ; then

  GPG_OPT_LU="--local-user $PGF_LOCAL_USER"

  test -n "$PGF_TO_SELF" \
    && GPG_OPT_LU="$GPG_OPT_LU --encrypt-to $PGF_LOCAL_USER"

fi

# -- send all STDERR nonsense from the gpg binary to pine's result
#    if the argument has been specified (otherwise, we'll just leave
#    STDERR alone)
#
test      -n "$PGF_RESULTFILE" \
  && exec 2> "$PGF_RESULTFILE"

# -- build up the primary action string for passing to GnuPG
#
GPG_OPT_ACTION="$PGF_QUIET --armor"

for ACTION in $PGF_MODE ; do

  GPG_OPT_ACTION="$GPG_OPT_ACTION ${!ACTION}"

done

# -- Let's see about suppressing that pretty little "comment" string,
#    shall we?  The --comment (which is completely sugar) is included
#    in the header of the PGP encrypted (or signed) data.
#   
test -n "$PGF_NOCOMMENT"  && PGF_COMMENT=""

GPG_OPT_ACTION="$GPG_OPT_ACTION --comment"

# -- And now, we are simply going to call GPG and pass this off.
#    We rely on GnuPG's error code to propagate back to pine, since
#    we are not handling any temporary files (if we can avoid it).
#
case "$PGF_MODE" in

  *E) pgf_encrypt      ;;
   V) pgf_verify       ;;
   *) pgf_catchall     ;;

esac

# -- end of file
