]> granicus.if.org Git - neomutt/commitdiff
Add debug_level/debug_file options 448/head
authorMehdi Abaakouk <sileht@sileht.net>
Wed, 1 Mar 2017 22:02:10 +0000 (23:02 +0100)
committerRichard Russon <rich@flatcap.org>
Fri, 12 May 2017 13:05:59 +0000 (14:05 +0100)
This change allows to change debug_level and debug_file on the fly.

It adds the -l mutt arguments to pass the logging file on startup.

debug options passed as mutt arguments always override the configuration
file.

Closes #445

globals.h
init.c
init.h
lib.c
lib.h
main.c

index 8c1f7d7e58482a6133cb993c69aea24b2e866697..9d250336ecee2ef004a1e73306273d0d62c073ee 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -233,6 +233,11 @@ WHERE short NewsPollTimeout;
 WHERE short NntpContext;
 #endif
 
+#ifdef DEBUG
+WHERE short DebugLevel;
+WHERE char *DebugFile;
+#endif
+
 WHERE short ConnectTimeout;
 WHERE short HistSize;
 WHERE short MenuContext;
diff --git a/init.c b/init.c
index 65fe5d792cafab376db77ecdfd07c2d98bb64bcc..8fe1dc5905c5ba6d4815dedefb9a7a20bbc6caf5 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1913,10 +1913,17 @@ static void restore_default(struct option_t *p)
       break;
     case DT_PATH:
       FREE((char **) p->data);
-      if (p->init)
+      char *init = NULL;
+#ifdef DEBUG
+      if (mutt_strcmp(p->option, "debug_file") == 0 && debugfile_cmdline)
+        init = debugfile_cmdline;
+      else
+#endif
+        init = (char *) p->init;
+      if (init)
       {
         char path[_POSIX_PATH_MAX];
-        strfcpy(path, (char *) p->init, sizeof(path));
+        strfcpy(path, init, sizeof(path));
         mutt_expand_path(path, sizeof(path));
         *((char **) p->data) = safe_strdup(path);
       }
@@ -1938,7 +1945,12 @@ static void restore_default(struct option_t *p)
     case DT_NUM:
     case DT_SORT:
     case DT_MAGIC:
-      *((short *) p->data) = p->init;
+#ifdef DEBUG
+      if (mutt_strcmp(p->option, "debug_level") == 0 && debuglevel_cmdline)
+        *((short *) p->data) = debuglevel_cmdline;
+      else
+#endif
+        *((short *) p->data) = p->init;
       break;
     case DT_RX:
     {
@@ -2100,6 +2112,69 @@ char **mutt_envlist(void)
   return envlist;
 }
 
+#ifdef DEBUG
+/**
+ * start_debug - prepare the debugging file
+ *
+ * @return nothing
+ *
+ * This method prepares and opens a new debug file for mutt_debug.
+ */
+static void start_debug(void)
+{
+  int i;
+  char buf[_POSIX_PATH_MAX];
+
+  /* rotate the old debug logs */
+  for (i = 3; i >= 0; i--)
+  {
+    snprintf(debugfilename, sizeof(debugfilename), "%s%d", DebugFile, i);
+    snprintf(buf, sizeof(buf), "%s%d", DebugFile, i + 1);
+    rename(debugfilename, buf);
+  }
+
+  if ((debugfile = safe_fopen(debugfilename, "w")) != NULL)
+  {
+    setbuf(debugfile, NULL); /* don't buffer the debugging output! */
+    mutt_debug(1, "NeoMutt/%s (%s) debugging at level %d\n", PACKAGE_VERSION,
+               MUTT_VERSION, debuglevel);
+  }
+}
+
+/**
+ * restart_debug - reload the debugging configuration
+ *
+ * @return nothing
+ *
+ * This method closes the old debug file is debug was enabled,
+ * then reconfigure the debugging system from the configuration options
+ * and start a new debug file if debug is enabled
+ */
+static void restart_debug(void)
+{
+  bool disable_debug = (debuglevel > 0 && DebugLevel == 0);
+  bool enable_debug = (debuglevel == 0 && DebugLevel > 0);
+  bool file_changed =
+      ((mutt_strlen(debugfilename) - 1) != mutt_strlen(DebugFile) ||
+       mutt_strncmp(debugfilename, DebugFile, mutt_strlen(debugfilename) - 1));
+
+  if (disable_debug || file_changed)
+  {
+    mutt_debug(1, "NeoMutt/%s (%s) stop debugging\n", PACKAGE_VERSION, MUTT_VERSION);
+    safe_fclose(&debugfile);
+  }
+
+  if (!enable_debug && !disable_debug && debuglevel != DebugLevel)
+    mutt_debug(1, "NeoMutt/%s (%s) debugging at level %d\n", PACKAGE_VERSION,
+               MUTT_VERSION, DebugLevel);
+
+  debuglevel = DebugLevel;
+
+  if (enable_debug || (file_changed && debuglevel > 0))
+    start_debug();
+}
+#endif
+
 /* Helper function for parse_setenv().
  * It's broken out because some other parts of mutt (filter.c) need
  * to set/overwrite environment variables in envlist before execing.
@@ -2456,6 +2531,14 @@ static int parse_set(BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
         }
         else if (DTYPE(MuttVars[idx].type) == DT_PATH)
         {
+#ifdef DEBUG
+          if (mutt_strcmp(MuttVars[idx].option, "debug_file") == 0 && debugfile_cmdline)
+          {
+            mutt_message(_("set debug_file ignored, it have been overridden "
+                           "with cmdline"));
+            break;
+          }
+#endif
           /* MuttVars[idx].data is already 'char**' (or some 'void**') or...
            * so cast to 'void*' is okay */
           FREE((void *) MuttVars[idx].data);
