diff --git a/NEWS b/NEWS index 55c8660d..5c871dd8 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,12 @@ Noteworthy changes in version 1.4.3 (unreleased) ------------------------------------------------ + * The default engine names are now taken from the output of gpgconf. + If gpgconf is not found the use of gpg 1 is assumed. + + * Under Windows the default engines names are first searched in the + installation directory of the gpgme DLL. + * Interface changes relative to the 1.4.2 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gpgme_signers_count NEW. diff --git a/configure.ac b/configure.ac index 2d26dbb0..d3258be4 100644 --- a/configure.ac +++ b/configure.ac @@ -920,11 +920,15 @@ AM_CONDITIONAL(HAVE_UISERVER, test "$uiserver" != "no") # Add a few constants to help porting to W32 AH_VERBATIM([SEPCONSTANTS], [ -/* Separators as used in $PATH. */ +/* Separators as used in $PATH and file name. */ #ifdef HAVE_DOSISH_SYSTEM #define PATHSEP_C ';' +#define DIRSEP_C '\\' +#define DIRSEP_S "\\" #else #define PATHSEP_C ':' +#define DIRSEP_C '/' +#define DIRSEP_S "/" #endif ]) diff --git a/src/Makefile.am b/src/Makefile.am index fa3b077f..37e34071 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -118,7 +118,7 @@ main_sources = \ $(uiserver_components) \ $(g13_components) vfs-mount.c vfs-create.c \ gpgconf.c \ - sema.h priv-io.h $(system_components) dirinfo.c \ + sema.h priv-io.h $(system_components) sys-util.h dirinfo.c \ debug.c debug.h gpgme.c version.c error.c libgpgme_la_SOURCES = $(main_sources) \ diff --git a/src/dirinfo.c b/src/dirinfo.c index 267e9888..27c0dd76 100644 --- a/src/dirinfo.c +++ b/src/dirinfo.c @@ -1,5 +1,5 @@ /* dirinfo.c - Get directory information - * Copyright (C) 2009 g10 Code GmbH + * Copyright (C) 2009, 2013 g10 Code GmbH * * This file is part of GPGME. * @@ -29,6 +29,7 @@ #include "priv-io.h" #include "debug.h" #include "sema.h" +#include "sys-util.h" DEFINE_STATIC_LOCK (dirinfo_lock); @@ -36,7 +37,11 @@ DEFINE_STATIC_LOCK (dirinfo_lock); enum { WANT_HOMEDIR, - WANT_AGENT_SOCKET + WANT_AGENT_SOCKET, + WANT_GPG_NAME, + WANT_GPGSM_NAME, + WANT_G13_NAME, + WANT_UISRV_SOCKET }; /* Values retrieved via gpgconf and cached here. */ @@ -44,13 +49,18 @@ static struct { int valid; /* Cached information is valid. */ char *homedir; char *agent_socket; + char *gpg_name; + char *gpgsm_name; + char *g13_name; + char *uisrv_socket; } dirinfo; /* Parse the output of "gpgconf --list-dirs". This function expects - that DIRINFO_LOCK is held by the caller. */ + that DIRINFO_LOCK is held by the caller. If COMPONENTS is set, the + output of --list-components is expected. */ static void -parse_output (char *line) +parse_output (char *line, int components) { char *value, *p; @@ -58,6 +68,14 @@ parse_output (char *line) if (!value) return; *value++ = 0; + if (components) + { + /* Skip the second field. */ + value = strchr (value, ':'); + if (!value) + return; + *value++ = 0; + } p = strchr (value, ':'); if (p) *p = 0; @@ -66,19 +84,45 @@ parse_output (char *line) 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); + if (components) + { + if (!strcmp (line, "gpg") && !dirinfo.gpg_name) + dirinfo.gpg_name = strdup (value); + else if (!strcmp (line, "gpgsm") && !dirinfo.gpgsm_name) + dirinfo.gpgsm_name = strdup (value); + else if (!strcmp (line, "g13") && !dirinfo.g13_name) + dirinfo.g13_name = strdup (value); + } + else + { + if (!strcmp (line, "homedir") && !dirinfo.homedir) + { + const char name[] = "S.uiserver"; + + dirinfo.homedir = strdup (value); + if (dirinfo.homedir) + { + dirinfo.uisrv_socket = malloc (strlen (dirinfo + .homedir) + + 1 + strlen (name) + 1); + if (dirinfo.uisrv_socket) + strcpy (stpcpy (stpcpy (dirinfo.uisrv_socket, dirinfo.homedir), + DIRSEP_S), name); + } + } + 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. */ + that DIRINFO_LOCK is held by the caller. PGNAME is the name of the + gpgconf binary. If COMPONENTS is set, not the directories bit the + name of the componeNts are read. */ static void -read_gpgconf_dirs (void) +read_gpgconf_dirs (const char *pgmname, int components) { - const char *pgmname; char linebuf[1024] = {0}; int linelen = 0; char * argv[3]; @@ -89,12 +133,8 @@ read_gpgconf_dirs (void) int nread; char *mark = NULL; - pgmname = _gpgme_get_gpgconf_path (); - if (!pgmname) - return; /* No way. */ - argv[0] = (char *)pgmname; - argv[1] = "--list-dirs"; + argv[1] = components? "--list-components" : "--list-dirs"; argv[2] = NULL; if (_gpgme_io_pipe (rp, 1) < 0) @@ -132,7 +172,7 @@ read_gpgconf_dirs (void) else mark[0] = '\0'; - parse_output (line); + parse_output (line, components); } nused = lastmark? (lastmark + 1 - linebuf) : 0; @@ -147,14 +187,38 @@ read_gpgconf_dirs (void) static const char * -get_gpgconf_dir (int what) +get_gpgconf_item (int what) { const char *result = NULL; LOCK (dirinfo_lock); if (!dirinfo.valid) { - read_gpgconf_dirs (); + const char *pgmname; + + pgmname = _gpgme_get_gpgconf_path (); + if (pgmname && access (pgmname, F_OK)) + { + _gpgme_debug (DEBUG_INIT, + "gpgme_dinfo: gpgconf='%s' [not installed]\n", pgmname); + pgmname = NULL; /* Not available. */ + } + else + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpgconf='%s'\n", + pgmname? pgmname : "[null]"); + if (!pgmname) + { + /* Probably gpgconf is not installed. Assume we are using + GnuPG-1. */ + pgmname = _gpgme_get_gpg_path (); + if (pgmname) + dirinfo.gpg_name = strdup (pgmname); + } + else + { + read_gpgconf_dirs (pgmname, 0); + read_gpgconf_dirs (pgmname, 1); + } /* 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 @@ -162,11 +226,33 @@ get_gpgconf_dir (int what) the read values later because they are practically statically allocated. */ dirinfo.valid = 1; + if (dirinfo.gpg_name) + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpg='%s'\n", + dirinfo.gpg_name); + if (dirinfo.g13_name) + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: g13='%s'\n", + dirinfo.g13_name); + if (dirinfo.gpgsm_name) + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: gpgsm='%s'\n", + dirinfo.gpgsm_name); + if (dirinfo.homedir) + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: homedir='%s'\n", + dirinfo.homedir); + if (dirinfo.agent_socket) + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: agent='%s'\n", + dirinfo.agent_socket); + if (dirinfo.uisrv_socket) + _gpgme_debug (DEBUG_INIT, "gpgme_dinfo: uisrv='%s'\n", + dirinfo.uisrv_socket); } switch (what) { case WANT_HOMEDIR: result = dirinfo.homedir; break; case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break; + case WANT_GPG_NAME: result = dirinfo.gpg_name; break; + case WANT_GPGSM_NAME: result = dirinfo.gpgsm_name; break; + case WANT_G13_NAME: result = dirinfo.g13_name; break; + case WANT_UISRV_SOCKET: result = dirinfo.uisrv_socket; break; } UNLOCK (dirinfo_lock); return result; @@ -177,13 +263,51 @@ get_gpgconf_dir (int what) const char * _gpgme_get_default_homedir (void) { - return get_gpgconf_dir (WANT_HOMEDIR); + return get_gpgconf_item (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); + return get_gpgconf_item (WANT_AGENT_SOCKET); } +/* Return the default gpg file name. Returns NULL if not known. */ +const char * +_gpgme_get_default_gpg_name (void) +{ + return get_gpgconf_item (WANT_GPG_NAME); +} + +/* Return the default gpgsm file name. Returns NULL if not known. */ +const char * +_gpgme_get_default_gpgsm_name (void) +{ + return get_gpgconf_item (WANT_GPGSM_NAME); +} + +/* Return the default g13 file name. Returns NULL if not known. */ +const char * +_gpgme_get_default_g13_name (void) +{ + return get_gpgconf_item (WANT_G13_NAME); +} + +/* Return the default gpgconf file name. Returns NULL if not known. + Because gpgconf is the binary used to retrieved all these default + names, this function is merely a simple wrapper around the function + used to locate this binary. */ +const char * +_gpgme_get_default_gpgconf_name (void) +{ + return _gpgme_get_gpgconf_path (); +} + +/* Return the default UI-server socket name. Returns NULL if not + known. */ +const char * +_gpgme_get_default_uisrv_socket (void) +{ + return get_gpgconf_item (WANT_UISRV_SOCKET); +} diff --git a/src/engine-g13.c b/src/engine-g13.c index de0aac80..b97e0b44 100644 --- a/src/engine-g13.c +++ b/src/engine-g13.c @@ -100,7 +100,7 @@ static char * g13_get_version (const char *file_name) { return _gpgme_get_program_version (file_name ? file_name - : _gpgme_get_g13_path ()); + : _gpgme_get_default_g13_name ()); } @@ -251,11 +251,11 @@ g13_new (void **engine, const char *file_name, const char *home_dir) #if USE_DESCRIPTOR_PASSING err = assuan_pipe_connect - (g13->assuan_ctx, file_name ? file_name : _gpgme_get_g13_path (), + (g13->assuan_ctx, file_name ? file_name : _gpgme_get_default_g13_name (), argv, NULL, NULL, NULL, ASSUAN_PIPE_CONNECT_FDPASSING); #else err = assuan_pipe_connect - (g13->assuan_ctx, file_name ? file_name : _gpgme_get_g13_path (), + (g13->assuan_ctx, file_name ? file_name : _gpgme_get_default_g13_name (), argv, NULL, NULL, NULL, 0); #endif if (err) @@ -757,7 +757,7 @@ g13_io_event (void *engine, gpgme_event_io_t type, void *type_data) struct engine_ops _gpgme_engine_ops_g13 = { /* Static functions. */ - _gpgme_get_g13_path, + _gpgme_get_default_g13_name, NULL, g13_get_version, g13_get_req_version, diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 72d3ad14..3bc9f660 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -296,7 +296,7 @@ static char * gpg_get_version (const char *file_name) { return _gpgme_get_program_version (file_name ? file_name - : _gpgme_get_gpg_path ()); + : _gpgme_get_default_gpg_name ()); } @@ -1296,7 +1296,7 @@ start (engine_gpg_t gpg) if (!gpg) return gpg_error (GPG_ERR_INV_VALUE); - if (!gpg->file_name && !_gpgme_get_gpg_path ()) + if (!gpg->file_name && !_gpgme_get_default_gpg_name ()) return trace_gpg_error (GPG_ERR_INV_ENGINE); if (gpg->lc_ctype) @@ -1352,7 +1352,7 @@ start (engine_gpg_t gpg) fd_list[n].dup_to = -1; status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name : - _gpgme_get_gpg_path (), gpg->argv, + _gpgme_get_default_gpg_name (), gpg->argv, IOSPAWN_FLAG_ALLOW_SET_FG, fd_list, NULL, NULL, &pid); { @@ -2401,7 +2401,7 @@ gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode) struct engine_ops _gpgme_engine_ops_gpg = { /* Static functions. */ - _gpgme_get_gpg_path, + _gpgme_get_default_gpg_name, NULL, gpg_get_version, gpg_get_req_version, diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c index 3a1c1c19..1d457bb9 100644 --- a/src/engine-gpgconf.c +++ b/src/engine-gpgconf.c @@ -61,7 +61,7 @@ static char * gpgconf_get_version (const char *file_name) { return _gpgme_get_program_version (file_name ? file_name - : _gpgme_get_gpgconf_path ()); + : _gpgme_get_default_gpgconf_name ()); } @@ -100,7 +100,7 @@ gpgconf_new (void **engine, const char *file_name, const char *home_dir) return gpg_error_from_syserror (); gpgconf->file_name = strdup (file_name ? file_name - : _gpgme_get_gpgconf_path ()); + : _gpgme_get_default_gpgconf_name ()); if (!gpgconf->file_name) err = gpg_error_from_syserror (); @@ -923,7 +923,7 @@ _gpgme_conf_release (gpgme_conf_comp_t conf) struct engine_ops _gpgme_engine_ops_gpgconf = { /* Static functions. */ - _gpgme_get_gpgconf_path, + _gpgme_get_default_gpgconf_name, NULL, gpgconf_get_version, gpgconf_get_req_version, diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c index 391b632d..cee20e31 100644 --- a/src/engine-gpgsm.c +++ b/src/engine-gpgsm.c @@ -120,7 +120,7 @@ static char * gpgsm_get_version (const char *file_name) { return _gpgme_get_program_version (file_name ? file_name - : _gpgme_get_gpgsm_path ()); + : _gpgme_get_default_gpgsm_name ()); } @@ -340,7 +340,8 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir) #if USE_DESCRIPTOR_PASSING err = assuan_pipe_connect - (gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (), + (gpgsm->assuan_ctx, + file_name ? file_name : _gpgme_get_default_gpgsm_name (), argv, NULL, NULL, NULL, ASSUAN_PIPE_CONNECT_FDPASSING); #else { @@ -352,7 +353,8 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir) achild_fds[i] = (assuan_fd_t) child_fds[i]; err = assuan_pipe_connect - (gpgsm->assuan_ctx, file_name ? file_name : _gpgme_get_gpgsm_path (), + (gpgsm->assuan_ctx, + file_name ? file_name : _gpgme_get_default_gpgsm_name (), argv, achild_fds, NULL, NULL, 0); /* For now... */ @@ -1945,7 +1947,7 @@ gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags) struct engine_ops _gpgme_engine_ops_gpgsm = { /* Static functions. */ - _gpgme_get_gpgsm_path, + _gpgme_get_default_gpgsm_name, NULL, gpgsm_get_version, gpgsm_get_req_version, diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c index a0008e41..bd140f90 100644 --- a/src/engine-uiserver.c +++ b/src/engine-uiserver.c @@ -296,7 +296,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir) err = assuan_socket_connect (uiserver->assuan_ctx, file_name ? - file_name : _gpgme_get_uiserver_socket_path (), + file_name : _gpgme_get_default_uisrv_socket (), 0, ASSUAN_SOCKET_SERVER_FDPASSING); if (err) goto leave; @@ -1302,7 +1302,7 @@ uiserver_io_event (void *engine, gpgme_event_io_t type, void *type_data) struct engine_ops _gpgme_engine_ops_uiserver = { /* Static functions. */ - _gpgme_get_uiserver_socket_path, + _gpgme_get_default_uisrv_socket, NULL, uiserver_get_version, uiserver_get_req_version, diff --git a/src/posix-util.c b/src/posix-util.c index 478055ab..fd445070 100644 --- a/src/posix-util.c +++ b/src/posix-util.c @@ -28,6 +28,7 @@ #include #include "util.h" +#include "sys-util.h" const char * _gpgme_get_gpg_path (void) @@ -70,29 +71,6 @@ _gpgme_get_g13_path (void) } -const char * -_gpgme_get_uiserver_socket_path (void) -{ - static char *socket_path; - const char *homedir; - const char name[] = "S.uiserver"; - - if (socket_path) - return socket_path; - - homedir = _gpgme_get_default_homedir (); - if (! homedir) - return NULL; - - socket_path = malloc (strlen (homedir) + 1 + strlen (name) + 1); - if (! socket_path) - return NULL; - - strcpy (stpcpy (stpcpy (socket_path, homedir), "/"), name); - return socket_path; -} - - /* See w32-util.c */ int _gpgme_get_conf_int (const char *key, int *value) diff --git a/src/sys-util.h b/src/sys-util.h new file mode 100644 index 00000000..f6506d33 --- /dev/null +++ b/src/sys-util.h @@ -0,0 +1,29 @@ +/* sys-util.h - System utilities not generally used. + * Copyright (C) 2013 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 . + */ + +#ifndef SYS_UTIL_H +#define SYS_UTIL_H + +/*-- {posix,w32}-util.c --*/ +const char *_gpgme_get_gpg_path (void); +const char *_gpgme_get_gpgsm_path (void); +const char *_gpgme_get_gpgconf_path (void); +const char *_gpgme_get_g13_path (void); + +#endif /* SYS_UTIL_H */ diff --git a/src/util.h b/src/util.h index db8dc397..c4329801 100644 --- a/src/util.h +++ b/src/util.h @@ -47,18 +47,17 @@ /*-- {posix,w32}-util.c --*/ -const char *_gpgme_get_gpg_path (void); -const char *_gpgme_get_gpgsm_path (void); -const char *_gpgme_get_gpgconf_path (void); -const char *_gpgme_get_g13_path (void); -const char *_gpgme_get_uiserver_socket_path (void); - int _gpgme_get_conf_int (const char *key, int *value); void _gpgme_allow_set_foreground_window (pid_t pid); /*-- dirinfo.c --*/ const char *_gpgme_get_default_homedir (void); const char *_gpgme_get_default_agent_socket (void); +const char *_gpgme_get_default_gpg_name (void); +const char *_gpgme_get_default_gpgsm_name (void); +const char *_gpgme_get_default_g13_name (void); +const char *_gpgme_get_default_gpgconf_name (void); +const char *_gpgme_get_default_uisrv_socket (void); diff --git a/src/w32-util.c b/src/w32-util.c index 27dc5bcc..4cee1cb6 100644 --- a/src/w32-util.c +++ b/src/w32-util.c @@ -62,6 +62,7 @@ #include "ath.h" #include "sema.h" #include "debug.h" +#include "sys-util.h" #ifndef HAVE_W32CE_SYSTEM @@ -492,29 +493,6 @@ _gpgme_get_g13_path (void) } -const char * -_gpgme_get_uiserver_socket_path (void) -{ - static char *socket_path; - const char *homedir; - const char name[] = "S.uiserver"; - - if (socket_path) - return socket_path; - - homedir = _gpgme_get_default_homedir (); - if (! homedir) - return NULL; - - socket_path = malloc (strlen (homedir) + 1 + strlen (name) + 1); - if (! socket_path) - return NULL; - - strcpy (stpcpy (stpcpy (socket_path, homedir), "\\"), name); - return socket_path; -} - - const char * _gpgme_get_w32spawn_path (void) {