GCK is a library for accessing PKCS#11 modules like smart cards, in a
(G)object oriented way.
+
+
+DEBUG TRACING
+==============
+
+The Gcr and Gck libraries contain statements which help debug flow
+and logic. In many cases these help you track down problems.
+
+Use the environment variable GCR_DEBUG='all' or GCR_HELP='xxx' to
+display either all messages or a specific category of debug messages.
+To figure out what you can use in place of the 'xxx' category above,
+use GCR_DEBUG='help' and you'll see a list of all the messages.
+
+Example to display all debug messages:
+
+ $ GCR_DEBUG=all gcr-viewer /path/to/certificate.crt
+ (gcr-viewer:9418): Gcr-DEBUG: gcr_pkcs11_initialize_async: starting initialize of registered modules
+ ...
+
+Example to display the various debug categories:
+
+ $ GCR_DEBUG=help gcr-viewer /path/to/certificate.crt
+ Supported debug values: library certificate-chain parse gnupg trust import key prompt all help
+
+Example to display debug messages for a specific category:
+
+ $ GCR_DEBUG=library gcr-viewer /path/to/certificate.crt
+ (gcr-viewer:9503): Gcr-DEBUG: gcr_pkcs11_initialize_async: starting initialize of registered modules
+ ...
+
+If you wish to permanently enable certain debug messages, include compiler
+directives like this when configuring this library:
+
+ $ CFLAGS='-DGCR_DEBUG=library' ./configure ...
+
+For the Gck debug messages simply replace 'GCR_DEBUG' with 'GCK_DEBUG'
+in the above examples.
}
static void
+on_gck_log_debug (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ GString *gstring;
+ const gchar *progname;
+
+ gstring = g_string_new (NULL);
+
+ progname = g_get_prgname ();
+ g_string_append_printf (gstring, "(%s:%lu): %s-DEBUG: %s\n",
+ progname ? progname : "process",
+ (gulong)getpid (), log_domain,
+ message ? message : "(NULL) message");
+
+ write (1, gstring->str, gstring->len);
+ g_string_free (gstring, TRUE);
+}
+
+static void
initialize_debug_flags (void)
{
+ const gchar *messages_env;
+ const gchar *debug_env;
+
if (g_once_init_enter (&initialized_flags)) {
- _gck_debug_set_flags (g_getenv ("GCK_DEBUG"));
+ messages_env = g_getenv ("G_MESSAGES_DEBUG");
+ debug_env = g_getenv ("GCK_DEBUG");
+#ifdef GCK_DEBUG
+ if (debug_env == NULL)
+ debug_env = G_STRINGIFY (GCK_DEBUG);
+#endif
+
+ /*
+ * If the caller is selectively asking for certain debug
+ * messages with the GCK_DEBUG environment variable, then
+ * we install our own output handler and only print those
+ * messages. This happens irrespective of G_MESSAGES_DEBUG
+ */
+ if (messages_env == NULL && debug_env != NULL)
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ on_gck_log_debug, NULL);
+
+ /*
+ * If the caller is using G_MESSAGES_DEBUG then we enable
+ * all our debug messages, and let Glib filter which ones
+ * to display.
+ */
+ if (messages_env != NULL && debug_env == NULL)
+ debug_env = "all";
+
+ _gck_debug_set_flags (debug_env);
+
g_once_init_leave (&initialized_flags, 1);
}
}
const gchar *format,
...)
{
- gchar *message;
va_list args;
if G_UNLIKELY (!initialized_flags)
initialize_debug_flags ();
- va_start (args, format);
- message = g_strdup_vprintf (format, args);
- va_end (args);
-
- if (flag & current_flags)
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", message);
-
- g_free (message);
+ if (flag & current_flags) {
+ va_start (args, format);
+ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args);
+ va_end (args);
+ }
}
#else /* !WITH_DEBUG */
return (flag & current_flags) != 0;
}
+static void
+on_gcr_log_debug (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ GString *gstring;
+ const gchar *progname;
+
+ gstring = g_string_new (NULL);
+
+ progname = g_get_prgname ();
+ g_string_append_printf (gstring, "(%s:%lu): %s-DEBUG: %s\n",
+ progname ? progname : "process",
+ (gulong)getpid (), log_domain,
+ message ? message : "(NULL) message");
+
+ write (1, gstring->str, gstring->len);
+ g_string_free (gstring, TRUE);
+}
+
void
_gcr_debug_message (GcrDebugFlags flag, const gchar *format, ...)
{
static gsize initialized_flags = 0;
- gchar *message;
+ const gchar *messages_env;
+ const gchar *debug_env;
va_list args;
if (g_once_init_enter (&initialized_flags)) {
- _gcr_debug_set_flags (g_getenv ("GCR_DEBUG"));
+ messages_env = g_getenv ("G_MESSAGES_DEBUG");
+ debug_env = g_getenv ("GCR_DEBUG");
+#ifdef GCR_DEBUG
+ if (debug_env == NULL)
+ debug_env = G_STRINGIFY (GCR_DEBUG);
+#endif
+
+ /*
+ * If the caller is selectively asking for certain debug
+ * messages with the GCR_DEBUG environment variable, then
+ * we install our own output handler and only print those
+ * messages. This happens irrespective of G_MESSAGES_DEBUG
+ */
+ if (messages_env == NULL && debug_env != NULL)
+ g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ on_gcr_log_debug, NULL);
+
+ /*
+ * If the caller is using G_MESSAGES_DEBUG then we enable
+ * all our debug messages, and let Glib filter which ones
+ * to display.
+ */
+ if (messages_env != NULL && debug_env == NULL)
+ debug_env = "all";
+
+ _gcr_debug_set_flags (debug_env);
+
g_once_init_leave (&initialized_flags, 1);
}
- va_start (args, format);
- message = g_strdup_vprintf (format, args);
- va_end (args);
-
- if (flag & current_flags)
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s", message);
-
- g_free (message);
+ if (flag & current_flags) {
+ va_start (args, format);
+ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args);
+ va_end (args);
+ }
}
#else /* !WITH_DEBUG */