Dies ist gpgme.info, hergestellt von Makeinfo Version 4.2 aus
gpgme.texi.

   This file documents the GPGME library.

   This is Edition 0.4.0, last updated 22 December 2002, of `The `GnuPG
Made Easy' Reference Manual', for Version 0.4.0.

   Copyright (C) 2002 g10 Code GmbH.

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with the
Invariant Sections being "Free Software Needs Free Documentation" and
"GNU Lesser General Public License", the Front-Cover texts being (a)
(see below), and with the Back-Cover Texts being (b) (see below).  A
copy of the license is included in the section entitled "GNU Free
Documentation License".

Verify
------

 - Data type: enum GpgmeSigStat
     The `GpgmeSigStat' type holds the result of a signature check, or
     the combined result of all signatures.  The following results are
     possible:

    `GPGME_SIG_STAT_NONE'
          This status should not occur in normal operation.

    `GPGME_SIG_STAT_GOOD'
          This status indicates that the signature is valid.  For the
          combined result this status means that all signatures are
          valid.

    `GPGME_SIG_STAT_GOOD_EXP'
          This status indicates that the signature is valid but
          expired.  For the combined result this status means that all
          signatures are valid and expired.

    `GPGME_SIG_STAT_GOOD_EXPKEY'
          This status indicates that the signature is valid but the key
          used to verify the signature has expired.  For the combined
          result this status means that all signatures are valid and
          all keys are expired.

    `GPGME_SIG_STAT_BAD'
          This status indicates that the signature is invalid.  For the
          combined result this status means that all signatures are
          invalid.

    `GPGME_SIG_STAT_NOKEY'
          This status indicates that the signature could not be
          verified due to a missing key.  For the combined result this
          status means that all signatures could not be checked due to
          missing keys.

    `GPGME_SIG_STAT_NOSIG'
          This status indicates that the signature data provided was
          not a real signature.

    `GPGME_SIG_STAT_ERROR'
          This status indicates that there was some other error which
          prevented the signature verification.

    `GPGME_SIG_STAT_DIFF'
          For the combined result this status means that at least two
          signatures have a different status.  You can get each key's
          status with `gpgme_get_sig_status'.

 - Funktion: GpgmeError gpgme_op_verify (GpgmeCtx CTX, GpgmeData SIG,
          GpgmeData SIGNED_TEXT, GpgmeData PLAIN, GpgmeSigStat *R_STAT)
     The function `gpgme_op_verify' verifies that the signature in the
     data object SIG is a valid signature.  If SIG is a detached
     signature, then the signed text should be provided in SIGNED_TEXT
     and PLAIN should be a null pointer.  Otherwise, if SIG is a normal
     (or cleartext) signature, SIGNED_TEXT should be a null pointer and
     PLAIN should be a writable data object that will contain the
     plaintext after successful verification.

     The combined status of all signatures is returned in R_STAT.  The
     results of the individual signature verifications can be retrieved
     with `gpgme_get_sig_status' and `gpgme_get_sig_key'.

     The function returns `GPGME_No_Error' if the operation could be
     completed successfully, `GPGME_Invalid_Value' if CTX, SIG, PLAIN
     or R_STAT is not a valid pointer, `GPGME_No_Data' if SIG does not
     contain any data to verify, and passes through any errors that are
     reported by the crypto engine support routines.

 - Funktion: GpgmeError gpgme_op_verify_start (GpgmeCtx CTX,
          GpgmeData SIG, GpgmeData SIGNED_TEXT, GpgmeData PLAIN)
     The function `gpgme_op_verify_start' initiates a `gpgme_op_verify'
     operation.  It can be completed by calling `gpgme_wait' on the
     context.  See Waiting For Completion.

     The function returns `GPGME_No_Error' if the operation could be
     started successfully, `GPGME_Invalid_Value' if CTX, SIG, PLAIN or
     R_STAT is not a valid pointer, and `GPGME_No_Data' if SIG or PLAIN
     does not contain any data to verify.

 - Funktion: const char * gpgme_get_sig_status (GpgmeCtx CTX, int IDX,
          GpgmeSigStat *R_STAT, time_t *R_CREATED)
     The function `gpgme_get_sig_status' receives information about a
     signature after the `gpgme_op_verify' or `gpgme_op_verify_decrypt'
     operation.  A single detached signature can contain signatures by
     more than one key.  The IDX specifies which signature's
     information should be retrieved, starting from 0.

     The status of the signature will be returned in R_STAT if it is
     not `NULL'.  The creation time stamp of the signature will be
     returned in R_CREATED if it is not NULL.

     The function returns a statically allocated string that contains
     the fingerprint of the key which signed the plaintext, or `NULL' if
     CTX is not a valid pointer, the operation is still pending, or no
     verification could be performed.

 - Funktion: const char * gpgme_get_sig_string_attr (GpgmeCtx CTX,
          int IDX, GpgmeAttr WHAT, int WHATIDX)
     This function is similar to `gpgme_get_sig_status' but may be used
     to retrieve more detailed information.  CTX should be the context
     used for the last signature verification, IDX is used to enumerate
     over all signatures starting with `0' and WHATIDX should be `0'
     unless otherwise stated.

     The following values may be used for WHAT:
    `GPGME_ATTR_FPR'
          Return the fingerprint of the key used to create the
          signature.

    `GPGME_ATTR_ERRTOK'
          Return a token with a more detailed error description.  A
          WHATIDX of `0' returns an error token associated with
          validity calculation, a value of `1' return an error token
          related to the certificate checking.

 - Funktion: const char * gpgme_get_sig_ulong_attr (GpgmeCtx CTX,
          int IDX, GpgmeAttr WAHT, int WHATIDX)
     This function is similar to `gpgme_get_sig_string_attr' but used
     for attributes which can be represented by an `unsigned long' data
     type.  CTX should be the context used for the last signature
     verification, IDX is used to enumerate over all signatures
     starting with `0' and WHATIDX should be `0' unless otherwise
     stated.

     The following values may be used for WHAT:
    `GPGME_ATTR_CREATED'
          Return the creation time of the signature in seconds since
          Epoch.  This is the same value as returned by
          `gpgme_get_sig_status'.

    `GPGME_ATTR_EXPIRE'
          Return the expiration time of the signature in seconds since
          Epoch.

    `GPGME_ATTR_VALIDITY'
          Returns the validity of the key used to create the signature.
          This is a shortcut function which avoids an extra key
          lookup.  The value returned is one of
          `GPGME_VALIDITY_UNKNOWN', `GPGME_VALIDITY_NEVER',
          `GPGME_VALIDITY_MARGINAL' or `GPGME_VALIDITY_FULL'.

    `GPGME_ATTR_SIG_STATUS'
          This is the same value as returned by `gpgme_get_sig_status'.

    `GPGME_ATTR_SIG_SUMMARY'
          This returns a bit vector giving a summary of the signature
          status.  Itprovides an easy interface to a defined semantic
          of the signature status.  Checking just one bit is sufficient
          to see whether a signature is valid without any restrictions.

          The defined bits are:
         `GPGME_SIGSUM_VALID'
               The signature is fully valid.

         `GPGME_SIGSUM_GREEN'
               The signature is good but one might want to display some
               extra   information.  Check the other bits.

         `GPGME_SIGSUM_RED'
               The signature is bad. It might be useful to checkother
               bits and   display moe information, i.e. a revoked
               certificate might not render a   signature invalid when
               the message was received prior to the cause for   the
               revocation.

         `GPGME_SIGSUM_KEY_REVOKED'
               The key or at least one certificate has been revoked.

         `GPGME_SIGSUM_KEY_EXPIRED'
               The key or one of the certificates has expired. It is
               probably a good   idea to display the date of the
               expiration.

         `GPGME_SIGSUM_SIG_EXPIRED'
               The signature has expired.

         `GPGME_SIGSUM_KEY_MISSING'
               Can't verifydue to a missing key o certificate.

         `GPGME_SIGSUM_CRL_MISSING'
               The CRL (or an equivalent mechanism) is not available.

         `GPGME_SIGSUM_CRL_TOO_OLD'
               Available CRL is too old.

         `GPGME_SIGSUM_BAD_POLICY'
               A policy requirement was not met.

         `GPGME_SIGSUM_SYS_ERROR'
               A system error occured.

 - Funktion: const char * gpgme_get_sig_key (GpgmeCtx CTX, int IDX,
          GpgmeKey *R_KEY)
     The function `gpgme_get_sig_status' receives a `GpgmeKey' object
     for the key which was used to verify the signature after the
     `gpgme_op_verify' or `gpgme_op_verify_decrypt' operation.  A
     single detached signature can contain signatures by more than one
     key.  The IDX specifies which signature's information should be
     retrieved, starting from 0.  The key will have on reference for
     the user.

     The function is a convenient way to retrieve the keys belonging to
     the fingerprints returned by `gpgme_get_sig_status'.

     The function returns `GPGME_No_Error' if the key could be
     returned, `GPGME_Invalid_Value' if R_KEY is not a valid pointer,
     `GPGME_Invalid_Key' if the fingerprint is not valid, `GPGME_EOF'
     if IDX is too large, or some other error value if a problem
     occurred requesting the key.

 - Funktion: char * gpgme_get_notation (GpgmeCtx CTX)
     The function `gpgme_get_notation' can be used to retrieve notation
     data from the last signature check in the context CTX.

     If there is notation data available from the last signature check,
     this function may be used to return this notation data as a string.
     The string is an XML representation of that data embedded in a
     <notation> container.  The user has to release the string with
     `free'.

     The function returns a string if the notation data is available or
     `NULL' if there is no such data available.

Decrypt and Verify
------------------

 - Funktion: GpgmeError gpgme_op_decrypt_verify (GpgmeCtx CTX,
          GpgmeData CIPHER, GpgmeData PLAIN, GpgmeSigStat *R_STAT)
     The function `gpgme_op_decrypt_verify' decrypts the ciphertext in
     the data object CIPHER and stores it into the data object PLAIN.
     If CIPHER contains signatures, they will be verified and their
     combined status will be returned in R_STAT.

     After the operation completed, `gpgme_op_get_sig_status' and
     `gpgme_op_get_sig_key' can be used to retrieve more information
     about the signatures.

     The function returns `GPGME_No_Error' if the ciphertext could be
     decrypted successfully, `GPGME_Invalid_Value' if CTX, CIPHER,
     PLAIN or R_STAT is not a valid pointer, `GPGME_No_Data' if CIPHER
     does not contain any data to decrypt, `GPGME_Decryption_Failed' if
     CIPHER is not a valid cipher text, `GPGME_No_Passphrase' if the
     passphrase for the secret key could not be retrieved, and passes
     through any errors that are reported by the crypto engine support
     routines.

 - Funktion: GpgmeError gpgme_op_decrypt_verify (GpgmeCtx CTX,
          GpgmeData CIPHER, GpgmeData PLAIN)
     The function `gpgme_op_decrypt_verify_start' initiates a
     `gpgme_op_decrypt_verify' operation.  It can be completed by
     calling `gpgme_wait' on the context.  See Waiting For Completion.

     The function returns `GPGME_No_Error' if the operation could be
     started successfully, `GPGME_Invalid_Value' if CTX, CIPHER, PLAIN
     or R_STAT is not a valid pointer, and `GPGME_No_Data' if CIPHER
     does not contain any data to decrypt.

Sign
----

   A signature can contain signatures by one or more keys.  The set of
keys used to create a signatures is contained in a context, and is
applied to all following signing operations in this context (until the
set is changed).

Selecting Signers
.................

 - Funktion: void gpgme_signers_clear (GpgmeCtx CTX)
     The function `gpgme_signers_clear' releases a reference for each
     key on the signers list and removes the list of signers from the
     context CTX.

     Every context starts with an empty list.

 - Funktion: GpgmeError gpgme_signers_add (GpgmeCtx CTX,
          const GpgmeKey KEY)
     The function `gpgme_signers_add' adds the key KEY to the list of
     signers in the context CTX.

     Calling this function acquires an additional reference for the key.

 - Funktion: GpgmeKey gpgme_signers_enum (const GpgmeCtx CTX, int SEQ)
     The function `gpgme_signers_enum' returns the SEQth key in the
     list of signers in the context CTX.  An additional reference is
     acquired for the user.

     If SEQ is out of range, `NULL' is returned.

Creating a Signature
....................

 - Data type: enum GpgmeSigMode
     The `GpgmeSigMode' type is used to specify the desired type of a
     signature.  The following modes are available:

    `GPGME_SIG_MODE_NORMAL'
          A normal signature is made, the output includes the plaintext
          and the signature.

    `GPGME_SIG_MODE_DETACH'
          A detached signature is made.

    `GPGME_SIG_MODE_CLEAR'
          A clear text signature is made.  The ASCII armor and text
          mode settings of the context are ignored.

 - Funktion: GpgmeError gpgme_op_sign (GpgmeCtx CTX, GpgmeData PLAIN,
          GpgmeData SIG, GpgmeSigMode MODE)
     The function `gpgme_op_sign' creates a signature for the text in
     the data object PLAIN and returns it in the data object SIG.  The
     type of the signature created is determined by the ASCII armor and
     text mode attributes set for the context CTX and the requested
     signature mode MODE.

     More information about the signatures is available with
     `gpgme_get_op_info'.  See Detailed Results.

     If an S/MIME signed message is created using the CMS crypto engine,
     the number of certificates to include in the message can be
     specified with `gpgme_set_include_certs'.  See Included Certificates.

     The function returns `GPGME_No_Error' if the signature could be
     created successfully, `GPGME_Invalid_Value' if CTX, PLAIN or SIG
     is not a valid pointer, `GPGME_No_Data' if the signature could not
     be created, `GPGME_No_Passphrase' if the passphrase for the secret
     key could not be retrieved, and passes through any errors that are
     reported by the crypto engine support routines.

 - Funktion: GpgmeError gpgme_op_sign_start (GpgmeCtx CTX,
          GpgmeData PLAIN, GpgmeData SIG, GpgmeSigMode MODE)
     The function `gpgme_op_sign_start' initiates a `gpgme_op_sign'
     operation.  It can be completed by calling `gpgme_wait' on the
     context.  See Waiting For Completion.

     The function returns `GPGME_No_Error' if the operation could be
     started successfully, and `GPGME_Invalid_Value' if CTX, PLAIN or
     SIG is not a valid pointer.

Encrypt
-------

   One plaintext can be encrypted for several recipients at the same
time.  The list of recipients is created independently of any context,
and then passed to the encryption operation.

Selecting Recipients
....................

 - Data type: GpgmeRecipients
     The `GpgmeRecipients' type is a handle for a set of recipients
     that can be used in an encryption process.

 - Funktion: GpgmeError gpgme_recipients_new (GpgmeRecipients *R_RSET)
     The function `gpgme_recipients_new' creates a new, empty set of
     recipients and returns a handle for it in R_RSET.

     The function returns `GPGME_No_Error' if the recipient set could
     be created successfully, and `GPGME_Out_Of_Core' if not enough
     memory was available.

 - Funktion: void gpgme_recipients_release (GpgmeRecipients RSET)
     The function `gpgme_recipients_release' destroys the set of
     recipients RSET and releases all associated resources.

 - Funktion: GpgmeError gpgme_recipients_add_name
          (GpgmeRecipients RSET, const char *NAME)
     The function `gpgme_recipients_add_name' adds the recipient NAME
     to the set of recipients RSET.  This is equivalent to
     `gpgme_recipients_add_name_with_validity' with a validity of
     `GPGME_VALIDITY_UNKNOWN'.

     The function returns `GPGME_No_Error' if the recipient was added
     successfully, `GPGME_Invalid_Value' if RSET or NAME is not a valid
     pointer, and `GPGME_Out_Of_Core' if not enough memory is available.

 - Funktion: GpgmeError gpgme_recipients_add_name_with_validity
          (GpgmeRecipients RSET, const char *NAME, GpgmeValidity VAL)
     The function `gpgme_recipients_add_name_with_validity' adds the
     recipient NAME with the validity VAL to the set of recipients
     RSET.  If the validity is not known, the function
     `gpgme_recipients_add_name' can be used.  See Information About Keys,
     for the possible values for VAL.

     The function returns `GPGME_No_Error' if the recipient was added
     successfully, `GPGME_Invalid_Value' if RSET or NAME is not a valid
     pointer, and `GPGME_Out_Of_Core' if not enough memory is available.

 - Funktion: unsigned int gpgme_recipients_count
          (const GPGMERECIPIENTS RSET)
     The function `gpgme_recipients_count' returns the number of
     recipients in the set RSET.

 - Funktion: GpgmeError gpgme_recipients_enum_open
          (const GpgmeRecipients RSET, void **ITER)
     The function `gpgme_recipients_enum_open' creates a new iterator
     ITER that can be used to walk through the set of recipients in
     RSET, using `gpgme_recipients_enum_read'.

     If the iterator is not needed anymore, it can be closed with
     `gpgme_recipients_enum_close'.

     The function returns `GPGME_No_Error' if the enumerator was
     successfully created and `GPGME_Invalid_Value' if RSET or ITER is
     not a valid pointer.

 - Funktion: const char * gpgme_recipients_enum_read
          (const GpgmeRecipients RSET, void **ITER)
     The function `gpgme_recipients_enum_read' returns a string
     containing the name of the next recipient in the set RSET for the
     iterator ITER.  The string is valid as long as RSET is valid or
     the function is called the next time with the same recipient set
     and iterator, whatever is earlier.

 - Funktion: GpgmeError gpgme_recipients_enum_close
          (const GpgmeRecipients RSET, void **ITER)
     The function `gpgme_recipients_enum_close' releases the iterator
     ITER for the recipient set RSET.

Encrypting a Plaintext
......................

 - Funktion: GpgmeError gpgme_op_encrypt (GpgmeCtx CTX,
          GpgmeRecipients RSET, GpgmeData PLAIN, GpgmeData CIPHER)
     The function `gpgme_op_encrypt' encrypts the plaintext in the data
     object PLAIN for the recipients RSET and stores the ciphertext in
     the data object CIPHER.  The type of the ciphertext created is
     determined by the ASCII armor and text mode attributes set for the
     context CTX.

     If `GPGME_Invalid_Recipients' is returned, some recipients in RSET
     are invalid, but not all.  In this case the plaintext is encrypted
     for all valid recipients and returned in CIPHER.  More information
     about the invalid recipients is available with
     `gpgme_get_op_info'.  See Detailed Results.

     If RECP is `NULL', symmetric rather than public key encryption is
     performed.  Symmetrically encrypted cipher text can be deciphered
     with `gpgme_op_decrypt'.  Note that in this case the crypto
     backend needs to retrieve a passphrase from the user.  Symmetric
     encryption is currently only supported for the OpenPGP crypto
     backend.

     The function returns `GPGME_No_Error' if the ciphertext could be
     created successfully, `GPGME_Invalid_Value' if CTX, RSET, PLAIN or
     CIPHER is not a valid pointer, `GPGME_No_Recipients' if RSET does
     not contain any valid recipients, `GPGME_Invalid_Recipients' if
     RSET contains some invalid recipients, `GPGME_No_Passphrase' if
     the passphrase for the secret key could not be retrieved, and
     passes through any errors that are reported by the crypto engine
     support routines.

 - Funktion: GpgmeError gpgme_op_encrypt_start (GpgmeCtx CTX,
          GpgmeRecipients RSET, GpgmeData PLAIN, GpgmeData CIPHER)
     The function `gpgme_op_encrypt_start' initiates a
     `gpgme_op_encrypt' operation.  It can be completed by calling
     `gpgme_wait' on the context.  See Waiting For Completion.

     The function returns `GPGME_No_Error' if the operation could be
     started successfully, `GPGME_Invalid_Value' if CTX, RSET, PLAIN or
     CIPHER is not a valid pointer, and `GPGME_No_Recipients' if RSET
     does not contain any valid recipients.

 - Funktion: GpgmeError gpgme_op_encrypt_sign (GpgmeCtx CTX,
          GpgmeRecipients RSET, GpgmeData PLAIN, GpgmeData CIPHER)
     The function `gpgme_op_encrypt_sign' does a combined encrypt and
     sign operation.  It is used like `gpgme_op_encrypt', but the
     ciphertext also contains signatures for the signers listed in CTX.

     The combined encrypt and sign operation is currently only available
     for the OpenPGP crypto engine.

 - Funktion: GpgmeError gpgme_op_encrypt_sign_start (GpgmeCtx CTX,
          GpgmeRecipients RSET, GpgmeData PLAIN, GpgmeData CIPHER)
     The function `gpgme_op_encrypt_sign_start' initiates a
     `gpgme_op_encrypt_sign' operation.  It can be completed by calling
     `gpgme_wait' on the context.  See Waiting For Completion.

     The function returns `GPGME_No_Error' if the operation could be
     started successfully, `GPGME_Invalid_Value' if CTX, RSET, PLAIN or
     CIPHER is not a valid pointer, and `GPGME_No_Recipients' if RSET
     does not contain any valid recipients.

Detailed Results
----------------

 - Funktion: char * gpgme_get_op_info (GpgmeCtx CTX, int RESERVED)
     The function `gpgme_get_op_info' retrieves more information about
     the last crypto operation.

     The function returns a string in the XML format.  The user has to
     release the string with `free'.

     Here is a sample of the information that might be returned:
          <GnupgOperationInfo>
            <signature>
              <detached/> <!-- or cleartext or standard -->
              <algo>17</algo>
              <hashalgo>2</hashalgo>
              <micalg>pgp-sha1</micalg>
              <sigclass>01</sigclass>
              <created>9222222</created>
              <fpr>121212121212121212</fpr>
            </signature>
          </GnupgOperationInfo>

     Currently, the only operations that return additional information
     are encrypt, sign and import.  See Encrypt, Sign,
     Importing Keys.

     The function returns a string or `NULL' if no such data is
     available.

