diff options
| author | Werner Koch <[email protected]> | 2001-01-22 20:22:41 +0000 | 
|---|---|---|
| committer | Werner Koch <[email protected]> | 2001-01-22 20:22:41 +0000 | 
| commit | f2be4142516bcd9536884bb0e40e8bf561352bd4 (patch) | |
| tree | ed2ac09ccc19dbcf076c719f8d11485b101c287f | |
| parent | Nicer W32 installation support (diff) | |
| download | gpgme-f2be4142516bcd9536884bb0e40e8bf561352bd4.tar.gz gpgme-f2be4142516bcd9536884bb0e40e8bf561352bd4.zip | |
Some new but untested functions
| -rw-r--r-- | acconfig.h | 2 | ||||
| -rwxr-xr-x | autogen.sh | 2 | ||||
| -rw-r--r-- | configure.in | 7 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 11 | ||||
| -rw-r--r-- | gpgme/Makefile.am | 3 | ||||
| -rw-r--r-- | gpgme/context.h | 3 | ||||
| -rw-r--r-- | gpgme/delete.c | 116 | ||||
| -rw-r--r-- | gpgme/errors.c | 2 | ||||
| -rw-r--r-- | gpgme/gpgme.c | 11 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 16 | ||||
| -rw-r--r-- | gpgme/key.c | 20 | ||||
| -rw-r--r-- | gpgme/key.h | 1 | ||||
| -rw-r--r-- | gpgme/rungpg.c | 19 | ||||
| -rw-r--r-- | gpgme/rungpg.h | 3 | ||||
| -rw-r--r-- | gpgme/sign.c | 13 | ||||
| -rw-r--r-- | gpgme/signers.c | 105 | ||||
| -rw-r--r-- | gpgme/util.h | 19 | ||||
| -rw-r--r-- | gpgme/version.c | 192 | ||||
| -rw-r--r-- | gpgme/wait.c | 3 | ||||
| -rw-r--r-- | tests/t-encrypt.c | 4 | 
20 files changed, 522 insertions, 30 deletions
| @@ -41,6 +41,8 @@  /* path to the gpg binary */  #undef GPG_PATH +/* min. needed GPG version */ +#undef NEED_GPG_VERSION  /* stuff needed by lnlib/ */  #undef HAVE_BYTE_TYPEDEF @@ -148,7 +148,7 @@ autoconf  if test "$*" = ""; then      conf_options="--enable-maintainer-mode"  else -   conf_options=$* +    conf_options=$*  fi  echo "Running ./configure $conf_options"  ./configure $conf_options diff --git a/configure.in b/configure.in index 9eb81d16..264dedaa 100644 --- a/configure.in +++ b/configure.in @@ -17,11 +17,13 @@ AM_INIT_AUTOMAKE(gpgme,0.1.4a)  LIBGPGME_LT_CURRENT=2  LIBGPGME_LT_AGE=2  LIBGPGME_LT_REVISION=0 +NEED_GPG_VERSION=1.0.4d  ##############################################  AC_SUBST(LIBGPGME_LT_CURRENT)  AC_SUBST(LIBGPGME_LT_AGE)  AC_SUBST(LIBGPGME_LT_REVISION) +AC_DEFINE_UNQUOTED(NEED_GPG_VERSION, "$NEED_GPG_VERSION")  dnl @@ -156,8 +158,9 @@ complus/Makefile  echo "  	GPGME v${VERSION} has been configured as follows: -	GPG path:   $GPG -	Component:  $component_system +        GPG version: min. $NEED_GPG_VERSION +	GPG path:    $GPG +	Component:   $component_system  " diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 79fed0f4..fe88ebba 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,14 @@ +2001-01-22  Werner Koch  <[email protected]> + +	* delete.c: New. + +	* signers.c: New. +	* key.c (gpgme_key_ref, gpgme_key_unref): New. +	* sign.c (gpgme_op_sign_start): Allow the use of other keys. + +	* version.c (gpgme_get_engine_info,gpgme_check_engine): New. +	* rungpg.c (_gpgme_gpg_set_simple_line_handler): New. +  2001-01-05  Werner Koch  <[email protected]>  	* data.c (gpgme_data_rewind): Allow to rewind data_type_none. diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index 8365678a..74d5955d 100644 --- a/gpgme/Makefile.am +++ b/gpgme/Makefile.am @@ -15,7 +15,7 @@ libgpgme_la_INCLUDES = -I$(top_srcdir)/lib  libgpgme_la_SOURCES = \  	gpgme.h types.h util.h util.c \  	context.h ops.h \ -	data.c recipient.c \ +	data.c recipient.c signers.c \          wait.c wait.h \  	encrypt.c \  	decrypt.c \ @@ -27,6 +27,7 @@ libgpgme_la_SOURCES = \  	import.c \          export.c \  	genkey.c \ +	delete.c \          rungpg.c rungpg.h status-table.h \  	syshdr.h io.h posix-io.c w32-io.c \  	gpgme.c version.c errors.c diff --git a/gpgme/context.h b/gpgme/context.h index 982eb1d3..57d9d1f0 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -63,6 +63,9 @@ struct gpgme_context_s {      int use_textmode;      int keylist_mode; +    int signers_size;  /* size of the following array */ +    GpgmeKey *signers; +      ResultType result_type;      union {          VerifyResult verify; diff --git a/gpgme/delete.c b/gpgme/delete.c new file mode 100644 index 00000000..4e3c9b42 --- /dev/null +++ b/gpgme/delete.c @@ -0,0 +1,116 @@ +/* delete.c -  delete a key  + *	Copyright (C) 2001 Werner Koch (dd9jn) + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <assert.h> + +#include "util.h" +#include "context.h" +#include "ops.h" +#include "key.h" + +static void +delete_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args ) +{ +    if ( ctx->out_of_core ) +        return; + +    switch (code) { +      case STATUS_EOF: +        break; + +      default: +        /* ignore all other codes */ +        break; +    } +} + + +GpgmeError +gpgme_op_delete_start ( GpgmeCtx c, const GpgmeKey key, int allow_secret ) +{ +    GpgmeError rc = 0; +    int i; +    const char *s; + +    fail_on_pending_request( c ); +    c->pending = 1; + +    if (!key) { +        rc = mk_error (Invalid_Value); +        goto leave; +    } + +    if ( c->gpg ) { +        _gpgme_gpg_release ( c->gpg );  +        c->gpg = NULL; +    } +     +    rc = _gpgme_gpg_new ( &c->gpg ); +    if (rc) +        goto leave; + +    _gpgme_gpg_set_status_handler ( c->gpg, delete_status_handler, c ); + +    /* build the commandline */ +    for ( i=0; i < c->verbosity; i++ ) +        _gpgme_gpg_add_arg ( c->gpg, "--verbose" ); +    _gpgme_gpg_add_arg ( c->gpg, allow_secret? +                         "--delete-secret-and-public-key":"--delete-key" ); +     +    _gpgme_gpg_add_arg ( c->gpg, "--" ); +    s = gpgme_key_get_string_attr ( key, GPGME_ATTR_FPR, NULL, 0 ); +    if (!s) { +        rc = mk_error (Invalid_Key); +        goto leave; +    } +    _gpgme_gpg_add_arg ( c->gpg, s ); + +    /* do it */ +    rc = _gpgme_gpg_spawn ( c->gpg, c ); + + leave: +    if (rc) { +        c->pending = 0;  +        _gpgme_gpg_release ( c->gpg ); c->gpg = NULL; +    } +    return rc; +} + + +GpgmeError +gpgme_op_delete ( GpgmeCtx c, const GpgmeKey key, int allow_secret ) +{ +    int rc = gpgme_op_delete_start ( c, key, allow_secret ); +    if ( !rc ) { +        gpgme_wait (c, 1); +        c->pending = 0; +        /* FIXME: check for success */ +    } +    return rc; +} + + + + diff --git a/gpgme/errors.c b/gpgme/errors.c index e25db3ec..f07d0861 100644 --- a/gpgme/errors.c +++ b/gpgme/errors.c @@ -42,6 +42,8 @@ gpgme_strerror (GpgmeError err)    case GPGME_Decryption_Failed: s="Decryption Failed"; break;    case GPGME_No_Passphrase: s="No Passphrase"; break;    case GPGME_Canceled: s="Canceled"; break; +  case GPGME_Invalid_Key: s="Invalid Key"; break; +  case GPGME_Invalid_Engine: s="Invalid Engine"; break;      default:  sprintf (buf, "ec=%d", err ); s=buf; break;  } diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index aea18fa5..54ec97fb 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -72,6 +72,9 @@ gpgme_release ( GpgmeCtx c )      gpgme_key_release ( c->tmp_key );      gpgme_data_release ( c->help_data_1 );      gpgme_data_release ( c->notation ); +    gpgme_signers_clear (c); +    if (c->signers) +        xfree (c->signers);      /* fixme: release the key_queue */      xfree (c);  } @@ -132,7 +135,6 @@ gpgme_get_notation ( GpgmeCtx c )      return _gpgme_data_get_as_string ( c->notation );  } -  /**   * gpgme_set_armor:   * @c: the contect  @@ -241,3 +243,10 @@ gpgme_set_progress_cb ( GpgmeCtx c, GpgmeProgressCb cb, void *cb_value )  } + + + + + + + diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 0fe59f78..971101b9 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -85,6 +85,8 @@ typedef enum {      GPGME_Decryption_Failed = 18,      GPGME_No_Passphrase = 19,      GPGME_Canceled = 20, +    GPGME_Invalid_Key = 21, +    GPGME_Invalid_Engine = 22,  } GpgmeError;  typedef enum { @@ -158,6 +160,9 @@ void gpgme_set_passphrase_cb (GpgmeCtx c,                                GpgmePassphraseCb cb, void *cb_value);  void gpgme_set_progress_cb (GpgmeCtx c, GpgmeProgressCb cb, void *cb_value); +void       gpgme_signers_clear (GpgmeCtx c); +GpgmeError gpgme_signers_add (GpgmeCtx c, const GpgmeKey key); +GpgmeKey   gpgme_signers_enum (const GpgmeCtx c, int seq);  /* Functions to handle recipients */ @@ -200,6 +205,8 @@ GpgmeError    gpgme_data_write ( GpgmeData dh,  /* Key and trust functions */ +void gpgme_key_ref (GpgmeKey key); +void gpgme_key_unref (GpgmeKey key);  void gpgme_key_release ( GpgmeKey key );  char *gpgme_key_get_as_xml ( GpgmeKey key );  const char  *gpgme_key_get_string_attr ( GpgmeKey key, GpgmeAttr what, @@ -233,6 +240,8 @@ GpgmeError gpgme_op_export_start ( GpgmeCtx c, GpgmeRecipients recp,                                     GpgmeData keydata );  GpgmeError gpgme_op_genkey_start ( GpgmeCtx c, const char *parms,                                     GpgmeData pubkey, GpgmeData seckey ); +GpgmeError gpgme_op_delete_start ( GpgmeCtx c, const GpgmeKey key, +                                   int allow_secret ); @@ -261,12 +270,15 @@ GpgmeError gpgme_op_export ( GpgmeCtx c, GpgmeRecipients recp,                               GpgmeData keydata );  GpgmeError gpgme_op_genkey ( GpgmeCtx c, const char *parms,                               GpgmeData pubkey, GpgmeData seckey ); +GpgmeError gpgme_op_delete ( GpgmeCtx c, const GpgmeKey key, int allow_secret);  /* miscellaneous functions */ -const char *gpgme_check_version ( const char *req_version ); +const char *gpgme_check_version (const char *req_version); +GpgmeError  gpgme_check_engine (void); +const char *gpgme_get_engine_info (void);  const char *gpgme_strerror (GpgmeError err); -void gpgme_register_idle ( void (*fnc)(void) ); +void        gpgme_register_idle (void (*fnc)(void));  #ifdef __cplusplus diff --git a/gpgme/key.c b/gpgme/key.c index 89e545b4..87a5602a 100644 --- a/gpgme/key.c +++ b/gpgme/key.c @@ -57,11 +57,18 @@ _gpgme_key_new( GpgmeKey *r_key )      key = xtrycalloc ( 1, sizeof *key );      if (!key)          return mk_error (Out_Of_Core); - +    key->ref_count = 1;      *r_key = key;      return 0;  } +void +gpgme_key_ref ( GpgmeKey key ) +{ +    return_if_fail (key); +    key->ref_count++; +} +  struct subkey_s *  _gpgme_key_add_subkey (GpgmeKey key) @@ -92,6 +99,10 @@ gpgme_key_release ( GpgmeKey key )      if (!key)          return; +    assert (key->ref_count); +    if ( --key->ref_count ) +        return; +      xfree (key->keys.fingerprint);      for (k = key->keys.next; k; k = k2 ) {          k2 = k->next; @@ -105,6 +116,13 @@ gpgme_key_release ( GpgmeKey key )      xfree (key);  } +void +gpgme_key_unref (GpgmeKey key) +{ +    gpgme_key_release (key); +} + +  static char *  set_user_id_part ( char *tail, const char *buf, size_t len )  { diff --git a/gpgme/key.h b/gpgme/key.h index 8c68779f..c9be9b0a 100644 --- a/gpgme/key.h +++ b/gpgme/key.h @@ -45,6 +45,7 @@ struct gpgme_key_s {          unsigned int expired:1 ;          unsigned int disabled:1 ;      } gloflags;  +    unsigned int ref_count;      struct subkey_s   keys;       struct user_id_s *uids;  }; diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 07231716..76313584 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -84,6 +84,7 @@ struct gpg_object_s {          int eof;          GpgColonLineHandler fnc;  /* this indicate use of this structrue */          void *fnc_value; +        int simple;      } colon;      char **argv;   @@ -376,10 +377,25 @@ _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,      gpg->colon.eof = 0;      gpg->colon.fnc = fnc;      gpg->colon.fnc_value = fnc_value; +    gpg->colon.simple = 0;      return 0;  } +GpgmeError +_gpgme_gpg_set_simple_line_handler ( GpgObject gpg, +                                     GpgColonLineHandler fnc, +                                     void *fnc_value )  +{ +    GpgmeError err; + +    err = _gpgme_gpg_set_colon_line_handler (gpg, fnc, fnc_value); +    if (!err) +        gpg->colon.simple = 1; +    return err; +} + +  /*    * The Fnc will be called to get a value for one of the commands with   * a key KEY.  If the Code pssed to FNC is 0, the function may release @@ -1094,7 +1110,8 @@ read_colon_line ( GpgObject gpg )                   * some other printed information.                   */                  *p = 0; -                if ( *buffer && strchr (buffer, ':') ) { +                if ( gpg->colon.simple +                     || (*buffer && strchr (buffer, ':')) ) {                      assert (gpg->colon.fnc);                      gpg->colon.fnc ( gpg->colon.fnc_value, buffer );                  } diff --git a/gpgme/rungpg.h b/gpgme/rungpg.h index 27ccf3ed..bdd4a7a3 100644 --- a/gpgme/rungpg.h +++ b/gpgme/rungpg.h @@ -105,6 +105,9 @@ void       _gpgme_gpg_set_status_handler ( GpgObject gpg,  GpgmeError _gpgme_gpg_set_colon_line_handler ( GpgObject gpg,                                                 GpgColonLineHandler fnc,                                                 void *fnc_value ); +GpgmeError _gpgme_gpg_set_simple_line_handler ( GpgObject gpg, +                                                GpgColonLineHandler fnc, +                                                void *fnc_value );  GpgmeError _gpgme_gpg_set_command_handler ( GpgObject gpg,                                              GpgCommandHandler fnc,                                              void *fnc_value ); diff --git a/gpgme/sign.c b/gpgme/sign.c index 11480e0a..cef099bb 100644 --- a/gpgme/sign.c +++ b/gpgme/sign.c @@ -130,6 +130,7 @@ gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out,  {      int rc = 0;      int i; +    GpgmeKey key;      fail_on_pending_request( c );      c->pending = 1; @@ -170,8 +171,18 @@ gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out,          if ( c->use_textmode )              _gpgme_gpg_add_arg ( c->gpg, "--textmode" );      } -    for ( i=0; i < c->verbosity; i++ ) +    for (i=0; i < c->verbosity; i++)          _gpgme_gpg_add_arg ( c->gpg, "--verbose" ); +    for (i=0; (key = gpgme_signers_enum (c, i)); i++ ) { +        const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, +                                                   NULL, 0); +        if (s) { +            _gpgme_gpg_add_arg (c->gpg, "-u"); +            _gpgme_gpg_add_arg (c->gpg, s); +        } +        gpgme_key_unref (key); +    } +      /* Check the supplied data */      if ( gpgme_data_get_type (in) == GPGME_DATA_TYPE_NONE ) { diff --git a/gpgme/signers.c b/gpgme/signers.c new file mode 100644 index 00000000..a9da7da6 --- /dev/null +++ b/gpgme/signers.c @@ -0,0 +1,105 @@ +/* signers.c - maintain signer sets + *	Copyright (C) 2001 Werner Koch (dd9jn) + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#include "util.h" +#include "context.h" +#include "rungpg.h" + +/* The signers are directly stored in the context. + * So this is quite different to a recipient set. + */ + + +void +gpgme_signers_clear (GpgmeCtx c) +{ +    int i; + +    return_if_fail (c); + +    if (!c->signers) +        return; +    for (i=0; i < c->signers_size; i++ ) { +        if (!c->signers[i]) +            break; +        gpgme_key_unref (c->signers[i]); +        c->signers[i] = NULL; +    } +} + + +GpgmeError +gpgme_signers_add (GpgmeCtx c, const GpgmeKey key) +{ +    int i = 0; + +    if (!c || !key) +        return mk_error (Invalid_Value); + +    if (!c->signers) +        c->signers_size = 0; + +    for (i=0; i < c->signers_size && c->signers[i]; i++ ) +        ; +    if ( !(i < c->signers_size) ) { +        GpgmeKey *newarr; +        int j; +        int n = c->signers_size + 5; + +        newarr = xtrycalloc ( n, sizeof *newarr ); +        if ( !newarr ) +            return mk_error (Out_Of_Core); +        for (j=0; j < c->signers_size; j++ ) +            newarr[j] = c->signers[j]; +        c->signers_size = n; +    } +    gpgme_key_ref (key); +    c->signers[i] = key; +    return 0; +} + + +GpgmeKey +gpgme_signers_enum (const GpgmeCtx c, int seq ) +{ +    int i; + +    return_null_if_fail (c); +    return_null_if_fail (seq<0); + +    if (!c->signers) +        c->signers_size = 0; +    for (i=0; i < c->signers_size && c->signers[i]; i++ ) { +        if (i==seq) { +            gpgme_key_ref (c->signers[i]); +            return c->signers[i]; +        } +    } +    return NULL; +} + + + + diff --git a/gpgme/util.h b/gpgme/util.h index 72e3eae3..39e18e83 100644 --- a/gpgme/util.h +++ b/gpgme/util.h @@ -47,6 +47,25 @@ void  _gpgme_free ( void *a );  char *stpcpy (char *a, const char *b);  #endif +#define return_if_fail(expr) do {                        \ +    if (!(expr)) {                                       \ +        fprintf (stderr, "%s:%d: assertion `%s' failed", \ +                 __FILE__, __LINE__, #expr );            \ +        return;	                                         \ +    } } while (0) +#define return_null_if_fail(expr) do {                   \ +    if (!(expr)) {                                       \ +        fprintf (stderr, "%s:%d: assertion `%s' failed", \ +                 __FILE__, __LINE__, #expr );            \ +        return NULL;	                                 \ +    } } while (0) +#define return_val_if_fail(expr,val) do {                \ +    if (!(expr)) {                                       \ +        fprintf (stderr, "%s:%d: assertion `%s' failed", \ +                 __FILE__, __LINE__, #expr );            \ +        return (val);	                                 \ +    } } while (0) +  #endif /* UTIL_H */ diff --git a/gpgme/version.c b/gpgme/version.c index 0319b06d..0dfe4a36 100644 --- a/gpgme/version.c +++ b/gpgme/version.c @@ -21,9 +21,20 @@  #include <config.h>  #include <stdio.h>  #include <stdlib.h> +#include <string.h>  #include <ctype.h>  #include "gpgme.h" +#include "context.h" +#include "rungpg.h" +#include "util.h" + + +static int lineno; +static char *tmp_engine_version; + +static const char *get_engine_info (void); +  static const char*  parse_version_number ( const char *s, int *number ) @@ -58,33 +69,22 @@ parse_version_string( const char *s, int *major, int *minor, int *micro )      return s; /* patchlevel */  } -/** - * gpgme_check_version: - * @req_version: A string with a version - *  - * Check that the the version of the library is at minimum the requested one - * and return the version string; return NULL if the condition is not - * met.  If a NULL is passed to this function, no check is done and - * the version string is simply returned. - *  - * Return value: The version string or NULL - **/ -const char * -gpgme_check_version ( const char *req_version ) +static const char * +compare_versions ( const char *my_version, const char *req_version )  { -    const char *ver = VERSION;      int my_major, my_minor, my_micro;      int rq_major, rq_minor, rq_micro;      const char *my_plvl, *rq_plvl;      if ( !req_version ) -	return ver; +	return my_version; -    my_plvl = parse_version_string ( ver, &my_major, &my_minor, &my_micro ); +    my_plvl = parse_version_string ( my_version, +                                     &my_major, &my_minor, &my_micro );      if ( !my_plvl )  	return NULL;  /* very strange: our own version is bogus */ -    rq_plvl = parse_version_string( req_version, &rq_major, &rq_minor, -                                    &rq_micro ); +    rq_plvl = parse_version_string( req_version, +                                    &rq_major, &rq_minor, &rq_micro );      if ( !rq_plvl )  	return NULL;  /* req version string is invalid */ @@ -95,10 +95,164 @@ gpgme_check_version ( const char *req_version )           || (my_major == rq_major && my_minor == rq_minor               && my_micro == rq_micro               && strcmp( my_plvl, rq_plvl ) >= 0) ) { -	return ver; +	return my_version;      }      return NULL;  } +/** + * gpgme_check_version: + * @req_version: A string with a version + *  + * Check that the the version of the library is at minimum the requested one + * and return the version string; return NULL if the condition is not + * met.  If a NULL is passed to this function, no check is done and + * the version string is simply returned. + *  + * Return value: The version string or NULL + **/ +const char * +gpgme_check_version ( const char *req_version ) +{ +    return compare_versions ( VERSION, req_version ); +} + + +/** + * gpgme_get_engine_info: + *   + * Return information about the underlying crypto engine.  This is an + * XML string with various information.  To get the version of the + * crypto engine it should be sufficient to grep for the first + * <literal>version</literal> tag and use it's content.  A string is + * always returned even if the crypto engine is not installed; in this + * case a XML string with some error information is returned. + *  + * Return value: A XML string with information about the crypto engine. + **/ +const char * +gpgme_get_engine_info () +{ +    return get_engine_info (); +} + +/** + * gpgme_check_engine: + *  + * Check whether the installed crypto engine matches the requirement of + * GPGME. + * + * Return value: 0 or an error code. + **/ +GpgmeError +gpgme_check_engine () +{ +    const char *info = gpgme_get_engine_info (); +    const char *s, *s2; + +    s = strstr (info, "<version>"); +    if (s) { +        s += 9; +        s2 = strchr (s, '>'); +        if (s2) { +            char *ver = xtrymalloc (s2 - s + 1); +            if (!ver) +                return mk_error (Out_Of_Core); +            memcpy (ver, s, s2-s); +            ver[s2-s] = 0; +            s = compare_versions ( ver, NEED_GPG_VERSION ); +            xfree (ver); +            if (s) +                return 0; +        } +    } +    return mk_error (Invalid_Engine); +} + + + +static void +version_line_handler ( GpgmeCtx c, char *line ) +{ +    char *p; +    size_t len; + +    lineno++; +    if ( c->out_of_core ) +        return; +    if (!line) +        return; /* EOF */ +    if (lineno==1) { +        if ( memcmp (line, "gpg ", 4) ) +            return; +        if ( !(p = strpbrk (line, "0123456789")) ) +            return; +        len = strcspn (p, " \t\r\n()<>" ); +        p[len] = 0; +        tmp_engine_version = xtrystrdup (p); +    } +} + + +static const char * +get_engine_info (void) +{ +    const char *engine_info =NULL; +    GpgmeCtx c = NULL; +    GpgmeError err = 0; + +    /* FIXME: make sure that only one instance does run */ +    if (engine_info) +        goto leave; + +    err = gpgme_new (&c); +    if (err)  +        goto leave; +    err = _gpgme_gpg_new ( &c->gpg ); +    if (err) +        goto leave; + +    err = _gpgme_gpg_set_simple_line_handler ( c->gpg, +                                               version_line_handler, c ); +    if (err) +        goto leave; + +    _gpgme_gpg_add_arg ( c->gpg, "--version" ); +    lineno = 0; +    xfree (tmp_engine_version); tmp_engine_version = NULL; +    err = _gpgme_gpg_spawn ( c->gpg, c ); +    if (err) +        goto leave; +    gpgme_wait (c, 1); +    if (tmp_engine_version) { +        const char *fmt; +        char *p; + +        fmt = "<GnupgInfo>\n" +              " <engine>\n" +              "  <version>%s</version>\n" +              " </engine>\n" +              "</GnupgInfo>\n"; +        /*(yes, I know that we allocating 2 extra bytes)*/ +        p = xtrymalloc ( strlen(fmt) + strlen (tmp_engine_version) + 1); +        if (!p) { +            err = mk_error (Out_Of_Core); +            goto leave; +        } +        sprintf (p, fmt, tmp_engine_version); +        engine_info = p; +        xfree (tmp_engine_version); tmp_engine_version = NULL; +    } +    else { +        err = mk_error (General_Error); +    } + + leave: +    if (err) +        engine_info = "<GnupgInfo>\n<error>No engine</error>\n</GnupgInfo>\n"; +    gpgme_release ( c ); +    return engine_info; +} + diff --git a/gpgme/wait.c b/gpgme/wait.c index 1cd2418f..ba7a22f1 100644 --- a/gpgme/wait.c +++ b/gpgme/wait.c @@ -189,7 +189,7 @@ _gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond )              if (q->exited) {                  /* this is the second time we reached this and we got no -                 * more data from the pipe (which may happen to to buffering). +                 * more data from the pipe (which may happen due to buffering).                   * Set all FDs inactive.                   */                  clear_active_fds (q->pid); @@ -377,3 +377,4 @@ run_idle ()      if (idle_function)          idle_function ();  } + diff --git a/tests/t-encrypt.c b/tests/t-encrypt.c index ba7097e3..15d21978 100644 --- a/tests/t-encrypt.c +++ b/tests/t-encrypt.c @@ -57,6 +57,10 @@ main (int argc, char **argv )      GpgmeData in, out;      GpgmeRecipients rset; +    err = gpgme_check_engine (); +    fail_if_err (err); +    puts ( gpgme_get_engine_info() ); +    do {      err = gpgme_new (&ctx);      fail_if_err (err); | 
