diff --git a/common/homedir.c b/common/homedir.c index 59b713526..6b40bb6bf 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -884,15 +884,60 @@ get_default_pinentry_name (int reset) } +/* If set, 'gnupg_module_name' returns modules from that build + * directory. */ +static char *gnupg_build_directory; + +/* For sanity checks. */ +static int gnupg_module_name_called; + + +/* Set NEWDIR as the new build directory. This will make + * 'gnupg_module_name' return modules from that build directory. Must + * be called before any invocation of 'gnupg_module_name', and must + * not be called twice. It can be used by test suites to make sure + * the components from the build directory are used instead of + * potentially outdated installed ones. */ +void +gnupg_set_builddir (const char *newdir) +{ + log_assert (! gnupg_module_name_called); + log_assert (! gnupg_build_directory); + gnupg_build_directory = xtrystrdup (newdir); +} + + +/* If no build directory has been configured, try to set it from the + * environment. We only do this in development builds to avoid + * increasing the set of influential environment variables and hence + * the attack surface of production builds. */ +static void +gnupg_set_builddir_from_env (void) +{ +#ifdef IS_DEVELOPMENT_VERSION + if (gnupg_build_directory) + return; + + gnupg_build_directory = getenv ("GNUPG_BUILDDIR"); +#endif +} + + /* Return the file name of a helper tool. WHICH is one of the GNUPG_MODULE_NAME_foo constants. */ const char * gnupg_module_name (int which) { -#define X(a,b) do { \ + gnupg_set_builddir_from_env (); + gnupg_module_name_called = 1; + +#define X(a,b,c) do { \ static char *name; \ if (!name) \ - name = xstrconcat (gnupg_ ## a (), DIRSEP_S b EXEEXT_S, NULL); \ + name = gnupg_build_directory \ + ? xstrconcat (gnupg_build_directory, \ + DIRSEP_S b DIRSEP_S c EXEEXT_S, NULL) \ + : xstrconcat (gnupg_ ## a (), DIRSEP_S c EXEEXT_S, NULL); \ return name; \ } while (0) @@ -902,7 +947,7 @@ gnupg_module_name (int which) #ifdef GNUPG_DEFAULT_AGENT return GNUPG_DEFAULT_AGENT; #else - X(bindir, "gpg-agent"); + X(bindir, "agent", "gpg-agent"); #endif case GNUPG_MODULE_NAME_PINENTRY: @@ -916,55 +961,57 @@ gnupg_module_name (int which) #ifdef GNUPG_DEFAULT_SCDAEMON return GNUPG_DEFAULT_SCDAEMON; #else - X(libexecdir, "scdaemon"); + X(libexecdir, "scd", "scdaemon"); #endif case GNUPG_MODULE_NAME_DIRMNGR: #ifdef GNUPG_DEFAULT_DIRMNGR return GNUPG_DEFAULT_DIRMNGR; #else - X(bindir, DIRMNGR_NAME); + X(bindir, "dirmngr", DIRMNGR_NAME); #endif case GNUPG_MODULE_NAME_PROTECT_TOOL: #ifdef GNUPG_DEFAULT_PROTECT_TOOL return GNUPG_DEFAULT_PROTECT_TOOL; #else - X(libexecdir, "gpg-protect-tool"); + X(libexecdir, "agent", "gpg-protect-tool"); #endif case GNUPG_MODULE_NAME_DIRMNGR_LDAP: #ifdef GNUPG_DEFAULT_DIRMNGR_LDAP return GNUPG_DEFAULT_DIRMNGR_LDAP; #else - X(libexecdir, "dirmngr_ldap"); + X(libexecdir, "dirmngr", "dirmngr_ldap"); #endif case GNUPG_MODULE_NAME_CHECK_PATTERN: - X(libexecdir, "gpg-check-pattern"); + X(libexecdir, "tools", "gpg-check-pattern"); case GNUPG_MODULE_NAME_GPGSM: - X(bindir, "gpgsm"); + X(bindir, "sm", "gpgsm"); case GNUPG_MODULE_NAME_GPG: #if USE_GPG2_HACK - X(bindir, GPG_NAME "2"); -#else - X(bindir, GPG_NAME); + if (! gnupg_build_directory) + X(bindir, "g10", GPG_NAME "2"); + else #endif + X(bindir, "g10", GPG_NAME); case GNUPG_MODULE_NAME_GPGV: #if USE_GPG2_HACK - X(bindir, GPG_NAME "v2"); -#else - X(bindir, GPG_NAME "v"); + if (! gnupg_build_directory) + X(bindir, "g10", GPG_NAME "v2"); + else #endif + X(bindir, "g10", GPG_NAME "v"); case GNUPG_MODULE_NAME_CONNECT_AGENT: - X(bindir, "gpg-connect-agent"); + X(bindir, "tools", "gpg-connect-agent"); case GNUPG_MODULE_NAME_GPGCONF: - X(bindir, "gpgconf"); + X(bindir, "tools", "gpgconf"); default: BUG (); diff --git a/common/util.h b/common/util.h index 2ff2bbcb3..f7a53e160 100644 --- a/common/util.h +++ b/common/util.h @@ -263,6 +263,7 @@ char *_gnupg_socketdir_internal (int skip_checks, unsigned *r_info); #define GNUPG_MODULE_NAME_GPGV 12 const char *gnupg_module_name (int which); void gnupg_module_name_flush_some (void); +void gnupg_set_builddir (const char *newdir); diff --git a/tests/openpgp/defs.scm b/tests/openpgp/defs.scm index 5249ca9da..ef81f9964 100644 --- a/tests/openpgp/defs.scm +++ b/tests/openpgp/defs.scm @@ -56,9 +56,7 @@ value))) (define tools - '((gpg "GPG" "g10/gpg") - (gpgv "GPGV" "g10/gpgv") - (gpg-agent "GPG_AGENT" "agent/gpg-agent") + '((gpgv "GPGV" "g10/gpgv") (gpg-connect-agent "GPG_CONNECT_AGENT" "tools/gpg-connect-agent") (gpgconf "GPGCONF" "tools/gpgconf") (gpg-preset-passphrase "GPG_PRESET_PASSPHRASE" @@ -67,7 +65,7 @@ (gpg-zip "GPGZIP" "tools/gpg-zip") (pinentry "PINENTRY" "tests/openpgp/fake-pinentry"))) -(define (tool which) +(define (tool-hardcoded which) (let ((t (assoc which tools)) (prefix (getenv "BIN_PREFIX"))) (getenv' (cadr t) @@ -75,6 +73,24 @@ (string-append (getenv "objdir") "/" (caddr t)) (string-append prefix "/" (basename (caddr t)))))))) +(define (gpg-conf . args) + (let ((s (call-popen `(,(tool-hardcoded 'gpgconf) ,@args) ""))) + (map (lambda (line) (string-split line #\:)) + (string-split-newlines s)))) +(define :gc:c:name car) +(define :gc:c:description cadr) +(define :gc:c:pgmname caddr) + +(setenv "GNUPG_BUILDDIR" (getenv "objdir") #t) +(define gpg-components (gpg-conf '--build-prefix (getenv "objdir") + '--list-components)) + +(define (tool which) + (case which + ((gpg gpg-agent scdaemon gpgsm dirmngr) + (:gc:c:pgmname (assoc (symbol->string which) gpg-components))) + (else + (tool-hardcoded which)))) (define (gpg-has-option? option) (string-contains? (call-popen `(,(tool 'gpg) --dump-options) "") diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 5f7912a03..d056f4f57 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -44,6 +44,7 @@ enum cmd_and_opt_values oNull = '0', oNoVerbose = 500, oHomedir, + oBuilddir, aListComponents, aCheckPrograms, @@ -98,6 +99,7 @@ static ARGPARSE_OPTS opts[] = { oRuntime, "runtime", 0, N_("activate changes at runtime, if possible") }, /* hidden options */ { oHomedir, "homedir", 2, "@" }, + { oBuilddir, "build-prefix", 2, "@" }, { oNull, "null", 0, "@" }, { oNoVerbose, "no-verbose", 0, "@"}, {0} @@ -483,6 +485,7 @@ main (int argc, char **argv) case oVerbose: opt.verbose++; break; case oNoVerbose: opt.verbose = 0; break; case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break; + case oBuilddir: gnupg_set_builddir (pargs.r.ret_str); break; case oNull: opt.null = 1; break; case aListDirs: