Skip to content

Commit

Permalink
Add debug_level/debug_file options
Browse files Browse the repository at this point in the history
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 neomutt#445
  • Loading branch information
sileht committed Mar 31, 2017
1 parent ee3fefe commit 48f03ff
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 40 deletions.
5 changes: 5 additions & 0 deletions globals.h
Expand Up @@ -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;
Expand Down
151 changes: 116 additions & 35 deletions init.c
Expand Up @@ -1927,10 +1927,15 @@ static void restore_default (struct option_t *p)
break;
case DT_PATH:
FREE((char **) p->data); /* __FREE_CHECKED__ */
if (p->init)
char* init = NULL;
if (mutt_strcmp (p->option, "debug_file") == 0 && debugfile_cmdline)
init = debugfile_cmdline;
else
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);
}
Expand All @@ -1952,7 +1957,10 @@ static void restore_default (struct option_t *p)
case DT_NUM:
case DT_SORT:
case DT_MAGIC:
*((short *) p->data) = p->init;
if (mutt_strcmp (p->option, "debug_level") == 0 && debuglevel_cmdline)
*((short *) p->data) = debuglevel_cmdline;
else
*((short *) p->data) = p->init;
break;
case DT_RX:
{
Expand Down Expand Up @@ -2106,6 +2114,73 @@ 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);
} else {
printf("lol: %s : %s\n", DebugFile, debugfilename);
mutt_any_key_to_continue(NULL);
}
}

/**
* 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.
Expand Down Expand Up @@ -2457,13 +2532,24 @@ 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); /* __FREE_CHECKED__ */

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)
{
Expand Down Expand Up @@ -2616,6 +2702,13 @@ 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;

Expand All @@ -2626,6 +2719,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)
Expand Down Expand Up @@ -3667,29 +3768,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) debugging at level %d\n",
PACKAGE_VERSION, MUTT_VERSION, debuglevel);
}
}
#endif

static int execute_commands (LIST *p)
{
BUFFER err, token;
Expand Down Expand Up @@ -3822,10 +3900,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... */
Expand Down Expand Up @@ -3956,13 +4044,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;


Expand Down
17 changes: 17 additions & 0 deletions init.h
Expand Up @@ -650,6 +650,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
Expand Down
3 changes: 3 additions & 0 deletions lib.c
Expand Up @@ -1023,8 +1023,11 @@ 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, ...)
{
Expand Down
3 changes: 3 additions & 0 deletions lib.h
Expand Up @@ -127,8 +127,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)
Expand Down
19 changes: 14 additions & 5 deletions main.c
Expand Up @@ -262,9 +262,9 @@ 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)
if ((i = getopt (argc, argv, "+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)
{
Expand Down Expand Up @@ -307,14 +307,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;

Expand All @@ -334,6 +334,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;
Expand Down

0 comments on commit 48f03ff

Please sign in to comment.