doveadm-log.c revision 8a2df8a89fc61c584429534a57a2ea20fcaf2d28
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#include "lib.h"
e9b6af083e34e2397a8ddbe9781920733d09d151Ted Gould#include "ioloop.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "istream.h"
685292a24e42a23ca4fa7cc467398ce10fcfd453JucaBlues#include "hash.h"
171bd4f3b6a8cdaa7d2ae5bdf0774b6e93e7d40dinsaner#include "str.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "strescape.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "time-util.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "master-service-private.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "master-service-settings.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "doveadm.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include "doveadm-print.h"
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include <stdio.h>
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include <unistd.h>
54f0b322de8b5934619f28f4971e5c1c95c14ffekeescook#include <fcntl.h>
54f0b322de8b5934619f28f4971e5c1c95c14ffekeescook#include <dirent.h>
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#include <signal.h>
963f23115db07f460bdd862b957f8bd9dba88b9bgustav_b#include <sys/stat.h>
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
9496d940d814b037c16b03e111bd238e57684125nicholasbishop#define LAST_LOG_TYPE LOG_TYPE_PANIC
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental#define TEST_LOG_MSG_PREFIX "This is Dovecot's "
4524755733342d1f59efec7d655bfb6a47c0ab72John Smith#define LOG_ERRORS_FNAME "log-errors"
280e31bdf7f5ffd28f8b14565c1d93de4070bd0cJucaBlues#define LOG_TIMESTAMP_FORMAT "%b %d %H:%M:%S"
d67024fee7c560721468212767fb6aa221d5b542John Smith
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmentalextern struct doveadm_cmd doveadm_cmd_log[];
5cacbbec22b42a0480f396eb94bcfb5f746ac68aAlex Valavanis
5cacbbec22b42a0480f396eb94bcfb5f746ac68aAlex Valavanisstatic void ATTR_NULL(2)
5cacbbec22b42a0480f396eb94bcfb5f746ac68aAlex Valavaniscmd_log_test(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner{
34ab311b934275c99d5a60e691a89c3a819e5d08insaner struct failure_context ctx;
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner unsigned int i;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental master_service->log_initialized = FALSE;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental master_service->flags |= MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental master_service_init_log(master_service, "doveadm: ");
b068af856bbc33238f425b3221426aa52e554ce0nicholasbishop
b068af856bbc33238f425b3221426aa52e554ce0nicholasbishop i_zero(&ctx);
963f23115db07f460bdd862b957f8bd9dba88b9bgustav_b for (i = 0; i < LAST_LOG_TYPE; i++) {
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental const char *prefix = failure_log_type_prefixes[i];
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b
963f23115db07f460bdd862b957f8bd9dba88b9bgustav_b /* add timestamp so that syslog won't just write
d297097bc1b9d4e074089ea5d649c2a0d270ff42nicholasbishop "repeated message" text */
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental ctx.type = i;
963f23115db07f460bdd862b957f8bd9dba88b9bgustav_b i_log_type(&ctx, TEST_LOG_MSG_PREFIX"%s log (%u)",
963f23115db07f460bdd862b957f8bd9dba88b9bgustav_b t_str_lcase(t_strcut(prefix, ':')),
7237c264c3e0190918510e1b239fc6dd1efdfcd0nicholasbishop (unsigned int)ioloop_time);
a0df1b8dd5b14367c583ce2f72a2ca6bf1cde799gustav_b }
aadf03ecf79b1860e1b3032a936d8a2c658f47b3nicholasbishop}
aadf03ecf79b1860e1b3032a936d8a2c658f47b3nicholasbishop
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmentalstatic void cmd_log_reopen(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
77e0947f5d14388f467e663e9f84e933ccfc0b80nicholasbishop{
9496d940d814b037c16b03e111bd238e57684125nicholasbishop doveadm_master_send_signal(SIGUSR1);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental}
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
75d2a56fc2c5b0d39e545d42909d64c3847cd68dnicholasbishopstruct log_find_file {
9496d940d814b037c16b03e111bd238e57684125nicholasbishop const char *path;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental uoff_t size;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop
9496d940d814b037c16b03e111bd238e57684125nicholasbishop /* 1 << enum log_type */
9496d940d814b037c16b03e111bd238e57684125nicholasbishop unsigned int mask;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop};
9496d940d814b037c16b03e111bd238e57684125nicholasbishop
9496d940d814b037c16b03e111bd238e57684125nicholasbishopstruct log_find_context {
9496d940d814b037c16b03e111bd238e57684125nicholasbishop pool_t pool;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental HASH_TABLE(char *, struct log_find_file *) files;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop};
9496d940d814b037c16b03e111bd238e57684125nicholasbishop
9496d940d814b037c16b03e111bd238e57684125nicholasbishopstatic void cmd_log_find_add(struct log_find_context *ctx,
9496d940d814b037c16b03e111bd238e57684125nicholasbishop const char *path, enum log_type type)
9496d940d814b037c16b03e111bd238e57684125nicholasbishop{
9496d940d814b037c16b03e111bd238e57684125nicholasbishop struct log_find_file *file;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop char *key;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop
171bd4f3b6a8cdaa7d2ae5bdf0774b6e93e7d40dinsaner file = hash_table_lookup(ctx->files, path);
9496d940d814b037c16b03e111bd238e57684125nicholasbishop if (file == NULL) {
9496d940d814b037c16b03e111bd238e57684125nicholasbishop file = p_new(ctx->pool, struct log_find_file, 1);
9496d940d814b037c16b03e111bd238e57684125nicholasbishop file->path = key = p_strdup(ctx->pool, path);
9496d940d814b037c16b03e111bd238e57684125nicholasbishop hash_table_insert(ctx->files, key, file);
9496d940d814b037c16b03e111bd238e57684125nicholasbishop }
171bd4f3b6a8cdaa7d2ae5bdf0774b6e93e7d40dinsaner
9496d940d814b037c16b03e111bd238e57684125nicholasbishop file->mask |= 1 << type;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop}
d67024fee7c560721468212767fb6aa221d5b542John Smith
9496d940d814b037c16b03e111bd238e57684125nicholasbishopstatic void
22bba30d53c7a27c4437b6f9de3c3740b8f30850John Smithcmd_log_find_syslog_files(struct log_find_context *ctx, const char *path)
d67024fee7c560721468212767fb6aa221d5b542John Smith{
d67024fee7c560721468212767fb6aa221d5b542John Smith struct log_find_file *file;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop DIR *dir;
7237c264c3e0190918510e1b239fc6dd1efdfcd0nicholasbishop struct dirent *d;
77e0947f5d14388f467e663e9f84e933ccfc0b80nicholasbishop struct stat st;
7391f378420d4ca5fb2a2eb2851fdd4b0682b90dnicholasbishop char *key;
7391f378420d4ca5fb2a2eb2851fdd4b0682b90dnicholasbishop string_t *full_path;
e71525989b5ea26180b94d7105781593cf8616a4Martin Owens size_t dir_len;
d031e1487fde246868c6b8ebac14d771b3eea787nicholasbishop
22cc3601360714cfef103dcf24a07439c99c56e2nicholasbishop dir = opendir(path);
171bd4f3b6a8cdaa7d2ae5bdf0774b6e93e7d40dinsaner if (dir == NULL) {
9496d940d814b037c16b03e111bd238e57684125nicholasbishop i_error("opendir(%s) failed: %m", path);
063bb27bebc4a01eefa879017c819a0058548955mental return;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental full_path = t_str_new(256);
4533e5e378aae1df5a980a1dd6b2359d02891513nicholasbishop str_append(full_path, path);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental str_append_c(full_path, '/');
d67024fee7c560721468212767fb6aa221d5b542John Smith dir_len = str_len(full_path);
d67024fee7c560721468212767fb6aa221d5b542John Smith
d67024fee7c560721468212767fb6aa221d5b542John Smith while ((d = readdir(dir)) != NULL) {
d67024fee7c560721468212767fb6aa221d5b542John Smith if (d->d_name[0] == '.')
d67024fee7c560721468212767fb6aa221d5b542John Smith continue;
d67024fee7c560721468212767fb6aa221d5b542John Smith
d67024fee7c560721468212767fb6aa221d5b542John Smith str_truncate(full_path, dir_len);
d67024fee7c560721468212767fb6aa221d5b542John Smith str_append(full_path, d->d_name);
d67024fee7c560721468212767fb6aa221d5b542John Smith if (stat(str_c(full_path), &st) < 0)
d67024fee7c560721468212767fb6aa221d5b542John Smith continue;
d67024fee7c560721468212767fb6aa221d5b542John Smith
d67024fee7c560721468212767fb6aa221d5b542John Smith if (S_ISDIR(st.st_mode)) {
d67024fee7c560721468212767fb6aa221d5b542John Smith /* recursively go through all subdirectories */
d67024fee7c560721468212767fb6aa221d5b542John Smith cmd_log_find_syslog_files(ctx, str_c(full_path));
d67024fee7c560721468212767fb6aa221d5b542John Smith } else if (hash_table_lookup(ctx->files,
d67024fee7c560721468212767fb6aa221d5b542John Smith str_c(full_path)) == NULL) {
9496d940d814b037c16b03e111bd238e57684125nicholasbishop file = p_new(ctx->pool, struct log_find_file, 1);
9496d940d814b037c16b03e111bd238e57684125nicholasbishop file->size = st.st_size;
9496d940d814b037c16b03e111bd238e57684125nicholasbishop file->path = key =
75d2a56fc2c5b0d39e545d42909d64c3847cd68dnicholasbishop p_strdup(ctx->pool, str_c(full_path));
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental hash_table_insert(ctx->files, key, file);
9496d940d814b037c16b03e111bd238e57684125nicholasbishop }
9496d940d814b037c16b03e111bd238e57684125nicholasbishop }
d031e1487fde246868c6b8ebac14d771b3eea787nicholasbishop
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental (void)closedir(dir);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental}
77e0947f5d14388f467e663e9f84e933ccfc0b80nicholasbishop
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmouginstatic bool log_type_find(const char *str, enum log_type *type_r)
280e31bdf7f5ffd28f8b14565c1d93de4070bd0cJucaBlues{
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin unsigned int i;
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin size_t len = strlen(str);
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental for (i = 0; i < LAST_LOG_TYPE; i++) {
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental if (strncasecmp(str, failure_log_type_prefixes[i], len) == 0 &&
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental failure_log_type_prefixes[i][len] == ':') {
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental *type_r = i;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental return TRUE;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental return FALSE;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental}
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmentalstatic void cmd_log_find_syslog_file_messages(struct log_find_file *file)
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental{
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental struct istream *input;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental const char *line, *p;
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen enum log_type type;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental int fd;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental fd = open(file->path, O_RDONLY);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental if (fd == -1)
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop return;
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop input = i_stream_create_fd_autoclose(&fd, 1024);
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop i_stream_seek(input, file->size);
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop while ((line = i_stream_read_next_line(input)) != NULL) {
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop p = strstr(line, TEST_LOG_MSG_PREFIX);
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop if (p == NULL)
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop continue;
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop p += strlen(TEST_LOG_MSG_PREFIX);
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis /* <type> log */
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis T_BEGIN {
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis if (log_type_find(t_strcut(p, ' '), &type))
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis file->mask |= 1 << type;
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis } T_END;
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis }
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis i_stream_destroy(&input);
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis}
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanisstatic void cmd_log_find_syslog_messages(struct log_find_context *ctx)
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis{
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis struct hash_iterate_context *iter;
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis struct stat st;
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis char *key;
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis struct log_find_file *file;
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis iter = hash_table_iterate_init(ctx->files);
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis while (hash_table_iterate(iter, ctx->files, &key, &file)) {
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop if (stat(file->path, &st) < 0 ||
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop (uoff_t)st.st_size <= file->size)
5c2e73cb2043701f57ea09c4e609e3a51004a828Alex Valavanis continue;
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop cmd_log_find_syslog_file_messages(file);
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop }
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop hash_table_iterate_deinit(&iter);
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop}
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop
063bb27bebc4a01eefa879017c819a0058548955mentalstatic void
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmentalcmd_log_find_syslog(struct log_find_context *ctx, int argc, char *argv[])
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental{
063bb27bebc4a01eefa879017c819a0058548955mental const char *log_dir;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental struct stat st;
77e0947f5d14388f467e663e9f84e933ccfc0b80nicholasbishop
063bb27bebc4a01eefa879017c819a0058548955mental if (argc > 1)
063bb27bebc4a01eefa879017c819a0058548955mental log_dir = argv[1];
063bb27bebc4a01eefa879017c819a0058548955mental else if (stat("/var/log", &st) == 0 && S_ISDIR(st.st_mode))
063bb27bebc4a01eefa879017c819a0058548955mental log_dir = "/var/log";
063bb27bebc4a01eefa879017c819a0058548955mental else if (stat("/var/adm", &st) == 0 && S_ISDIR(st.st_mode))
063bb27bebc4a01eefa879017c819a0058548955mental log_dir = "/var/adm";
56ec4d9cbe391c84f361faa851d796f61cc5fbc8nicholasbishop else
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop return;
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop
70ec876c756620ca1d28d8861e47cbe37c21b2fcapenner printf("Looking for log files from %s\n", log_dir);
70ec876c756620ca1d28d8861e47cbe37c21b2fcapenner cmd_log_find_syslog_files(ctx, log_dir);
063bb27bebc4a01eefa879017c819a0058548955mental cmd_log_test(0, NULL);
e3271b0a2e3756201f8b783a80f37930d267d987Alex Valavanis
24efdd63267aa7bc6958eb9116285730174f9b74Alex Valavanis /* give syslog some time to write the messages to files */
24efdd63267aa7bc6958eb9116285730174f9b74Alex Valavanis sleep(1);
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop cmd_log_find_syslog_messages(ctx);
24efdd63267aa7bc6958eb9116285730174f9b74Alex Valavanis}
24efdd63267aa7bc6958eb9116285730174f9b74Alex Valavanis
063bb27bebc4a01eefa879017c819a0058548955mentalstatic void cmd_log_find(int argc, char *argv[])
063bb27bebc4a01eefa879017c819a0058548955mental{
063bb27bebc4a01eefa879017c819a0058548955mental const struct master_service_settings *set;
063bb27bebc4a01eefa879017c819a0058548955mental const char *log_file_path;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental struct log_find_context ctx;
70ec876c756620ca1d28d8861e47cbe37c21b2fcapenner unsigned int i;
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis i_zero(&ctx);
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis ctx.pool = pool_alloconly_create("log file", 1024*32);
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis hash_table_create(&ctx.files, ctx.pool, 0, str_hash, strcmp);
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis /* first get the paths that we know are used */
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop set = master_service_settings_get(master_service);
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis log_file_path = set->log_path;
b86a3edf4bc42ea90eacf621e8d5400b64cbc512nicholasbishop if (strcmp(log_file_path, "syslog") == 0)
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop log_file_path = "";
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis if (*log_file_path != '\0') {
7fcc133d7a6abd9200846c75e46a29ae74ff4a3fAlex Valavanis cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_WARNING);
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_ERROR);
04d2e120ddfbd611206889d33696c7a1cf103e14nicholasbishop cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_FATAL);
77e0947f5d14388f467e663e9f84e933ccfc0b80nicholasbishop }
d9fd6f9c4b3b41adaeb164b1029d17d862b03255nicholasbishop
063bb27bebc4a01eefa879017c819a0058548955mental if (strcmp(set->info_log_path, "syslog") != 0) {
063bb27bebc4a01eefa879017c819a0058548955mental if (*set->info_log_path != '\0')
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop log_file_path = set->info_log_path;
02df4842dc780e15999cae54bad38b11ed197b90nicholasbishop if (*log_file_path != '\0')
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_INFO);
063bb27bebc4a01eefa879017c819a0058548955mental }
6ec5144d37a7fc9228eb04f7ebd8b2c7bfead332nicholasbishop
063bb27bebc4a01eefa879017c819a0058548955mental if (strcmp(set->debug_log_path, "syslog") != 0) {
04d2e120ddfbd611206889d33696c7a1cf103e14nicholasbishop if (*set->debug_log_path != '\0')
77e0947f5d14388f467e663e9f84e933ccfc0b80nicholasbishop log_file_path = set->debug_log_path;
d9fd6f9c4b3b41adaeb164b1029d17d862b03255nicholasbishop if (*log_file_path != '\0')
5cd6256452c48fa9071c560b8b4d002cdb3593deinsaner cmd_log_find_add(&ctx, log_file_path, LOG_TYPE_DEBUG);
5cd6256452c48fa9071c560b8b4d002cdb3593deinsaner }
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin
280e31bdf7f5ffd28f8b14565c1d93de4070bd0cJucaBlues if (*set->log_path == '\0' ||
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin strcmp(set->log_path, "syslog") == 0 ||
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin strcmp(set->info_log_path, "syslog") == 0 ||
f1f9ad8176ddd6913180a1fb76e7ce1558e6a82eMarc Jeanmougin strcmp(set->debug_log_path, "syslog") == 0) {
70ec876c756620ca1d28d8861e47cbe37c21b2fcapenner /* at least some logs were logged via syslog */
70ec876c756620ca1d28d8861e47cbe37c21b2fcapenner cmd_log_find_syslog(&ctx, argc, argv);
063bb27bebc4a01eefa879017c819a0058548955mental }
063bb27bebc4a01eefa879017c819a0058548955mental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental /* print them */
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental for (i = 0; i < LAST_LOG_TYPE; i++) {
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental struct hash_iterate_context *iter;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental char *key;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental struct log_find_file *file;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental bool found = FALSE;
f313394fee34e964f4088211bdf5fb82cce31378nicholasbishop
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental iter = hash_table_iterate_init(ctx.files);
3f32b7eb40422e3a8172495cad80a2f40a563d9cJon A. Cruz while (hash_table_iterate(iter, ctx.files, &key, &file)) {
3f32b7eb40422e3a8172495cad80a2f40a563d9cJon A. Cruz if ((file->mask & (1 << i)) != 0) {
3f32b7eb40422e3a8172495cad80a2f40a563d9cJon A. Cruz printf("%s%s\n", failure_log_type_prefixes[i],
b86a3edf4bc42ea90eacf621e8d5400b64cbc512nicholasbishop file->path);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental found = TRUE;
cd090649718da48f667e425406f075cbd81d29f7JucaBlues }
7ace9792963d30c410ca3e339b9b795c318f3b4cnicholasbishop }
087b237ce230e9b7a16dc95537dbb62f7d715026nicholasbishop hash_table_iterate_deinit(&iter);
e516eaa7497ddc87b5f6a96941d316d265b46ebcjucablues
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental if (!found)
e516eaa7497ddc87b5f6a96941d316d265b46ebcjucablues printf("%sNot found\n", failure_log_type_prefixes[i]);
e516eaa7497ddc87b5f6a96941d316d265b46ebcjucablues }
e516eaa7497ddc87b5f6a96941d316d265b46ebcjucablues}
34ab311b934275c99d5a60e691a89c3a819e5d08insaner
e516eaa7497ddc87b5f6a96941d316d265b46ebcjucabluesstatic const char *t_cmd_log_error_trim(const char *orig)
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental{
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner size_t pos;
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner /* Trim whitespace from suffix and remove ':' if it exists */
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner for (pos = strlen(orig); pos > 0; pos--) {
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner if (orig[pos-1] != ' ') {
8f40ed19303d1d55144ded13fa6e3465134ffbbbinsaner if (orig[pos-1] == ':')
d9a7c806ee7f408ddb61ff4f233c9d96111ee2b5johanengelen pos--;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental break;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
d297097bc1b9d4e074089ea5d649c2a0d270ff42nicholasbishop }
cd090649718da48f667e425406f075cbd81d29f7JucaBlues return orig[pos] == '\0' ? orig : t_strndup(orig, pos);
cd090649718da48f667e425406f075cbd81d29f7JucaBlues}
cd090649718da48f667e425406f075cbd81d29f7JucaBlues
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmentalstatic void cmd_log_error_write(const char *const *args, time_t min_timestamp)
cd090649718da48f667e425406f075cbd81d29f7JucaBlues{
47ecd8bd5fb672cd99c3cd0445360e421a4d6a42jucablues /* <type> <timestamp> <prefix> <text> */
2b3b5a2a04c62bc07b7f0740e7c705f142f9b173jucablues const char *type_prefix = "?";
d297097bc1b9d4e074089ea5d649c2a0d270ff42nicholasbishop unsigned int type;
2ef3c2ef15d6c81069a1f6abeb5bdf502d18f616nicholasbishop time_t t;
2ef3c2ef15d6c81069a1f6abeb5bdf502d18f616nicholasbishop
5fdfb2a8aa9c3fb2d1c7d2f8b183a3643a4bc300tavmjong-free /* find type's prefix */
d16763fbe2a4e6b778d417469a8f047e86ffab91nicholasbishop for (type = 0; type < LOG_TYPE_COUNT; type++) {
d297097bc1b9d4e074089ea5d649c2a0d270ff42nicholasbishop if (strcmp(args[0], failure_log_type_names[type]) == 0) {
cd090649718da48f667e425406f075cbd81d29f7JucaBlues type_prefix = failure_log_type_prefixes[type];
d16763fbe2a4e6b778d417469a8f047e86ffab91nicholasbishop break;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
087b237ce230e9b7a16dc95537dbb62f7d715026nicholasbishop }
087b237ce230e9b7a16dc95537dbb62f7d715026nicholasbishop
087b237ce230e9b7a16dc95537dbb62f7d715026nicholasbishop if (str_to_time(args[1], &t) < 0) {
5fdfb2a8aa9c3fb2d1c7d2f8b183a3643a4bc300tavmjong-free i_error("Invalid timestamp: %s", args[1]);
5fdfb2a8aa9c3fb2d1c7d2f8b183a3643a4bc300tavmjong-free t = 0;
5fdfb2a8aa9c3fb2d1c7d2f8b183a3643a4bc300tavmjong-free }
f313394fee34e964f4088211bdf5fb82cce31378nicholasbishop if (t >= min_timestamp) {
2ef3c2ef15d6c81069a1f6abeb5bdf502d18f616nicholasbishop doveadm_print(t_strflocaltime(LOG_TIMESTAMP_FORMAT, t));
b068af856bbc33238f425b3221426aa52e554ce0nicholasbishop doveadm_print(t_cmd_log_error_trim(args[2]));
b068af856bbc33238f425b3221426aa52e554ce0nicholasbishop doveadm_print(t_cmd_log_error_trim(type_prefix));
f313394fee34e964f4088211bdf5fb82cce31378nicholasbishop doveadm_print(args[3]);
d297097bc1b9d4e074089ea5d649c2a0d270ff42nicholasbishop }
d297097bc1b9d4e074089ea5d649c2a0d270ff42nicholasbishop}
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
7237c264c3e0190918510e1b239fc6dd1efdfcd0nicholasbishopstatic void cmd_log_errors(int argc, char *argv[])
7237c264c3e0190918510e1b239fc6dd1efdfcd0nicholasbishop{
9da625e1ff559d10b9830fcfc127d8b12404386fnicholasbishop struct istream *input;
7237c264c3e0190918510e1b239fc6dd1efdfcd0nicholasbishop const char *path, *line, *const *args;
72ca199b70b9c4f5e9bbc921ac85fe9e3f9932b9mental time_t min_timestamp = 0;
72ca199b70b9c4f5e9bbc921ac85fe9e3f9932b9mental int c, fd;
72ca199b70b9c4f5e9bbc921ac85fe9e3f9932b9mental
72ca199b70b9c4f5e9bbc921ac85fe9e3f9932b9mental while ((c = getopt(argc, argv, "s:")) > 0) {
72ca199b70b9c4f5e9bbc921ac85fe9e3f9932b9mental switch (c) {
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental case 's':
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental if (str_to_time(optarg, &min_timestamp) < 0)
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental i_fatal("Invalid timestamp: %s", optarg);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental break;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental default:
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental help(&doveadm_cmd_log[3]);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental }
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental argv += optind - 1;
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental if (argv[1] != NULL)
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental help(&doveadm_cmd_log[3]);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental path = t_strconcat(doveadm_settings->base_dir,
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental "/"LOG_ERRORS_FNAME, NULL);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental fd = net_connect_unix(path);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental if (fd == -1)
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental i_fatal("net_connect_unix(%s) failed: %m", path);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental net_set_nonblock(fd, FALSE);
6e369d7e74c36e07f5fb1e27d37923fbed7dd89cmental
a4030d5ca449e7e384bc699cd249ee704faaeab0Chris Morgan input = i_stream_create_fd_autoclose(&fd, (size_t)-1);
doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
doveadm_print_formatted_set_format("%{timestamp} %{type}: %{prefix}: %{text}\n");
doveadm_print_header_simple("timestamp");
doveadm_print_header_simple("prefix");
doveadm_print_header_simple("type");
doveadm_print_header_simple("text");
while ((line = i_stream_read_next_line(input)) != NULL) T_BEGIN {
args = t_strsplit_tabescaped(line);
if (str_array_length(args) == 4)
cmd_log_error_write(args, min_timestamp);
else {
i_error("Invalid input from log: %s", line);
doveadm_exit_code = EX_PROTOCOL;
}
} T_END;
i_stream_destroy(&input);
}
struct doveadm_cmd doveadm_cmd_log[] = {
{ cmd_log_test, "log test", "" },
{ cmd_log_reopen, "log reopen", "" },
{ cmd_log_find, "log find", "[<dir>]" },
};
struct doveadm_cmd_ver2 doveadm_cmd_log_errors_ver2 = {
.name = "log errors",
.usage = "[-s <min_timestamp>]",
.old_cmd = cmd_log_errors,
DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_PARAM('s', "since", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAMS_END
};
void doveadm_register_log_commands(void)
{
unsigned int i;
doveadm_cmd_register_ver2(&doveadm_cmd_log_errors_ver2);
for (i = 0; i < N_ELEMENTS(doveadm_cmd_log); i++)
doveadm_register_cmd(&doveadm_cmd_log[i]);
}