From f2be4142516bcd9536884bb0e40e8bf561352bd4 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 22 Jan 2001 20:22:41 +0000 Subject: [PATCH] Some new but untested functions --- acconfig.h | 2 + autogen.sh | 2 +- configure.in | 7 +- gpgme/ChangeLog | 11 +++ gpgme/Makefile.am | 3 +- gpgme/context.h | 3 + gpgme/delete.c | 116 ++++++++++++++++++++++++++ gpgme/errors.c | 2 + gpgme/gpgme.c | 11 ++- gpgme/gpgme.h | 16 +++- gpgme/key.c | 20 ++++- gpgme/key.h | 1 + gpgme/rungpg.c | 19 ++++- gpgme/rungpg.h | 3 + gpgme/sign.c | 13 ++- gpgme/signers.c | 105 +++++++++++++++++++++++ gpgme/util.h | 19 +++++ gpgme/version.c | 206 ++++++++++++++++++++++++++++++++++++++++------ gpgme/wait.c | 3 +- tests/t-encrypt.c | 4 + 20 files changed, 529 insertions(+), 37 deletions(-) create mode 100644 gpgme/delete.c create mode 100644 gpgme/signers.c diff --git a/acconfig.h b/acconfig.h index e8cd7581..1a7f63c2 100644 --- a/acconfig.h +++ b/acconfig.h @@ -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 diff --git a/autogen.sh b/autogen.sh index 10b498c4..13e4b368 100755 --- a/autogen.sh +++ b/autogen.sh @@ -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 + + * 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 * 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 +#include +#include +#include +#include +#include + +#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 +#include +#include +#include + +#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 #include #include +#include #include #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,6 +69,38 @@ parse_version_string( const char *s, int *major, int *minor, int *micro ) return s; /* patchlevel */ } +static const char * +compare_versions ( const char *my_version, const char *req_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 my_version; + + 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 ); + if ( !rq_plvl ) + return NULL; /* req version string is invalid */ + + if ( my_major > rq_major + || (my_major == rq_major && my_minor > rq_minor) + || (my_major == rq_major && my_minor == rq_minor + && my_micro > rq_micro) + || (my_major == rq_major && my_minor == rq_minor + && my_micro == rq_micro + && strcmp( my_plvl, rq_plvl ) >= 0) ) { + return my_version; + } + return NULL; +} + + /** * gpgme_check_version: * @req_version: A string with a version @@ -72,33 +115,144 @@ parse_version_string( const char *s, int *major, int *minor, int *micro ) const char * gpgme_check_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; - - my_plvl = parse_version_string ( ver, &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 ); - if ( !rq_plvl ) - return NULL; /* req version string is invalid */ - - if ( my_major > rq_major - || (my_major == rq_major && my_minor > rq_minor) - || (my_major == rq_major && my_minor == rq_minor - && my_micro > rq_micro) - || (my_major == rq_major && my_minor == rq_minor - && my_micro == rq_micro - && strcmp( my_plvl, rq_plvl ) >= 0) ) { - return ver; - } - return NULL; + 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 + * version 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, ""); + 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 = "\n" + " \n" + " %s\n" + " \n" + "\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 = "\nNo engine\n\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);