Hi,

Sorry for the delay in replying, I was away for a few weeks :) I have finally
reworked the patch according to your feedback.

On Mon, Oct 25, 2010 at 05:47:20PM +0100, Timo Sirainen wrote:
> You can simplify the environment preserving with these changes:
> 
> http://hg.dovecot.org/dovecot-2.0/rev/e0a97842182f
> http://hg.dovecot.org/dovecot-2.0/rev/d1fd5b84d410

Ah, that indeed makes things much simpler, thanks!

> 
> I don't think this is portable. You could do it instead like:

Ok, I changed it even after reading your other email.

> 
> > +        AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for 
> > systemd service files]),
> > +        [], [with_systemdsystemunitdir=$($PKG_CONFIG 
> > --variable=systemdsystemunitdir systemd)])
> 
> Is this a common name for this option? If not, I'd prefer a shorter
> name.

I asked upstream about it, and I was told it's the usual way of naming options
with the autotools, so they'd prefer if it was kept this way. But I don't mind
changing it to something else if you prefer, I have a patch changing it to
--with-systemd if needed.

Here is the updated patch, if you want I also have it as a patch series:
systemd: Add proper systemd configure.in blob (from daemon(7))
systemd: Preserve LISTEN_FDS and LISTEN_PID during env cleanup when systemd is 
used
systemd: Use sockets provided by systemd if possible
systemd: When systemd didn't provide a suitable socket, fallback to the regular 
socket creation code
systemd: Add systemd unit files

Christophe
diff --git a/Makefile.am b/Makefile.am
index d037258..8a6000a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,17 @@ dovecot-config: dovecot-config.in Makefile
        -e "s|^\(dovecot_moduledir\)=|\1=$(moduledir)|" \
        > dovecot-config
 
+if HAVE_SYSTEMD
+%.service: %.service.in
+       $(AM_V_GEN)sed -e 's,@sbindir\@,$(sbindir),g' $< > $@
+
+systemdsystemunit_DATA = \
+        dovecot.socket \
+        dovecot.service
+else
+EXTRA_DIST+= dovecot.socket dovecot.service.in
+endif
+
 install-exec-hook:
        rm $(DESTDIR)$(pkglibdir)/dovecot-config && \
        grep -v '^LIBDOVECOT_.*_INCLUDE' dovecot-config | \
@@ -62,6 +73,9 @@ install-exec-hook:
        > $(DESTDIR)$(pkglibdir)/dovecot-config
 
 CLEANFILES = $(datafiles)
+if HAVE_SYSTEMD
+CLEANFILES += $systedmsystemunit_DATA
+endif
 
 DISTCLEANFILES = $(top_builddir)/dovecot-version.h
 
diff --git a/configure.in b/configure.in
index 348f441..ecb3046 100644
--- a/configure.in
+++ b/configure.in
@@ -2628,6 +2628,16 @@ fi
 AC_SUBST(RUN_TEST)
 AC_SUBST(abs_top_builddir)
 
