summaryrefslogtreecommitdiff
path: root/libmailutils/gdebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/gdebug.c')
-rw-r--r--libmailutils/gdebug.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/libmailutils/gdebug.c b/libmailutils/gdebug.c
new file mode 100644
index 000000000..3d1a54c38
--- /dev/null
+++ b/libmailutils/gdebug.c
@@ -0,0 +1,263 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
+
+ This library 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 3 of the License, or (at your option) any later version.
+
+ This library 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 library; if not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <mailutils/cctype.h>
+#include <mailutils/assoc.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/argcv.h>
+#include <mailutils/debug.h>
+#include <mailutils/cfg.h>
+#include <mailutils/nls.h>
+
+int mu_debug_line_info = 0;
+
+struct debug_level
+{
+ unsigned level;
+};
+
+static mu_assoc_t debug_table;
+
+mu_log_level_t
+mu_global_debug_level (const char *object_name)
+{
+ struct debug_level *p = mu_assoc_ref (debug_table, object_name);
+ if (p)
+ return p->level;
+ return 0;
+}
+
+int
+mu_global_debug_set_level (const char *object_name, mu_log_level_t level)
+{
+ int rc;
+ struct debug_level *dbg;
+
+ if (!debug_table)
+ {
+ rc = mu_assoc_create (&debug_table, sizeof(struct debug_level), 0);
+ if (rc)
+ return rc;
+ }
+
+ rc = mu_assoc_ref_install (debug_table, object_name, (void**) &dbg);
+ if (rc == 0 || rc == MU_ERR_EXISTS)
+ dbg->level = level;
+ return rc;
+}
+
+int
+mu_global_debug_clear_level (const char *object_name)
+{
+ int rc = 0;
+
+ if (!object_name)
+ mu_assoc_clear (debug_table);
+ else
+ rc = mu_assoc_remove (debug_table, object_name);
+ return rc;
+}
+
+int
+decode_debug_level (const char *p, int *lev)
+{
+ if (strcmp (p, "error") == 0)
+ *lev = MU_DEBUG_ERROR;
+ else if (strncmp (p, "trace", 5) == 0 && mu_isdigit (p[5]) && p[6] == 0)
+ *lev = MU_DEBUG_TRACE0 + atoi (p + 5);
+ else if (strcmp (p, "proto") == 0)
+ *lev = MU_DEBUG_PROT;
+ else
+ return 1;
+ return 0;
+}
+
+int
+mu_debug_level_from_string (const char *string, mu_log_level_t *plev,
+ mu_debug_t debug)
+{
+ char *q;
+ unsigned level = MU_DEBUG_INHERIT;
+
+ if (mu_isdigit (*string))
+ {
+ level = strtoul (string, &q, 0);
+ if (*q)
+ {
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR,
+ _("invalid debugging specification `%s': "
+ "expected levels or number after `=', "
+ "but found `%s'"),
+ string, string);
+ return MU_ERR_FAILURE;
+ }
+ }
+ else
+ {
+ char *p = strdup (string);
+ size_t len = strlen (p);
+ if (len > 0 && p[len-1] == '\n')
+ p[len-1] = 0;
+ for (q = strtok (p, ","); q; q = strtok (NULL, ","))
+ {
+ int flag;
+ int revert = 0;
+ int upto = 0;
+
+ if (*q == '!')
+ {
+ q++;
+ revert = 1;
+ }
+ if (*q == '<')
+ {
+ q++;
+ upto = 1;
+ }
+
+ if (decode_debug_level (q, &flag))
+ mu_cfg_format_error (debug, MU_DEBUG_ERROR,
+ _("invalid debugging level `%s'"),
+ q);
+ else if (revert)
+ {
+ if (upto)
+ level &= ~MU_DEBUG_LEVEL_UPTO (flag);
+ else
+ level &= ~MU_DEBUG_LEVEL_MASK (flag);
+ }
+ else
+ {
+ if (upto)
+ level |= MU_DEBUG_LEVEL_UPTO (flag);
+ else
+ level |= MU_DEBUG_LEVEL_MASK (flag);
+ }
+ }
+ free (p);
+ }
+ *plev = level;
+ return 0;
+}
+
+int
+mu_global_debug_from_string (const char *string, const char *errpfx)
+{
+ int rc;
+ int argc;
+ char **argv;
+ int i;
+
+ rc = mu_argcv_get (string, ";", NULL, &argc, &argv);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < argc; i++)
+ {
+ char *p;
+ mu_log_level_t level = MU_DEBUG_INHERIT;
+ char *object_name = argv[i];
+
+ for (p = object_name; *p && *p != '='; p++)
+ ;
+
+ if (*p == '=')
+ {
+ /* FIXME: Use mu_debug_level_from_string */
+ char *q;
+
+ *p++ = 0;
+ if (mu_isdigit (*p))
+ {
+ level = strtoul (p, &q, 0);
+ if (*q)
+ {
+ mu_error ("%s: invalid debugging specification `%s': "
+ "expected levels or number after `=', "
+ "but found `%s'",
+ errpfx, argv[i], p);
+ break;
+ }
+ }
+ else
+ {
+ char *q;
+ for (q = strtok (p, ","); q; q = strtok (NULL, ","))
+ {
+ int flag;
+ int revert = 0;
+ int upto = 0;
+
+ if (*q == '!')
+ {
+ q++;
+ revert = 1;
+ }
+ if (*q == '<')
+ {
+ q++;
+ upto = 1;
+ }
+
+ if (decode_debug_level (q, &flag))
+ mu_error ("%s: invalid debugging level `%s'",
+ errpfx, q);
+ else if (revert)
+ {
+ if (upto)
+ level &= ~MU_DEBUG_LEVEL_UPTO (flag);
+ else
+ level &= ~MU_DEBUG_LEVEL_MASK (flag);
+ }
+ else
+ {
+ if (upto)
+ level |= MU_DEBUG_LEVEL_UPTO (flag);
+ else
+ level |= MU_DEBUG_LEVEL_MASK (flag);
+ }
+ }
+ }
+ }
+ else
+ level |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_PROT);
+
+ if (p[-1] == ':')
+ {
+ p[-1] = 0;
+ level &= ~MU_DEBUG_INHERIT;
+ }
+
+ mu_global_debug_set_level (object_name, level);
+ }
+
+ mu_argcv_free (argc, argv);
+ return 0;
+}
+
+

Return to:

Send suggestions and report system problems to the System administrator.