File cyrus-imapd-openslp.patch of Package cyrus-imapd.import5240

Index: configure.in
===================================================================
--- configure.in.orig
+++ configure.in
@@ -1193,6 +1193,19 @@ AC_ARG_WITH(drac, [  --with-drac=DIR
 	fi)
 AC_SUBST(DRACLIBS)
 
+dnl
+dnl Test for OpenSLP
+dnl
+SLPLIBS=
+AC_ARG_WITH(openslp, [  --with-openslp=DIR         use OpenSLP library in <DIR> [no] ],
+       if test -d "$withval"; then
+               LDFLAGS="$LDFLAGS -L${withval}"
+               AC_CHECK_LIB(slp, SLPOpen,
+                       AC_DEFINE(USE_SLP,[],[Compile with OpenSLP?])
+                       SLPLIBS="-lslp")
+       fi)
+AC_SUBST(SLPLIBS)
+
 CMU_LIBWRAP
 CMU_UCDSNMP
 
Index: master/Makefile.in
===================================================================
--- master/Makefile.in.orig
+++ master/Makefile.in
@@ -58,7 +58,7 @@ DEPLIBS = @DEPLIBS@
 
 CFLAGS = @CFLAGS@
 LDFLAGS = @LDFLAGS@ @COM_ERR_LDFLAGS@
-LIBS = ../lib/libcyrus_min.a @LIB_UCDSNMP@ @LIBS@ @COM_ERR_LIBS@
+LIBS = ../lib/libcyrus_min.a @LIB_UCDSNMP@ @LIBS@ @COM_ERR_LIBS@ @SLPLIBS@
 
 SHELL = /bin/sh
 MAKEDEPEND = @MAKEDEPEND@
Index: master/master.c
===================================================================
--- master/master.c.orig
+++ master/master.c
@@ -110,6 +110,10 @@
   int deny_severity = LOG_ERR;
 #endif
 
+#ifdef USE_SLP
+#include <slp.h>
+#endif
+
 #include "masterconf.h"
 
 #include "master.h"
@@ -119,6 +123,16 @@
 #include "util.h"
 #include "xmalloc.h"
 
+#ifdef USE_SLP
+#define URL_MAX 1024
+SLPHandle  phslp;
+struct slpurl {
+    char srvurl[URL_MAX];
+    struct slpurl *next;
+};
+struct slpurl *start = NULL;
+#endif
+
 enum {
     become_cyrus_early = 1,
     child_table_size = 10000,
@@ -181,10 +195,41 @@ static struct timeval janitor_mark;	/* L
 void limit_fds(rlim_t);
 void schedule_event(struct event *a);
 
+#ifdef USE_SLP
+void SLPRegReportCB(SLPHandle hslp, SLPError errcode, void* cookie)
+{
+    /* return the error code in the cookie */
+    *(SLPError*)cookie = errcode;
+
+    /* You could do something else here like print out  */
+    /* the errcode, etc.  Remember, as a general rule,  */
+    /* do not try to do too much in a callback because  */
+    /* it is being executed by the same thread that is  */
+    /* reading slp packets from the wire.               */
+}
+
+void SLPshutdown(void)
+{ 
+    struct slpurl *ttmp,*tmp = start;
+    SLPError callbackerr;
+    while( tmp ) {
+       syslog(LOG_INFO,"SLPderegister [%s]",tmp->srvurl);
+       SLPDereg(phslp, tmp->srvurl, SLPRegReportCB, &callbackerr);
+       ttmp = tmp;
+       tmp = tmp->next;
+       free(ttmp);
+    }
+    SLPClose(&phslp);
+}
+#endif
+
 void fatal(const char *msg, int code)
 {
     syslog(LOG_CRIT, "%s", msg);
     syslog(LOG_NOTICE, "exiting");
+#ifdef USE_SLP
+    SLPshutdown();
+#endif
     exit(code);
 }
 
@@ -466,7 +511,90 @@ void service_create(struct service *s)
 	    s->socket = 0;
 	    continue;
 	}
