degesch: add logging to file

This commit is contained in:
Přemysl Eric Janouch 2015-07-04 15:24:08 +02:00
parent 3503b76015
commit 94d495fbfa

115
degesch.c
View File

@ -1018,6 +1018,8 @@ struct buffer
unsigned unseen_messages_count; ///< # messages since last visited
bool highlighted; ///< We've been highlighted
FILE *log_file; ///< Log file
// Origin information:
struct server *server; ///< Reference to server
@ -1041,6 +1043,8 @@ buffer_destroy (struct buffer *self)
input_buffer_destroy (self->input_data);
LIST_FOR_EACH (struct buffer_line, iter, self->lines)
buffer_line_destroy (iter);
if (self->log_file)
(void) fclose (self->log_file);
if (self->user)
user_unref (self->user);
if (self->channel)
@ -1550,6 +1554,10 @@ static struct config_schema g_config_behaviour[] =
.comment = "Beep when highlighted or on a new invisible PM",
.type = CONFIG_ITEM_BOOLEAN,
.default_ = "on" },
{ .name = "logging",
.comment = "Log buffer contents to file",
.type = CONFIG_ITEM_BOOLEAN,
.default_ = "off" },
{}
};
@ -2482,6 +2490,20 @@ buffer_update_time (struct app_context *ctx, time_t now)
// Else the buffer was too small, which is pretty weird
}
static void
buffer_line_flush (struct buffer_line *line, struct formatter *f, FILE *output)
{
int flags = line->flags;
if (flags & BUFFER_LINE_INDENT) formatter_add (f, " ");
if (flags & BUFFER_LINE_STATUS) formatter_add (f, " - ");
if (flags & BUFFER_LINE_ERROR) formatter_add (f, "#a=!=#r ", ATTR_ERROR);
formatter_add_from (f, line->formatter);
formatter_add (f, "\n");
formatter_flush (f, output);
formatter_free (f);
}
static void
buffer_line_display (struct app_context *ctx,
struct buffer_line *line, bool is_external)
@ -2494,12 +2516,13 @@ buffer_line_display (struct app_context *ctx,
formatter_init (&f, ctx, NULL);
struct tm current;
char buf[9];
if (!localtime_r (&line->when, &current))
print_error ("%s: %s", "localtime_r", strerror (errno));
else if (!strftime (buf, sizeof buf, "%T", &current))
print_error ("%s: %s", "strftime", "buffer too small");
else
formatter_add (&f, "#a#&s#r ", ATTR_TIMESTAMP,
xstrdup_printf ("%02d:%02d:%02d",
current.tm_hour, current.tm_min, current.tm_sec));
formatter_add (&f, "#a#s#r ", ATTR_TIMESTAMP, buf);
// Ignore all formatting for messages coming from other buffers, that is
// either from the global or server buffer. Instead print them in grey.
@ -2509,26 +2532,33 @@ buffer_line_display (struct app_context *ctx,
FORMATTER_ADD_ITEM (&f, IGNORE_ATTR, .attribute = 1);
}
if (line->flags & BUFFER_LINE_INDENT)
formatter_add (&f, " ");
if (line->flags & BUFFER_LINE_STATUS)
formatter_add (&f, " - ");
if (line->flags & BUFFER_LINE_ERROR)
formatter_add (&f, "#a=!=#r ", ATTR_ERROR);
formatter_add_from (&f, line->formatter);
input_hide (&ctx->input);
// TODO: write the line to a log file; note that the global and server
// buffers musn't collide with filenames
formatter_add (&f, "\n");
formatter_flush (&f, stdout);
formatter_free (&f);
buffer_line_flush (line, &f, stdout);
input_show (&ctx->input);
}
static void
buffer_line_write_to_log (struct app_context *ctx,
struct buffer_line *line, FILE *log_file)
{
if (line->flags & BUFFER_LINE_SKIP_FILE)
return;
struct formatter f;
formatter_init (&f, ctx, NULL);
struct tm current;
char buf[20];
if (!gmtime_r (&line->when, &current))
print_error ("%s: %s", "gmtime_r", strerror (errno));
else if (!strftime (buf, sizeof buf, "%F %T", &current))
print_error ("%s: %s", "strftime", "buffer too small");
else
formatter_add (&f, "#s ", buf);
buffer_line_flush (line, &f, log_file);
}
static void
log_formatter (struct app_context *ctx,
struct buffer *buffer, int flags, struct formatter *f)
@ -2547,6 +2577,9 @@ log_formatter (struct app_context *ctx,
LIST_APPEND_WITH_TAIL (buffer->lines, buffer->lines_tail, line);
buffer->lines_count++;
if (buffer->log_file)
buffer_line_write_to_log (ctx, line, buffer->log_file);
if (get_config_boolean (ctx->config.root, "behaviour.beep_on_highlight"))
if ((flags & BUFFER_LINE_HIGHLIGHT)
|| (buffer->type == BUFFER_PM && buffer != ctx->current_buffer))
@ -2634,6 +2667,41 @@ log_full (struct app_context *ctx, struct server *s, struct buffer *buffer,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
make_log_filename (const char *filename, struct str *output)
{
for (const char *p = filename; *p; p++)
// XXX: anything more to replace?
if (strchr ("/\\ ", *p))
str_append_c (output, '_');
else
str_append_c (output, tolower_ascii (*p));
}
static void
buffer_open_log_file (struct app_context *ctx, struct buffer *buffer)
{
if (!get_config_boolean (ctx->config.root, "behaviour.logging"))
return;
struct str path;
str_init (&path);
get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
str_append_printf (&path, "/%s/%s", PROGRAM_NAME, "logs");
(void) mkdir_with_parents (path.str, NULL);
// TODO: make sure global and server buffers don't collide with filenames
str_append_c (&path, '/');
make_log_filename (buffer->name, &path);
str_append (&path, ".log");
if (!(buffer->log_file = fopen (path.str, "ab")))
log_global_error (ctx, "Couldn't open log file `#s': #s",
path.str, strerror (errno));
str_free (&path);
}
static struct buffer *
buffer_by_name (struct app_context *ctx, const char *name)
{
@ -2648,6 +2716,8 @@ buffer_add (struct app_context *ctx, struct buffer *buffer)
str_map_set (&ctx->buffers_by_name, buffer->name, buffer);
LIST_APPEND_WITH_TAIL (ctx->buffers, ctx->buffers_tail, buffer);
buffer_open_log_file (ctx, buffer);
// In theory this can't cause changes in the prompt
refresh_prompt (ctx);
}
@ -2776,6 +2846,13 @@ buffer_rename (struct app_context *ctx,
str_map_set (&ctx->buffers_by_name, buffer->name, NULL);
str_map_set (&ctx->buffers_by_name, new_name, buffer);
if (buffer->log_file)
{
(void) fclose (buffer->log_file);
buffer->log_file = NULL;
}
buffer_open_log_file (ctx, buffer);
free (buffer->name);
buffer->name = xstrdup (new_name);