aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-10-02 10:44:13 +0000
committerWerner Koch <[email protected]>2020-10-02 10:45:52 +0000
commita298ba02ee76a9291ef5cec1a3564d8e254b9ca7 (patch)
tree7f0163260c417f9be219d57ccab8484af4243231
parentdoc: Typo fixes (diff)
downloadgnupg-a298ba02ee76a9291ef5cec1a3564d8e254b9ca7.tar.gz
gnupg-a298ba02ee76a9291ef5cec1a3564d8e254b9ca7.zip
gpgconf: New option --show-versions.
* tools/gpgconf.c: Include exechelp.h. New option --show-versions. (get_revision_from_blurb): New. (show_version_gnupg): New. (show_version_libgcrypt): New. (show_version_gpgrt): New. (show_versions_via_dirmngr): New. (show_versions): New. * dirmngr/dirmngr.c (main): New internal option --gpgconf-versions. (get_revision_from_blurb): New. (gpgconf_versions): New. -- This option should be helpful to gather information for debugging. Signed-off-by: Werner Koch <[email protected]> Backported-from-master: 357ad9ae29677c1676b56d2b81282e2f78ec8040
-rw-r--r--dirmngr/dirmngr.c66
-rw-r--r--tools/gpgconf.c171
2 files changed, 236 insertions, 1 deletions
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 3beaab843..db3014c11 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -100,6 +100,7 @@ enum cmd_and_opt_values {
aFlush,
aGPGConfList,
aGPGConfTest,
+ aGPGConfVersions,
oOptions,
oDebug,
@@ -174,6 +175,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_c (aFlush, "flush", N_("flush the cache")),
ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
+ ARGPARSE_c (aGPGConfVersions, "gpgconf-versions", "@"),
ARGPARSE_group (301, N_("@\nOptions:\n ")),
@@ -378,6 +380,8 @@ static ldap_server_t parse_ldapserver_file (const char* filename, int ienoent);
static fingerprint_list_t parse_ocsp_signer (const char *string);
static void netactivity_action (void);
static void handle_connections (assuan_fd_t listen_fd);
+static void gpgconf_versions (void);
+
/* NPth wrapper function definitions. */
ASSUAN_SYSTEM_NPTH_IMPL;
@@ -982,6 +986,7 @@ main (int argc, char **argv)
case aFetchCRL:
case aGPGConfList:
case aGPGConfTest:
+ case aGPGConfVersions:
cmd = pargs.r_opt;
break;
@@ -1543,6 +1548,9 @@ main (int argc, char **argv)
es_printf ("resolver-timeout:%lu:%u\n",
flags | GC_OPT_FLAG_DEFAULT, 0);
}
+ else if (cmd == aGPGConfVersions)
+ gpgconf_versions ();
+
cleanup ();
return !!rc;
}
@@ -2347,3 +2355,61 @@ dirmngr_get_current_socket_name (void)
else
return dirmngr_socket_name ();
}
+
+
+
+/* Parse the revision part from the extended version blurb. */
+static const char *
+get_revision_from_blurb (const char *blurb, int *r_len)
+{
+ const char *s = blurb? blurb : "";
+ int n;
+
+ for (; *s; s++)
+ if (*s == '\n' && s[1] == '(')
+ break;
+ if (s)
+ {
+ s += 2;
+ for (n=0; s[n] && s[n] != ' '; n++)
+ ;
+ }
+ else
+ {
+ s = "?";
+ n = 1;
+ }
+ *r_len = n;
+ return s;
+}
+
+
+/* Print versions of dirmngr and used libraries. This is used by
+ * "gpgconf --show-versions" so that there is no need to link gpgconf
+ * against all these libraries. This is an internal API and should
+ * not be relied upon. */
+static void
+gpgconf_versions (void)
+{
+ const char *s;
+ int n;
+
+ /* Unfortunately Npth has no way to get the version. */
+
+ s = get_revision_from_blurb (assuan_check_version ("\x01\x01"), &n);
+ es_fprintf (es_stdout, "* Libassuan %s (%.*s)\n\n",
+ assuan_check_version (NULL), n, s);
+
+ es_fprintf (es_stdout, "* KSBA %s \n\n",
+ ksba_check_version (NULL));
+
+#ifdef HTTP_USE_NTBTLS
+ s = get_revision_from_blurb (ntbtls_check_version ("\x01\x01"), &n);
+ es_fprintf (es_stdout, "* NTBTLS %s (%.*s)\n\n",
+ ntbtls_check_version (NULL), n, s);
+#elif HTTP_USE_GNUTLS
+ es_fprintf (es_stdout, "* GNUTLS %s\n\n",
+ gnutls_check_version (NULL));
+#endif
+
+}
diff --git a/tools/gpgconf.c b/tools/gpgconf.c
index 945d0e528..3d791faf2 100644
--- a/tools/gpgconf.c
+++ b/tools/gpgconf.c
@@ -31,6 +31,7 @@
#include "../common/sysutils.h"
#include "../common/init.h"
#include "../common/status.h"
+#include "../common/exechelp.h"
/* Constants to identify the commands and options. */
@@ -65,7 +66,8 @@ enum cmd_and_opt_values
aCreateSocketDir,
aRemoveSocketDir,
aApplyProfile,
- aReload
+ aReload,
+ aShowVersions
};
@@ -96,6 +98,8 @@ static ARGPARSE_OPTS opts[] =
{ aKill, "kill", 256, N_("kill a given component")},
{ aCreateSocketDir, "create-socketdir", 256, "@"},
{ aRemoveSocketDir, "remove-socketdir", 256, "@"},
+ ARGPARSE_c (aShowVersions, "show-versions", "@"),
+
{ 301, NULL, 0, N_("@\nOptions:\n ") },
@@ -120,6 +124,9 @@ static ARGPARSE_OPTS opts[] =
* this is NULL. */
static estream_t statusfp;
+static void show_versions (estream_t fp);
+
+
/* Print usage information and provide strings for help. */
static const char *
@@ -594,6 +601,7 @@ main (int argc, char **argv)
case aKill:
case aCreateSocketDir:
case aRemoveSocketDir:
+ case aShowVersions:
cmd = pargs.r_opt;
break;
@@ -897,6 +905,13 @@ main (int argc, char **argv)
}
break;
+ case aShowVersions:
+ {
+ get_outfp (&outfp);
+ show_versions (outfp);
+ }
+ break;
+
}
if (outfp != es_stdout)
@@ -923,3 +938,157 @@ gpgconf_failure (gpg_error_t err)
gpg_err_code (err) == GPG_ERR_USER_2? GPG_ERR_EINVAL : err);
exit (gpg_err_code (err) == GPG_ERR_USER_2? 2 : 1);
}
+
+
+
+/* Parse the revision part from the extended version blurb. */
+static const char *
+get_revision_from_blurb (const char *blurb, int *r_len)
+{
+ const char *s = blurb? blurb : "";
+ int n;
+
+ for (; *s; s++)
+ if (*s == '\n' && s[1] == '(')
+ break;
+ if (s)
+ {
+ s += 2;
+ for (n=0; s[n] && s[n] != ' '; n++)
+ ;
+ }
+ else
+ {
+ s = "?";
+ n = 1;
+ }
+ *r_len = n;
+ return s;
+}
+
+
+static void
+show_version_gnupg (estream_t fp)
+{
+ es_fprintf (fp, "* GnuPG %s (%s)\n%s\n",
+ strusage (13), BUILD_REVISION, strusage (17));
+#ifdef HAVE_W32_SYSTEM
+ {
+ OSVERSIONINFO osvi = { sizeof (osvi) };
+
+ GetVersionEx (&osvi);
+ es_fprintf (fp, "Windows %lu.%lu build %lu%s%s%s\n",
+ (unsigned long)osvi.dwMajorVersion,
+ (unsigned long)osvi.dwMinorVersion,
+ (unsigned long)osvi.dwBuildNumber,
+ *osvi.szCSDVersion? " (":"",
+ osvi.szCSDVersion,
+ *osvi.szCSDVersion? ")":""
+ );
+ }
+#endif /*HAVE_W32_SYSTEM*/
+}
+
+
+static void
+show_version_libgcrypt (estream_t fp)
+{
+ const char *s;
+ int n;
+
+ s = get_revision_from_blurb (gcry_check_version ("\x01\x01"), &n);
+ es_fprintf (fp, "* Libgcrypt %s (%.*s)\n",
+ gcry_check_version (NULL), n, s);
+#if GCRYPT_VERSION_NUMBER >= 0x010800
+ s = gcry_get_config (0, NULL);
+ if (s)
+ es_fputs (s, fp);
+#endif
+}
+
+
+static void
+show_version_gpgrt (estream_t fp)
+{
+ const char *s;
+ int n;
+
+ s = get_revision_from_blurb (gpg_error_check_version ("\x01\x01"), &n);
+ es_fprintf (fp, "* GpgRT %s (%.*s)\n",
+ gpg_error_check_version (NULL), n, s);
+}
+
+
+/* Printing version information for other libraries is problematic
+ * because we don't want to link gpgconf to all these libraries. The
+ * best solution is delegating this to dirmngr which uses libassuan,
+ * libksba, libnpth and ntbtls anyway. */
+static void
+show_versions_via_dirmngr (estream_t fp)
+{
+ gpg_error_t err;
+ const char *pgmname;
+ const char *argv[2];
+ estream_t outfp;
+ pid_t pid;
+ char *line = NULL;
+ size_t line_len = 0;
+ ssize_t length;
+ int exitcode;
+
+ pgmname = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
+ argv[0] = "--gpgconf-versions";
+ argv[1] = NULL;
+ err = gnupg_spawn_process (pgmname, argv, NULL, NULL, 0,
+ NULL, &outfp, NULL, &pid);
+ if (err)
+ {
+ log_error ("error spawning %s: %s", pgmname, gpg_strerror (err));
+ es_fprintf (fp, "[error: can't get further info]\n");
+ return;
+ }
+
+ while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
+ {
+ /* Strip newline and carriage return, if present. */
+ while (length > 0
+ && (line[length - 1] == '\n' || line[length - 1] == '\r'))
+ line[--length] = '\0';
+ es_fprintf (fp, "%s\n", line);
+ }
+ if (length < 0 || es_ferror (outfp))
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error reading from %s: %s\n", pgmname, gpg_strerror (err));
+ }
+ if (es_fclose (outfp))
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error closing output stream of %s: %s\n",
+ pgmname, gpg_strerror (err));
+ }
+
+ err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
+ if (err)
+ {
+ log_error ("running %s failed (exitcode=%d): %s\n",
+ pgmname, exitcode, gpg_strerror (err));
+ es_fprintf (fp, "[error: can't get further info]\n");
+ }
+ gnupg_release_process (pid);
+ xfree (line);
+}
+
+
+/* Show all kind of version information. */
+static void
+show_versions (estream_t fp)
+{
+ show_version_gnupg (fp);
+ es_fputc ('\n', fp);
+ show_version_libgcrypt (fp);
+ es_fputc ('\n', fp);
+ show_version_gpgrt (fp);
+ es_fputc ('\n', fp);
+ show_versions_via_dirmngr (fp);
+}