]> code.citadel.org Git - citadel.git/blobdiff - citadel/dynloader.c
* Got bounce messages working (mostly ... testers, please beat this up!)
[citadel.git] / citadel / dynloader.c
index 1f6dab1cd164c956ab981a0492d1775ad5346872..be6d6353a1e0fe1c1602fcbff392481884f1518b 100644 (file)
 #include <dirent.h>
 #include <strings.h>
 #include <syslog.h>
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
 #include <limits.h>
-#include "dynloader.h"
+#include <ctype.h>
 #include "citadel.h"
 #include "server.h"
+#include "dynloader.h"
 #include "sysdep_decls.h"
+#include "msgbase.h"
+#include "tools.h"
+#include "config.h"
 
 #ifndef HAVE_SNPRINTF
 #include <stdarg.h>
@@ -35,6 +36,9 @@ struct LogFunctionHook *LogHookTable = NULL;
 struct CleanupFunctionHook *CleanupHookTable = NULL;
 struct SessionFunctionHook *SessionHookTable = NULL;
 struct UserFunctionHook *UserHookTable = NULL;
+struct XmsgFunctionHook *XmsgHookTable = NULL;
+struct MessageFunctionHook *MessageHookTable = NULL;
+struct ServiceFunctionHook *ServiceHookTable = NULL;
 
 struct ProtoFunctionHook {
        void (*handler) (char *cmdbuf);
@@ -56,6 +60,7 @@ void CtdlRegisterProtoHook(void (*handler) (char *), char *cmd, char *desc)
        p->desc = desc;
        p->next = ProtoHookList;
        ProtoHookList = p;
+       lprintf(5, "Registered server command %s (%s)\n", cmd, desc);
 }
 
 int DLoader_Exec_Cmd(char *cmdbuf)
@@ -74,11 +79,12 @@ int DLoader_Exec_Cmd(char *cmdbuf)
 void DLoader_Init(char *pathname)
 {
        void *fcn_handle;
-       const char *dl_error;
+       char dl_error[256];
        DIR *dir;
+       int i;
        struct dirent *dptr;
-       struct DLModule_Info *(*h_init_fcn) (void);
-       struct DLModule_Info *dl_info;
+       char *(*h_init_fcn) (void);
+       char *dl_info;
 
        char pathbuf[PATH_MAX];
 
@@ -87,7 +93,9 @@ void DLoader_Init(char *pathname)
                exit(1);
        }
        while ((dptr = readdir(dir)) != NULL) {
-               if (dptr->d_name[0] == '.')
+               if (strlen(dptr->d_name) < 4)
+                       continue;
+               if (strcasecmp(&dptr->d_name[strlen(dptr->d_name)-3], ".so"))
                        continue;
 
                snprintf(pathbuf, PATH_MAX, "%s/%s", pathname, dptr->d_name);
@@ -97,27 +105,29 @@ void DLoader_Init(char *pathname)
                if (!(fcn_handle = dlopen(pathbuf, DL_LAZY)))
 #endif
                {
-                       /* dl_error = dlerror(); */
-                       fprintf(stderr, "DLoader_Init dlopen failed\n");
+                       safestrncpy(dl_error, dlerror(), sizeof dl_error);
+                       for (i=0; i<strlen(dl_error); ++i)
+                               if (!isprint(dl_error[i]))
+                                       dl_error[i]='.';
+                       fprintf(stderr, "DLoader_Init dlopen failed: %s\n",
+                               dl_error);
                        continue;
                }
-               h_init_fcn = (struct DLModule_Info * (*)(void))
+               h_init_fcn = (char * (*)(void))
 #ifndef __OpenBSD__
                    dlsym(fcn_handle, "Dynamic_Module_Init");
 #else
                    dlsym(fcn_handle, "_Dynamic_Module_Init");
 #endif
 
-               if ((dl_error = dlerror()) != NULL) {
-                       fprintf(stderr, "DLoader_Init dlsym failed (%s)\n", dl_error);
+               if (dlerror() != NULL) {
+                       fprintf(stderr, "DLoader_Init dlsym failed\n");
                        continue;
                }
                dl_info = h_init_fcn();
 
-               printf("Loaded module: %s v%d.%d\nBy %s (%s)\n", dl_info->module_name,
-                      dl_info->major_version, dl_info->minor_version,
-                  dl_info->module_author, dl_info->module_author_email);
-       }                       /* While */
+               lprintf(3, "Loaded module: %s\n", dl_info);
+       }       /* While */
 }
 
 
