/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "istream.h"
#include "llist.h"
#include "hash.h"
#include "time-util.h"
#include "process-title.h"
#include "master-interface.h"
#include "master-service.h"
#include "log-error-buffer.h"
#include "log-connection.h"
#include <stdio.h>
#include <unistd.h>
/* Log a warning after 1 secs when we've been all the time busy writing the
log connection. */
/* If we keep being busy, log a warning every 60 seconds. */
struct log_client {
char *prefix;
};
struct log_connection {
int fd;
int listen_fd;
char *default_prefix;
unsigned int pending_count;
};
static unsigned int global_pending_count;
static void
static void log_refresh_proctitle(void)
{
if (!verbose_proctitle)
return;
if (global_pending_count == 0)
process_title_set("");
else if (last_pending_log == NULL) {
"[%u services too fast]", global_pending_count));
} else if (global_pending_count > 1) {
"[%u services too fast, last: %d/%d/%s]",
} else {
"[service too fast: %d/%d/%s]",
}
}
{
}
return client;
}
{
}
const struct failure_line *failure)
{
}
}
static void
const struct failure_context *ctx,
{
case LOG_TYPE_DEBUG:
case LOG_TYPE_INFO:
case LOG_TYPE_OPTION:
break;
case LOG_TYPE_WARNING:
case LOG_TYPE_ERROR:
case LOG_TYPE_FATAL:
case LOG_TYPE_PANIC:
break;
case LOG_TYPE_COUNT:
i_unreached();
}
}
static void
{
}
}
}
static void
{
unsigned int count;
unsigned int service_fd;
return;
}
return;
}
/* master is probably shutting down and we already
noticed the log fd closing */
return;
}
i_error("Received master input for invalid service_fd %u: %s",
service_fd, line);
return;
}
/* we haven't seen anything important from this client.
it's not an error. */
return;
}
message. */
} else {
}
}
static void
{
const char *prefix;
T_BEGIN {
} T_END;
return;
}
case LOG_TYPE_FATAL:
case LOG_TYPE_PANIC:
}
break;
case LOG_TYPE_OPTION:
return;
default:
break;
}
}
{
const unsigned char *data;
/* we're reading from a FIFO, so we're assuming that we're getting a
full handshake packet immediately. if not, treat it as an error
message that we want to log. */
if (ret < 0) {
return -1;
}
/* this isn't a handshake */
return 0;
}
/* this isn't a handshake */
return 0;
}
i_error("Missing prefix data in handshake");
return -1;
}
i_error("Received master prefix in handshake "
return -1;
}
}
return 0;
}
{
const char *line;
if (!log->handshaked) {
if (log_connection_handshake(log) < 0) {
return;
}
/* come back here even if we read something else besides a
handshake. the first few lines could be coming from e.g.
libc before the proper handshake line is sent. */
}
/* get new timestamps for every read() */
break;
}
}
} else {
if (!too_much) {
if (log->pending_count > 0) {
log->pending_count = 0;
i_assert(global_pending_count > 0);
if (log == last_pending_log)
}
return;
}
if (log->pending_count++ == 0) {
}
i_warning("Log connection fd %d listen_fd %d prefix '%s' is sending input faster than we can write",
}
}
}
{
}
static void
{
void *key;
unsigned int client_count = 0;
client_count++;
}
if (client_count > 0 && shutting_down) {
i_warning("Shutting down logging for '%s' with %u clients",
}
i_error("close(log connection fd) failed: %m");
}
void log_connections_init(void)
{
}
void log_connections_deinit(void)
{
/* normally we don't exit until all log connections are gone,
but we could get here when we're being killed by a signal */
while (log_connections != NULL)
}