Run Control
===========

   GPGME supports running operations synchronously and asynchronously.
You can use asynchronous operation to set up a context up to initiating
the desired operation, but delay performing it to a later point.

   Furthermore, you can use an external event loop to control exactly
when GPGME runs.  This ensures that GPGME only runs when necessary and
also prevents it from blocking for a long time.

Waiting For Completion
----------------------

 - Funktion: GpgmeCtx gpgme_wait (GpgmeCtx CTX, GpgmeError *STATUS,
          int HANG)
     The function `gpgme_wait' continues the pending operation within
     the context CTX.  In particular, it ensures the data exchange
     between GPGME and the crypto backend and watches over the run time
     status of the backend process.

     If HANG is true, the function does not return until the operation
     is completed or cancelled.  Otherwise the function will not block
     for a long time.

     The error status of the finished operation is returned in STATUS
     if `gpgme_wait' does not return `NULL'.

     The CTX argument can be `NULL'.  In that case, `gpgme_wait' waits
     for any context to complete its operation.

     `gpgme_wait' can be used only in conjunction with any context that
     has a pending operation initiated with one of the
     `gpgme_op_*_start' functions except `gpgme_op_keylist_start' and
     `gpgme_op_trustlist_start' (for which you should use the
     corresponding `gpgme_op_*_next' functions).  If CTX is `NULL', all
     of such contexts are waited upon and possibly returned.
     Synchronous operations running in parallel, as well as key and
     trust item list operations, do not affect `gpgme_wait'.

     In a multi-threaded environment, only one thread should ever call
     `gpgme_wait' at any time, irregardless if CTX is specified or not.
     This means that all calls to this function should be fully
     synchronized by locking primitives.

     The function returns the CTX of the context which has finished the
     operation.