@@ -2463,6 +2546,10 @@ static int parse_set(BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
           strfcpy(scratch, tmp->data, sizeof(scratch));
           mutt_expand_path(scratch, sizeof(scratch));
           *((char **) MuttVars[idx].data) = safe_strdup(scratch);
+#ifdef DEBUG
+          if (mutt_strcmp(MuttVars[idx].option, "debug_file") == 0)
+            restart_debug();
+#endif
         }
         else if (DTYPE(MuttVars[idx].type) == DT_STR)
         {
@@ -2620,6 +2707,14 @@ static int parse_set(BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
         r = -1;
         break;
       }
+#ifdef DEBUG
+      else if (mutt_strcmp(MuttVars[idx].option, "debug_level") == 0 && debuglevel_cmdline)
+      {
+        mutt_message(
+            _("set debug_level ignored, it have been overridden with cmdline"));
+        break;
+      }
+#endif
       else
         *ptr = val;
 
@@ -2630,6 +2725,14 @@ static int parse_set(BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
           *ptr = 0;
         mutt_init_history();
       }
+#ifdef DEBUG
+      else if (mutt_strcmp(MuttVars[idx].option, "debug_level") == 0)
+      {
+        if (*ptr < 0)
+          *ptr = 0;
+        restart_debug();
+      }
+#endif
       else if (mutt_strcmp(MuttVars[idx].option, "pager_index_lines") == 0)
       {
         if (*ptr < 0)
@@ -3700,29 +3803,6 @@ int mutt_getvaluebyname(const char *name, const struct mapping_t *map)
   return -1;
 }
 
-#ifdef DEBUG
-static void start_debug(void)
-{
-  int i;
-  char buf[_POSIX_PATH_MAX];
-  char buf2[_POSIX_PATH_MAX];
-
-  /* rotate the old debug logs */
-  for (i = 3; i >= 0; i--)
-  {
-    snprintf(buf, sizeof(buf), "%s/.muttdebug%d", NONULL(Homedir), i);
-    snprintf(buf2, sizeof(buf2), "%s/.muttdebug%d", NONULL(Homedir), i + 1);
-    rename(buf, buf2);
-  }
-  if ((debugfile = safe_fopen(buf, "w")) != NULL)
-  {
-    setbuf(debugfile, NULL); /* don't buffer the debugging output! */
-    mutt_debug(1, "NeoMutt %s%s (%s) debugging at level %d\n", PACKAGE_VERSION,
-               GitVer, MUTT_VERSION, debuglevel);
-  }
-}
-#endif
-
 static int execute_commands(LIST *p)
 {
   BUFFER err, token;
@@ -3856,10 +3936,20 @@ void mutt_init(int skip_sys_rc, LIST *commands)
     Shell = safe_strdup((p = getenv("SHELL")) ? p : "/bin/sh");
   }
 
+  /* Set standard defaults */
+  for (i = 0; MuttVars[i].option; i++)
+  {
+    set_default(&MuttVars[i]);
+    restore_default(&MuttVars[i]);
+  }
+
 #ifdef DEBUG
-  /* Start up debugging mode if requested */
-  if (debuglevel > 0)
+  /* Start up debugging mode if requested from cmdline */
+  if (debuglevel_cmdline > 0)
+  {
+    debuglevel = debuglevel_cmdline;
     start_debug();
+  }
 #endif
 
   /* And about the host... */
@@ -3988,13 +4078,6 @@ void mutt_init(int skip_sys_rc, LIST *commands)
 
   Matches = safe_calloc(Matches_listsize, sizeof(char *));
 
-  /* Set standard defaults */
-  for (i = 0; MuttVars[i].option; i++)
-  {
-    set_default(&MuttVars[i]);
-    restore_default(&MuttVars[i]);
-  }
-
   CurrentMenu = MENU_MAIN;
 
 
diff --git a/init.h b/init.h
index aba95166918ac3e42e47554290e4aa73b47a63b1..d24d217da5a548c4c67fd38286297fc674a3744c 100644 (file)
--- a/init.h
+++ b/init.h
@@ -651,6 +651,23 @@ struct option_t MuttVars[] = {
   ** rest of the string are expanded in the \fIC\fP locale (that is in US
   ** English).
   */
+#ifdef DEBUG
+  { "debug_level", DT_NUM, R_NONE, UL &DebugLevel, 0 },
+  /*
+  ** .pp
+  ** The debug level. Note: to debug the early startup process (before the
+  ** configuration is loaded), ``-d'' mutt argument must be used.
+  ** debug_level/debug_file are ignored until it's read from the configuration
+  ** file.
+  */
+  { "debug_file", DT_PATH, R_NONE, UL &DebugFile, UL "~/.muttdebug" },
+  /*
+  ** .pp
+  ** The location prefix of the debug file, 0 is append to the debug file
+  ** Old debug files are renamed with the prefix 1, 2, 3 and 4.
+  ** See ``debug_level'' for more detail.
+  */
+#endif
   { "default_hook",     DT_STR,  R_NONE, UL &DefaultHook, UL "~f %s !~P | (~P ~C %s)" },
   /*
   ** .pp
diff --git a/lib.c b/lib.c
index b7bcf87665bf3280aeb0cf4d1553d915dcf31f4f..e35663af3b5ee99a1be3ebdf16eca1e858a6b6f1 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -1015,8 +1015,11 @@ const char *mutt_strsysexit(int e)
 }
 
 #ifdef DEBUG
+char debugfilename[_POSIX_PATH_MAX];
 FILE *debugfile;
 int debuglevel;
+char *debugfile_cmdline = NULL;
+int debuglevel_cmdline;
 
 void mutt_debug(int level, const char *fmt, ...)
 {
diff --git a/lib.h b/lib.h
index 6a6fa2ca21f0380a839c580f165c3cb05a8c1c31..3b8c0627570170e1b6c8505de2f84393426227d7 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -114,8 +114,11 @@ void mutt_exit(int);
 
 
 #ifdef DEBUG
+extern char debugfilename[_POSIX_PATH_MAX];
 extern FILE *debugfile;
 extern int debuglevel;
+extern char *debugfile_cmdline;
+extern int debuglevel_cmdline;
 void mutt_debug(int level, const char *fmt, ...);
 #else
 #define mutt_debug(...) do { } while (0)
diff --git a/main.c b/main.c
index 23eff35203c2f4e6d10509edcef5260b6647e45b..761ef2ee3775816d770858b36d2633b5efa2b02b 100644 (file)
--- a/main.c
+++ b/main.c
@@ -252,9 +252,10 @@ int main(int argc, char **argv, char **environ)
 
 #ifdef USE_NNTP
     if ((i = getopt(argc, argv,
-                    "+A:a:Bb:F:f:c:Dd:Ee:g:GH:s:i:hm:npQ:RSvxyzZ")) != EOF)
+                    "+A:a:Bb:F:f:c:Dd:l:Ee:g:GH:s:i:hm:npQ:RSvxyzZ")) != EOF)
 #else
-    if ((i = getopt(argc, argv, "+A:a:Bb:F:f:c:Dd:Ee:H:s:i:hm:npQ:RSvxyzZ")) != EOF)
+    if ((i = getopt(argc, argv,
+                    "+A:a:Bb:F:f:c:Dd:l:Ee:H:s:i:hm:npQ:RSvxyzZ")) != EOF)
 #endif
       switch (i)
       {
@@ -297,14 +298,14 @@ int main(int argc, char **argv, char **environ)
 
         case 'd':
 #ifdef DEBUG
-          if (mutt_atoi(optarg, &debuglevel) < 0 || debuglevel <= 0)
+          if (mutt_atoi(optarg, &debuglevel_cmdline) < 0 || debuglevel_cmdline <= 0)
           {
             fprintf(stderr, _("Error: value '%s' is invalid for -d.\n"), optarg);
             return 1;
           }
-          printf(_("Debugging at level %d.\n"), debuglevel);
+          printf(_("Debugging at level %d.\n"), debuglevel_cmdline);
 #else
-          printf(_("DEBUG was not defined during compilation.  Ignored.\n"));
+          printf(_("DEBUG was not defined during compilation. -d Ignored.\n"));
 #endif
           break;
 
@@ -324,6 +325,15 @@ int main(int argc, char **argv, char **environ)
           includeFile = optarg;
           break;
 
+        case 'l':
+#ifdef DEBUG
+          debugfile_cmdline = optarg;
+          printf(_("Debugging at file %s.\n"), debugfile_cmdline);
+#else
+          printf(_("DEBUG was not defined during compilation. -l Ignored.\n"));
+#endif
+          break;
+
         case 'm':
           /* should take precedence over .muttrc setting, so save it for later */
           newMagic = optarg;