+PKG_PROG_PKG_CONFIG
+AC_ARG_WITH([systemdsystemunitdir],
+        AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for 
systemd service files]),
+        [], [with_systemdsystemunitdir=$($PKG_CONFIG 
--variable=systemdsystemunitdir systemd)])
+if test "x$with_systemdsystemunitdir" != xno; then
+        AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+        AC_DEFINE(HAVE_SYSTEMD,, Define if you want to use systemd socket 
activation)
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a 
"x$with_systemdsystemunitdir" != xno ])
+
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_FILES([
 Makefile
diff --git a/dovecot.service.in b/dovecot.service.in
new file mode 100644
index 0000000..db03946
--- /dev/null
+++ b/dovecot.service.in
@@ -0,0 +1,8 @@
+[Unit]
+Description=Dovecot IMAP/POP3 email server
+After=local-fs.target network.target
+
+[Service]
+Type=simple
+execsta...@sbindir@/dovecot -F
+NonBlocking=yes
diff --git a/dovecot.socket b/dovecot.socket
new file mode 100644
index 0000000..0fdef6f
--- /dev/null
+++ b/dovecot.socket
@@ -0,0 +1,15 @@
+[Unit]
+Description=Dovecot IMAP/POP3 email server activation socket
+
+[Socket]
+#dovecot expects separate IPv4 and IPv6 sockets
+BindIPv6Only=ipv6-only
+ListenStream=0.0.0.0:143
+ListenStream=[::]:143
+ListenStream=0.0.0.0:993
+ListenStream=[::]:993
+KeepAlive=true
+
+[Install]
+WantedBy=sockets.target
+
diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c
index e2dc98d..5925bb6 100644
--- a/src/lib-master/master-service.c
+++ b/src/lib-master/master-service.c
@@ -400,6 +400,10 @@ void master_service_env_clean(bool preserve_home)
 #ifdef DEBUG
                "GDB",
 #endif
+#ifdef HAVE_SYSTEMD
+               "LISTEN_PID",
+               "LISTEN_FDS",
+#endif
                NULL
        };
        env_clean_except(preserve_envs + (preserve_home ? 0 : 1));
diff --git a/src/master/Makefile.am b/src/master/Makefile.am
index 526b75b..9d3ad78 100644
--- a/src/master/Makefile.am
+++ b/src/master/Makefile.am
@@ -2,6 +2,11 @@ pkglibexecdir = $(libexecdir)/dovecot
 
 sbin_PROGRAMS = dovecot
 
+if HAVE_SYSTEMD
+SYSTEMD_SOURCES = sd-daemon.c
+endif
+
+
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
        -I$(top_srcdir)/src/lib-settings \
@@ -27,13 +32,15 @@ dovecot_SOURCES = \
        service-monitor.c \
        service-process.c \
        service-process-notify.c \
-       service.c
+       service.c \
+       $(SYSTEMD_SOURCES)
 
 noinst_HEADERS = \
        capabilities.h \
        common.h \
        dup2-array.h \
        master-settings.h \
+       sd-daemon.h \
        service-anvil.h \
        service-listen.h \
        service-log.h \
@@ -41,3 +48,4 @@ noinst_HEADERS = \
        service-process.h \
        service-process-notify.h \
        service.h
+
diff --git a/src/master/main.c b/src/master/main.c
index 5e390d6..2d862a0 100644
--- a/src/master/main.c
+++ b/src/master/main.c
@@ -601,6 +601,10 @@ int main(int argc, char *argv[])
        static const char *preserve_envs[] = {
                /* AIX depends on TZ to get the timezone correctly. */
                "TZ",
+#ifdef HAVE_SYSTEMD
+               "LISTEN_PID",
+               "LISTEN_FDS",
+#endif
                NULL
        };
        struct master_settings *set;
diff --git a/src/master/service-listen.c b/src/master/service-listen.c
index 318c098..976036b 100644
--- a/src/master/service-listen.c
+++ b/src/master/service-listen.c
@@ -5,6 +5,9 @@
 #include "fd-set-nonblock.h"
 #include "fd-close-on-exec.h"
 #include "network.h"
+#ifdef HAVE_SYSTEMD
+#include "sd-daemon.h"
+#endif
 #include "service.h"
 #include "service-listen.h"
 
@@ -147,20 +150,47 @@ static int service_inet_listener_listen(struct 
service_listener *l)
         struct service *service = l->service;
        const struct inet_listener_settings *set = l->set.inetset.set;
        unsigned int port = set->port;
-       int fd;
-
-       fd = net_listen(&l->set.inetset.ip, &port,
-                       service_get_backlog(service));
-       if (fd < 0) {
-               service_error(service, "listen(%s, %u) failed: %m",
-                             l->inet_address, set->port);
-               return errno == EADDRINUSE ? 0 : -1;
+       int fd = -1;
+#ifdef HAVE_SYSTEMD
+       int n;
+
+       n = sd_listen_fds(0);
+       if (n < 0) {
+               errno = -n;
+               goto failure;
+       } else if (n > 0) {
+               for (fd = SD_LISTEN_FDS_START;
+                    fd <= SD_LISTEN_FDS_START + n - 1;
+                    fd++) {
+                       if (sd_is_socket_inet(fd, l->set.inetset.ip.family,
+                                             SOCK_STREAM, 1, port))
+                               break;
+               }
+               if (fd > SD_LISTEN_FDS_START + n - 1) {
+                       /* when systemd didn't provide a usable socket,
+                        * fall back to the regular socket creation code
+                        */
+                       fd = -1;
+               }
+       }
+#endif
+
+       if (fd == -1) {
+               fd = net_listen(&l->set.inetset.ip, &port,
+                               service_get_backlog(service));
+               if (fd < 0)
+                       goto failure;
+               net_set_nonblock(fd, TRUE);
+               fd_close_on_exec(fd, TRUE);
        }
-       net_set_nonblock(fd, TRUE);
-       fd_close_on_exec(fd, TRUE);
 
        l->fd = fd;
        return 1;
+
+failure:
+       service_error(service, "listen(%s, %u) failed: %m",
+                     l->inet_address, set->port);
+       return errno == EADDRINUSE ? 0 : -1;
 }
 
 static int service_listen(struct service *service)

Attachment: pgpnbxIRhH13O.pgp
Description: PGP signature

Reply via email to