service.c revision 832bcb7bea1f6b67bf28527896a7ee6c977b7a0f
/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
#include "common.h"
#include "ioloop.h"
#include "array.h"
#include "aqueue.h"
#include "hash.h"
#include "str.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "service.h"
#include "service-anvil.h"
#include "service-process.h"
#include "service-monitor.h"
#include <unistd.h>
#include <signal.h>
#define SERVICE_LOGIN_NOTIFY_MIN_INTERVAL_SECS 2
struct hash_table *service_pids;
{
}
static struct service_listener *
enum service_listener_type type,
const struct file_listener_settings *set,
const char **error_r)
{
struct service_listener *l;
l->fd = -1;
return NULL;
return NULL;
return l;
}
static int
{
unsigned int ips_count;
int ret;
/* IPv4 any */
return 0;
}
/* IPv6 any */
return 0;
}
/* Return the first IP if there happens to be multiple. */
if (ret != 0) {
return -1;
}
if (ips_count < 1) {
return -1;
}
if (ips_count > 1) {
address);
return -1;
}
return 0;
}
static struct service_listener *
const struct inet_listener_settings *set,
{
struct service_listener *l;
l->type = SERVICE_LISTENER_INET;
l->fd = -1;
return NULL;
*error_r = "Port not given";
return NULL;
}
return NULL;
}
return l;
}
static int
const struct inet_listener_settings *set,
const char **error_r)
{
static struct service_listener *l;
/* disabled */
return 0;
}
else {
/* use the default listen address */
}
continue;
error_r);
if (l == NULL)
return -1;
}
return 0;
}
static struct service *
{
struct file_listener_settings *const *unix_listeners;
struct file_listener_settings *const *fifo_listeners;
struct inet_listener_settings *const *inet_listeners;
struct service_listener *l;
const char *const *tmp;
if (set->service_count > 0 &&
if (set->process_limit == 0) {
/* unlimited */
/* use default */
} else {
}
*error_r = "executable not given";
return NULL;
}
/* default gid to user's primary group */
return NULL;
return NULL;
}
error_r) < 0)
return NULL;
return NULL;
}
}
else {
}
/* set these later, so if something fails we don't have to worry about
closing them */
}
else {
unix_count = 0;
}
else {
fifo_count = 0;
}
else {
inet_count = 0;
}
*error_r = "Service must have unix listeners";
return NULL;
}
for (i = 0; i < unix_count; i++) {
if (unix_listeners[i]->mode == 0) {
/* disabled */
continue;
}
unix_listeners[i], error_r);
if (l == NULL)
return NULL;
}
for (i = 0; i < fifo_count; i++) {
if (unix_listeners[i]->mode == 0) {
/* disabled */
continue;
}
fifo_listeners[i], error_r);
if (l == NULL)
return NULL;
}
for (i = 0; i < inet_count; i++) {
error_r) < 0)
return NULL;
}
return NULL;
}
return service;
}
static unsigned int pid_hash(const void *p)
{
return (unsigned int)*pid;
}
{
}
struct service *
{
return service;
}
return NULL;
}
struct service *
{
return service;
}
return NULL;
}
{
char *const *proto;
return TRUE;
return TRUE;
}
return FALSE;
}
const char *const *child_process_env,
{
struct service_list *service_list;
struct service_settings *const *service_settings;
const char *error;
unsigned int i, count;
for (i = 0; i < count; i++) {
if (!service_want(service_settings[i]))
continue;
service_list, &error);
return -1;
}
case SERVICE_TYPE_LOG:
*error_r = "Multiple log services specified";
return -1;
}
break;
case SERVICE_TYPE_CONFIG:
*error_r = "Multiple config services specified";
return -1;
}
break;
case SERVICE_TYPE_ANVIL:
*error_r = "Multiple anvil services specified";
return -1;
}
break;
default:
break;
}
}
*error_r = "log service not specified";
return -1;
}
*error_r = "config process not specified";
return -1;
}
return 0;
}
{
if (!SERVICE_PROCESS_IS_INITIALIZED(process) &&
/* too early to signal it */
continue;
}
}
}
}
{
}
{
}
{
enum master_login_state state;
int diff;
return;
/* change the state always immediately. it's cheap. */
/* but don't send signal to processes too often */
return;
service);
} else {
}
}
{
bool sigterm_log;
int sig;
else
i_warning("Processes aren't dying after reload, sending %s.",
log_service = NULL;
else
}
/* kill log service later so it could still have a chance of logging
something */
}
}
{
/* make sure we log if child processes died unexpectedly */
}
}
{
service_list->refcount++;
}
{
if (--service_list->refcount > 0)
return;
}
{
struct service_listener *const *listeners;
unsigned int count;
}
{
}
{
return;
}
unsigned int secs)
{
}
}
void service_pids_init(void)
{
}
void service_pids_deinit(void)
{
struct hash_iterate_context *iter;
/* free all child process information */
}