[dovecot-cvs] dovecot/src/util .cvsignore,NONE,1.1 Makefile.am,NONE,1.1 rawlog.c,NONE,1.1

cras at procontrol.fi cras at procontrol.fi
Thu Aug 21 03:24:31 EEST 2003


Update of /home/cvs/dovecot/src/util
In directory danu:/tmp/cvs-serv21652/src/util

Added Files:
	.cvsignore Makefile.am rawlog.c 
Log Message:
Separated rawlog into it's own binary.



--- NEW FILE: .cvsignore ---
*.la
*.lo
*.o
.deps
.libs
Makefile
Makefile.in
so_locations
rawlog

--- NEW FILE: Makefile.am ---
bin_PROGRAMS = rawlog

INCLUDES = \
	-I$(top_srcdir)/src/lib

rawlog_LDADD = \
	../lib/liblib.a

rawlog_SOURCES = \
	rawlog.c

--- NEW FILE: rawlog.c ---
/* Copyright (C) 2002-2003 Timo Sirainen */

#include "lib.h"

#include "ioloop.h"
#include "network.h"
#include "write-full.h"
#include "process-title.h"

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>

#define TIMESTAMP_WAIT_TIME 5
#define TIMESTAMP_FORMAT "* OK [RAWLOG TIMESTAMP] %Y-%m-%d %H:%M:%S\n"

static struct ioloop *ioloop;
static int client_in, client_out, imap_in, imap_out;
static int log_in, log_out;

static time_t last_write = 0;
static int last_lf = TRUE;

static void copy(int in, int out, int log)
{
	struct tm *tm;
	char buf[1024];
	ssize_t r_ret, s_ret;

	if (last_lf && ioloop_time - last_write > TIMESTAMP_WAIT_TIME) {
		tm = localtime(&ioloop_time);

		if (strftime(buf, sizeof(buf), TIMESTAMP_FORMAT, tm) <= 0)
			i_fatal("strftime() failed");
		if (write_full(log, buf, strlen(buf)) < 0)
			i_fatal("Can't write to log file: %m");
	}

	net_set_nonblock(in, TRUE);
	do {
		r_ret = net_receive(in, buf, sizeof(buf));
	} while (r_ret == 0);

	if (r_ret < 0) {
		if (r_ret == -1)
			i_error("imap_in: net_receive() failed: %m");

		/* disconnected */
		io_loop_stop(ioloop);
		return;
	}

	last_lf = buf[r_ret-1] == '\n';
	if (write_full(log, buf, r_ret) < 0)
		i_fatal("Can't write to log file: %m");

	net_set_nonblock(out, FALSE);
	do {
		s_ret = net_transmit(out, buf, r_ret);
		if (s_ret < 0) {
			if (s_ret == -1)
				i_error("imap_in: net_transmit() failed: %m");

			/* disconnected */
			io_loop_stop(ioloop);
			return;
		}
		r_ret -= s_ret;
	} while (r_ret > 0);

	last_write = time(NULL);
}

static void imap_input(void *context __attr_unused__)
{
	copy(imap_in, client_out, log_out);
}

static void client_input(void *context __attr_unused__)
{
	copy(client_in, imap_out, log_in);
}

static void rawlog_open(void)
{
	struct io *io_imap, *io_client;
	const char *home, *path, *fname;
	char timestamp[50];
	struct tm *tm;
	struct stat st;
	int sfd[2];
	pid_t pid, parent_pid;

	home = getenv("HOME");
	if (home == NULL)
		home = ".";

	/* see if we want rawlog */
	path = t_strconcat(home, "/dovecot.rawlog", NULL);
	if (stat(path, &st) < 0) {
		if (errno != ENOENT)
			i_warning("stat() failed for %s: %m", path);
		return;
	}

	/* yes, open the files. Do it before forking to make sure we don't
	   unneededly do it. */
	tm = localtime(&ioloop_time);
	if (strftime(timestamp, sizeof(timestamp), "%Y%m%d-%H%M%S", tm) <= 0)
		i_fatal("strftime() failed");

	fname = t_strdup_printf("%s/%s-%s.in", path, timestamp,
				dec2str(getpid()));
	log_in = open(fname, O_CREAT|O_EXCL|O_WRONLY, 0600);
	if (log_in == -1) {
		i_warning("rawlog_open: open() failed for %s: %m", fname);
		return;
	}

	fname = t_strdup_printf("%s/%s-%s.out", path, timestamp,
				dec2str(getpid()));
	log_out = open(fname, O_CREAT|O_EXCL|O_WRONLY, 0600);
	if (log_out == -1) {
		i_warning("rawlog_open: open() failed for %s: %m", fname);
		close(log_in);
		return;
	}

	/* we need to fork the rawlog writer to separate process since
	   imap process does blocking writes. */
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0)
		i_fatal("socketpair() failed: %m");

	parent_pid = getpid();

	pid = fork();
	if (pid < 0)
		i_fatal("fork() failed: %m");

	if (pid > 0) {
		/* parent */
		close(log_in); close(log_out);
		close(sfd[0]);
		if (dup2(sfd[1], 0) < 0)
			i_fatal("dup2(sfd, 0)");
		if (dup2(sfd[1], 1) < 0)
			i_fatal("dup2(sfd, 1)");
		return;
	}
	close(sfd[1]);

	process_title_set(t_strdup_printf("[%s:%s rawlog]", getenv("USER"),
					  dec2str(parent_pid)));

	/* child */
	client_in = 0;
	client_out = 1;
	imap_in = sfd[0];
	imap_out = sfd[0];

	ioloop = io_loop_create(system_pool);
	io_imap = io_add(imap_in, IO_READ, imap_input, NULL);
	io_client = io_add(client_in, IO_READ, client_input, NULL);

	io_loop_run(ioloop);

	io_remove(io_imap);
	io_remove(io_client);
	io_loop_destroy(ioloop);

	lib_deinit();
	exit(0);
}

int main(int argc, char *argv[], char *envp[])
{
	char *executable, *p;

	lib_init();
        process_title_init(argv, envp);

	if (argc < 2)
		i_fatal("Usage: rawlog <binary> <arguments>");

	rawlog_open();

	argv++;
	executable = argv[0];

	/* hide path, it's ugly */
	p = strrchr(argv[0], '/');
	if (p != NULL) argv[0] = p+1;
	execv(executable, argv);

	i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);

	/* not reached */
	return FATAL_EXEC;
}



More information about the dovecot-cvs mailing list