Cancelling an Operation
-----------------------

 - Funktion: void gpgme_cancel (GpgmeCtx CTX)
     The function `gpgme_cancel' tries to cancel the pending operation.
     A running synchronous operation in the context or the function
     `gpgme_wait' with this context as its CTX argument might notice
     the cancellation flag and return.  It is currently not guaranteed
     to work under all circumstances.  Its current primary purpose is
     to prevent asking for a passphrase again in the passphrase
     callback.

Hooking Up Into Idle Time
-------------------------

 - Data type: void (*GpgmeIdleFunc) (void)
     The `GpgmeIdleFunc' type is the type of functions usable as an
     idle function that can be registered with `gpgme_register_idle'.

 - Funktion: GpgmeIdleFunc gpgme_register_idle (GpgmeIdleFunc IDLE)
     The function `gpgme_register_idle' can be used to register IDLE as
     the idle function.

     IDLE will be called whenever GPGME thinks that it is idle and time
     can better be spent elsewhere.  Setting IDLE to `NULL' disables
     use of the idle function (this is the default).

     The function returns the old idle function, or `NULL' if none was
     registered yet.

Using External Event Loops
--------------------------

   GPGME hides the complexity of the communication between the library
and the crypto engine.  The price of this convenience is that the
calling thread can block arbitrary long waiting for the data returned
by the crypto engine.  In single-threaded programs, in particular if
they are interactive, this is an unwanted side-effect.  OTOH, if
`gpgme_wait' is used without the HANG option being enabled, it might be
called unnecessarily often, wasting CPU time that could be used
otherwise.

   The I/O callback interface described in this section lets the user