-	
+
+#ifdef USE_SLP
+	if ((!strcmp(s->proto, "tcp")) && s->listen[0] != '/' ) {
+	   SLPError err;
+	   SLPError callbackerr;
+	   char *listen, *service;
+	   char *listen_addr;
+	   int port;
+	   char hname[URL_MAX];
+	   char dname[URL_MAX];
+	   char turl[URL_MAX];
+	   struct slpurl *u;
+	   char registered = 0;
+
+
+	   /* parse_listen() and resolve_host() are destructive,
+	    * so make a work copy of s->listen
+	    */
+	   listen = xstrdup(s->listen);
+
+           if ((service = parse_listen(listen)) == NULL) {
+               /* listen IS the port */
+	       service = listen;
+	       listen_addr = NULL;
+           } else {
+               /* s->listen is now just the address */
+	       listen_addr = parse_host(listen);
+	       if (*listen_addr == '\0')
+	   	listen_addr = NULL;	    
+           }
+	   port = ntohs(((struct sockaddr_in *)(res)->ai_addr)->sin_port);
+	   gethostname(hname,URL_MAX);
+	   getdomainname(dname,URL_MAX);
+
+	   snprintf(turl,URL_MAX,"service:%s://%s.%s:%d",
+		 service,
+		 hname, dname,
+		 port);
+
+	   /* check, whether we already registered the service */
+	   u = start;
+	   while( u ) {
+	     if( ! strcmp(u->srvurl,turl) ) registered = 1;
+	     u = u->next;
+	   }
+
+	   if( ! registered ) {
+	       u = (struct slpurl *)calloc(1,sizeof(struct slpurl));
+	       if( ! u )
+	            fatal("out of memory", EX_UNAVAILABLE);
+
+	       strncpy(u->srvurl,turl,URL_MAX);
+
+	       if( start == NULL ) {
+	         start = u;
+	       } else {
+	         struct slpurl *tmp = start;
+	         while( tmp->next ) tmp = tmp->next;
+	         tmp->next = u;
+	       }
+	       syslog(LOG_INFO,"SLPRegister [%s]",u->srvurl);
+
+	       err = SLPReg(phslp,
+                      u->srvurl,
+                      SLP_LIFETIME_MAXIMUM,
+                      0,
+                      "",
+                      SLP_TRUE,
+                      SLPRegReportCB,
+                      &callbackerr );
+
+	       if(( err != SLP_OK) || (callbackerr != SLP_OK))
+	       {
+	           syslog(LOG_ERR,"Error registering service with slp %i",err);
+	       }
+	       
+	       if( callbackerr != SLP_OK)
+	       {
+	           syslog(LOG_ERR,"Error registering service with slp %i",callbackerr);
+	       }
+	   }
+	}
+#endif
+
 	s->ready_workers = 0;
 	s->associate = nsocket;
 	s->family = res->ai_family;
@@ -1022,6 +1150,9 @@ void sigterm_handler(int sig __attribute
     /* tell master agent we're exiting */
     snmp_shutdown("cyrusMaster");
 #endif
+#ifdef USE_SLP
+    SLPshutdown();
+#endif
 
     syslog(LOG_INFO, "exiting on SIGTERM/SIGINT");
     exit(0);
@@ -1876,6 +2007,16 @@ int main(int argc, char **argv)
 
     syslog(LOG_NOTICE, "process started");
 
+#ifdef USE_SLP
+    {
+      int slperr;
+      if ( (slperr = SLPOpen(NULL, SLP_FALSE, &phslp)) != SLP_OK ) {
+         syslog(LOG_ERR, "SLPOpen() failed, return code: %d", slperr);
+      }
+    }
+#endif
+
+
 #if defined(HAVE_UCDSNMP) || defined(HAVE_NETSNMP)
     /* initialize SNMP agent */