Memleak: free the list of search hooks on exit
[citadel.git] / citadel / serv_extensions.c
index 421824a9b0ce156b4f90b44b837ba41a7668883c..e23772e9602c9f72086375e5e185b7ecec7b6de2 100644 (file)
@@ -1,9 +1,6 @@
 /*
- * $Id$
- *
  * Citadel Dynamic Loading Module
  * Written by Brian Costello <btx@calyx.net>
- *
  */
 
 #include "sysdep.h"
@@ -78,7 +75,7 @@ char *ErrPortShort = "We couldn't bind all ports you configured to be provided b
 char *ErrPortWhere = "Admin->System Preferences->Network.\n\nThe failed ports and sockets are: ";
 char *ErrPortHint = "If you want citadel to provide you with that functionality, "
 "check the output of \"netstat -lnp\" on linux Servers or \"netstat -na\" on *BSD"
-" and stop the programm, that binds these ports. You should eventually remove "
+" and stop the programm, that binds these ports.\n You should eventually remove "
 " their initscripts in /etc/init.d so that you won't get this trouble once more.\n"
 " After that goto Administration -> Shutdown Citadel to make Citadel retry to bind this port.\n";
 
@@ -192,7 +189,7 @@ int DLoader_Exec_Cmd(char *cmdbuf)
        return 0;
 }
 
-int FourHash(const char *key, long length) 
+long FourHash(const char *key, long length) 
 {
        int i;
        int ret = 0;
@@ -727,12 +724,11 @@ void CtdlRegisterServiceHook(int tcp_port,
 {
        struct ServiceFunctionHook *newfcn;
        char *message;
-       char *error;
+       char error[SIZ];
 
-       error = NULL;
-       newfcn = (struct ServiceFunctionHook *)
-           malloc(sizeof(struct ServiceFunctionHook));
-       message = (char*) malloc (SIZ);
+       strcpy(error, "");
+       newfcn = (struct ServiceFunctionHook *) malloc(sizeof(struct ServiceFunctionHook));
+       message = (char*) malloc (SIZ + SIZ);
        
        newfcn->next = ServiceHookTable;
        newfcn->tcp_port = tcp_port;
@@ -743,7 +739,7 @@ void CtdlRegisterServiceHook(int tcp_port,
        newfcn->ServiceName = ServiceName;
 
        if (sockpath != NULL) {
-               newfcn->msock = ig_uds_server(sockpath, config.c_maxsessions, &error);
+               newfcn->msock = ctdl_uds_server(sockpath, config.c_maxsessions, error);
                snprintf(message, SIZ, "Unix domain socket '%s': ", sockpath);
        }
        else if (tcp_port <= 0) {       /* port -1 to disable */
@@ -753,10 +749,10 @@ void CtdlRegisterServiceHook(int tcp_port,
                return;
        }
        else {
-               newfcn->msock = ig_tcp_server(config.c_ip_addr,
+               newfcn->msock = ctdl_tcp_server(config.c_ip_addr,
                                              tcp_port,
                                              config.c_maxsessions, 
-                                             &error);
+                                             error);
                snprintf(message, SIZ, "TCP port %s:%d: (%s) ", 
                         config.c_ip_addr, tcp_port, ServiceName);
        }
@@ -770,7 +766,6 @@ void CtdlRegisterServiceHook(int tcp_port,
                AddPortError(message, error);
                strcat(message, "FAILED.");
                CtdlLogPrintf(CTDL_CRIT, "%s\n", message);
-               free(error);
                free(newfcn);
        }
        free(message);
@@ -785,7 +780,8 @@ void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
 {
        struct ServiceFunctionHook *cur, *p;
 
-       for (cur = ServiceHookTable; cur != NULL; cur = cur->next) {
+       cur = ServiceHookTable;
+       while (cur != NULL) {
                /* This will also remove duplicates if any */
                while (cur != NULL &&
                                !(sockpath && cur->sockpath &&
@@ -813,6 +809,32 @@ void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
        }
 }
 
+
+void CtdlShutdownServiceHooks(void)
+{
+       /* sort of a duplicate of close_masters() but called earlier */
+       struct ServiceFunctionHook *cur;
+
+       cur = ServiceHookTable;
+       while (cur != NULL) 
+       {
+               if (cur->msock != -1)
+               {
+                       close(cur->msock);
+                       cur->msock = -1;
+                       if (cur->sockpath != NULL){
+                               CtdlLogPrintf(CTDL_INFO, "[%s] Closed UNIX domain socket %s\n",
+                                             cur->ServiceName,
+                                             cur->sockpath);
+                       } else {
+                               CtdlLogPrintf(CTDL_INFO, "[%s] closing service\n", 
+                                             cur->ServiceName);
+                       }
+               }
+               cur = cur->next;
+       }
+}
+
 void CtdlDestroyServiceHook(void)
 {
        struct ServiceFunctionHook *cur, *p;
@@ -836,7 +858,7 @@ void CtdlDestroyServiceHook(void)
        ServiceHookTable = NULL;
 }
 
-void CtdlRegisterSearchFuncHook(void (*fcn_ptr)(int *, long **, char *), char *name)
+void CtdlRegisterSearchFuncHook(void (*fcn_ptr)(int *, long **, const char *), char *name)
 {
        struct SearchFunctionHook *newfcn;
 
@@ -854,7 +876,7 @@ void CtdlRegisterSearchFuncHook(void (*fcn_ptr)(int *, long **, char *), char *n
        CtdlLogPrintf(CTDL_INFO, "Registered a new search function (%s)\n", name);
 }
 
-void CtdlUnregisterSearchFuncHook(void (*fcn_ptr)(int *, long **, char *), char *name)
+void CtdlUnregisterSearchFuncHook(void (*fcn_ptr)(int *, long **, const char *), char *name)
 {
        struct SearchFunctionHook *cur, *p;
        
@@ -871,7 +893,20 @@ void CtdlUnregisterSearchFuncHook(void (*fcn_ptr)(int *, long **, char *), char
        }
 }
 
-void CtdlModuleDoSearch(int *num_msgs, long **search_msgs, char *search_string, char *func_name)
+void CtdlDestroySearchHooks(void)
+{
+        struct SearchFunctionHook *cur, *p;
+
+       cur = SearchFunctionHookTable;
+       SearchFunctionHookTable = NULL;
+        while (cur != NULL) {
+               p = cur->next;
+               free(cur);
+               cur = p;
+       }
+}
+
+void CtdlModuleDoSearch(int *num_msgs, long **search_msgs, const char *search_string, const char *func_name)
 {
        struct SearchFunctionHook *fcn = NULL;
 
@@ -891,6 +926,9 @@ void PerformSessionHooks(int EventType)
 
        for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
                if (fcn->eventtype == EventType) {
+                       if (EventType == EVT_TIMER) {
+                               citthread_setspecific(MyConKey, NULL);  /* for every hook */
+                       }
                        (*fcn->h_function_pointer) ();
                }
        }