#include <time.h>
#include <poll.h>
+#define LOG_TYPE_FLAG_PREFIX_LEN 0x40
#define LOG_TYPE_FLAG_DISABLE_LOG_PREFIX 0x80
const char *failure_log_type_prefixes[LOG_TYPE_COUNT] = {
static bool line_parse_prefix(const char *line, enum log_type *log_type_r,
- bool *replace_prefix_r)
+ bool *replace_prefix_r, bool *have_prefix_len_r)
{
if (*line != 1)
return FALSE;
- unsigned char log_type = (line[1] & 0x7f);
+ unsigned char log_type = (line[1] & 0x3f);
if (log_type == '\0') {
i_warning("Broken log line follows (type=NUL)");
return FALSE;
}
*log_type_r = log_type;
*replace_prefix_r = (line[1] & LOG_TYPE_FLAG_DISABLE_LOG_PREFIX) != 0;
+ *have_prefix_len_r = (line[1] & LOG_TYPE_FLAG_PREFIX_LEN) != 0;
return TRUE;
}
void i_failure_parse_line(const char *line, struct failure_line *failure)
{
+ bool have_prefix_len = FALSE;
i_zero(failure);
if (!line_parse_prefix(line, &failure->log_type,
- &failure->disable_log_prefix)) {
+ &failure->disable_log_prefix,
+ &have_prefix_len)) {
failure->log_type = LOG_TYPE_ERROR;
failure->text = line;
return;
failure->pid = 0;
return;
}
- failure->text = line + 1;
+ line++;
+
+ if (have_prefix_len) {
+ if (str_parse_uint(line, &failure->log_prefix_len, &line) < 0 ||
+ line[0] != ' ') {
+ /* unexpected, but ignore */
+ } else {
+ line++;
+ if (failure->log_prefix_len > strlen(line)) {
+ /* invalid */
+ failure->log_prefix_len = 0;
+ }
+ }
+ }
+ failure->text = line;
}
static void ATTR_NORETURN ATTR_FORMAT(2, 0)
struct failure_line {
pid_t pid;
enum log_type log_type;
+ /* If non-zero, the first log_prefix_len bytes in text indicate
+ the log prefix. This implies disable_log_prefix=TRUE. */
+ unsigned int log_prefix_len;
+ /* Disable the global log prefix. */
bool disable_log_prefix;
const char *text;
};
struct failure_line failure;
struct failure_context failure_ctx;
struct log_client *client = NULL;
- const char *prefix;
+ const char *prefix = "";
if (log->master) {
log_parse_master_line(line, log_time, tm);
failure_ctx.type = failure.log_type;
failure_ctx.timestamp = tm;
failure_ctx.timestamp_usecs = log_time->tv_usec;
- if (failure.disable_log_prefix)
+ if (failure.log_prefix_len != 0) {
+ failure_ctx.log_prefix =
+ t_strndup(failure.text, failure.log_prefix_len);
+ failure.text += failure.log_prefix_len;
+ } else if (failure.disable_log_prefix) {
failure_ctx.log_prefix = "";
-
- prefix = client != NULL && client->prefix != NULL ?
- client->prefix : log->default_prefix;
+ } else {
+ prefix = client != NULL && client->prefix != NULL ?
+ client->prefix : log->default_prefix;
+ }
client_log_ctx(log, &failure_ctx, log_time, prefix, failure.text);
}