take control over what happens when.  GPGME will provide the user with
the file descriptors that should be monitored, and the callback
functions that should be invoked when a file descriptor is ready for
reading or writing.  It is then the user's responsibility to decide
when to check the file descriptors and when to invoke the callback
functions.  Usually this is done in an event loop, that also checks for
events in other parts of the program.  If the callback functions are
only called when the file descriptors are ready, GPGME will never
block.  This gives the user mroe control over the program flow, and
allows to perform other tasks when GPGME would block otherwise.

   By using this advanced mechanism, GPGME can be integrated smoothly
into GUI toolkits like GTK+ even for single-threaded programs.

I/O Callback Interface
......................

 - Data type: void (*GpgmeIOCb) (void *DATA, int FD)
     The `GpgmeIOCb' type is the type of functions which GPGME wants to
     register as I/O callback handlers using the `GpgmeRegisterIOCb'
     functions provided by the user.

     DATA and FD are provided by GPGME when the I/O callback handler is
     registered, and should be passed through to the handler when it is
     invoked by the user because it noticed activity on the file
     descriptor FD.

 - Data type: GpgmeError (*GpgmeRegisterIOCb) (void *DATA, int FD,
int DIR, GpgmeIOCb FNC, void *FNC_DATA, void **TAG)
     The `GpgmeRegisterIOCb' type is the type of functions which can be
     called by GPGME to register an I/O callback funtion FNC for the
     file descriptor FD with the user.  FNC_DATA should be passed as
     the first argument to FNC when the handler is invoked (the second
     argument should be FD).  If DIR is 0, FNC should be called by the
     user when FD is ready for writing.  If DIR is 1, FNC should be
     called when FD is ready for reading.

     DATA was provided by the user when registering the
     `GpgmeRegisterIOCb' function with GPGME and will always be passed
     as the first argument when registering a callback function.  For
     example, the user can use this to determine the event loop to
     which the file descriptor should be added.

     GPGME will call this function when a crypto operation is initiated
     in a context for which the user has registered I/O callback
     handler functions with `gpgme_set_io_cbs'.  It can also call this
     function when it is in an I/O callback handler for a file
     descriptor associated to this context.

     The user should return a unique handle in TAG identifying this I/O
     callback registration, which will be passed to the
     `GpgmeRegisterIOCb' function without interpretation when the file
     descriptor should not be monitored anymore.

 - Data type: void (*GpgmeRemoveIOCb) (void *TAG)
     The `GpgmeRemoveIOCb' type is the type of functions which can be
     called by GPGME to remove an I/O callback handler that was
     registered before.  TAG is the handle that was returned by the
     `GpgmeRegisterIOCb' for this I/O callback.

     GPGME can call this function when a crypto operation is in an I/O
     callback.  It will also call this function when the context is
     destroyed while an operation is pending.

 - Data type: enum GpgmeEventIO
     The `GpgmeEventIO' type specifies the type of an event that is
     reported to the user by GPGME as a consequence of an I/O
     operation.  The following events are defined:

    `GPGME_EVENT_DONE'
          The operation is finished, the last I/O callback for this
          operation was removed.  The accompanying TYPE_DATA points to a
          `GpgmeError' variable that contains the status of the
          operation that finished.  This event is signalled after the
          last I/O callback has been removed.

    `GPGME_EVENT_NEXT_KEY'
          In a `gpgme_op_keylist_start' operation, the next key was
          received from the crypto engine.  The accompanying TYPE_DATA
          is a `GpgmeKey' variable that contains the key with one
          reference for the user.

    `GPGME_EVENT_NEXT_TRUSTITEM'
          In a `gpgme_op_trustlist_start' operation, the next trust item
          was received from the crypto engine.  The accompanying
          TYPE_DATA is a `GpgmeTrustItem' variable that contains the
          trust item with one reference for the user.

 - Data type: void (*GpgmeEventIOCb) (void *DATA, GpgmeEventIO TYPE,
void *TYPE_DATA)
     The `GpgmeEventIOCb' type is the type of functions which can be
     called by GPGME to signal an event for an operation running in a
     context which has I/O callback functions registered by the user.

     DATA was provided by the user when registering the
     `GpgmeEventIOCb' function with GPGME and will always be passed as
     the first argument when registering a callback function.  For
     example, the user can use this to determine the context in which
     this event has occured.

     TYPE will specify the type of event that has occured.  TYPE_DATA
     specifies the event further, as described in the above list of
     possible `GpgmeEventIO' types.

     GPGME can call this function in an I/O callback handler.

