[dovecot-cvs] dovecot/src/login-common Makefile.am,1.2,1.3 main.c,1.6,1.7 master.c,1.4,1.5 master.h,1.1,1.2

cras at procontrol.fi cras at procontrol.fi
Tue Mar 4 06:02:58 EET 2003


Update of /home/cvs/dovecot/src/login-common
In directory danu:/tmp/cvs-serv14529/login-common

Modified Files:
	Makefile.am main.c master.c master.h 
Log Message:
Somewhat working code to support loading Dovecot from inetd and such. It
still needs possibility to specify which login process to use, and LOGIN and
AUTHENTICATE commands shouldn't be allowed before we're connected to auth
process.



Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/login-common/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile.am	2 Feb 2003 10:46:20 -0000	1.2
+++ Makefile.am	4 Mar 2003 04:02:56 -0000	1.3
@@ -1,7 +1,9 @@
 noinst_LIBRARIES = liblogin-common.a
 
 INCLUDES = \
-	-I$(top_srcdir)/src/lib
+	-I$(top_srcdir)/src/lib \
+	-DPKG_RUNDIR=\""$(localstatedir)/run/$(PACKAGE)"\" \
+	-DSBINDIR=\""$(sbindir)"\"
 
 liblogin_common_a_SOURCES = \
 	auth-common.c \

Index: main.c
===================================================================
RCS file: /home/cvs/dovecot/src/login-common/main.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- main.c	23 Feb 2003 19:44:47 -0000	1.6
+++ main.c	4 Mar 2003 04:02:56 -0000	1.7
@@ -23,7 +23,7 @@
 static struct ioloop *ioloop;
 static struct io *io_listen, *io_ssl_listen;
 static int main_refcount;
