diff -Nru mailutils.cvs/imap4d/imap4d.c mailutils.nebu/imap4d/imap4d.c
--- mailutils.cvs/imap4d/imap4d.c	2004-01-15 14:18:35.000000000 +0100
+++ mailutils.nebu/imap4d/imap4d.c	2004-03-21 13:55:52.000000000 +0100
@@ -219,6 +219,7 @@
 imap4d_mainloop (int fd, FILE *infile, FILE *outfile)
 {
   char *text;
+  char *peer;
 
   /* Reset hup to exit.  */
   signal (SIGHUP, imap4d_signal);
@@ -230,15 +231,10 @@
   /* log information on the connecting client */
   if (!debug_mode)
     {
-      struct sockaddr_in cs;
-      int len = sizeof cs;
-
       syslog (LOG_INFO, _("Incoming connection opened"));
-      if (getpeername (fd, (struct sockaddr *) &cs, &len) < 0)
-	syslog (LOG_ERR, _("can't obtain IP address of client: %s"),
-		strerror (errno));
-      else
-	syslog (LOG_INFO, _("connect from %s"), inet_ntoa (cs.sin_addr));
+      if (mu_getpeername (fd, &peer)) {
+	syslog (LOG_INFO, _("connect from %s"), peer);
+      }
       text = "IMAP4rev1";
     }
   else
@@ -300,75 +296,30 @@
 static void
 imap4d_daemon (unsigned int maxchildren, unsigned int port)
 {
-  struct sockaddr_in server, client;
-  pid_t pid;
-  int listenfd, connfd;
-  size_t size;
+  int ret;
 
-  listenfd = socket (PF_INET, SOCK_STREAM, 0);
-  if (listenfd == -1)
-    {
-      syslog (LOG_ERR, "socket: %s", strerror (errno));
-      exit (1);
-    }
-  size = 1;			/* Use size here to avoid making a new variable.  */
-  setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof (size));
-  size = sizeof (server);
-  memset (&server, 0, size);
-  server.sin_family = AF_INET;
-  server.sin_addr.s_addr = htonl (INADDR_ANY);
-  server.sin_port = htons (port);
+  list_t sockets;
 
-  if (bind (listenfd, (struct sockaddr *) &server, size) == -1)
-    {
-      syslog (LOG_ERR, "bind: %s", strerror (errno));
-      exit (1);
-    }
+  list_create(&sockets);
 
-  if (listen (listenfd, 128) == -1)
+  /* FIXME: need to handle a liste of interfaces to listen on
+   * for each interface, create the corresponding sockets*/
+    
+    ret = mu_getsockets(0, NULL, port, 0, sockets);
+  if (ret)
     {
-      syslog (LOG_ERR, "listen: %s", strerror (errno));
-      exit (1);
-    }
+    syslog (LOG_ERR, "imap4d_daemon: unable to create sockets");
+    exit(1);
+  }
 
   syslog (LOG_INFO, _("GNU imap4d started"));
 
-  for (;;)
-    {
-      if (children > maxchildren)
-	{
-	  syslog (LOG_ERR, _("too many children (%lu)"),
-		  (unsigned long) children);
-	  pause ();
-	  continue;
-	}
-      connfd = accept (listenfd, (struct sockaddr *) &client,
-		       (socklen_t *) & size);
-      if (connfd == -1)
-	{
-	  if (errno == EINTR)
-	    continue;
-	  syslog (LOG_ERR, "accept: %s", strerror (errno));
-	  exit (1);
-	}
-
-      pid = fork ();
-      if (pid == -1)
-	syslog (LOG_ERR, "fork: %s", strerror (errno));
-      else if (pid == 0)	/* Child.  */
-	{
-	  int status;
-	  close (listenfd);
-	  status = imap4d_mainloop (connfd,
-				    fdopen (connfd, "r"),
-				    fdopen (connfd, "w"));
-	  closelog ();
-	  exit (status);
-	}
-      else
-	{
-	  ++children;
-	}
-      close (connfd);
-    }
+  ret = mu_select (sockets, maxchildren, &imap4d_mainloop);
+  if (ret) {
+    syslog (LOG_ERR, "imap4d_daemon: unbale to listen for connections");
+    exit(1);
+  }
+
+  exit(0);
+  
 }
diff -Nru mailutils.cvs/imap4d/imap4d.h mailutils.nebu/imap4d/imap4d.h
--- mailutils.cvs/imap4d/imap4d.h	2003-10-06 15:08:50.000000000 +0200
+++ mailutils.nebu/imap4d/imap4d.h	2003-12-31 00:58:03.000000000 +0100
@@ -57,6 +57,9 @@
 #include <netdb.h>
 #include <ctype.h>
 
+/* POSIX 1003.1g: 6.2 Select from File Descriptor Sets <sys/select.h>  */
+#include <sys/select.h>
+
 #ifdef HAVE_ALLOCA_H
 # include <alloca.h>
 #endif
