diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index d500acae..bf9796d2 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,10 +1,21 @@ 2001-12-13 Werner Koch + * engine-gpgsm.c (_gpgme_gpgsm_set_colon_line_handler): New. + (gpgsm_status_handler): Pass datalines to a colon handler + * engine.c (_gpgme_engine_set_colon_line_handler): Set the colon + handler for gpgsm. + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist): Allow NULL for pattern. (gpgsm_assuan_simple_command): Removed underscore from assuan_write_line. - (_gpgme_gpgsm_start): Ditto. + (_gpgme_gpgsm_start): Ditto. + (gpgsm_assuan_simple_command): Replaced interal Assuan read + function by the new assuan_read_line. Removed the use of the + internal header. + (gpgsm_status_handler): Ditto. Use the new assuan_pending_line. + (_gpgme_gpgsm_start): Use the documented way to get an fd from + assuan. * keylist.c (keylist_colon_handler): Handle "crt" records * key.h (gpgme_key_s): Add an x509 flag. diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index ea3cd0d6..38ce87d8 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -36,13 +36,6 @@ #include #include /* FIXME */ -/* FIXME */ -#include "../assuan/assuan-defs.h" -#undef xtrymalloc -#undef xtrycalloc -#undef xtryrealloc -#undef xfree - #include "rungpg.h" #include "status-table.h" @@ -58,6 +51,11 @@ #include "assuan.h" +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + + struct gpgsm_object_s { ASSUAN_CONTEXT assuan_ctx; @@ -80,14 +78,19 @@ struct gpgsm_object_s GpgStatusHandler fnc; void *fnc_value; } status; + + struct + { + GpgColonLineHandler fnc; + void *fnc_value; + } colon; }; const char * _gpgme_gpgsm_get_version (void) { -#warning version check is disabled - static const char *gpgsm_version = "0.0.1"; + static const char *gpgsm_version; /* FIXME: Locking. */ if (!gpgsm_version) @@ -192,25 +195,27 @@ _gpgme_gpgsm_release (GpgsmObject gpgsm) } static AssuanError -gpgsm_assuan_simple_command (ASSUAN_CONTEXT ctx, char *line) +gpgsm_assuan_simple_command (ASSUAN_CONTEXT ctx, char *cmd) { AssuanError err; + char *line; + size_t linelen; - err = assuan_write_line (ctx, line); + err = assuan_write_line (ctx, cmd); if (err) return err; do { - err = _assuan_read_line (ctx); + err = assuan_read_line (ctx, &line, &linelen); if (err) return err; } - while (*ctx->inbound.line == '#' || !ctx->inbound.linelen); + while (*line == '#' || !linelen); - if (ctx->inbound.linelen >= 2 - && ctx->inbound.line[0] == 'O' && ctx->inbound.line[1] == 'K' - && (ctx->inbound.line[2] == '\0' || ctx->inbound.line[2] == ' ')) + if (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) return 0; else return ASSUAN_General_Error; @@ -477,21 +482,17 @@ gpgsm_status_handler (void *opaque, int pid, int fd) { int err; GpgsmObject gpgsm = opaque; - ASSUAN_CONTEXT actx = gpgsm->assuan_ctx; char *line; - int linelen; + size_t linelen; do { - assert (fd == gpgsm->assuan_ctx->inbound.fd); + err = assuan_read_line (gpgsm->assuan_ctx, &line, &linelen); - err = _assuan_read_line (gpgsm->assuan_ctx); - line = actx->inbound.line; - linelen = strlen (line); - - if ((linelen >= 2 - && line[0] == 'O' && line[1] == 'K' - && (line[2] == '\0' || line[2] == ' ')) + if (err + || (linelen >= 2 + && line[0] == 'O' && line[1] == 'K' + && (line[2] == '\0' || line[2] == ' ')) || (linelen >= 3 && line[0] == 'E' && line[1] == 'R' && line[2] == 'R' && (line[3] == '\0' || line[3] == ' '))) @@ -501,9 +502,41 @@ gpgsm_status_handler (void *opaque, int pid, int fd) gpgsm->status.fnc (gpgsm->status.fnc_value, STATUS_EOF, ""); return 1; } - /* FIXME: Parse the status and call the handler. */ - + if (linelen > 2 + && line[0] == 'D' && line[1] == ' ' + && gpgsm->colon.fnc ) + { + unsigned char *s, *d; + + line += 2; + linelen -= 2; + /* Hmmm, we are using the colon handler even for plain + inline data - strange name for that fucntion but for + historic reasons we keep it */ + for (s=d=line; linelen; linelen--) + { + if (*s == '%' && linelen > 2) + { /* handle escaping */ + s++; + *d++ = xtoi_2 (s); + s += 2; + linelen -= 2; + } + else + *d++ = *s++; + } + *d = 0; /* add a hidden string terminator */ + + /* fixme: should we handle the return code? */ + /* fixme: Hmmm: we can't use this for binary data because we + assume this is a string. For the current usage of colon + output it is correct */ + /* FIXME: we need extra bufferring to pass colon lines line + by line */ + gpgsm->colon.fnc (gpgsm->colon.fnc_value, line); + } + else if (linelen > 2 && line[0] == 'S' && line[1] == ' ') { struct status_table_s t, *r; @@ -528,7 +561,7 @@ gpgsm_status_handler (void *opaque, int pid, int fd) fprintf (stderr, "[UNKNOWN STATUS]%s %s", t.name, rest); } } - while (gpgsm->assuan_ctx->inbound.attic.linelen); + while (assuan_pending_line (gpgsm->assuan_ctx)); return 0; } @@ -543,19 +576,39 @@ _gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm, gpgsm->status.fnc_value = fnc_value; } +void +_gpgme_gpgsm_set_colon_line_handler (GpgsmObject gpgsm, + GpgColonLineHandler fnc, void *fnc_value) +{ + assert (gpgsm); + + gpgsm->colon.fnc = fnc; + gpgsm->colon.fnc_value = fnc_value; +} + GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque) { GpgmeError err = 0; pid_t pid; + int fdlist[5]; + int nfds; if (!gpgsm) return mk_error (Invalid_Value); pid = assuan_get_pid (gpgsm->assuan_ctx); + /* We need to know the fd used by assuan for reads. We do this by + using the assumption that the first returned fd from + assuan_get_active_fds() is always this one. */ + nfds = assuan_get_active_fds (gpgsm->assuan_ctx, 0 /* read fds */, + fdlist, DIM (fdlist)); + if (nfds < 1) + return mk_error (General_Error); err = _gpgme_register_pipe_handler (opaque, gpgsm_status_handler, gpgsm, pid, - gpgsm->assuan_ctx->inbound.fd, 1); + fdlist[0], 1); + if (gpgsm->input_fd != -1) { diff --git a/gpgme/engine-gpgsm.h b/gpgme/engine-gpgsm.h index bd6dd1e7..9ebd8d7b 100644 --- a/gpgme/engine-gpgsm.h +++ b/gpgme/engine-gpgsm.h @@ -33,6 +33,8 @@ void _gpgme_gpgsm_release (GpgsmObject gpg); void _gpgme_gpgsm_set_status_handler (GpgsmObject gpgsm, GpgStatusHandler fnc, void *fnc_value); +void _gpgme_gpgsm_set_colon_line_handler (GpgsmObject gpgsm, + GpgColonLineHandler fnc, void *fnc_value) ; GpgmeError _gpgme_gpgsm_op_decrypt (GpgsmObject gpgsm, GpgmeData ciph, GpgmeData plain); GpgmeError _gpgme_gpgsm_op_delete (GpgsmObject gpgsm, GpgmeKey key, @@ -57,3 +59,7 @@ GpgmeError _gpgme_gpgsm_op_verify (GpgsmObject gpgsm, GpgmeData sig, GpgmeError _gpgme_gpgsm_start (GpgsmObject gpgsm, void *opaque); #endif /* ENGINE_GPGSM_H */ + + + + diff --git a/gpgme/engine.c b/gpgme/engine.c index 08fb9515..025832bb 100644 --- a/gpgme/engine.c +++ b/gpgme/engine.c @@ -226,11 +226,13 @@ GpgmeError _gpgme_engine_set_colon_line_handler (EngineObject engine, switch (engine->protocol) { case GPGME_PROTOCOL_OpenPGP: - return _gpgme_gpg_set_colon_line_handler (engine->engine.gpg, fnc, - fnc_value); + return _gpgme_gpg_set_colon_line_handler (engine->engine.gpg, + fnc, fnc_value); case GPGME_PROTOCOL_CMS: - /* FIXME */ + _gpgme_gpgsm_set_colon_line_handler (engine->engine.gpgsm, + fnc, fnc_value); break; + default: break; }