@@ -187,6 +197,66 @@ void CtdlRegisterUserHook(void (*fcn_ptr) (char *, long), int EventType)
 }
 
 
+void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
+                               int EventType)
+{
+
+       struct MessageFunctionHook *newfcn;
+
+       newfcn = (struct MessageFunctionHook *)
+           mallok(sizeof(struct MessageFunctionHook));
+       newfcn->next = MessageHookTable;
+       newfcn->h_function_pointer = handler;
+       newfcn->eventtype = EventType;
+       MessageHookTable = newfcn;
+
+       lprintf(5, "Registered a new message function (type %d)\n",
+               EventType);
+}
+
+
+void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
+{
+
+       struct XmsgFunctionHook *newfcn;
+
+       newfcn = (struct XmsgFunctionHook *)
+           mallok(sizeof(struct XmsgFunctionHook));
+       newfcn->next = XmsgHookTable;
+       newfcn->order = order;
+       newfcn->h_function_pointer = fcn_ptr;
+       XmsgHookTable = newfcn;
+       lprintf(5, "Registered a new x-msg function (priority %d)\n", order);
+}
+
+void CtdlRegisterServiceHook(int tcp_port,
+                       void (*h_greeting_function) (void),
+                       void (*h_command_function) (void) )
+{
+       struct ServiceFunctionHook *newfcn;
+
+       newfcn = (struct ServiceFunctionHook *)
+           mallok(sizeof(struct ServiceFunctionHook));
+       newfcn->next = ServiceHookTable;
+       newfcn->tcp_port = tcp_port;
+       newfcn->h_greeting_function = h_greeting_function;
+       newfcn->h_command_function = h_command_function;
+       newfcn->msock = ig_tcp_server(tcp_port, config.c_maxsessions);
+
+       if (newfcn->msock >= 0) {
+               ServiceHookTable = newfcn;
+               lprintf(5, "Registered a new service (TCP port %d)\n",
+                       tcp_port);
+       }
+       else {
+               lprintf(2, "ERROR: could not bind to TCP port %d.\n",
+                       tcp_port);
+               phree(newfcn);
+       }
+}
+
+
+
 void PerformSessionHooks(int EventType)
 {
        struct SessionFunctionHook *fcn;
@@ -219,3 +289,60 @@ void PerformUserHooks(char *username, long usernum, int EventType)
                }
        }
 }
+
+int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
+{
+       struct MessageFunctionHook *fcn;
+       int total_retval = 0;
+
+       /* Other code may elect to protect this message from server-side
+        * handlers; if this is the case, don't do anything.
+        */
+       lprintf(9, "** Event type is %d, flags are %d\n",
+               EventType, msg->cm_flags);
+       if (msg->cm_flags & CM_SKIP_HOOKS) {
+               lprintf(9, "Skipping hooks\n");
+               return(0);
+       }
+
+       /* Otherwise, run all the hooks appropriate to this event type.
+        */
+       for (fcn = MessageHookTable; fcn != NULL; fcn = fcn->next) {
+               if (fcn->eventtype == EventType) {
+                       total_retval = total_retval +
+                               (*fcn->h_function_pointer) (msg);
+               }
+       }
+
+       /* Return the sum of the return codes from the hook functions.  If
+        * this is an EVT_BEFORESAVE event, a nonzero return code will cause
+        * the save operation to abort.
+        */
+       return total_retval;
+}
+
+
+
+int PerformXmsgHooks(char *sender, char *recp, char *msg)
+{
+       struct XmsgFunctionHook *fcn;
+       int total_sent = 0;
+       int p;
+
+       for (p=0; p<MAX_XMSG_PRI; ++p) {
+               for (fcn = XmsgHookTable; fcn != NULL; fcn = fcn->next) {
+                       if (fcn->order == p) {
+                               total_sent +=
+                                       (*fcn->h_function_pointer)
+                                               (sender, recp, msg);
+                       }
+               }
+               /* Break out of the loop if a higher-priority function
+                * successfully delivered the message.  This prevents duplicate
+                * deliveries to local users simultaneously signed onto
+                * remote services.
+                */
+               if (total_sent) goto DONE;
+       }
+DONE:  return total_sent;
+}