Registering I/O Callbacks
.........................

 - Data type: struct GpgmeIOCbs
     This structure is used to store the I/O callback interface
     functions described in the previous section.  It has the following
     members:

    `GpgmeRegisterIOCb add'
          This is the function called by GPGME to register an I/O
          callback handler.  It must be specified.

    `void *add_data'
          This is passed as the first argument to the `add' function
          when it is called by GPGME.  For example, it can be used to
          determine the event loop to which the file descriptor should
          be added.

    `GpgmeRemoveIOCb remove'
          This is the function called by GPGME to remove an I/O
          callback handler.  It must be specified.

    `GpgmeEventIOCb event'
          This is the function called by GPGME to signal an event for
          an operation.  It is optional, but if you don't specify it,
          you can not retrieve the return value of the operation.

    `void *event_data'
          This is passed as the first argument to the `event' function
          when it is called by GPGME.  For example, it can be used to
          determine the context in which the event has occured.

 - Funktion: void gpgme_set_io_cbs (GpgmeCtx CTX,
          struct GpgmeIOCbs *IO_CBS)
     The function `gpgme_set_io_cbs' enables the I/O callback interface
     for the context CTX.  The I/O callback functions are specified by
     IO_CBS.

     If IO_CBS->`add' is `NULL', the I/O callback interface is disabled
     for the context, and normal operation is restored.

 - Funktion: void gpgme_get_io_cbs (GpgmeCtx CTX,
          struct GpgmeIOCbs *IO_CBS)
     The function `gpgme_get_io_cbs' returns the I/O callback functions
     set with `gpgme_set_io_cbs' in IO_CBS.