diff -Nru mailutils.cvs/include/mailutils/mutil.h mailutils.nebu/include/mailutils/mutil.h
--- mailutils.cvs/include/mailutils/mutil.h	2004-01-13 16:08:24.000000000 +0100
+++ mailutils.nebu/include/mailutils/mutil.h	2004-03-20 20:47:10.000000000 +0100
@@ -66,6 +66,16 @@
  */
 extern int mu_get_host_name __P((char **host));
 
+/* Get the peername using getaddrinfo */
+extern int mu_getpeername __P((int fd, char** peer));
+
+/*  Get sockets for a host and store them in a list.
+ *   if family = 0 we use PF_UNSPEC
+ *   if node is NULL we use AI_PASSIVE
+ *   if sock_type = 0 we use SOCK_STREAM
+ */
+extern int mu_getsockets __P((int family, char *node, int port, int sock_type, list_t sockets));
+
 /* Set the default user email address.
  *
  * Subsequent calls to mu_get_user_email() with a NULL name will return this
diff -Nru mailutils.cvs/mailbox/mutil.c mailutils.nebu/mailbox/mutil.c
--- mailutils.cvs/mailbox/mutil.c	2004-01-13 16:08:24.000000000 +0100
+++ mailutils.nebu/mailbox/mutil.c	2004-03-21 13:39:36.000000000 +0100
@@ -303,6 +303,262 @@
   return 0;
 }
 
+
+int
+mu_getpeername (int fd, char** peer)
+{
+  struct sockaddr_storage cs;
+  int len = sizeof cs;
+
+  if (getpeername (fd, (struct sockaddr *) &cs, &len) < 0)
+    mu_error ("can't obtain IP address of client: %s", strerror (errno));
+  else {
+    switch (cs.ss_family) {
+    case AF_INET: {
+      *peer = malloc (INET_ADDRSTRLEN);
+      struct in_addr src = ((struct sockaddr_in *) &cs)->sin_addr;
+
+      if (!inet_ntop (AF_INET, (const void*) &src, *peer, INET_ADDRSTRLEN)) {
+	mu_error ("inet_ntop error: %s", strerror (errno));
+	break;
+      }
+      return 0;
+    }
+    case AF_INET6: {
+      *peer = malloc (INET6_ADDRSTRLEN);
+      struct in6_addr src = ((struct sockaddr_in6 *) &cs)->sin6_addr;
+
+      if (!inet_ntop (AF_INET6, (const void*) &src, *peer, INET6_ADDRSTRLEN)) {
+	mu_error ("inet_ntop error: %s", strerror (errno));
+	break;
+      }
+      return 0;
+    }
+    default:
+      mu_error ("mu_getpeername: %s", strerror(EAFNOSUPPORT));
+    }
+  }
+  return -1;
+}
+
+/* Create sockets an append them in the sockets list ready for listen
+   we do not take care of the protocol, 0 by default */
+int
+mu_getsockets (int family, char *node, int port, int sock_type, list_t sockets)
+{
+  int ret, on;
+  int *v4_fd = malloc (sizeof(int));
+  int *v6_fd = malloc (sizeof(int));
+
+  struct addrinfo *srv, *ptr;
+  struct addrinfo hints = {
+    0,
+    PF_UNSPEC,
+    0,
+    0,
+    0,
+    NULL,
+    NULL,
+    NULL
+  };
+
+  /* port in null terminated string format for getaddrinfo 5+1 char (port is a
+     short)*/
+  char service[6];
+
+  /* if sockets are for a client get canonname of target node */
+  hints.ai_flags = (node != NULL ? AI_CANONNAME : AI_PASSIVE) ;
+
+  /* get the good family from PF_UNSPEC, PF_INET, PF_INET6
+     if 0 default is PF_UNSPEC*/
+  hints.ai_family = (family != 0 ? family : PF_UNSPEC) ;
+
+  /* set sock_type of the socket default is SOCK_STREAM */
+  hints.ai_socktype = (sock_type != 0 ? sock_type : SOCK_STREAM);
+
+  snprintf (service, sizeof (service), "%d", port);
+  service[5] = 0;
+
+  ret = getaddrinfo (node, service, &hints, &srv);
+  if (ret)
+    {
+      mu_error ("getaddrinfo: %s", gai_strerror (ret));
+      return -1;
+    }
+
+  for (ptr = srv; ptr; ptr = ptr->ai_next)
+    {
+      switch (ptr->ai_family)
+	{
+/* #ifndef NO_IPV4 */
+	case AF_INET:
+	  {
+	    /* FIXME add an --ipv4 | -4 option to break here if ipv4 is unwanted */
+
+	    *v4_fd = socket (PF_INET, SOCK_STREAM, 0);
+	    if (*v4_fd == -1)
+	      {
+		mu_error ("socket: %s", strerror (errno));
+		break;
+	      }
+
+	    on = 1;
+	    setsockopt (*v4_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
+
+	    if (bind (*v4_fd, ptr->ai_addr, ptr->ai_addrlen) == -1)
+	      {
+		mu_error ("bind: %s", strerror (errno));
+		exit (1);
+	      }
+	    list_append (sockets, (void*) v4_fd);
+	    break;
+	  }
+/* #endif */
+/* #ifndef NO_IPV6 */
+	case AF_INET6:
+	  {
+	    /* FIXME add an --ipv6 | -6 option to break here if ipv6 is unwanted */
+	    
+	    *v6_fd = socket (PF_INET6, SOCK_STREAM, 0);
+	    if (*v6_fd == -1)
+	      {
+		mu_error ("socket: %s", strerror (errno));
+		exit (1);
+	      }
+
+	    ((struct sockaddr_in6 *) ptr->ai_addr)->sin6_flowinfo = 0;
+
+	    on = 1;
+	    if (setsockopt(*v6_fd, IPPROTO_IPV6, IPV6_V6ONLY,
+			   (char *)&on, sizeof(on)) == -1)
+		mu_error ("setsockopt: %s\n", strerror (errno));
+	    
+	    on = 1;
+	    setsockopt (*v6_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
+
+	    if (bind (*v6_fd, ptr->ai_addr, ptr->ai_addrlen) == -1)
+	      {
+		mu_error ("bind: %s", strerror (errno));
+		exit (1);
+	      }
+
+	    list_append (sockets, (void*) v6_fd);
+	    break;
+	  }
+/* #endif */
+	default:
+	  mu_error ("mu_getsockets: %s", strerror(EAFNOSUPPORT));
+	}
+    }
+  freeaddrinfo (srv);
+
+  return 0;
+}
+
+/* Make all the necesary work to listen on incomming sockets */
+int
+mu_select (list_t sockets, int maxchildren,
+	       int (*handler) (int fd, FILE *infile, FILE *outfile))
+{
+  pid_t pid;
+  fd_set fdset;
+  int *fd;
+  int connfd;
+
+  struct sockaddr_storage client;
+  socklen_t size = sizeof (client);
+
+  iterator_t itr;
+
+  int ret, children = 0;
+
+  ret = iterator_create (&itr, sockets);
+  if (ret) {
+    mu_error ("iterator_create : error number %d", ret);
+    return 1;
+  }
+
+  for (;;)
+    {
+      if (children > maxchildren)
+	{
+	  mu_error (_("too many children (%lu)"),
+		  (unsigned long) children);
+	  pause ();
+	  continue;
+	}
+
+      FD_ZERO (&fdset);
+
+      for (iterator_first(itr); !iterator_is_done(itr); iterator_next(itr))
+	{
+	  iterator_current (itr, (void**) &fd);
+
+	  /* Do not listen on fd if unwanted or file descriptor to big for slect
+	   *  (paranoiac attitude)
+	   */
+	  if (listen (*fd, 128) == -1)
+	    {
+	      mu_error ("listen: %s", strerror (errno));
+	      exit (1);
+	    }
+
+	  if (*fd && (*fd < FD_SETSIZE))
+	    FD_SET (*fd, &fdset);
+
+	}
+
+      if (select (FD_SETSIZE, &fdset, NULL, NULL, NULL) < 0)
+	{
+	  if (errno == EINTR)
+	    continue;
+	  mu_error ("mu_select: %s", strerror (errno));
+	  iterator_destroy (&itr);
+	  return 1;
+	}
+
+      /* We have something interesting somewhere*/
+      for (iterator_first(itr); !iterator_is_done(itr); iterator_next(itr))
+	{
+	  iterator_current (itr, (void**) &fd);
+
+	  if (*fd && FD_ISSET (*fd, &fdset))
+	    {
+	      connfd = accept (*fd, (struct sockaddr *) &client, &size);
+	      if (connfd == -1)
+		{
+		  if (errno == EINTR)
+		    continue;
+		  mu_error ("accept: %s", strerror (errno));
+		  iterator_destroy (&itr);
+		  return 1;
+		}
+
+	      pid = fork ();
+	      if (pid == -1)
+		mu_error ("fork: %s", strerror (errno));
+	      else if (pid == 0)	/* Child.  */
+		{
+		  int status;
+		  close (*fd);
+
+		  status = handler (connfd,
+				    fdopen (connfd, "r"),
+				    fdopen (connfd, "w"));
+		  exit (status);
+		}
+	      else
+		{
+		  ++children;
+		}
+	      close (connfd);
+	    }
+	}
+    }
+  iterator_destroy (&itr);
+  return 0;
+}
+
 /*
  * Functions used to convert unix mailbox/user names into RFC822 addr-specs.
  */
@@ -1170,4 +1426,3 @@
     return 1;
   return 0;
 }
-    
