First take on the low-level assuan interface.
This commit is contained in:
parent
23022dd9d9
commit
d951cb713f
@ -1,3 +1,7 @@
|
|||||||
|
2009-01-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* configure.ac (AC_CONFIG_FILES): Add tests/opassuan/Makefile.
|
||||||
|
|
||||||
2008-12-08 Marcus Brinkmann <marcus@g10code.de>
|
2008-12-08 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
Release GPGME 1.1.8.
|
Release GPGME 1.1.8.
|
||||||
@ -720,8 +724,8 @@
|
|||||||
|
|
||||||
* configure.ac (AC_INIT): Bump version to 0.3.3.
|
* configure.ac (AC_INIT): Bump version to 0.3.3.
|
||||||
* jnlib/Makefile.am: Rever to older version that includes xmalloc
|
* jnlib/Makefile.am: Rever to older version that includes xmalloc
|
||||||
but not dotlock and some other files. Reported by Stéphane
|
but not dotlock and some other files. Reported by Stéphane
|
||||||
Corthésy.
|
Corthésy.
|
||||||
|
|
||||||
2002-02-10 Marcus Brinkmann <marcus@g10code.de>
|
2002-02-10 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
# Public License for more details.
|
# Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
16
NEWS
16
NEWS
@ -1,3 +1,19 @@
|
|||||||
|
Noteworthy changes in version 1.1.9
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
* Interface changes relative to the 1.1.7 release:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
GPGME_PROTOCOL_ASSUAN NEW.
|
||||||
|
gpgme_assuan_data_cb_t NEW.
|
||||||
|
gpgme_assuan_sendfnc_ctx_t NEW.
|
||||||
|
gpgme_assuan_inquire_cb_t NEW.
|
||||||
|
gpgme_assuan_status_cb_t NEW.
|
||||||
|
gpgme_op_assuan_transact_start NEW.
|
||||||
|
gpgme_op_assuan_transact NEW.
|
||||||
|
gpgme_op_assuan_result NEW.
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 1.1.8 (2008-12-08)
|
Noteworthy changes in version 1.1.8 (2008-12-08)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
@ -159,4 +159,6 @@ $AUTOMAKE --gnu;
|
|||||||
echo "Running autoconf${FORCE} ..."
|
echo "Running autoconf${FORCE} ..."
|
||||||
$AUTOCONF${FORCE}
|
$AUTOCONF${FORCE}
|
||||||
|
|
||||||
echo "You may now run \"./configure --enable-maintainer-mode && make\"."
|
echo "You may now run:
|
||||||
|
./configure --enable-maintainer-mode && make
|
||||||
|
"
|
||||||
|
@ -31,8 +31,8 @@ min_automake_version="1.10"
|
|||||||
# specific feature can already be done under the assumption that the
|
# specific feature can already be done under the assumption that the
|
||||||
# SVN version is the most recent one in a branch. To disable the SVN
|
# SVN version is the most recent one in a branch. To disable the SVN
|
||||||
# version for the real release, set the my_issvn macro to no.
|
# version for the real release, set the my_issvn macro to no.
|
||||||
m4_define(my_version, [1.1.8])
|
m4_define(my_version, [1.1.9])
|
||||||
m4_define(my_issvn, [no])
|
m4_define(my_issvn, [yes])
|
||||||
|
|
||||||
m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
|
m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
|
||||||
|| echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
|
|| echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
|
||||||
@ -744,7 +744,10 @@ AC_SUBST(LTLIBOBJS)
|
|||||||
# Create config files
|
# Create config files
|
||||||
|
|
||||||
AC_CONFIG_FILES(Makefile assuan/Makefile src/Makefile
|
AC_CONFIG_FILES(Makefile assuan/Makefile src/Makefile
|
||||||
tests/Makefile tests/gpg/Makefile tests/gpgsm/Makefile
|
tests/Makefile
|
||||||
|
tests/gpg/Makefile
|
||||||
|
tests/gpgsm/Makefile
|
||||||
|
tests/opassuan/Makefile
|
||||||
doc/Makefile complus/Makefile
|
doc/Makefile complus/Makefile
|
||||||
src/versioninfo.rc
|
src/versioninfo.rc
|
||||||
src/gpgme.h)
|
src/gpgme.h)
|
||||||
|
@ -1,3 +1,36 @@
|
|||||||
|
2009-01-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* opassuan.c, dirinfo.c, engine-assuan.c: New.
|
||||||
|
* Makefile.am: Add them.
|
||||||
|
* engine-backend.h: Add _gpgme_engine_ops_assuan.
|
||||||
|
(struct engine_ops): Add field OPASSUAN_TRANSACT. Update all
|
||||||
|
engine intializers.
|
||||||
|
* Makefile.am (gpgsm_components): Add engine-assuan.c.
|
||||||
|
* gpgme.h.in (gpgme_protocol_t): Add GPGME_PROTOCOL_ASSUAN.
|
||||||
|
(gpgme_assuan_data_cb_t, gpgme_assuan_sendfnc_ctx_t)
|
||||||
|
(gpgme_assuan_inquire_cb_t, gpgme_assuan_status_cb_t): New.
|
||||||
|
(gpgme_op_assuan_transact_start, gpgme_op_assuan_transact): New.
|
||||||
|
* gpgme.c (gpgme_get_protocol_name): Ditto.
|
||||||
|
(gpgme_set_protocol): Support it.
|
||||||
|
* engine.c (gpgme_get_engine_info): Ditto.
|
||||||
|
(engine_ops): Register it.
|
||||||
|
(_gpgme_engine_op_assuan_transact): New.
|
||||||
|
* libgpgme.vers (gpgme_op_assuan_transact_start)
|
||||||
|
(gpgme_op_assuan_transact): New.
|
||||||
|
* gpgme.def (gpgme_op_assuan_transact_start)
|
||||||
|
(gpgme_op_assuan_transact): New.
|
||||||
|
* engine-backend.h (struct engine_ops): Add GET_HOME_DIR and
|
||||||
|
initialize to NULL for all engines.
|
||||||
|
* engine.c (engine_get_home_dir): New.
|
||||||
|
(gpgme_get_engine_info): Use it.
|
||||||
|
(_gpgme_set_engine_info): Use it.
|
||||||
|
* engine.h (engine_assuan_result_cb_t): New.
|
||||||
|
* context.h (ctx_op_data_id_t): Add OPDATA_ASSUAN.
|
||||||
|
|
||||||
|
* util.h (GPG_ERR_UNFINISHED): Define if not yet defined.
|
||||||
|
|
||||||
|
* version.c (gpgme_check_version): Protect trace arg against NULL.
|
||||||
|
|
||||||
2009-01-19 Werner Koch <wk@g10code.com>
|
2009-01-19 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* rungpg.c: Rename to engine-gpg.c
|
* rungpg.c: Rename to engine-gpg.c
|
||||||
@ -803,7 +836,7 @@
|
|||||||
|
|
||||||
* engine.c (gpgme_engine_check_version): Reimplemented to allow
|
* engine.c (gpgme_engine_check_version): Reimplemented to allow
|
||||||
checking the version correctly even after changing the engine
|
checking the version correctly even after changing the engine
|
||||||
information. Bug reported by Stéphane Corthésy.
|
information. Bug reported by Stéphane Corthésy.
|
||||||
|
|
||||||
* rungpg.c (read_colon_line): Invoke colon preprocess handler if
|
* rungpg.c (read_colon_line): Invoke colon preprocess handler if
|
||||||
it is set.
|
it is set.
|
||||||
@ -868,7 +901,7 @@
|
|||||||
2005-11-27 Marcus Brinkmann <marcus@g10code.de>
|
2005-11-27 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* engine.c (_gpgme_set_engine_info): Use new_file_name in
|
* engine.c (_gpgme_set_engine_info): Use new_file_name in
|
||||||
engine_get_version invocation. Reported by Stéphane Corthésy.
|
engine_get_version invocation. Reported by Stéphane Corthésy.
|
||||||
|
|
||||||
2005-11-24 Marcus Brinkmann <marcus@g10code.de>
|
2005-11-24 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
@ -1818,7 +1851,7 @@
|
|||||||
|
|
||||||
* gpgme-config.in (gpg_error_libs): Quote GPG_ERROR_CFLAGS and
|
* gpgme-config.in (gpg_error_libs): Quote GPG_ERROR_CFLAGS and
|
||||||
GPG_ERROR_LIBS when setting the corresponding variables.
|
GPG_ERROR_LIBS when setting the corresponding variables.
|
||||||
Reported by Stéphane Corthésy.
|
Reported by Stéphane Corthésy.
|
||||||
|
|
||||||
2003-07-22 Marcus Brinkmann <marcus@g10code.de>
|
2003-07-22 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
@ -3707,7 +3740,7 @@
|
|||||||
2002-09-28 Marcus Brinkmann <marcus@g10code.de>
|
2002-09-28 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* conversion.c (_gpgme_hextobyte): Prevent superfluous
|
* conversion.c (_gpgme_hextobyte): Prevent superfluous
|
||||||
multiplication with base. Reported by Stéphane Corthésy.
|
multiplication with base. Reported by Stéphane Corthésy.
|
||||||
|
|
||||||
* keylist.c (gpgme_op_keylist_ext_start): Use private asynchronous
|
* keylist.c (gpgme_op_keylist_ext_start): Use private asynchronous
|
||||||
operation type in invocation of _gpgme_op_reset.
|
operation type in invocation of _gpgme_op_reset.
|
||||||
@ -3820,7 +3853,7 @@
|
|||||||
variables encrypt_info and encrypt_info_len.
|
variables encrypt_info and encrypt_info_len.
|
||||||
* trustlist.c (gpgme_op_trustlist_start): Set colon line handler.
|
* trustlist.c (gpgme_op_trustlist_start): Set colon line handler.
|
||||||
* posix-sema.c (sema_fatal): Remove function.
|
* posix-sema.c (sema_fatal): Remove function.
|
||||||
All these reported by Stéphane Corthésy.
|
All these reported by Stéphane Corthésy.
|
||||||
|
|
||||||
2002-08-23 Werner Koch <wk@gnupg.org>
|
2002-08-23 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
@ -3993,7 +4026,7 @@
|
|||||||
* vasprintf.c: Update to more recent libiberty version.
|
* vasprintf.c: Update to more recent libiberty version.
|
||||||
* debug.h: Replace #elsif with #elif.
|
* debug.h: Replace #elsif with #elif.
|
||||||
|
|
||||||
Submitted by Stéphane Corthésy:
|
Submitted by Stéphane Corthésy:
|
||||||
* util.h (vasprintf): Correct prototype.
|
* util.h (vasprintf): Correct prototype.
|
||||||
* encrypt-sign.c: Include <stddef.h>.
|
* encrypt-sign.c: Include <stddef.h>.
|
||||||
(encrypt_sign_status_handler): Change type of ENCRYPT_INFO_LEN to
|
(encrypt_sign_status_handler): Change type of ENCRYPT_INFO_LEN to
|
||||||
@ -4003,14 +4036,14 @@
|
|||||||
|
|
||||||
2002-07-25 Marcus Brinkmann <marcus@g10code.de>
|
2002-07-25 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* wait.c (fdt_global): Make static. Reported by Stéphane
|
* wait.c (fdt_global): Make static. Reported by Stéphane
|
||||||
Corthésy.
|
Corthésy.
|
||||||
|
|
||||||
* rungpg.c (_gpgme_gpg_op_keylist_ext): Skip empty string
|
* rungpg.c (_gpgme_gpg_op_keylist_ext): Skip empty string
|
||||||
patterns. Reported by Stéphane Corthésy.
|
patterns. Reported by Stéphane Corthésy.
|
||||||
|
|
||||||
* key.c (gpgme_key_get_as_xml): Add OTRUST attribute. Requested
|
* key.c (gpgme_key_get_as_xml): Add OTRUST attribute. Requested
|
||||||
by Stéphane Corthésy.
|
by Stéphane Corthésy.
|
||||||
(gpgme_key_get_string_attr): Add GPGME_ATTR_SIG_SUMMARY case to
|
(gpgme_key_get_string_attr): Add GPGME_ATTR_SIG_SUMMARY case to
|
||||||
silence gcc warning.
|
silence gcc warning.
|
||||||
|
|
||||||
@ -5060,7 +5093,7 @@
|
|||||||
|
|
||||||
2001-12-19 Marcus Brinkmann <marcus@g10code.de>
|
2001-12-19 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* engine.c: Include `string.h'. Reported by Stéphane Corthésy.
|
* engine.c: Include `string.h'. Reported by Stéphane Corthésy.
|
||||||
|
|
||||||
* version.c (get_engine_info): Remove prototype.
|
* version.c (get_engine_info): Remove prototype.
|
||||||
|
|
||||||
@ -5597,7 +5630,7 @@
|
|||||||
callers to use this function without a check for tmp_key.
|
callers to use this function without a check for tmp_key.
|
||||||
|
|
||||||
* keylist.c (gpgme_op_keylist_next): Reset the key_cond after
|
* keylist.c (gpgme_op_keylist_next): Reset the key_cond after
|
||||||
emptying the queue. Bug reported by Stéphane Corthésy.
|
emptying the queue. Bug reported by Stéphane Corthésy.
|
||||||
|
|
||||||
2001-09-12 Werner Koch <wk@gnupg.org>
|
2001-09-12 Werner Koch <wk@gnupg.org>
|
||||||
|
|
||||||
@ -5679,7 +5712,7 @@
|
|||||||
* version.c (gpgme_check_engine): Stop version number parsing at
|
* version.c (gpgme_check_engine): Stop version number parsing at
|
||||||
the opening angle and not the closing one. By Tommy Reynolds.
|
the opening angle and not the closing one. By Tommy Reynolds.
|
||||||
|
|
||||||
2001-05-01 José Carlos García Sogo <jose@jaimedelamo.eu.org>
|
2001-05-01 José Carlos García Sogo <jose@jaimedelamo.eu.org>
|
||||||
|
|
||||||
* encrypt.c (gpgme_op_encrypt_start): Deleted the assert ( !c->gpg )
|
* encrypt.c (gpgme_op_encrypt_start): Deleted the assert ( !c->gpg )
|
||||||
line, because it gave an error if another operation had been made
|
line, because it gave an error if another operation had been made
|
||||||
@ -5865,8 +5898,8 @@
|
|||||||
* rungpg.c (_gpgme_gpg_spawn): Use new function to get GPG's path.
|
* rungpg.c (_gpgme_gpg_spawn): Use new function to get GPG's path.
|
||||||
|
|
||||||
* signers.c (gpgme_signers_add): Ooops, one should test code and
|
* signers.c (gpgme_signers_add): Ooops, one should test code and
|
||||||
not just write it; the newarr was not assigned. Thanks to José
|
not just write it; the newarr was not assigned. Thanks to José
|
||||||
for pointing this out. Hmmm, still not tested, why shoudl a coder
|
for pointing this out. Hmmm, still not tested, why should a coder
|
||||||
test his fix :-)
|
test his fix :-)
|
||||||
|
|
||||||
* w32-io.c: Does now use reader threads, so that we can use
|
* w32-io.c: Does now use reader threads, so that we can use
|
||||||
|
@ -78,7 +78,7 @@ system_components_not_extra =
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_GPGSM
|
if HAVE_GPGSM
|
||||||
gpgsm_components = engine-gpgsm.c
|
gpgsm_components = engine-gpgsm.c engine-assuan.c
|
||||||
else
|
else
|
||||||
gpgsm_components =
|
gpgsm_components =
|
||||||
endif
|
endif
|
||||||
@ -105,9 +105,10 @@ main_sources = \
|
|||||||
sign.c passphrase.c progress.c \
|
sign.c passphrase.c progress.c \
|
||||||
key.c keylist.c trust-item.c trustlist.c \
|
key.c keylist.c trust-item.c trustlist.c \
|
||||||
import.c export.c genkey.c delete.c edit.c getauditlog.c \
|
import.c export.c genkey.c delete.c edit.c getauditlog.c \
|
||||||
|
opassuan.c \
|
||||||
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
|
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
|
||||||
$(gpgsm_components) $(gpgconf_components) gpgconf.c \
|
$(gpgsm_components) $(gpgconf_components) gpgconf.c \
|
||||||
sema.h priv-io.h $(system_components) \
|
sema.h priv-io.h $(system_components) dirinfo.c \
|
||||||
debug.c debug.h gpgme.c version.c error.c
|
debug.c debug.h gpgme.c version.c error.c
|
||||||
|
|
||||||
libgpgme_la_SOURCES = $(main_sources) \
|
libgpgme_la_SOURCES = $(main_sources) \
|
||||||
|
@ -36,7 +36,7 @@ typedef enum
|
|||||||
{
|
{
|
||||||
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
|
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
|
||||||
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
|
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
|
||||||
OPDATA_VERIFY, OPDATA_TRUSTLIST
|
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN
|
||||||
} ctx_op_data_id_t;
|
} ctx_op_data_id_t;
|
||||||
|
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ struct ctx_op_data
|
|||||||
ctx_op_data_id_t type;
|
ctx_op_data_id_t type;
|
||||||
|
|
||||||
/* The function to release HOOK and all its associated resources.
|
/* The function to release HOOK and all its associated resources.
|
||||||
Can be NULL if no special dealllocation routine is necessary. */
|
Can be NULL if no special deallocation routine is necessary. */
|
||||||
void (*cleanup) (void *hook);
|
void (*cleanup) (void *hook);
|
||||||
|
|
||||||
/* The hook that points to the operation data. */
|
/* The hook that points to the operation data. */
|
||||||
|
189
src/dirinfo.c
Normal file
189
src/dirinfo.c
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/* dirinfo.c - Get directory information
|
||||||
|
* Copyright (C) 2009 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "priv-io.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "sema.h"
|
||||||
|
|
||||||
|
DEFINE_STATIC_LOCK (dirinfo_lock);
|
||||||
|
|
||||||
|
/* Constants used internally to select the data. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
WANT_HOMEDIR,
|
||||||
|
WANT_AGENT_SOCKET
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Values retrieved via gpgconf and cached here. */
|
||||||
|
static struct {
|
||||||
|
int valid; /* Cached information is valid. */
|
||||||
|
char *homedir;
|
||||||
|
char *agent_socket;
|
||||||
|
} dirinfo;
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse the output of "gpgconf --list-dirs". This function expects
|
||||||
|
that DIRINFO_LOCK is held by the caller. */
|
||||||
|
static void
|
||||||
|
parse_output (char *line)
|
||||||
|
{
|
||||||
|
char *value, *p;
|
||||||
|
|
||||||
|
value = strchr (line, ':');
|
||||||
|
if (!value)
|
||||||
|
return;
|
||||||
|
*value++ = 0;
|
||||||
|
p = strchr (value, ':');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
if (_gpgme_decode_percent_string (value, &value, strlen (value)+1, 0))
|
||||||
|
return;
|
||||||
|
if (!*value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!strcmp (line, "homedir") && !dirinfo.homedir)
|
||||||
|
dirinfo.homedir = strdup (value);
|
||||||
|
else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
|
||||||
|
dirinfo.agent_socket = strdup (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read the directory information from gpgconf. This function expects
|
||||||
|
that DIRINFO_LOCK is held by the caller. */
|
||||||
|
static void
|
||||||
|
read_gpgconf_dirs (void)
|
||||||
|
{
|
||||||
|
const char *pgmname;
|
||||||
|
char linebuf[1024] = {0};
|
||||||
|
int linelen = 0;
|
||||||
|
char * argv[3];
|
||||||
|
int rp[2];
|
||||||
|
struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
|
||||||
|
{-1, -1} };
|
||||||
|
int status;
|
||||||
|
int nread;
|
||||||
|
char *mark = NULL;
|
||||||
|
|
||||||
|
pgmname = _gpgme_get_gpgconf_path ();
|
||||||
|
if (!pgmname)
|
||||||
|
return; /* No way. */
|
||||||
|
|
||||||
|
argv[0] = (char *)pgmname;
|
||||||
|
argv[1] = "--list-dirs";
|
||||||
|
argv[2] = NULL;
|
||||||
|
|
||||||
|
if (_gpgme_io_pipe (rp, 1) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cfd[0].fd = rp[1];
|
||||||
|
|
||||||
|
status = _gpgme_io_spawn (pgmname, argv, cfd, NULL);
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
_gpgme_io_close (rp[0]);
|
||||||
|
_gpgme_io_close (rp[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nread = _gpgme_io_read (rp[0],
|
||||||
|
linebuf + linelen,
|
||||||
|
sizeof linebuf - linelen - 1);
|
||||||
|
if (nread > 0)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
const char *lastmark = NULL;
|
||||||
|
size_t nused;
|
||||||
|
|
||||||
|
linelen += nread;
|
||||||
|
linebuf[linelen] = '\0';
|
||||||
|
|
||||||
|
for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 )
|
||||||
|
{
|
||||||
|
lastmark = mark;
|
||||||
|
if (mark > line && mark[-1] == '\r')
|
||||||
|
mark[-1] = '\0';
|
||||||
|
else
|
||||||
|
mark[0] = '\0';
|
||||||
|
|
||||||
|
parse_output (line);
|
||||||
|
}
|
||||||
|
|
||||||
|
nused = lastmark? (lastmark + 1 - linebuf) : 0;
|
||||||
|
memmove (linebuf, linebuf + nused, linelen - nused);
|
||||||
|
linelen -= nused;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (nread > 0 && linelen < sizeof linebuf - 1);
|
||||||
|
|
||||||
|
_gpgme_io_close (rp[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_gpgconf_dir (int what)
|
||||||
|
{
|
||||||
|
const char *result = NULL;
|
||||||
|
|
||||||
|
LOCK (dirinfo_lock);
|
||||||
|
if (!dirinfo.valid)
|
||||||
|
{
|
||||||
|
read_gpgconf_dirs ();
|
||||||
|
/* Even if the reading of the directories failed (e.g. due to an
|
||||||
|
too old version gpgconf or no gpgconf at all), we need to
|
||||||
|
mark the entries as valid so that we won't try over and over
|
||||||
|
to read them. Note further that we are not able to change
|
||||||
|
the read values later because they are practically statically
|
||||||
|
allocated. */
|
||||||
|
dirinfo.valid = 1;
|
||||||
|
}
|
||||||
|
switch (what)
|
||||||
|
{
|
||||||
|
case WANT_HOMEDIR: result = dirinfo.homedir; break;
|
||||||
|
case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
|
||||||
|
}
|
||||||
|
UNLOCK (dirinfo_lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the default home directory. Returns NULL if not known. */
|
||||||
|
const char *
|
||||||
|
_gpgme_get_default_homedir (void)
|
||||||
|
{
|
||||||
|
return get_gpgconf_dir (WANT_HOMEDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the default gpg-agent socket name. Returns NULL if not known. */
|
||||||
|
const char *
|
||||||
|
_gpgme_get_default_agent_socket (void)
|
||||||
|
{
|
||||||
|
return get_gpgconf_dir (WANT_AGENT_SOCKET);
|
||||||
|
}
|
||||||
|
|
744
src/engine-assuan.c
Normal file
744
src/engine-assuan.c
Normal file
@ -0,0 +1,744 @@
|
|||||||
|
/* engine-assuan.c - Low-level Assuan protocol engine
|
||||||
|
* Copyright (C) 2009 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note: This engine requires a modern Assuan server which uses
|
||||||
|
gpg-error codes. In particular there is no backward compatible
|
||||||
|
mapping of old Assuan error codes implemented.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "ops.h"
|
||||||
|
#include "wait.h"
|
||||||
|
#include "priv-io.h"
|
||||||
|
#include "sema.h"
|
||||||
|
|
||||||
|
#include "assuan.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "engine-backend.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int fd; /* FD we talk about. */
|
||||||
|
int server_fd;/* Server FD for this connection. */
|
||||||
|
int dir; /* Inbound/Outbound, maybe given implicit? */
|
||||||
|
void *data; /* Handler-specific data. */
|
||||||
|
void *tag; /* ID from the user for gpgme_remove_io_callback. */
|
||||||
|
} iocb_data_t;
|
||||||
|
|
||||||
|
/* Engine instance data. */
|
||||||
|
struct engine_llass
|
||||||
|
{
|
||||||
|
assuan_context_t assuan_ctx;
|
||||||
|
|
||||||
|
int lc_ctype_set;
|
||||||
|
int lc_messages_set;
|
||||||
|
|
||||||
|
iocb_data_t status_cb;
|
||||||
|
|
||||||
|
struct gpgme_io_cbs io_cbs;
|
||||||
|
|
||||||
|
/* Internal callbacks. */
|
||||||
|
engine_assuan_result_cb_t result_cb;
|
||||||
|
void *result_cb_value;
|
||||||
|
|
||||||
|
/* User provided callbacks. */
|
||||||
|
struct {
|
||||||
|
gpgme_assuan_data_cb_t data_cb;
|
||||||
|
void *data_cb_value;
|
||||||
|
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb;
|
||||||
|
void *inq_cb_value;
|
||||||
|
|
||||||
|
gpgme_assuan_status_cb_t status_cb;
|
||||||
|
void *status_cb_value;
|
||||||
|
} user;
|
||||||
|
|
||||||
|
/* Option flags. */
|
||||||
|
struct {
|
||||||
|
int gpg_agent:1; /* Assume this is a gpg-agent connection. */
|
||||||
|
} opt;
|
||||||
|
|
||||||
|
};
|
||||||
|
typedef struct engine_llass *engine_llass_t;
|
||||||
|
|
||||||
|
/* Helper to pass data to a callback. */
|
||||||
|
struct _gpgme_assuan_sendfnc_ctx
|
||||||
|
{
|
||||||
|
assuan_context_t assuan_ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Prototypes. */
|
||||||
|
static void llass_io_event (void *engine,
|
||||||
|
gpgme_event_io_t type, void *type_data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* return the default home directory. */
|
||||||
|
static const char *
|
||||||
|
llass_get_home_dir (void)
|
||||||
|
{
|
||||||
|
/* For this engine the home directory is not a filename but a string
|
||||||
|
used to convey options. The exclamation mark is a marker to show
|
||||||
|
that this is not a directory name. Options are strings delimited
|
||||||
|
by a space. The only option defined for now is GPG_AGENT to
|
||||||
|
enable GPG_AGENT specific commands to send to the server at
|
||||||
|
connection startup. */
|
||||||
|
return "!GPG_AGENT";
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
llass_get_version (const char *file_name)
|
||||||
|
{
|
||||||
|
return strdup ("1.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
llass_get_req_version (void)
|
||||||
|
{
|
||||||
|
return "1.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_notify_handler (int fd, void *opaque)
|
||||||
|
{
|
||||||
|
engine_llass_t llass = opaque;
|
||||||
|
|
||||||
|
assert (fd != -1);
|
||||||
|
if (llass->status_cb.fd == fd)
|
||||||
|
{
|
||||||
|
if (llass->status_cb.tag)
|
||||||
|
llass->io_cbs.remove (llass->status_cb.tag);
|
||||||
|
llass->status_cb.fd = -1;
|
||||||
|
llass->status_cb.tag = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
llass_cancel (void *engine)
|
||||||
|
{
|
||||||
|
engine_llass_t llass = engine;
|
||||||
|
|
||||||
|
if (!llass)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
if (llass->status_cb.fd != -1)
|
||||||
|
_gpgme_io_close (llass->status_cb.fd);
|
||||||
|
|
||||||
|
if (llass->assuan_ctx)
|
||||||
|
{
|
||||||
|
assuan_disconnect (llass->assuan_ctx);
|
||||||
|
llass->assuan_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
llass_release (void *engine)
|
||||||
|
{
|
||||||
|
engine_llass_t llass = engine;
|
||||||
|
|
||||||
|
if (!llass)
|
||||||
|
return;
|
||||||
|
|
||||||
|
llass_cancel (engine);
|
||||||
|
|
||||||
|
free (llass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a new instance. If HOME_DIR is NULL standard options for use
|
||||||
|
with gpg-agent are issued. */
|
||||||
|
static gpgme_error_t
|
||||||
|
llass_new (void **engine, const char *file_name, const char *home_dir)
|
||||||
|
{
|
||||||
|
gpgme_error_t err = 0;
|
||||||
|
engine_llass_t llass;
|
||||||
|
char *optstr;
|
||||||
|
|
||||||
|
llass = calloc (1, sizeof *llass);
|
||||||
|
if (!llass)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
llass->status_cb.fd = -1;
|
||||||
|
llass->status_cb.dir = 1;
|
||||||
|
llass->status_cb.tag = 0;
|
||||||
|
llass->status_cb.data = llass;
|
||||||
|
|
||||||
|
/* Parse_options. */
|
||||||
|
if (home_dir && *home_dir == '!')
|
||||||
|
{
|
||||||
|
home_dir++;
|
||||||
|
/* Very simple parser only working for the one option we support. */
|
||||||
|
if (!strncmp (home_dir, "GPG_AGENT", 9)
|
||||||
|
&& (!home_dir[9] || home_dir[9] == ' '))
|
||||||
|
llass->opt.gpg_agent = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = assuan_socket_connect (&llass->assuan_ctx, file_name, 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if (llass->opt.gpg_agent)
|
||||||
|
{
|
||||||
|
char *dft_display = NULL;
|
||||||
|
|
||||||
|
err = _gpgme_getenv ("DISPLAY", &dft_display);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
if (dft_display)
|
||||||
|
{
|
||||||
|
if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
free (dft_display);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
free (dft_display);
|
||||||
|
|
||||||
|
err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (llass->opt.gpg_agent && isatty (1))
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char dft_ttyname[64];
|
||||||
|
char *dft_ttytype = NULL;
|
||||||
|
|
||||||
|
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_errno (rc);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = _gpgme_getenv ("TERM", &dft_ttytype);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
if (dft_ttytype)
|
||||||
|
{
|
||||||
|
if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
free (dft_ttytype);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
free (dft_ttytype);
|
||||||
|
|
||||||
|
err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
/* Under Windows we need to use AllowSetForegroundWindow. Tell
|
||||||
|
llass to tell us when it needs it. */
|
||||||
|
if (!err && llass->opt.gpg_agent)
|
||||||
|
{
|
||||||
|
err = assuan_transact (llass->assuan_ctx, "OPTION allow-pinentry-notify",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
|
||||||
|
err = 0; /* This work only with recent gpg-agents. */
|
||||||
|
}
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
|
||||||
|
leave:
|
||||||
|
/* Close the server ends of the pipes (because of this, we must use
|
||||||
|
the stored server_fd_str in the function start). Our ends are
|
||||||
|
closed in llass_release(). */
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
llass_release (llass);
|
||||||
|
else
|
||||||
|
*engine = llass;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
llass_set_locale (void *engine, int category, const char *value)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
engine_llass_t llass = engine;
|
||||||
|
char *optstr;
|
||||||
|
char *catstr;
|
||||||
|
|
||||||
|
if (!llass->opt.gpg_agent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* FIXME: If value is NULL, we need to reset the option to default.
|
||||||
|
But we can't do this. So we error out here. gpg-agent needs
|
||||||
|
support for this. */
|
||||||
|
if (category == LC_CTYPE)
|
||||||
|
{
|
||||||
|
catstr = "lc-ctype";
|
||||||
|
if (!value && llass->lc_ctype_set)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
if (value)
|
||||||
|
llass->lc_ctype_set = 1;
|
||||||
|
}
|
||||||
|
#ifdef LC_MESSAGES
|
||||||
|
else if (category == LC_MESSAGES)
|
||||||
|
{
|
||||||
|
catstr = "lc-messages";
|
||||||
|
if (!value && llass->lc_messages_set)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
if (value)
|
||||||
|
llass->lc_messages_set = 1;
|
||||||
|
}
|
||||||
|
#endif /* LC_MESSAGES */
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
/* FIXME: Reset value to default. */
|
||||||
|
if (!value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
|
||||||
|
err = gpg_error_from_errno (errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = assuan_transact (llass->assuan_ctx, optstr, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
inquire_cb_sendfnc (gpgme_assuan_sendfnc_ctx_t ctx,
|
||||||
|
const void *data, size_t datalen)
|
||||||
|
{
|
||||||
|
if (data && datalen)
|
||||||
|
return assuan_send_data (ctx->assuan_ctx, data, datalen);
|
||||||
|
else
|
||||||
|
return 0; /* Don't allow an inquire to send a flush. */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the inquiry callback. It handles stuff which ee need to
|
||||||
|
handle here and passes everything on to the user callback. */
|
||||||
|
static gpgme_error_t
|
||||||
|
inquire_cb (engine_llass_t llass, const char *keyword, const char *args)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
if (llass->opt.gpg_agent && !strcmp (keyword, "PINENTRY_LAUNCHED"))
|
||||||
|
{
|
||||||
|
_gpgme_allow_set_foregound_window ((pid_t)strtoul (args, NULL, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (llass->user.inq_cb)
|
||||||
|
{
|
||||||
|
struct _gpgme_assuan_sendfnc_ctx sendfnc_ctx;
|
||||||
|
|
||||||
|
sendfnc_ctx.assuan_ctx = llass->assuan_ctx;
|
||||||
|
err = llass->user.inq_cb (llass->user.inq_cb_value,
|
||||||
|
keyword, args,
|
||||||
|
inquire_cb_sendfnc, &sendfnc_ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
llass_status_handler (void *opaque, int fd)
|
||||||
|
{
|
||||||
|
gpgme_error_t err = 0;
|
||||||
|
engine_llass_t llass = opaque;
|
||||||
|
char *line;
|
||||||
|
size_t linelen;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
err = assuan_read_line (llass->assuan_ctx, &line, &linelen);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
|
"fd 0x%x: error reading assuan line: %s",
|
||||||
|
fd, gpg_strerror (err));
|
||||||
|
}
|
||||||
|
else if (linelen >= 2 && line[0] == 'D' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
char *src = line + 2;
|
||||||
|
char *end = line + linelen;
|
||||||
|
char *dst = src;
|
||||||
|
|
||||||
|
linelen = 0;
|
||||||
|
while (src < end)
|
||||||
|
{
|
||||||
|
if (*src == '%' && src + 2 < end)
|
||||||
|
{
|
||||||
|
/* Handle escaped characters. */
|
||||||
|
++src;
|
||||||
|
*dst++ = _gpgme_hextobyte (src);
|
||||||
|
src += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*dst++ = *src++;
|
||||||
|
|
||||||
|
linelen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = line + 2;
|
||||||
|
if (linelen && llass->user.data_cb)
|
||||||
|
err = llass->user.data_cb (llass->user.data_cb_value,
|
||||||
|
src, linelen);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
|
"fd 0x%x: D inlinedata; status from cb: %s",
|
||||||
|
fd, (llass->user.data_cb ?
|
||||||
|
(err? gpg_strerror (err):"ok"):"no callback"));
|
||||||
|
}
|
||||||
|
else if (linelen >= 3
|
||||||
|
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
||||||
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
|
{
|
||||||
|
/* END received. Tell the data callback. */
|
||||||
|
if (llass->user.data_cb)
|
||||||
|
err = llass->user.data_cb (llass->user.data_cb_value, NULL, 0);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
|
"fd 0x%x: END line; status from cb: %s",
|
||||||
|
fd, (llass->user.data_cb ?
|
||||||
|
(err? gpg_strerror (err):"ok"):"no callback"));
|
||||||
|
}
|
||||||
|
else if (linelen > 2 && line[0] == 'S' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
char *args;
|
||||||
|
char *src;
|
||||||
|
|
||||||
|
for (src=line+2; *src == ' '; src++)
|
||||||
|
;
|
||||||
|
|
||||||
|
args = strchr (src, ' ');
|
||||||
|
if (!args)
|
||||||
|
args = line + linelen; /* Let it point to an empty string. */
|
||||||
|
else
|
||||||
|
*(args++) = 0;
|
||||||
|
|
||||||
|
while (*args == ' ')
|
||||||
|
args++;
|
||||||
|
|
||||||
|
if (llass->user.status_cb)
|
||||||
|
err = llass->user.status_cb (llass->user.status_cb_value,
|
||||||
|
src, args);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
TRACE3 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
|
"fd 0x%x: S line (%s) - status from cb: %s",
|
||||||
|
fd, line+2, (llass->user.status_cb ?
|
||||||
|
(err? gpg_strerror (err):"ok"):"no callback"));
|
||||||
|
}
|
||||||
|
else if (linelen >= 7
|
||||||
|
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
||||||
|
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
||||||
|
&& line[6] == 'E'
|
||||||
|
&& (line[7] == '\0' || line[7] == ' '))
|
||||||
|
{
|
||||||
|
char *src;
|
||||||
|
char *args;
|
||||||
|
|
||||||
|
for (src=line+7; *src == ' '; src++)
|
||||||
|
;
|
||||||
|
|
||||||
|
args = strchr (src, ' ');
|
||||||
|
if (!args)
|
||||||
|
args = line + linelen; /* Let it point to an empty string. */
|
||||||
|
else
|
||||||
|
*(args++) = 0;
|
||||||
|
|
||||||
|
while (*args == ' ')
|
||||||
|
args++;
|
||||||
|
|
||||||
|
err = inquire_cb (llass, src, args);
|
||||||
|
if (!err) /* Flush and send END. */
|
||||||
|
err = assuan_send_data (llass->assuan_ctx, NULL, 0);
|
||||||
|
}
|
||||||
|
else if (linelen >= 3
|
||||||
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
|
{
|
||||||
|
if (line[3] == ' ')
|
||||||
|
err = atoi (line+4);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
|
"fd 0x%x: ERR line: %s",
|
||||||
|
fd, err ? gpg_strerror (err) : "ok");
|
||||||
|
if (llass->result_cb)
|
||||||
|
err = llass->result_cb (llass->result_cb_value, err);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
_gpgme_io_close (llass->status_cb.fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (linelen >= 2
|
||||||
|
&& line[0] == 'O' && line[1] == 'K'
|
||||||
|
&& (line[2] == '\0' || line[2] == ' '))
|
||||||
|
{
|
||||||
|
TRACE1 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
|
"fd 0x%x: OK line", fd);
|
||||||
|
if (llass->result_cb)
|
||||||
|
err = llass->result_cb (llass->result_cb_value, 0);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
_gpgme_io_close (llass->status_cb.fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Comment line or invalid line. */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
while (!err && assuan_pending_line (llass->assuan_ctx));
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
add_io_cb (engine_llass_t llass, iocb_data_t *iocbd, gpgme_io_cb_t handler)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
TRACE_BEG2 (DEBUG_ENGINE, "engine-assuan:add_io_cb", llass,
|
||||||
|
"fd %d, dir %d", iocbd->fd, iocbd->dir);
|
||||||
|
err = (*llass->io_cbs.add) (llass->io_cbs.add_priv,
|
||||||
|
iocbd->fd, iocbd->dir,
|
||||||
|
handler, iocbd->data, &iocbd->tag);
|
||||||
|
if (err)
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
if (!iocbd->dir)
|
||||||
|
/* FIXME Kludge around poll() problem. */
|
||||||
|
err = _gpgme_io_set_nonblocking (iocbd->fd);
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
start (engine_llass_t llass, const char *command)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
int fdlist[5];
|
||||||
|
int nfds;
|
||||||
|
|
||||||
|
/* 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 (llass->assuan_ctx, 0 /* read fds */,
|
||||||
|
fdlist, DIM (fdlist));
|
||||||
|
if (nfds < 1)
|
||||||
|
return gpg_error (GPG_ERR_GENERAL); /* FIXME */
|
||||||
|
|
||||||
|
/* We "duplicate" the file descriptor, so we can close it here (we
|
||||||
|
can't close fdlist[0], as that is closed by libassuan, and
|
||||||
|
closing it here might cause libassuan to close some unrelated FD
|
||||||
|
later). Alternatively, we could special case status_fd and
|
||||||
|
register/unregister it manually as needed, but this increases
|
||||||
|
code duplication and is more complicated as we can not use the
|
||||||
|
close notifications etc. A third alternative would be to let
|
||||||
|
Assuan know that we closed the FD, but that complicates the
|
||||||
|
Assuan interface. */
|
||||||
|
|
||||||
|
llass->status_cb.fd = _gpgme_io_dup (fdlist[0]);
|
||||||
|
if (llass->status_cb.fd < 0)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
if (_gpgme_io_set_close_notify (llass->status_cb.fd,
|
||||||
|
close_notify_handler, llass))
|
||||||
|
{
|
||||||
|
_gpgme_io_close (llass->status_cb.fd);
|
||||||
|
llass->status_cb.fd = -1;
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = add_io_cb (llass, &llass->status_cb, llass_status_handler);
|
||||||
|
if (!err)
|
||||||
|
err = assuan_write_line (llass->assuan_ctx, command);
|
||||||
|
|
||||||
|
/* FIXME: If *command == '#' no answer is expected. */
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
llass_io_event (llass, GPGME_EVENT_START, NULL);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
llass_transact (void *engine,
|
||||||
|
const char *command,
|
||||||
|
engine_assuan_result_cb_t result_cb,
|
||||||
|
void *result_cb_value,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
engine_llass_t llass = engine;
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
if (!llass || !command || !*command)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
llass->result_cb = result_cb;
|
||||||
|
llass->result_cb_value = result_cb_value;
|
||||||
|
llass->user.data_cb = data_cb;
|
||||||
|
llass->user.data_cb_value = data_cb_value;
|
||||||
|
llass->user.inq_cb = inq_cb;
|
||||||
|
llass->user.inq_cb_value = inq_cb_value;
|
||||||
|
llass->user.status_cb = status_cb;
|
||||||
|
llass->user.status_cb_value = status_cb_value;
|
||||||
|
|
||||||
|
err = start (llass, command);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
llass_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
|
||||||
|
{
|
||||||
|
engine_llass_t llass = engine;
|
||||||
|
llass->io_cbs = *io_cbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
llass_io_event (void *engine, gpgme_event_io_t type, void *type_data)
|
||||||
|
{
|
||||||
|
engine_llass_t llass = engine;
|
||||||
|
|
||||||
|
TRACE3 (DEBUG_ENGINE, "gpgme:llass_io_event", llass,
|
||||||
|
"event %p, type %d, type_data %p",
|
||||||
|
llass->io_cbs.event, type, type_data);
|
||||||
|
if (llass->io_cbs.event)
|
||||||
|
(*llass->io_cbs.event) (llass->io_cbs.event_priv, type, type_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct engine_ops _gpgme_engine_ops_assuan =
|
||||||
|
{
|
||||||
|
/* Static functions. */
|
||||||
|
_gpgme_get_default_agent_socket,
|
||||||
|
llass_get_home_dir,
|
||||||
|
llass_get_version,
|
||||||
|
llass_get_req_version,
|
||||||
|
llass_new,
|
||||||
|
|
||||||
|
/* Member functions. */
|
||||||
|
llass_release,
|
||||||
|
NULL, /* reset */
|
||||||
|
NULL, /* set_status_handler */
|
||||||
|
NULL, /* set_command_handler */
|
||||||
|
NULL, /* set_colon_line_handler */
|
||||||
|
llass_set_locale,
|
||||||
|
NULL, /* decrypt */
|
||||||
|
NULL, /* delete */
|
||||||
|
NULL, /* edit */
|
||||||
|
NULL, /* encrypt */
|
||||||
|
NULL, /* encrypt_sign */
|
||||||
|
NULL, /* export */
|
||||||
|
NULL, /* export_ext */
|
||||||
|
NULL, /* genkey */
|
||||||
|
NULL, /* import */
|
||||||
|
NULL, /* keylist */
|
||||||
|
NULL, /* keylist_ext */
|
||||||
|
NULL, /* sign */
|
||||||
|
NULL, /* trustlist */
|
||||||
|
NULL, /* verify */
|
||||||
|
NULL, /* getauditlog */
|
||||||
|
llass_transact, /* opassuan_transact */
|
||||||
|
NULL, /* conf_load */
|
||||||
|
NULL, /* conf_save */
|
||||||
|
llass_set_io_cbs,
|
||||||
|
llass_io_event,
|
||||||
|
llass_cancel
|
||||||
|
};
|
@ -1,5 +1,5 @@
|
|||||||
/* engine-backend.h - A crypto backend for the engine interface.
|
/* engine-backend.h - A crypto backend for the engine interface.
|
||||||
Copyright (C) 2002, 2003, 2004 g10 Code GmbH
|
Copyright (C) 2002, 2003, 2004, 2009 g10 Code GmbH
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
|
|
||||||
@ -14,9 +14,8 @@
|
|||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this program; if not, write to the Free Software
|
License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
*/
|
||||||
02111-1307, USA. */
|
|
||||||
|
|
||||||
#ifndef ENGINE_BACKEND_H
|
#ifndef ENGINE_BACKEND_H
|
||||||
#define ENGINE_BACKEND_H
|
#define ENGINE_BACKEND_H
|
||||||
@ -35,6 +34,11 @@ struct engine_ops
|
|||||||
/* Return the default file name for the binary of this engine. */
|
/* Return the default file name for the binary of this engine. */
|
||||||
const char *(*get_file_name) (void);
|
const char *(*get_file_name) (void);
|
||||||
|
|
||||||
|
/* Return the default home dir for the binary of this engine. If
|
||||||
|
this function pointer is not set, the standard default home dir
|
||||||
|
of the engine is used. */
|
||||||
|
const char *(*get_home_dir) (void);
|
||||||
|
|
||||||
/* Returns a malloced string containing the version of the engine
|
/* Returns a malloced string containing the version of the engine
|
||||||
with the given binary file name (or the default if FILE_NAME is
|
with the given binary file name (or the default if FILE_NAME is
|
||||||
NULL. */
|
NULL. */
|
||||||
@ -96,6 +100,16 @@ struct engine_ops
|
|||||||
gpgme_data_t plaintext);
|
gpgme_data_t plaintext);
|
||||||
gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output,
|
gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
gpgme_error_t (*opassuan_transact) (void *engine,
|
||||||
|
const char *command,
|
||||||
|
engine_assuan_result_cb_t result_cb,
|
||||||
|
void *result_cb_value,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value);
|
||||||
|
|
||||||
gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p);
|
gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p);
|
||||||
gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf);
|
gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf);
|
||||||
@ -114,5 +128,8 @@ extern struct engine_ops _gpgme_engine_ops_gpgsm; /* CMS. */
|
|||||||
#ifdef ENABLE_GPGCONF
|
#ifdef ENABLE_GPGCONF
|
||||||
extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */
|
extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_GPGSM /* If this is enabled we also have assuan support. */
|
||||||
|
extern struct engine_ops _gpgme_engine_ops_assuan; /* Low-level Assuan. */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ENGINE_BACKEND_H */
|
#endif /* ENGINE_BACKEND_H */
|
||||||
|
@ -2158,6 +2158,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
|
|||||||
{
|
{
|
||||||
/* Static functions. */
|
/* Static functions. */
|
||||||
_gpgme_get_gpg_path,
|
_gpgme_get_gpg_path,
|
||||||
|
NULL,
|
||||||
gpg_get_version,
|
gpg_get_version,
|
||||||
gpg_get_req_version,
|
gpg_get_req_version,
|
||||||
gpg_new,
|
gpg_new,
|
||||||
@ -2184,6 +2185,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
|
|||||||
gpg_trustlist,
|
gpg_trustlist,
|
||||||
gpg_verify,
|
gpg_verify,
|
||||||
NULL, /* getauditlog */
|
NULL, /* getauditlog */
|
||||||
|
NULL, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
gpg_set_io_cbs,
|
gpg_set_io_cbs,
|
||||||
|
@ -885,6 +885,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
|
|||||||
{
|
{
|
||||||
/* Static functions. */
|
/* Static functions. */
|
||||||
_gpgme_get_gpgconf_path,
|
_gpgme_get_gpgconf_path,
|
||||||
|
NULL,
|
||||||
gpgconf_get_version,
|
gpgconf_get_version,
|
||||||
gpgconf_get_req_version,
|
gpgconf_get_req_version,
|
||||||
gpgconf_new,
|
gpgconf_new,
|
||||||
@ -911,6 +912,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
|
|||||||
NULL, /* trustlist */
|
NULL, /* trustlist */
|
||||||
NULL, /* verify */
|
NULL, /* verify */
|
||||||
NULL, /* getauditlog */
|
NULL, /* getauditlog */
|
||||||
|
NULL, /* opassuan_transact */
|
||||||
gpgconf_conf_load,
|
gpgconf_conf_load,
|
||||||
gpgconf_conf_save,
|
gpgconf_conf_save,
|
||||||
gpgconf_set_io_cbs,
|
gpgconf_set_io_cbs,
|
||||||
|
@ -1922,6 +1922,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
|||||||
{
|
{
|
||||||
/* Static functions. */
|
/* Static functions. */
|
||||||
_gpgme_get_gpgsm_path,
|
_gpgme_get_gpgsm_path,
|
||||||
|
NULL,
|
||||||
gpgsm_get_version,
|
gpgsm_get_version,
|
||||||
gpgsm_get_req_version,
|
gpgsm_get_req_version,
|
||||||
gpgsm_new,
|
gpgsm_new,
|
||||||
@ -1952,6 +1953,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
|||||||
NULL, /* trustlist */
|
NULL, /* trustlist */
|
||||||
gpgsm_verify,
|
gpgsm_verify,
|
||||||
gpgsm_getauditlog,
|
gpgsm_getauditlog,
|
||||||
|
NULL, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
gpgsm_set_io_cbs,
|
gpgsm_set_io_cbs,
|
||||||
|
80
src/engine.c
80
src/engine.c
@ -1,6 +1,6 @@
|
|||||||
/* engine.c - GPGME engine support.
|
/* engine.c - GPGME engine support.
|
||||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
Copyright (C) 2001, 2002, 2003, 2004, 2006 g10 Code GmbH
|
Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009 g10 Code GmbH
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
|
|
||||||
@ -15,9 +15,8 @@
|
|||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this program; if not, write to the Free Software
|
License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
*/
|
||||||
02111-1307, USA. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -52,7 +51,12 @@ static struct engine_ops *engine_ops[] =
|
|||||||
NULL,
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_GPGCONF
|
#ifdef ENABLE_GPGCONF
|
||||||
&_gpgme_engine_ops_gpgconf /* gpg-conf. */
|
&_gpgme_engine_ops_gpgconf, /* gpg-conf. */
|
||||||
|
#else
|
||||||
|
NULL,
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_GPGSM /* This indicates that we have assuan support. */
|
||||||
|
&_gpgme_engine_ops_assuan /* Low-Level Assuan. */
|
||||||
#else
|
#else
|
||||||
NULL
|
NULL
|
||||||
#endif
|
#endif
|
||||||
@ -78,6 +82,20 @@ engine_get_file_name (gpgme_protocol_t proto)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the standard home dir of the engine for PROTOCOL. */
|
||||||
|
static const char *
|
||||||
|
engine_get_home_dir (gpgme_protocol_t proto)
|
||||||
|
{
|
||||||
|
if (proto > DIM (engine_ops))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
|
||||||
|
return (*engine_ops[proto]->get_home_dir) ();
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get a malloced string containing the version number of the engine
|
/* Get a malloced string containing the version number of the engine
|
||||||
for PROTOCOL. */
|
for PROTOCOL. */
|
||||||
static char *
|
static char *
|
||||||
@ -175,18 +193,22 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
|
|||||||
gpgme_engine_info_t *lastp = &engine_info;
|
gpgme_engine_info_t *lastp = &engine_info;
|
||||||
gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
|
gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
|
||||||
GPGME_PROTOCOL_CMS,
|
GPGME_PROTOCOL_CMS,
|
||||||
GPGME_PROTOCOL_GPGCONF };
|
GPGME_PROTOCOL_GPGCONF,
|
||||||
|
GPGME_PROTOCOL_ASSUAN };
|
||||||
unsigned int proto;
|
unsigned int proto;
|
||||||
|
|
||||||
for (proto = 0; proto < DIM (proto_list); proto++)
|
for (proto = 0; proto < DIM (proto_list); proto++)
|
||||||
{
|
{
|
||||||
const char *ofile_name = engine_get_file_name (proto_list[proto]);
|
const char *ofile_name = engine_get_file_name (proto_list[proto]);
|
||||||
|
const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
|
||||||
char *file_name;
|
char *file_name;
|
||||||
|
char *home_dir;
|
||||||
|
|
||||||
if (!ofile_name)
|
if (!ofile_name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
file_name = strdup (ofile_name);
|
file_name = strdup (ofile_name);
|
||||||
|
home_dir = ohome_dir? strdup (ohome_dir): NULL;
|
||||||
|
|
||||||
*lastp = malloc (sizeof (*engine_info));
|
*lastp = malloc (sizeof (*engine_info));
|
||||||
if (!*lastp || !file_name)
|
if (!*lastp || !file_name)
|
||||||
@ -198,6 +220,8 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
|
|||||||
|
|
||||||
if (file_name)
|
if (file_name)
|
||||||
free (file_name);
|
free (file_name);
|
||||||
|
if (home_dir)
|
||||||
|
free (home_dir);
|
||||||
|
|
||||||
UNLOCK (engine_info_lock);
|
UNLOCK (engine_info_lock);
|
||||||
return gpg_error_from_errno (saved_errno);
|
return gpg_error_from_errno (saved_errno);
|
||||||
@ -205,7 +229,7 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
|
|||||||
|
|
||||||
(*lastp)->protocol = proto_list[proto];
|
(*lastp)->protocol = proto_list[proto];
|
||||||
(*lastp)->file_name = file_name;
|
(*lastp)->file_name = file_name;
|
||||||
(*lastp)->home_dir = NULL;
|
(*lastp)->home_dir = home_dir;
|
||||||
(*lastp)->version = engine_get_version (proto_list[proto], NULL);
|
(*lastp)->version = engine_get_version (proto_list[proto], NULL);
|
||||||
(*lastp)->req_version = engine_get_req_version (proto_list[proto]);
|
(*lastp)->req_version = engine_get_req_version (proto_list[proto]);
|
||||||
(*lastp)->next = NULL;
|
(*lastp)->next = NULL;
|
||||||
@ -347,7 +371,20 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
new_home_dir = NULL;
|
{
|
||||||
|
const char *ohome_dir = engine_get_home_dir (proto);
|
||||||
|
if (ohome_dir)
|
||||||
|
{
|
||||||
|
new_home_dir = strdup (ohome_dir);
|
||||||
|
if (!new_home_dir)
|
||||||
|
{
|
||||||
|
free (new_file_name);
|
||||||
|
return gpg_error_from_errno (errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
new_home_dir = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove the old members. */
|
/* Remove the old members. */
|
||||||
assert (info->file_name);
|
assert (info->file_name);
|
||||||
@ -730,6 +767,33 @@ _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_error_t
|
||||||
|
_gpgme_engine_op_assuan_transact (engine_t engine,
|
||||||
|
const char *command,
|
||||||
|
engine_assuan_result_cb_t result_cb,
|
||||||
|
void *result_cb_value,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
if (!engine)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
if (!engine->ops->opassuan_transact)
|
||||||
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
|
return (*engine->ops->opassuan_transact) (engine->engine,
|
||||||
|
command,
|
||||||
|
result_cb, result_cb_value,
|
||||||
|
data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value,
|
||||||
|
status_cb, status_cb_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gpgme_error_t
|
gpgme_error_t
|
||||||
_gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
|
_gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
|
||||||
{
|
{
|
||||||
|
14
src/engine.h
14
src/engine.h
@ -35,6 +35,9 @@ typedef gpgme_error_t (*engine_command_handler_t) (void *priv,
|
|||||||
gpgme_status_code_t code,
|
gpgme_status_code_t code,
|
||||||
const char *keyword,
|
const char *keyword,
|
||||||
int fd, int *processed);
|
int fd, int *processed);
|
||||||
|
typedef gpgme_error_t (*engine_assuan_result_cb_t) (void *priv,
|
||||||
|
gpgme_error_t result);
|
||||||
|
|
||||||
|
|
||||||
/* Get a deep copy of the engine info and return it in INFO. */
|
/* Get a deep copy of the engine info and return it in INFO. */
|
||||||
gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info);
|
gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info);
|
||||||
@ -126,6 +129,17 @@ gpgme_error_t _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
|
|||||||
gpgme_error_t _gpgme_engine_op_getauditlog (engine_t engine,
|
gpgme_error_t _gpgme_engine_op_getauditlog (engine_t engine,
|
||||||
gpgme_data_t output,
|
gpgme_data_t output,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
gpgme_error_t _gpgme_engine_op_assuan_transact
|
||||||
|
(engine_t engine,
|
||||||
|
const char *command,
|
||||||
|
engine_assuan_result_cb_t result_cb,
|
||||||
|
void *result_cb_value,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value);
|
||||||
|
|
||||||
gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine,
|
gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine,
|
||||||
gpgme_conf_comp_t *conf_p);
|
gpgme_conf_comp_t *conf_p);
|
||||||
|
@ -192,7 +192,9 @@ gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
|
|||||||
protocol, gpgme_get_protocol_name (protocol)
|
protocol, gpgme_get_protocol_name (protocol)
|
||||||
? gpgme_get_protocol_name (protocol) : "unknown");
|
? gpgme_get_protocol_name (protocol) : "unknown");
|
||||||
|
|
||||||
if (protocol != GPGME_PROTOCOL_OpenPGP && protocol != GPGME_PROTOCOL_CMS)
|
if (protocol != GPGME_PROTOCOL_OpenPGP
|
||||||
|
&& protocol != GPGME_PROTOCOL_CMS
|
||||||
|
&& protocol != GPGME_PROTOCOL_ASSUAN)
|
||||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||||
|
|
||||||
if (ctx->protocol != protocol)
|
if (ctx->protocol != protocol)
|
||||||
@ -233,6 +235,9 @@ gpgme_get_protocol_name (gpgme_protocol_t protocol)
|
|||||||
case GPGME_PROTOCOL_CMS:
|
case GPGME_PROTOCOL_CMS:
|
||||||
return "CMS";
|
return "CMS";
|
||||||
|
|
||||||
|
case GPGME_PROTOCOL_ASSUAN:
|
||||||
|
return "Assuan";
|
||||||
|
|
||||||
case GPGME_PROTOCOL_UNKNOWN:
|
case GPGME_PROTOCOL_UNKNOWN:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|
||||||
|
@ -167,5 +167,9 @@ EXPORTS
|
|||||||
gpgme_op_conf_save @130
|
gpgme_op_conf_save @130
|
||||||
|
|
||||||
gpgme_cancel_async @131
|
gpgme_cancel_async @131
|
||||||
|
|
||||||
|
gpgme_op_assuan_result @132
|
||||||
|
gpgme_op_assuan_transact_start @133
|
||||||
|
gpgme_op_assuan_transact @134
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*-
|
/* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*-
|
||||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||||
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
|
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
|
||||||
|
|
||||||
This file is part of GPGME.
|
This file is part of GPGME.
|
||||||
|
|
||||||
@ -301,6 +301,7 @@ typedef enum
|
|||||||
GPGME_PROTOCOL_OpenPGP = 0, /* The default mode. */
|
GPGME_PROTOCOL_OpenPGP = 0, /* The default mode. */
|
||||||
GPGME_PROTOCOL_CMS = 1,
|
GPGME_PROTOCOL_CMS = 1,
|
||||||
GPGME_PROTOCOL_GPGCONF = 2, /* Special code for gpgconf. */
|
GPGME_PROTOCOL_GPGCONF = 2, /* Special code for gpgconf. */
|
||||||
|
GPGME_PROTOCOL_ASSUAN = 3, /* Low-level access to an Assuan server. */
|
||||||
GPGME_PROTOCOL_UNKNOWN = 255
|
GPGME_PROTOCOL_UNKNOWN = 255
|
||||||
}
|
}
|
||||||
gpgme_protocol_t;
|
gpgme_protocol_t;
|
||||||
@ -746,6 +747,8 @@ typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque,
|
|||||||
gpgme_status_code_t status,
|
gpgme_status_code_t status,
|
||||||
const char *args, int fd);
|
const char *args, int fd);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Context management functions. */
|
/* Context management functions. */
|
||||||
|
|
||||||
@ -1656,6 +1659,51 @@ gpgme_error_t gpgme_op_getauditlog_start (gpgme_ctx_t ctx, gpgme_data_t output,
|
|||||||
gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output,
|
gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Low-level Assuan protocol access. */
|
||||||
|
typedef gpgme_error_t (*gpgme_assuan_data_cb_t)
|
||||||
|
(void *opaque, const void *data, size_t datalen);
|
||||||
|
|
||||||
|
struct _gpgme_assuan_sendfnc_ctx;
|
||||||
|
typedef struct _gpgme_assuan_sendfnc_ctx *gpgme_assuan_sendfnc_ctx_t;
|
||||||
|
typedef gpgme_error_t (*gpgme_assuan_sendfnc_t)
|
||||||
|
(gpgme_assuan_sendfnc_ctx_t ctx, const void *data, size_t datalen);
|
||||||
|
|
||||||
|
typedef gpgme_error_t (*gpgme_assuan_inquire_cb_t)
|
||||||
|
(void *opaque, const char *name, const char *args,
|
||||||
|
gpgme_assuan_sendfnc_t sendfnc,
|
||||||
|
gpgme_assuan_sendfnc_ctx_t sendfnc_ctx);
|
||||||
|
|
||||||
|
typedef gpgme_error_t (*gpgme_assuan_status_cb_t)
|
||||||
|
(void *opaque, const char *status, const char *args);
|
||||||
|
|
||||||
|
/* Return the result of the last Assuan command. */
|
||||||
|
gpgme_error_t gpgme_op_assuan_result (gpgme_ctx_t ctx);
|
||||||
|
|
||||||
|
/* Send the Assuan COMMAND and return results via the callbacks.
|
||||||
|
Asynchronous variant. */
|
||||||
|
gpgme_error_t gpgme_op_assuan_transact_start (gpgme_ctx_t ctx,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t stat_cb,
|
||||||
|
void *stat_cb_value);
|
||||||
|
|
||||||
|
/* Send the Assuan COMMAND and return results via the callbacks.
|
||||||
|
Synchronous variant. */
|
||||||
|
gpgme_error_t gpgme_op_assuan_transact (gpgme_ctx_t ctx,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t stat_cb,
|
||||||
|
void *stat_cb_value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Interface to gpgconf(1). */
|
/* Interface to gpgconf(1). */
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# libgpgme.vers - List of symbols to export.
|
# libgpgme.vers - List of symbols to export.
|
||||||
# Copyright (C) 2002, 2004, 2005 g10 Code GmbH
|
# Copyright (C) 2002, 2004, 2005, 2009 g10 Code GmbH
|
||||||
#
|
#
|
||||||
# This file is part of GPGME.
|
# This file is part of GPGME.
|
||||||
#
|
#
|
||||||
@ -14,8 +14,7 @@
|
|||||||
# GNU Lesser General Public License for more details.
|
# GNU Lesser General Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
#-------------------------------------------------------
|
#-------------------------------------------------------
|
||||||
# Please remember to add new functions also to gpgme.def
|
# Please remember to add new functions also to gpgme.def
|
||||||
@ -48,6 +47,10 @@ GPGME_1.1 {
|
|||||||
gpgme_op_conf_save;
|
gpgme_op_conf_save;
|
||||||
|
|
||||||
gpgme_cancel_async;
|
gpgme_cancel_async;
|
||||||
|
|
||||||
|
gpgme_op_assuan_result;
|
||||||
|
gpgme_op_assuan_transact;
|
||||||
|
gpgme_op_assuan_transact_start;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
158
src/opassuan.c
Normal file
158
src/opassuan.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/* opassuan.c - Low-level Assuan operations.
|
||||||
|
Copyright (C) 2009 g10 Code GmbH
|
||||||
|
|
||||||
|
This file is part of GPGME.
|
||||||
|
|
||||||
|
GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "ops.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* The result of the assuan command with 0 for OK and an error value
|
||||||
|
for ERR. */
|
||||||
|
gpgme_error_t result;
|
||||||
|
} *op_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This callback is used to return the status of the assuan command
|
||||||
|
back. Note that this is different from the error code returned
|
||||||
|
from gpgme_op_assuan_transact because the later only reflects error
|
||||||
|
with the connection. */
|
||||||
|
static gpgme_error_t
|
||||||
|
result_cb (void *priv, gpgme_error_t result)
|
||||||
|
{
|
||||||
|
gpgme_ctx_t ctx = (gpgme_ctx_t)priv;
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
|
||||||
|
opd = hook;
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (!opd)
|
||||||
|
return gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
|
||||||
|
opd->result = result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_error_t
|
||||||
|
gpgme_op_assuan_result (gpgme_ctx_t ctx)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
|
||||||
|
opd = hook;
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (!opd)
|
||||||
|
return gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
|
||||||
|
return opd->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
opassuan_start (gpgme_ctx_t ctx, int synchronous,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
if (!command || !*command)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
/* The flag value 256 is used to suppress an engine reset. This is
|
||||||
|
required to keep the connection running. */
|
||||||
|
err = _gpgme_op_reset (ctx, ((synchronous&255) | 256));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, sizeof (*opd), NULL);
|
||||||
|
opd = hook;
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
opd->result = gpg_error (GPG_ERR_UNFINISHED);
|
||||||
|
|
||||||
|
return _gpgme_engine_op_assuan_transact (ctx->engine, command,
|
||||||
|
result_cb, ctx,
|
||||||
|
data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value,
|
||||||
|
status_cb, status_cb_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* XXXX. This is the asynchronous variant. */
|
||||||
|
gpgme_error_t
|
||||||
|
gpgme_op_assuan_transact_start (gpgme_ctx_t ctx,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
return opassuan_start (ctx, 0, command,
|
||||||
|
data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value,
|
||||||
|
status_cb, status_cb_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* XXXX. This is the synchronous variant. */
|
||||||
|
gpgme_error_t
|
||||||
|
gpgme_op_assuan_transact (gpgme_ctx_t ctx,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
err = opassuan_start (ctx, 1, command,
|
||||||
|
data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value,
|
||||||
|
status_cb, status_cb_value);
|
||||||
|
if (!err)
|
||||||
|
err = _gpgme_wait_one (ctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
11
src/util.h
11
src/util.h
@ -35,6 +35,11 @@ const char *_gpgme_get_gpgconf_path (void);
|
|||||||
int _gpgme_get_conf_int (const char *key, int *value);
|
int _gpgme_get_conf_int (const char *key, int *value);
|
||||||
void _gpgme_allow_set_foregound_window (pid_t pid);
|
void _gpgme_allow_set_foregound_window (pid_t pid);
|
||||||
|
|
||||||
|
/*-- dirinfo.c --*/
|
||||||
|
const char *_gpgme_get_default_homedir (void);
|
||||||
|
const char *_gpgme_get_default_agent_socket (void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- replacement functions in <funcname>.c --*/
|
/*-- replacement functions in <funcname>.c --*/
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -111,4 +116,10 @@ int _gpgme_mkstemp (int *fd, char **name);
|
|||||||
const char *_gpgme_get_w32spawn_path (void);
|
const char *_gpgme_get_w32spawn_path (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*-- Error codes not yet available in current gpg-error.h. --*/
|
||||||
|
#ifndef GPG_ERR_UNFINISHED
|
||||||
|
#define GPG_ERR_UNFINISHED 199
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* UTIL_H */
|
#endif /* UTIL_H */
|
||||||
|
@ -179,7 +179,8 @@ gpgme_check_version (const char *req_version)
|
|||||||
automagically initialize the debug system with out the locks
|
automagically initialize the debug system with out the locks
|
||||||
being initialized and missing the assuan log level setting. */
|
being initialized and missing the assuan log level setting. */
|
||||||
TRACE2 (DEBUG_INIT, "gpgme_check_version: ", 0,
|
TRACE2 (DEBUG_INIT, "gpgme_check_version: ", 0,
|
||||||
"req_version=%s, VERSION=%s", req_version, VERSION);
|
"req_version=%s, VERSION=%s",
|
||||||
|
req_version? req_version:"(null)", VERSION);
|
||||||
|
|
||||||
return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
|
return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2009-01-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* opassuan/: New.
|
||||||
|
* opassuan/Makefile.am: New.
|
||||||
|
* opassuan/t-command.c: New.
|
||||||
|
|
||||||
2008-12-03 Marcus Brinkmann <marcus@g10code.de>
|
2008-12-03 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* Makefile.am (INCLUDES): Fix path to include file.
|
* Makefile.am (INCLUDES): Fix path to include file.
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
# Public License for more details.
|
# Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
## Process this file with automake to produce Makefile.in
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ gpgtests =
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if RUN_GPGSM_TESTS
|
if RUN_GPGSM_TESTS
|
||||||
gpgsmtests = gpgsm
|
gpgsmtests = gpgsm opassuan
|
||||||
else
|
else
|
||||||
gpgsmtests =
|
gpgsmtests =
|
||||||
endif
|
endif
|
||||||
|
35
tests/opassuan/Makefile.am
Normal file
35
tests/opassuan/Makefile.am
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Copyright (C) 2009 g10 Code GmbH
|
||||||
|
#
|
||||||
|
# This file is part of GPGME.
|
||||||
|
#
|
||||||
|
# GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU Lesser General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 2.1 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 Lesser General
|
||||||
|
# Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
## Process this file with automake to produce Makefile.in
|
||||||
|
|
||||||
|
TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) GPG_AGENT_INFO=
|
||||||
|
|
||||||
|
noinst_HEADERS =
|
||||||
|
TESTS =
|
||||||
|
|
||||||
|
EXTRA_DIST =
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_builddir)/src
|
||||||
|
|
||||||
|
AM_CPPFLAGS = @GPG_ERROR_CFLAGS@
|
||||||
|
LDADD = ../../src/libgpgme.la
|
||||||
|
|
||||||
|
noinst_PROGRAMS = $(TESTS) t-command
|
||||||
|
|
||||||
|
DISTCLEANFILES =
|
||||||
|
|
121
tests/opassuan/t-command.c
Normal file
121
tests/opassuan/t-command.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* t-command.c - Regression test.
|
||||||
|
Copyright (C) 2009 g10 Code GmbH
|
||||||
|
|
||||||
|
This file is part of GPGME.
|
||||||
|
|
||||||
|
GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 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
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
#include <gpgme.h>
|
||||||
|
|
||||||
|
#define fail_if_err(err) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (err) \
|
||||||
|
{ \
|
||||||
|
fprintf (stderr, "%s:%d: %s: %s (%d.%d)\n", \
|
||||||
|
__FILE__, __LINE__, gpg_strsource (err), \
|
||||||
|
gpg_strerror (err), \
|
||||||
|
gpg_err_source (err), gpg_err_code (err)); \
|
||||||
|
exit (1); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
data_cb (void *opaque, const void *data, size_t datalen)
|
||||||
|
{
|
||||||
|
printf ("DATA_CB: datalen=%d\n", (int)datalen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
inq_cb (void *opaque, const char *name, const char *args,
|
||||||
|
gpgme_assuan_sendfnc_t sendfnc,
|
||||||
|
gpgme_assuan_sendfnc_ctx_t sendfnc_value)
|
||||||
|
{
|
||||||
|
printf ("INQ_CB: name=`%s' args=`%s'\n", name, args);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
status_cb (void *opaque, const char *status, const char *args)
|
||||||
|
{
|
||||||
|
printf ("STATUS_CB: status=`%s' args=`%s'\n", status, args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
const char *command;
|
||||||
|
|
||||||
|
gpgme_check_version (NULL);
|
||||||
|
#ifndef HAVE_W32_SYSTEM
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
|
||||||
|
gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (argc)
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
command = argc? *argv : "NOP";
|
||||||
|
|
||||||
|
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_ASSUAN);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
err = gpgme_op_assuan_transact (ctx, command,
|
||||||
|
data_cb, NULL,
|
||||||
|
inq_cb, NULL,
|
||||||
|
status_cb, NULL);
|
||||||
|
fail_if_err (err);
|
||||||
|
err = gpgme_op_assuan_result (ctx);
|
||||||
|
if (err)
|
||||||
|
fprintf (stderr, "assuan command `%s' failed: %s <%s> (%d)\n",
|
||||||
|
command, gpg_strerror (err), gpg_strsource (err), err);
|
||||||
|
else
|
||||||
|
fprintf (stderr, "assuan command `%s' succeeded\n", command);
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_release (ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user