master-service.c revision 6ed1e82824590b514201d9db84ba96bdfc832dd5
/* Copyright (C) 2005-2009 Timo Sirainen */
#include "lib.h"
#include "lib-signals.h"
#include "ioloop.h"
#include "array.h"
#include "env-util.h"
#include "home-expand.h"
#include "restrict-access.h"
#include "fd-close-on-exec.h"
#include "settings-parser.h"
#include "syslog-util.h"
#include "master-service-private.h"
#include "master-service-settings.h"
#include <stdlib.h>
#include <unistd.h>
#include <syslog.h>
#define MASTER_CONFIG_FILE_ENV "CONFIG_FILE"
/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
struct master_service *master_service;
const char *master_service_getopt_string(void)
{
return "c:ko:Os:L";
}
{
/* warn about being killed because of some signal, except SIGINT (^C)
which is too common at least while testing :) */
i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
}
}
{
i_fatal("Dovecot version mismatch: "
"(if you don't care, set version_ignore=yes)",
}
}
struct master_service *
{
struct master_service *service;
const char *str;
#ifdef DEBUG
(flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
int count;
}
#endif
/* NOTE: we start rooted, so keep the code minimal until
restrict_access_by_env() is called */
lib_init();
/* Set a logging prefix temporarily. This will be ignored once the log
is properly initialized */
if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
} else {
}
/* set up some kind of logging until we know exactly how and where
we want to log */
} else {
}
return service;
}
unsigned int max_lines_per_sec)
{
const char *path;
return;
}
/* logging via log service */
return;
}
return;
}
/* log to syslog */
int facility;
&facility))
} else {
/* log to file or stderr */
}
if (*path != '\0')
}
bool set)
{
}
{
int i;
switch (opt) {
case 'c':
break;
case 'k':
break;
case 'o':
break;
case 'O':
break;
case 's':
service->socket_count = i;
break;
case 'L':
break;
default:
return FALSE;
}
return TRUE;
}
{
else
}
static void master_status_error(void *context)
{
/* status fd is a write-only pipe, so if we're here it means the
master wants us to die (or died itself). don't die until all
service connections are finished. */
/* the log fd may also be closed already, don't die when trying to
log later */
}
{
const char *value;
unsigned int count;
/* set default signal handlers */
i_fatal("Must be started by dovecot master process");
/* initialize master_status structure */
/* set the default limit */
if (count == 0)
/* set the default service count */
if (count > 0)
/* start listening errors for status fd, it means master died */
} else {
}
/* we already have a connection to be served */
}
}
void master_service_env_clean(bool preserve_home)
{
#ifdef DEBUG
#endif
/* Note that if the original environment was set with env_put(), the
environment strings will be invalid after env_clean(). That's why
we t_strconcat() them above. */
env_clean();
#ifdef DEBUG
#endif
}
unsigned int client_limit)
{
unsigned int used;
}
{
return service->total_available_count;
}
unsigned int count)
{
unsigned int used;
}
}
{
return service->service_count_left;
}
{
return service->socket_count;
}
{
return service->config_path;
}
{
return service->version_string;
}
{
}
{
}
{
}
{
return;
if (ret < 0) {
/* anvil process was probably recreated, don't bother
logging an error about losing connection to it */
return;
}
i_error("write(anvil) failed: %m");
} else if (ret == 0)
i_error("write(anvil) failed: EOF");
else {
}
}
{
/* we can listen again */
} else {
/* we have only limited amount of service requests left */
if (service->service_count_left == 0) {
}
}
/* we've finished handling all clients, and
a) master has closed the connection
b) there are no listeners (std-client?) */
}
}
{
}
lib_deinit();
}
static void master_service_listen(struct master_service_listener *l)
{
struct master_service_connection conn;
/* we are full. stop listening for now. */
return;
}
return;
i_error("net_accept() failed: %m");
return;
}
/* it's not a socket. probably a fifo. use the "listener"
as the connection fd and stop the listener. */
l->fd = -1;
}
}
{
unsigned int i;
if (service->socket_count == 0)
return;
for (i = 0; i < service->socket_count; i++) {
l->fd = MASTER_LISTEN_FD_FIRST + i;
}
}
{
unsigned int i;
for (i = 0; i < service->socket_count; i++) {
}
}
}
{
unsigned int i;
for (i = 0; i < service->socket_count; i++) {
}
}
}
{
return TRUE;
if (!service->initial_status_sent)
return TRUE;
return FALSE;
}
{
return; /* closed */
sizeof(service->master_status));
if (ret > 0) {
/* success */
/* delayed important update sent successfully */
}
} else if (ret == 0) {
/* shouldn't happen? */
i_error("write(master_status_fd) returned 0");
/* failure */
i_error("write(master_status_fd) failed: %m");
} else if (master_status_update_is_important(service)) {
/* reader is busy, but it's important to get this notification
through. send it when possible. */
}
}
}