[dovecot-cvs] dovecot/src/master dict-process.c, NONE, 1.1 dict-process.h, NONE, 1.1

cras at dovecot.org cras at dovecot.org
Thu Jan 12 12:54:29 EET 2006


Update of /var/lib/cvs/dovecot/src/master
In directory talvi:/tmp/cvs-serv3602

Added Files:
	dict-process.c dict-process.h 
Log Message:
Forgot to add in last commit.



--- NEW FILE: dict-process.c ---
/* Copyright (C) 2006 Timo Sirainen */

#include "common.h"
#include "ioloop.h"
#include "network.h"
#include "fd-close-on-exec.h"
#include "env-util.h"
#include "log.h"
#include "dict-process.h"

#include <syslog.h>
#include <unistd.h>
#include <sys/stat.h>

#define DEFAULT_DICT_SERVER_SOCKET_PATH "/var/run/dovecot/dict-server"

struct dict_process {
	const char *path;
	int fd;
	struct io *io;
};

static struct dict_process *process;

static void dict_process_unlisten(struct dict_process *process);

static int dict_process_start(struct dict_process *process)
{
	struct log_io *log;
	const char *executable;
	int i, log_fd;
	pid_t pid;

	log_fd = log_create_pipe(&log, 0);
	if (log_fd < 0)
		pid = -1;
	else {
		pid = fork();
		if (pid < 0)
			i_error("fork() failed: %m");
	}

	if (pid < 0) {
		(void)close(log_fd);
		return -1;
	}

	if (pid != 0) {
		/* master */
		PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_DICT);
		log_set_prefix(log, "dict: ");
		(void)close(log_fd);

                dict_process_unlisten(process);
		return 0;
	}
	log_set_prefix(log, "master-dict: ");

	/* set stdin and stdout to /dev/null, so anything written into it
	   gets ignored. */
	if (dup2(null_fd, 0) < 0)
		i_fatal("dup2(stdin) failed: %m");
	if (dup2(null_fd, 1) < 0)
		i_fatal("dup2(stdout) failed: %m");

	/* stderr = log, 3 = listener */
	if (dup2(log_fd, 2) < 0)
		i_fatal("dup2(stderr) failed: %m");
	if (dup2(process->fd, 3) < 0)
		i_fatal("dup2(3) failed: %m");

	for (i = 0; i <= 3; i++)
		fd_close_on_exec(i, FALSE);

	child_process_init_env();
	env_put(t_strconcat("DICT_LISTEN_FROM_FD=", process->path, NULL));

	/* make sure we don't leak syslog fd, but do it last so that
	   any errors above will be logged */
	closelog();

	executable = PKG_LIBEXECDIR"/dict";
	client_process_exec(executable, "");
	i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);
	return -1;
}

static void dict_process_listen_input(void *context)
{
	struct dict_process *process = context;

	dict_process_start(process);
}

static int dict_process_listen(struct dict_process *process)
{
	mode_t old_umask;
	int fd, i = 0;

	for (;;) {
		old_umask = umask(0);
		process->fd = net_listen_unix(process->path, 64);
		umask(old_umask);

		if (process->fd != -1)
			break;

		if (errno != EADDRINUSE || ++i == 2) {
			i_error("net_listen_unix(%s) failed: %m",
				process->path);
			return -1;
		}

		/* see if it really exists */
		fd = net_connect_unix(process->path);
		if (fd != -1 || errno != ECONNREFUSED) {
			if (fd != -1) (void)close(fd);
			i_error("Socket already exists: %s", process->path);
			return -1;
		}

		/* delete and try again */
		if (unlink(process->path) < 0 && errno != ENOENT) {
			i_error("unlink(%s) failed: %m", process->path);
			return -1;
		}
	}

	fd_close_on_exec(process->fd, TRUE);
	process->io = io_add(process->fd, IO_READ,
			     dict_process_listen_input, process);

	return process->fd != -1 ? 0 : -1;
}

static void dict_process_unlisten(struct dict_process *process)
{
	if (process->fd == -1)
		return;

	if (close(process->fd) < 0)
		i_error("close(dict) failed: %m");
	process->fd = -1;

	io_remove(process->io);
	process->io = NULL;
}

void dict_process_init(void)
{
	process = i_new(struct dict_process, 1);
	process->fd = -1;
	process->path = DEFAULT_DICT_SERVER_SOCKET_PATH;
	(void)dict_process_listen(process);
}

void dict_process_deinit(void)
{
	dict_process_unlisten(process);
	i_free(process);
}

void dict_process_restart(void)
{
	dict_process_deinit();
	dict_process_init();
}

--- NEW FILE: dict-process.h ---
#ifndef __DICT_PROCESS_H
#define __DICT_PROCESS_H

void dict_process_init(void);
void dict_process_deinit(void);
void dict_process_restart(void);

#endif



More information about the dovecot-cvs mailing list