-static int closing_down;
+static int is_inetd, closing_down;
 
 void main_ref(void)
 {
@@ -99,7 +99,6 @@
 
 static void login_accept_ssl(void *context __attr_unused__)
 {
-	struct client *client;
 	struct ip_addr ip;
 	int fd, fd_ssl;
 
@@ -124,7 +123,7 @@
 	if (fd_ssl == -1)
 		net_disconnect(fd);
 	else
-		client = client_create(fd_ssl, &ip, TRUE);
+		(void)client_create(fd_ssl, &ip, TRUE);
 }
 
 static void open_logfile(const char *name)
@@ -185,25 +184,29 @@
 
 	io_listen = io_ssl_listen = NULL;
 
-	if (net_getsockname(LOGIN_LISTEN_FD, NULL, NULL) == 0) {
-		io_listen = io_add(LOGIN_LISTEN_FD, IO_READ,
-				   login_accept, NULL);
-	}
+	if (!is_inetd) {
+		if (net_getsockname(LOGIN_LISTEN_FD, NULL, NULL) == 0) {
+			io_listen = io_add(LOGIN_LISTEN_FD, IO_READ,
+					   login_accept, NULL);
+		}
 
-	if (net_getsockname(LOGIN_SSL_LISTEN_FD, NULL, NULL) == 0) {
-		if (!ssl_initialized) {
-			/* this shouldn't happen, master should have
-			   disabled the ssl socket.. */
-			i_fatal("BUG: SSL initialization parameters not given "
-				"while they should have been");
+		if (net_getsockname(LOGIN_SSL_LISTEN_FD, NULL, NULL) == 0) {
+			if (!ssl_initialized) {
+				/* this shouldn't happen, master should have
+				   disabled the ssl socket.. */
+				i_fatal("BUG: SSL initialization parameters "
+					"not given while they should have "
+					"been");
+			}
+
+			io_ssl_listen = io_add(LOGIN_SSL_LISTEN_FD, IO_READ,
+					       login_accept_ssl, NULL);
 		}
 
-		io_ssl_listen = io_add(LOGIN_SSL_LISTEN_FD, IO_READ,
-				       login_accept_ssl, NULL);
+		/* initialize master last - it sends the "we're ok"
+		   notification */
+		master_init(LOGIN_MASTER_SOCKET_FD);
 	}
-
-	/* initialize master last - it sends the "we're ok" notification */
-	master_init();
 }
 
 static void main_deinit(void)
@@ -226,23 +229,54 @@
 int main(int argc __attr_unused__, char *argv[], char *envp[])
 {
 	const char *name;
+	struct ip_addr ip;
+	int fd = -1, master_fd = -1;
+
+	is_inetd = getenv("DOVECOT_MASTER") == NULL;
 
 #ifdef DEBUG
-        fd_debug_verify_leaks(4, 1024);
+	if (!is_inetd)
+		fd_debug_verify_leaks(4, 1024);
 #endif
 	/* NOTE: we start rooted, so keep the code minimal until
 	   restrict_access_by_env() is called */
 	lib_init();
 
+	if (is_inetd) {
+		/* running from inetd. create master process before
+		   dropping privileges */
+		master_fd = master_connect();
+	}
+
 	name = strrchr(argv[0], '/');
 	drop_privileges(name == NULL ? argv[0] : name+1);
 
 	process_title_init(argv, envp);
 	ioloop = io_loop_create(system_pool);
 
-	main_init();
-        io_loop_run(ioloop);
-	main_deinit();
+	if (is_inetd) {
+		master_init(master_fd);
+
+		if (net_getsockname(1, &ip, NULL) < 0) {
+			i_fatal("%s can be started only through dovecot "
+				"master process, inetd or equilevant", argv[0]);
+		}
+
+		if (argc < 2 || strcmp(argv[1], "--ssl") != 0)
+			fd = 1;
+		else
+			fd = ssl_proxy_new(fd, &ip);
+	}
+
+	if (fd != -1 || !is_inetd) {
+		main_init();
+
+		if (fd != -1)
+			(void)client_create(fd, &ip, TRUE);
+
+		io_loop_run(ioloop);
+		main_deinit();
+	}
 
 	io_loop_destroy(ioloop);
 	lib_deinit();

Index: master.c
===================================================================
RCS file: /home/cvs/dovecot/src/login-common/master.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- master.c	11 Feb 2003 16:53:14 -0000	1.4
+++ master.c	4 Mar 2003 04:02:56 -0000	1.5
@@ -5,11 +5,14 @@
 #include "ioloop.h"
 #include "network.h"
 #include "fdpass.h"
+#include "istream.h"
+#include "env-util.h"
 #include "master.h"
 #include "client-common.h"
 
 #include <unistd.h>
 
+static int master_fd;
 static struct io *io_master;
 static struct hash_table *master_requests;
 
@@ -42,8 +45,7 @@
 	req.auth_id = auth_id;
 	req.ip = client->ip;
 
-	if (fd_send(LOGIN_MASTER_SOCKET_FD,
-		    client->fd, &req, sizeof(req)) != sizeof(req))
+	if (fd_send(master_fd, client->fd, &req, sizeof(req)) != sizeof(req))
 		i_fatal("fd_send(%d) failed: %m", client->fd);
 
 	client->master_callback = callback;
@@ -60,8 +62,7 @@
 	memset(&req, 0, sizeof(req));
 
 	/* sending -1 as fd does the notification */
-	if (fd_send(LOGIN_MASTER_SOCKET_FD,
-		    -1, &req, sizeof(req)) != sizeof(req))
+	if (fd_send(master_fd, -1, &req, sizeof(req)) != sizeof(req))
 		i_fatal("fd_send(-1) failed: %m");
 }
 
@@ -70,8 +71,9 @@
 	if (io_master == NULL)
 		return;
 
-	if (close(LOGIN_MASTER_SOCKET_FD) < 0)
+	if (close(master_fd) < 0)
 		i_fatal("close(master) failed: %m");
+	master_fd = -1;
 
 	io_remove(io_master);
 	io_master = NULL;
@@ -83,11 +85,94 @@
 	clients_destroy_all();
 }
 
+static void master_exec(int fd)
+{
+	char *argv[] = { "dovecot", "--inetd", NULL };
+
+	switch (fork()) {
+	case -1:
+		i_fatal("fork() failed: %m");
+	case 0:
+		if (dup2(fd, 0) < 0)
+			i_fatal("master_exec: dup2(%d, 0) failed: %m", fd);
+		(void)close(fd);
+
+		if (setsid() < 0)
+			i_fatal("setsid() failed: %m");
+
+		execv(SBINDIR"/dovecot", argv);
+		i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
+			       SBINDIR"/dovecot");
+	default:
+		(void)close(fd);
+	}
+}
+
+static void master_read_env(int fd)
+{
+	struct istream *input;
+	const char *line;
+
+	env_clean();
+
+	/* read environment variable lines until empty line comes */
+	input = i_stream_create_file(fd, default_pool, 8192, FALSE);
+	do {
+		switch (i_stream_read(input)) {
+		case -1:
+			i_fatal("EOF while reading environment from master");
+		case -2:
+			i_fatal("Too large environment line from master");
+		}
+
+		while ((line = i_stream_next_line(input)) != NULL &&
+		       *line != '\0')
+			env_put(line);
+	} while (line == NULL);
+
+	i_stream_unref(input);
+}
+
+int master_connect(void)
+{
+	const char *path = PKG_RUNDIR"/master";
+	int i, fd = -1;
+
+	for (i = 0; i < 5 && fd == -1; i++) {
+		fd = net_connect_unix(path);
+		if (fd != -1)
+			break;
+
+		if (errno == ECONNREFUSED) {
+			if (unlink(path) < 0)
+				i_error("unlink(%s) failed: %m", path);
+		} else if (errno != ENOENT) {
+			i_fatal("Can't connect to master UNIX socket %s: %m",
+				path);
+		}
+
+		/* need to create it */
+		fd = net_listen_unix(path);
+		if (fd != -1) {
+			master_exec(fd);
+			fd = -1;
+		} else if (errno != EADDRINUSE) {
+			i_fatal("Can't create master UNIX socket %s: %m", path);
+		}
+	}
+
+	if (fd == -1)
+		i_fatal("Couldn't use/create UNIX socket %s", path);
+
+	master_read_env(fd);
+	return fd;
+}
+
 static void master_input(void *context __attr_unused__)
 {
 	int ret;
 
-	ret = net_receive(LOGIN_MASTER_SOCKET_FD, master_buf + master_pos,
+	ret = net_receive(master_fd, master_buf + master_pos,
 			  sizeof(master_buf) - master_pos);
 	if (ret < 0) {
 		/* master died, kill all clients logging in */
@@ -104,19 +189,20 @@
 	master_pos = 0;
 }
 
-void master_init(void)
+void master_init(int fd)
 {
 	main_ref();
 
+	master_fd = fd;
 	master_requests = hash_create(default_pool, default_pool,
 				      0, NULL, NULL);
 
         master_pos = 0;
-	io_master = io_add(LOGIN_MASTER_SOCKET_FD, IO_READ, master_input, NULL);
+	io_master = io_add(master_fd, IO_READ, master_input, NULL);
 
 	/* just a note to master that we're ok. if we die before,
 	   master should shutdown itself. */
-        master_notify_finished();
+	master_notify_finished();
 }
 
 void master_deinit(void)

Index: master.h
===================================================================
RCS file: /home/cvs/dovecot/src/login-common/master.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- master.h	28 Jan 2003 21:35:26 -0000	1.1
+++ master.h	4 Mar 2003 04:02:56 -0000	1.2
@@ -16,7 +16,10 @@
 /* Close connection to master process */
 void master_close(void);
 
-void master_init(void);
+/* inetd: Connect to existing master process, or create new one. */
+int master_connect(void);
+
+void master_init(int fd);
 void master_deinit(void);
 
 #endif




More information about the dovecot-cvs mailing list