I/O Callback Example
....................

   To actually use an external event loop, you have to implement the I/O
callback functions that are used by GPGME to register and unregister
file descriptors.  Furthermore, you have to actually monitor these file
descriptors for activity and call the appropriate I/O callbacks.

   The following example illustrates how to do that.  The example uses
locking to show in which way the the callbacks and the event loop can
run concurrently.  For the event loop, we use a fixed array.  For a
real-world implementation, you should use a dynamically sized structure
because the number of file descriptors needed for a crypto operation in
GPGME is not predictable.

     #include <pthread.h>
     #include <sys/types.h>
     #include <gpgme.h>

     /* The following structure holds the result of a crypto operation.  */
     struct op_result
     {
       int done;
       GpgmeError err;
     };

     /* The following structure holds the data associated with one I/O
     callback.  */
     struct one_fd
     {
       int fd;
       int dir;
       GpgmeIOCb fnc;
       void *fnc_data;
     };

     struct event_loop
     {
       pthread_mutex_t lock;
     #define MAX_FDS 32
       /* Unused slots are marked with FD being -1.  */
       struct one_fd fds[MAX_FDS];
     };

   The following functions implement the I/O callback interface.

     GpgmeError
     add_io_cb (void *data, int fd, int dir, GpgmeIOCb fnc, void *fnc_data,
     	   void **r_tag)
     {
       struct event_loop *loop = data;
       struct one_fd *fds = loop->fds;
       int i;

       pthread_mutex_lock (&loop->lock);
       for (i = 0; i < MAX_FDS; i++)
         {
           if (fds[i].fd == -1)
     	{
     	  fds[i].fd = fd;
     	  fds[i].dir = dir;
     	  fds[i].fnc = fnc;
     	  fds[i].fnc_data = fnc_data;
     	  break;
     	}
         }
       pthread_mutex_unlock (&loop->lock);
       if (i == MAX_FDS)
         return GPGME_General_Error;
       *r_tag = &fds[i];
       return 0;
     }

     void
     remove_io_cb (void *tag)
     {
       struct one_fd *fd = tag;

       pthread_mutex_lock (&loop->lock);
       fd->fd = -1;
       pthread_mutex_unlock (&loop->lock);
     }

     void
     event_io_cb (void *data, GpgmeEventIO type, void *type_data)
     {
       struct op_result *result = data;
       GpgmeError *err = data;

       /* We don't support list operations here.  */
       if (type == GPGME_EVENT_DONE)
         {
           result->done = 1;
           result->err = *data;
         }
     }

   The final missing piece is the event loop, which will be presented
