#include <unistd.h>
#include "ply-utils.h"
+#include "ply-list.h"
#ifndef PLY_LOGGER_OPEN_FLAGS
#define PLY_LOGGER_OPEN_FLAGS (O_WRONLY | O_TRUNC | O_CREAT | O_NOFOLLOW)
#define PLY_LOGGER_MAX_BUFFER_CAPACITY (8 * 4096)
#endif
+typedef struct
+{
+ ply_logger_filter_handler_t handler;
+ void *user_data;
+} ply_logger_filter_t;
+
struct _ply_logger
{
int output_fd;
size_t buffer_capacity;
ply_logger_flush_policy_t flush_policy;
+ ply_list_t *filters;
uint32_t is_enabled : 1;
uint32_t tracing_is_enabled : 1;
logger->buffer = calloc (1, logger->buffer_capacity);
logger->buffer_size = 0;
+ logger->filters = ply_list_new ();
+
return logger;
}
return logger;
}
+static void
+ply_logger_free_filters (ply_logger_t *logger)
+{
+ ply_list_node_t *node;
+
+ node = ply_list_get_first_node (logger->filters);
+ while (node != NULL)
+ {
+ ply_list_node_t *next_node;
+ ply_logger_filter_t *filter;
+
+ filter = (ply_logger_filter_t *) ply_list_node_get_data (node);
+
+ next_node = ply_list_get_next_node (logger->filters, node);
+ free (filter);
+ node = next_node;
+ }
+
+ ply_list_free (logger->filters);
+}
+
void
ply_logger_free (ply_logger_t *logger)
{
close (logger->output_fd);
}
+ ply_logger_free_filters (logger);
+
free (logger->filename);
free (logger->buffer);
free (logger);
const void *bytes,
size_t number_of_bytes)
{
+ ply_list_node_t *node;
+ void *filtered_bytes;
+ size_t filtered_size;
+
assert (logger != NULL);
assert (bytes != NULL);
assert (number_of_bytes != 0);
- ply_logger_buffer (logger, bytes, number_of_bytes);
+ filtered_bytes = NULL;
+ filtered_size = 0;
+ node = ply_list_get_first_node (logger->filters);
+ while (node != NULL)
+ {
+ ply_list_node_t *next_node;
+ ply_logger_filter_t *filter;
+
+ filter = (ply_logger_filter_t *) ply_list_node_get_data (node);
+
+ next_node = ply_list_get_next_node (logger->filters, node);
+
+ if (filtered_bytes == NULL)
+ filter->handler (filter->user_data, bytes, number_of_bytes,
+ &filtered_bytes, &filtered_size, logger);
+ else
+ {
+ void *new_bytes;
+ size_t new_size;
+
+ new_bytes = NULL;
+ new_size = 0;
+ filter->handler (filter->user_data, filtered_bytes, filtered_size,
+ &new_bytes, &new_size, logger);
+
+ if (new_bytes != NULL)
+ {
+ free (filtered_bytes);
+ filtered_bytes = new_bytes;
+ filtered_size = new_size;
+ }
+ }
+
+ node = next_node;
+ }
+
+ if (filtered_bytes == NULL)
+ ply_logger_buffer (logger, bytes, number_of_bytes);
+ else
+ {
+ ply_logger_buffer (logger, filtered_bytes, filtered_size);
+ free (filtered_bytes);
+ }
assert ((logger->flush_policy == PLY_LOGGER_FLUSH_POLICY_WHEN_ASKED)
|| (logger->flush_policy == PLY_LOGGER_FLUSH_POLICY_EVERY_TIME));
ply_logger_flush (logger);
}
+void
+ply_logger_add_filter (ply_logger_t *logger,
+ ply_logger_filter_handler_t filter_handler,
+ void *user_data)
+{
+ ply_logger_filter_t *filter;
+
+ filter = calloc (1, sizeof (ply_logger_filter_t));
+
+ filter->handler = filter_handler;
+ filter->user_data = user_data;
+
+ ply_list_append_data (logger->filters, filter);
+}
+
#ifdef PLY_ENABLE_TRACING
void
ply_logger_toggle_tracing (ply_logger_t *logger)
PLY_LOGGER_FLUSH_POLICY_EVERY_TIME
} ply_logger_flush_policy_t;
+typedef void (* ply_logger_filter_handler_t) (void *user_data,
+ const void *in_bytes,
+ size_t in_size,
+ void **out_bytes,
+ size_t *out_size,
+ ply_logger_t *logger);
+
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
ply_logger_t *ply_logger_new (void);
void ply_logger_free (ply_logger_t *logger);
void ply_logger_inject_bytes (ply_logger_t *logger,
const void *bytes,
size_t number_of_bytes);
+void ply_logger_add_filter (ply_logger_t *logger,
+ ply_logger_filter_handler_t filter_handler,
+ void *user_data);
#define ply_logger_inject(logger, format, args...) \
ply_logger_inject_with_non_literal_format_string (logger, \
format "", ##args)
#include <linux/kd.h>
#include <linux/vt.h>
+#include "ply-buffer.h"
#include "ply-command-parser.h"
#include "ply-boot-server.h"
#include "ply-boot-splash.h"
static void dump_details_and_quit_splash (state_t *state);
static void update_display (state_t *state);
+static ply_buffer_t *debug_buffer;
+
static void
switch_to_vt (int vt_number)
{
return true;
}
+static void
+on_error_message (ply_buffer_t *debug_buffer,
+ const void *bytes,
+ size_t number_of_bytes)
+{
+ ply_buffer_append_bytes (debug_buffer, bytes, number_of_bytes);
+}
+
static void
on_crash (int signum)
{
int fd;
+ const char *bytes;
+ size_t size;
fd = open ("/dev/tty1", O_RDWR | O_NOCTTY);
close (fd);
+ if (debug_buffer != NULL) {
+ fd = open (PLYMOUTH_LOG_DIRECTORY "/plymouth-crash.log",
+ O_WRONLY | O_CREAT, 0600);
+ size = ply_buffer_get_size (debug_buffer);
+ bytes = ply_buffer_get_bytes (debug_buffer);
+ ply_write (fd, bytes, size);
+ close (fd);
+
+ pause ();
+ }
+
signal (signum, SIG_DFL);
raise(signum);
}
}
}
+ if (debug)
+ {
+ debug_buffer = ply_buffer_new ();
+
+ ply_logger_add_filter (ply_logger_get_error_default (),
+ (ply_logger_filter_handler_t)
+ on_error_message,
+ debug_buffer);
+ }
+
signal (SIGABRT, on_crash);
signal (SIGSEGV, on_crash);
ply_trace ("freeing event loop");
ply_event_loop_free (state.loop);
+ ply_buffer_free (debug_buffer);
+
ply_trace ("exiting with code %d", exit_code);
ply_free_error_log();