NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
mutt_logging.c File Reference

NeoMutt Logging. More...

#include "config.h"
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt_logging.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "options.h"
+ Include dependency graph for mutt_logging.c:

Go to the source code of this file.

Macros

#define S_TO_MS   1000L
 

Functions

static void error_pause (void)
 Wait for an error message to be read. More...
 
static const char * rotate_logs (const char *file, int count)
 Rotate a set of numbered files. More...
 
void mutt_clear_error (void)
 Clear the message line (bottom line of screen) More...
 
int log_disp_curses (time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
 Display a log line in the message line - Implements log_dispatcher_t. More...
 
void mutt_log_prep (void)
 Prepare to log. More...
 
void mutt_log_stop (void)
 Close the log file. More...
 
int mutt_log_set_file (const char *file, bool verbose)
 Change the logging file. More...
 
int mutt_log_set_level (enum LogLevel level, bool verbose)
 Change the logging level. More...
 
int mutt_log_start (void)
 Enable file logging. More...
 
int level_validator (const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
 Validate the "debug_level" config variable - Implements ConfigDef::validator() More...
 
int mutt_log_observer (struct NotifyCallback *nc)
 Listen for config changes affecting the log file - Implements observer_t. More...
 

Variables

uint64_t LastError = 0
 Time of the last error message (in milliseconds since the Unix epoch) More...
 
short C_DebugLevel = 0
 Config: Logging level for debug logs. More...
 
char * C_DebugFile = NULL
 Config: File to save debug logs. More...
 
char * CurrentFile = NULL
 The previous log file name. More...
 
const int NumOfLogs = 5
 How many log files to rotate. More...
 

Detailed Description

NeoMutt Logging.

Authors
  • Richard Russon

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file mutt_logging.c.

Macro Definition Documentation

◆ S_TO_MS

#define S_TO_MS   1000L

Definition at line 53 of file mutt_logging.c.

Function Documentation

◆ error_pause()

static void error_pause ( void  )
static

Wait for an error message to be read.

If '$sleep_time' seconds hasn't elapsed since LastError, then wait

Definition at line 60 of file mutt_logging.c.

61 {
62  const uint64_t elapsed = mutt_date_epoch_ms() - LastError;
63  const uint64_t sleep = C_SleepTime * S_TO_MS;
64  if ((LastError == 0) || (elapsed >= sleep))
65  return;
66 
67  mutt_refresh();
68  mutt_date_sleep_ms(sleep - elapsed);
69 }
uint64_t mutt_date_epoch_ms(void)
Return the number of milliseconds since the Unix epoch.
Definition: date.c:425
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
Definition: mutt_globals.h:114
uint64_t LastError
Time of the last error message (in milliseconds since the Unix epoch)
Definition: mutt_logging.c:46
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:108
#define S_TO_MS
Definition: mutt_logging.c:53
void mutt_date_sleep_ms(size_t ms)
Sleep for milliseconds.
Definition: date.c:693
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rotate_logs()

static const char* rotate_logs ( const char *  file,
int  count 
)
static

Rotate a set of numbered files.

Parameters
fileTemplate filename
countMaximum number of files
Return values
ptrName of the 0'th file

Given a template 'temp', rename files numbered 0 to (count-1).

Rename:

  • ...
  • temp1 -> temp2
  • temp0 -> temp1

Definition at line 84 of file mutt_logging.c.

85 {
86  if (!file)
87  return NULL;
88 
89  struct Buffer *old_file = mutt_buffer_pool_get();
90  struct Buffer *new_file = mutt_buffer_pool_get();
91 
92  /* rotate the old debug logs */
93  for (count -= 2; count >= 0; count--)
94  {
95  mutt_buffer_printf(old_file, "%s%d", file, count);
96  mutt_buffer_printf(new_file, "%s%d", file, count + 1);
97 
98  mutt_buffer_expand_path(old_file);
99  mutt_buffer_expand_path(new_file);
100  rename(mutt_b2s(old_file), mutt_b2s(new_file));
101  }
102 
103  file = mutt_buffer_strdup(old_file);
104  mutt_buffer_pool_release(&old_file);
105  mutt_buffer_pool_release(&new_file);
106 
107  return file;
108 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_clear_error()

void mutt_clear_error ( void  )

Clear the message line (bottom line of screen)

Definition at line 113 of file mutt_logging.c.

114 {
115  /* Make sure the error message has had time to be read */
116  if (OptMsgErr)
117  error_pause();
118 
119  ErrorBufMessage = false;
120  if (!OptNoCurses)
122 }
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:48
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:232
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
WHERE bool OptMsgErr
(pseudo) used by mutt_error/mutt_message
Definition: options.h:41
WHERE bool ErrorBufMessage
true if the last message was an error
Definition: mutt_globals.h:44
static void error_pause(void)
Wait for an error message to be read.
Definition: mutt_logging.c:60
+ Here is the call graph for this function:

◆ log_disp_curses()

int log_disp_curses ( time_t  stamp,
const char *  file,
int  line,
const char *  function,
enum LogLevel  level,
  ... 
)

Display a log line in the message line - Implements log_dispatcher_t.

Definition at line 127 of file mutt_logging.c.

129 {
130  if (level > C_DebugLevel)
131  return 0;
132 
133  char buf[1024];
134 
135  va_list ap;
136  va_start(ap, level);
137  const char *fmt = va_arg(ap, const char *);
138  int ret = vsnprintf(buf, sizeof(buf), fmt, ap);
139  va_end(ap);
140 
141  if (level == LL_PERROR)
142  {
143  char *buf2 = buf + ret;
144  int len = sizeof(buf) - ret;
145  const char *p = strerror(errno);
146  if (!p)
147  p = _("unknown error");
148 
149  ret += snprintf(buf2, len, ": %s (errno = %d)", p, errno);
150  }
151 
152  const bool dupe = (strcmp(buf, ErrorBuf) == 0);
153  if (!dupe)
154  {
155  /* Only log unique messages */
156  log_disp_file(stamp, file, line, function, level, "%s", buf);
157  if (stamp == 0)
158  log_disp_queue(stamp, file, line, function, level, "%s", buf);
159  }
160 
161  /* Don't display debugging message on screen */
162  if (level > LL_MESSAGE)
163  return 0;
164 
165  /* Only pause if this is a message following an error */
166  if ((level > LL_ERROR) && OptMsgErr && !dupe)
167  error_pause();
168 
171  JUSTIFY_LEFT, 0, buf, sizeof(buf), false);
172  ErrorBufMessage = true;
173 
174  if (!OptKeepQuiet)
175  {
176  switch (level)
177  {
178  case LL_ERROR:
179  mutt_beep(false);
181  break;
182  case LL_WARNING:
184  break;
185  default:
187  break;
188  }
189 
193  mutt_refresh();
194  }
195 
196  if ((level <= LL_ERROR) && !dupe)
197  {
198  OptMsgErr = true;
200  }
201  else
202  {
203  OptMsgErr = false;
204  LastError = 0;
205  }
206 
207  return ret;
208 }
Log error.
Definition: logging.h:37
uint64_t mutt_date_epoch_ms(void)
Return the number of milliseconds since the Unix epoch.
Definition: date.c:425
Left justify the text.
Definition: curs_lib.h:47
Informational message.
Definition: color.h:75
void mutt_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:57
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:244
Log perror (using errno)
Definition: logging.h:36
#define _(a)
Definition: message.h:28
uint64_t LastError
Time of the last error message (in milliseconds since the Unix epoch)
Definition: mutt_logging.c:46
Log informational message.
Definition: logging.h:39
WHERE char ErrorBuf[256]
Copy of the last error message.
Definition: mutt_globals.h:45
int mutt_window_mvaddstr(struct MuttWindow *win, int col, int row, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:396
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:99
int log_disp_file(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to a file - Implements log_dispatcher_t.
Definition: logging.c:246
Plain text.
Definition: color.h:77
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:108
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
Error message.
Definition: color.h:70
WHERE bool OptMsgErr
(pseudo) used by mutt_error/mutt_message
Definition: options.h:41
WHERE bool ErrorBufMessage
true if the last message was an error
Definition: mutt_globals.h:44
int log_disp_queue(time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
Save a log line to an internal queue - Implements log_dispatcher_t.
Definition: logging.c:400
static void error_pause(void)
Wait for an error message to be read.
Definition: mutt_logging.c:60
WHERE bool OptKeepQuiet
(pseudo) shut up the message and refresh functions while we are executing an external program ...
Definition: options.h:39
Warning messages.
Definition: color.h:98
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: curs_lib.c:1093
Log warning.
Definition: logging.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_log_prep()

void mutt_log_prep ( void  )

Prepare to log.

Definition at line 213 of file mutt_logging.c.

214 {
215  char ver[64];
216  snprintf(ver, sizeof(ver), "-%s%s", PACKAGE_VERSION, GitVer);
218 }
void log_file_set_version(const char *version)
Set the program&#39;s version number.
Definition: logging.c:221
const char * GitVer
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_log_stop()

void mutt_log_stop ( void  )

Close the log file.

Definition at line 223 of file mutt_logging.c.

224 {
225  log_file_close(false);
226  FREE(&CurrentFile);
227 }
void log_file_close(bool verbose)
Close the log file.
Definition: logging.c:98
char * CurrentFile
The previous log file name.
Definition: mutt_logging.c:50
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_log_set_file()

int mutt_log_set_file ( const char *  file,
bool  verbose 
)

Change the logging file.

Parameters
fileName to use
verboseIf true, then log the event
Return values
0Success, file opened
-1Error, see errno

Close the old log, rotate the new logs and open the new log.

Definition at line 238 of file mutt_logging.c.

239 {
241  {
242  const char *name = rotate_logs(C_DebugFile, NumOfLogs);
243  if (!name)
244  return -1;
245 
246  log_file_set_filename(name, false);
247  FREE(&name);
249  }
250 
251  cs_subset_str_string_set(NeoMutt->sub, "debug_file", file, NULL);
252 
253  return 0;
254 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
const int NumOfLogs
How many log files to rotate.
Definition: mutt_logging.c:51
char * CurrentFile
The previous log file name.
Definition: mutt_logging.c:50
int log_file_set_filename(const char *file, bool verbose)
Set the filename for the log.
Definition: logging.c:149
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:395
char * C_DebugFile
Config: File to save debug logs.
Definition: mutt_logging.c:49
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
#define FREE(x)
Definition: memory.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
static const char * rotate_logs(const char *file, int count)
Rotate a set of numbered files.
Definition: mutt_logging.c:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_log_set_level()

int mutt_log_set_level ( enum LogLevel  level,
bool  verbose 
)

Change the logging level.

Parameters
levelLogging level
verboseIf true, then log the event
Return values
0Success
-1Error, level is out of range

Definition at line 263 of file mutt_logging.c.

264 {
265  if (!CurrentFile)
267 
268  if (log_file_set_level(level, verbose) != 0)
269  return -1;
270 
271  cs_subset_str_native_set(NeoMutt->sub, "debug_level", level, NULL);
272  return 0;
273 }
int mutt_log_set_file(const char *file, bool verbose)
Change the logging file.
Definition: mutt_logging.c:238
char * CurrentFile
The previous log file name.
Definition: mutt_logging.c:50
Container for Accounts, Notifications.
Definition: neomutt.h:36
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:292
int log_file_set_level(enum LogLevel level, bool verbose)
Set the logging level.
Definition: logging.c:175
char * C_DebugFile
Config: File to save debug logs.
Definition: mutt_logging.c:49
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_log_start()

int mutt_log_start ( void  )

Enable file logging.

Return values
0Success, or already running
-1Failed to start

This also handles file rotation.

Definition at line 282 of file mutt_logging.c.

283 {
284  if (C_DebugLevel < 1)
285  return 0;
286 
287  if (log_file_running())
288  return 0;
289 
291 
292  /* This will trigger the file creation */
293  if (log_file_set_level(C_DebugLevel, true) < 0)
294  return -1;
295 
296  return 0;
297 }
int mutt_log_set_file(const char *file, bool verbose)
Change the logging file.
Definition: mutt_logging.c:238
int log_file_set_level(enum LogLevel level, bool verbose)
Set the logging level.
Definition: logging.c:175
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
bool log_file_running(void)
Is the log file running?
Definition: logging.c:230
char * C_DebugFile
Config: File to save debug logs.
Definition: mutt_logging.c:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ level_validator()

int level_validator ( const struct ConfigSet cs,
const struct ConfigDef cdef,
intptr_t  value,
struct Buffer err 
)

Validate the "debug_level" config variable - Implements ConfigDef::validator()

Definition at line 302 of file mutt_logging.c.

304 {
305  if ((value < 0) || (value >= LL_MAX))
306  {
307  mutt_buffer_printf(err, _("Invalid value for option %s: %ld"), cdef->name, value);
308  return CSR_ERR_INVALID;
309  }
310 
311  return CSR_SUCCESS;
312 }
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
#define CSR_ERR_INVALID
Value hasn&#39;t been set.
Definition: set.h:38
#define _(a)
Definition: message.h:28
Definition: logging.h:47
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
const char * name
User-visible name.
Definition: set.h:63
+ Here is the call graph for this function:

◆ mutt_log_observer()

int mutt_log_observer ( struct NotifyCallback nc)

Listen for config changes affecting the log file - Implements observer_t.

Definition at line 317 of file mutt_logging.c.

318 {
319  if (!nc->event_data)
320  return -1;
321  if (nc->event_type != NT_CONFIG)
322  return 0;
323 
324  struct EventConfig *ec = nc->event_data;
325 
326  if (mutt_str_equal(ec->name, "debug_file"))
328  else if (mutt_str_equal(ec->name, "debug_level"))
330 
331  return 0;
332 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
int mutt_log_set_file(const char *file, bool verbose)
Change the logging file.
Definition: mutt_logging.c:238
A config-change event.
Definition: subset.h:70
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
int mutt_log_set_level(enum LogLevel level, bool verbose)
Change the logging level.
Definition: mutt_logging.c:263
short C_DebugLevel
Config: Logging level for debug logs.
Definition: mutt_logging.c:48
void * event_data
Data from notify_send()
Definition: observer.h:44
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:37
char * C_DebugFile
Config: File to save debug logs.
Definition: mutt_logging.c:49
const char * name
Name of config item that changed.
Definition: subset.h:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ LastError

uint64_t LastError = 0

Time of the last error message (in milliseconds since the Unix epoch)

Definition at line 46 of file mutt_logging.c.

◆ C_DebugLevel

short C_DebugLevel = 0

Config: Logging level for debug logs.

Definition at line 48 of file mutt_logging.c.

◆ C_DebugFile

char* C_DebugFile = NULL

Config: File to save debug logs.

Definition at line 49 of file mutt_logging.c.

◆ CurrentFile

char* CurrentFile = NULL

The previous log file name.

Definition at line 50 of file mutt_logging.c.

◆ NumOfLogs

const int NumOfLogs = 5

How many log files to rotate.

Definition at line 51 of file mutt_logging.c.