next.  We only support waiting for the success of a single operation.

     int
     do_select (struct event_loop *loop)
     {
       fd_set rfds;
       fd_set wfds;
       int i, n;
       int any = 0;

       pthread_mutex_lock (&loop->lock);
       FD_ZERO (&rfds);
       FD_ZERO (&wfds);
       for (i = 0; i < FDLIST_MAX; i++)
         if (fdlist[i].fd != -1)
           FD_SET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds);
       pthread_mutex_unlock (&loop->unlock);

       do
         {
           n = select (FD_SETSIZE, &rfds, &wfds, NULL, 0);
         }
       while (n < 0 && errno == EINTR);

       if (n < 0)
         return n;	/* Error or timeout.  */

       pthread_mutex_lock (&loop->lock);
       for (i = 0; i < FDLIST_MAX && n; i++)
         {
           if (fdlist[i].fd != -1)
     	{
     	  if (FD_ISSET (fdlist[i].fd, fdlist[i].dir ? &rfds : &wfds))
     	    {
     	      assert (n);
     	      n--;
     	      any = 1;
                   /* The I/O callback handler can register/remove callbacks,
                      so we have to unlock the file descriptor list.  */
                   pthread_mutex_unlock (&loop->lock);
     	      (*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd);
                   pthread_mutex_lock (&loop->lock);
     	    }
     	}
         }
       pthread_mutex_unlock (&loop->lock);
       return any;
     }

     void
     wait_for_op (struct event_loop *loop, struct op_result *result)
     {
       int ret;

       do
         {
           ret = do_select (loop);
         }
       while (ret >= 0 && !result->done);
       return ret;
     }

   The main function shows how to put it all together.

     int
     main (int argc, char *argv[])
     {
       struct event_loop loop;
       struct op_result result;
       GpgmeCtx ctx;
       GpgmeError err;
       GpgmeData sig, text;
       GpgmeSigStat status;
       int i;
       struct GpgmeIOCbs io_cbs =
       {
         add_io_cb,
         &loop,
         remove_io_cb,
         event_io_cb,
         &result
       };

       /* Initialize the loop structure.  */
       loop.lock = PTHREAD_MUTEX_INITIALIZER;
       for (i = 0; i < MAX_FDS; i++)
         loop->fds[i].fd = -1;

       /* Initialize the result structure.  */
       result.done = 0;

       err = gpgme_data_new_from_file (&sig, "signature", 1);
       if (!err)
         err = gpgme_data_new_from_file (&text, "text", 1);
       if (!err)
         err = gpgme_new (&ctx);
       if (!err)
         {
            gpgme_set_io_cbs (ctx, &io_cbs);
            err = gpgme_op_verify_start (ctx, sig, text, &status);
         }
       if (err)
         {
           fprintf (stderr, "gpgme error: %s\n", gpgme_strerror (err));
           exit (1);
         }

       wait_for_op (&loop, &result);
       if (!result.done)
         {
           fprintf (stderr, "select error\n");
           exit (1);
         }
       if (!result.err)
         {
           fprintf (stderr, "verification failed: %s\n", gpgme_strerror (result.err));
           exit (1);
         }
       /* Evaluate STATUS.  */
       ...
       return 0;
     }

I/O Callback Example GTK+
.........................

   The I/O callback interface can be used to integrate GPGME with the
GTK+ event loop.  The following code snippets shows how this can be
done using the appropriate register and remove I/O callback functions.
In this example, the private data of the register I/O callback function
is unused.  The event notifications is missing because it does not
require any GTK+ specific setup.

     #include <gtk/gtk.h>

     struct my_gpgme_io_cb
     {
       GpgmeIOCb fnc;
       void *fnc_data;
       guint input_handler_id
     };

     void
     my_gpgme_io_cb (gpointer data, gint source, GdkInputCondition condition)
     {
       struct my_gpgme_io_cb *iocb = data;
       (*(iocb->fnc)) (iocb->data, source);
     }

     void
     my_gpgme_remove_io_cb (void *data)
     {
       struct my_gpgme_io_cb *iocb = data;
       gtk_input_remove (data->input_handler_id);
     }

     void
     my_gpgme_register_io_callback (void *data, int fd, int dir, GpgmeIOCb fnc,
                                    void *fnc_data, void **tag)
     {
       struct my_gpgme_io_cb *iocb = g_malloc (sizeof (struct my_gpgme_io_cb));
       iocb->fnc = fnc;
       iocb->data = fnc_data;
       iocb->input_handler_id = gtk_input_add_full (fd, dir
                                                        ? GDK_INPUT_READ
                                                        : GDK_INPUT_WRITE,
                                                    my_gpgme_io_callback,
                                                    0, iocb, NULL);
       *tag = iocb;
       return 0;
     }

I/O Callback Example GDK
........................

   The I/O callback interface can also be used to integrate GPGME with
the GDK event loop.  The following code snippets shows how this can be
done using the appropriate register and remove I/O callback functions.
In this example, the private data of the register I/O callback function
is unused.  The event notifications is missing because it does not
require any GDK specific setup.

   It is very similar to the GTK+ example in the previous section.

     #include <gdk/gdk.h>

     struct my_gpgme_io_cb
     {
       GpgmeIOCb fnc;
       void *fnc_data;
       gint tag;
     };

     void
     my_gpgme_io_cb (gpointer data, gint source, GdkInputCondition condition)
     {
       struct my_gpgme_io_cb *iocb = data;
       (*(iocb->fnc)) (iocb->data, source);
     }

     void
     my_gpgme_remove_io_cb (void *data)
     {
       struct my_gpgme_io_cb *iocb = data;
       gdk_input_remove (data->tag);
     }

     void
     my_gpgme_register_io_callback (void *data, int fd, int dir, GpgmeIOCb fnc,
                                    void *fnc_data, void **tag)
     {
       struct my_gpgme_io_cb *iocb = g_malloc (sizeof (struct my_gpgme_io_cb));
       iocb->fnc = fnc;
       iocb->data = fnc_data;
       iocb->tag = gtk_input_add_full (fd, dir ? GDK_INPUT_READ : GDK_INPUT_WRITE,
                                       my_gpgme_io_callback, iocb, NULL);
       *tag = iocb;
       return 0;
     }