2 * Citadel Dynamic Loading Module
3 * Written by Brian Costello <btx@calyx.net>
5 * Copyright (c) 1987-2011 by the citadel.org team
7 * This program is open source software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <sys/types.h>
32 #include <libcitadel.h>
35 #include "serv_extensions.h"
36 #include "sysdep_decls.h"
40 #include "modules/crypto/serv_crypto.h" /* Needed until a universal crypto startup hook is implimented for CtdlStartTLS */
42 #include "ctdl_module.h"
49 struct CleanupFunctionHook *CleanupHookTable = NULL;
50 struct CleanupFunctionHook *EVCleanupHookTable = NULL;
51 struct SessionFunctionHook *SessionHookTable = NULL;
52 struct UserFunctionHook *UserHookTable = NULL;
53 struct XmsgFunctionHook *XmsgHookTable = NULL;
54 struct MessageFunctionHook *MessageHookTable = NULL;
55 struct NetprocFunctionHook *NetprocHookTable = NULL;
56 struct DeleteFunctionHook *DeleteHookTable = NULL;
57 struct ServiceFunctionHook *ServiceHookTable = NULL;
58 struct FixedOutputHook *FixedOutputTable = NULL;
59 struct RoomFunctionHook *RoomHookTable = NULL;
60 struct SearchFunctionHook *SearchFunctionHookTable = NULL;
62 struct ProtoFunctionHook {
63 void (*handler) (char *cmdbuf);
68 HashList *ProtoHookList = NULL;
71 #define ERR_PORT (1 << 1)
74 static StrBuf *portlist = NULL;
76 static StrBuf *errormessages = NULL;
79 long DetailErrorFlags;
80 ConstStr Empty = {HKEY("")};
81 char *ErrSubject = "Startup Problems";
82 ConstStr ErrGeneral[] = {
83 {HKEY("Citadel had trouble on starting up. ")},
84 {HKEY(" This means, citadel won't be the service provider for a specific service you configured it to.\n\n"
85 "If you don't want citadel to provide these services, turn them off in WebCit via: ")},
86 {HKEY("To make both ways actualy take place restart the citserver with \"sendcommand down\"\n\n"
87 "The errors returned by the system were:\n")},
88 {HKEY("You can recheck the above if you follow this faq item:\n"
89 "http://www.citadel.org/doku.php?id=faq:mastering_your_os:net#netstat")}
92 ConstStr ErrPortShort = { HKEY("We couldn't bind all ports you configured to be provided by citadel server.\n")};
93 ConstStr ErrPortWhere = { HKEY("\"Admin->System Preferences->Network\".\n\nThe failed ports and sockets are: ")};
94 ConstStr ErrPortHint = { HKEY("If you want citadel to provide you with that functionality, "
95 "check the output of \"netstat -lnp\" on linux Servers or \"netstat -na\" on *BSD"
96 " and stop the program that binds these ports.\n You should eventually remove "
97 " their initscripts in /etc/init.d so that you won't get this trouble once more.\n"
98 " After that goto \"Administration -> Shutdown Citadel\" to make Citadel restart & retry to bind this port.\n")};
101 void LogPrintMessages(long err)
104 StrBuf *List, *DetailList;
105 ConstStr *Short, *Where, *Hint;
108 Message = NewStrBufPlain(NULL,
109 StrLength(portlist) + StrLength(errormessages));
111 DetailErrorFlags = DetailErrorFlags & ~err;
116 Short = &ErrPortShort;
117 Where = &ErrPortWhere;
120 DetailList = errormessages;
130 StrBufAppendBufPlain(Message, CKEY(ErrGeneral[0]), 0);
131 StrBufAppendBufPlain(Message, CKEY(*Short), 0);
132 StrBufAppendBufPlain(Message, CKEY(ErrGeneral[1]), 0);
133 StrBufAppendBufPlain(Message, CKEY(*Where), 0);
134 StrBufAppendBuf(Message, List, 0);
135 StrBufAppendBufPlain(Message, HKEY("\n\n"), 0);
136 StrBufAppendBufPlain(Message, CKEY(*Hint), 0);
137 StrBufAppendBufPlain(Message, HKEY("\n\n"), 0);
138 StrBufAppendBufPlain(Message, CKEY(ErrGeneral[2]), 0);
139 StrBufAppendBuf(Message, DetailList, 0);
140 StrBufAppendBufPlain(Message, HKEY("\n\n"), 0);
141 StrBufAppendBufPlain(Message, CKEY(ErrGeneral[3]), 0);
143 syslog(LOG_EMERG, "%s", ChrPtr(Message));
144 syslog(LOG_EMERG, "%s", ErrSubject);
145 quickie_message("Citadel", NULL, NULL, AIDEROOM, ChrPtr(Message), FMT_FIXED, ErrSubject);
147 FreeStrBuf(&Message);
149 FreeStrBuf(&DetailList);
153 void AddPortError(char *Port, char *ErrorMessage)
157 DetailErrorFlags |= ERR_PORT;
159 len = StrLength(errormessages);
160 if (len > 0) StrBufAppendBufPlain(errormessages, HKEY("; "), 0);
161 else errormessages = NewStrBuf();
162 StrBufAppendBufPlain(errormessages, ErrorMessage, -1, 0);
165 len = StrLength(portlist);
166 if (len > 0) StrBufAppendBufPlain(portlist, HKEY(";"), 0);
167 else portlist = NewStrBuf();
168 StrBufAppendBufPlain(portlist, Port, -1, 0);
172 int DLoader_Exec_Cmd(char *cmdbuf)
175 struct ProtoFunctionHook *p;
177 if (GetHash(ProtoHookList, cmdbuf, 4, &vP) && (vP != NULL)) {
178 p = (struct ProtoFunctionHook*) vP;
179 p->handler(&cmdbuf[5]);
185 long FourHash(const char *key, long length)
189 const unsigned char *ptr = (const unsigned char*)key;
191 for (i = 0; i < 4; i++, ptr ++)
201 void CtdlRegisterProtoHook(void (*handler) (char *), char *cmd, char *desc)
203 struct ProtoFunctionHook *p;
205 if (ProtoHookList == NULL)
206 ProtoHookList = NewHash (1, FourHash);
209 p = (struct ProtoFunctionHook *)
210 malloc(sizeof(struct ProtoFunctionHook));
213 fprintf(stderr, "can't malloc new ProtoFunctionHook\n");
216 p->handler = handler;
220 Put(ProtoHookList, cmd, 4, p, NULL);
221 syslog(LOG_INFO, "Registered server command %s (%s)\n", cmd, desc);
224 void CtdlDestroyProtoHooks(void)
227 DeleteHash(&ProtoHookList);
231 void CtdlRegisterCleanupHook(void (*fcn_ptr) (void))
234 struct CleanupFunctionHook *newfcn;
236 newfcn = (struct CleanupFunctionHook *)
237 malloc(sizeof(struct CleanupFunctionHook));
238 newfcn->next = CleanupHookTable;
239 newfcn->h_function_pointer = fcn_ptr;
240 CleanupHookTable = newfcn;
242 syslog(LOG_INFO, "Registered a new cleanup function\n");
246 void CtdlUnregisterCleanupHook(void (*fcn_ptr) (void))
248 struct CleanupFunctionHook *cur, *p;
250 for (cur = CleanupHookTable; cur != NULL; cur = cur->next) {
251 /* This will also remove duplicates if any */
252 while (cur != NULL &&
253 fcn_ptr == cur->h_function_pointer) {
254 syslog(LOG_INFO, "Unregistered cleanup function\n");
256 if (cur == CleanupHookTable) {
257 CleanupHookTable = p;
266 void CtdlDestroyCleanupHooks(void)
268 struct CleanupFunctionHook *cur, *p;
270 cur = CleanupHookTable;
273 syslog(LOG_INFO, "Destroyed cleanup function\n");
278 CleanupHookTable = NULL;
281 void CtdlRegisterEVCleanupHook(void (*fcn_ptr) (void))
284 struct CleanupFunctionHook *newfcn;
286 newfcn = (struct CleanupFunctionHook *)
287 malloc(sizeof(struct CleanupFunctionHook));
288 newfcn->next = EVCleanupHookTable;
289 newfcn->h_function_pointer = fcn_ptr;
290 EVCleanupHookTable = newfcn;
292 syslog(LOG_INFO, "Registered a new cleanup function\n");
296 void CtdlUnregisterEVCleanupHook(void (*fcn_ptr) (void))
298 struct CleanupFunctionHook *cur, *p;
300 for (cur = EVCleanupHookTable; cur != NULL; cur = cur->next) {
301 /* This will also remove duplicates if any */
302 while (cur != NULL &&
303 fcn_ptr == cur->h_function_pointer) {
304 syslog(LOG_INFO, "Unregistered cleanup function\n");
306 if (cur == EVCleanupHookTable) {
307 EVCleanupHookTable = p;
316 void CtdlDestroyEVCleanupHooks(void)
318 struct CleanupFunctionHook *cur, *p;
320 cur = EVCleanupHookTable;
323 syslog(LOG_INFO, "Destroyed cleanup function\n");
328 EVCleanupHookTable = NULL;
332 void CtdlRegisterSessionHook(void (*fcn_ptr) (void), int EventType)
335 struct SessionFunctionHook *newfcn;
337 newfcn = (struct SessionFunctionHook *)
338 malloc(sizeof(struct SessionFunctionHook));
339 newfcn->next = SessionHookTable;
340 newfcn->h_function_pointer = fcn_ptr;
341 newfcn->eventtype = EventType;
342 SessionHookTable = newfcn;
344 syslog(LOG_INFO, "Registered a new session function (type %d)\n",
349 void CtdlUnregisterSessionHook(void (*fcn_ptr) (void), int EventType)
351 struct SessionFunctionHook *cur, *p;
353 for (cur = SessionHookTable; cur != NULL; cur = cur->next) {
354 /* This will also remove duplicates if any */
355 while (cur != NULL &&
356 fcn_ptr == cur->h_function_pointer &&
357 EventType == cur->eventtype) {
358 syslog(LOG_INFO, "Unregistered session function (type %d)\n",
361 if (cur == SessionHookTable) {
362 SessionHookTable = p;
370 void CtdlDestroySessionHooks(void)
372 struct SessionFunctionHook *cur, *p;
374 cur = SessionHookTable;
377 syslog(LOG_INFO, "Destroyed session function\n");
382 SessionHookTable = NULL;
386 void CtdlRegisterUserHook(void (*fcn_ptr) (struct ctdluser *), int EventType)
389 struct UserFunctionHook *newfcn;
391 newfcn = (struct UserFunctionHook *)
392 malloc(sizeof(struct UserFunctionHook));
393 newfcn->next = UserHookTable;
394 newfcn->h_function_pointer = fcn_ptr;
395 newfcn->eventtype = EventType;
396 UserHookTable = newfcn;
398 syslog(LOG_INFO, "Registered a new user function (type %d)\n",
403 void CtdlUnregisterUserHook(void (*fcn_ptr) (struct ctdluser *), int EventType)
405 struct UserFunctionHook *cur, *p;
407 for (cur = UserHookTable; cur != NULL; cur = cur->next) {
408 /* This will also remove duplicates if any */
409 while (cur != NULL &&
410 fcn_ptr == cur->h_function_pointer &&
411 EventType == cur->eventtype) {
412 syslog(LOG_INFO, "Unregistered user function (type %d)\n",
415 if (cur == UserHookTable) {
424 void CtdlDestroyUserHooks(void)
426 struct UserFunctionHook *cur, *p;
431 syslog(LOG_INFO, "Destroyed user function \n");
436 UserHookTable = NULL;
440 void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
444 struct MessageFunctionHook *newfcn;
446 newfcn = (struct MessageFunctionHook *)
447 malloc(sizeof(struct MessageFunctionHook));
448 newfcn->next = MessageHookTable;
449 newfcn->h_function_pointer = handler;
450 newfcn->eventtype = EventType;
451 MessageHookTable = newfcn;
453 syslog(LOG_INFO, "Registered a new message function (type %d)\n",
458 void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *),
461 struct MessageFunctionHook *cur, *p;
463 for (cur = MessageHookTable; cur != NULL; cur = cur->next) {
464 /* This will also remove duplicates if any */
465 while (cur != NULL &&
466 handler == cur->h_function_pointer &&
467 EventType == cur->eventtype) {
468 syslog(LOG_INFO, "Unregistered message function (type %d)\n",
471 if (cur == MessageHookTable) {
472 MessageHookTable = p;
480 void CtdlDestroyMessageHook(void)
482 struct MessageFunctionHook *cur, *p;
484 cur = MessageHookTable;
487 syslog(LOG_INFO, "Destroyed message function (type %d)\n", cur->eventtype);
492 MessageHookTable = NULL;
496 void CtdlRegisterRoomHook(int (*fcn_ptr)(struct ctdlroom *))
498 struct RoomFunctionHook *newfcn;
500 newfcn = (struct RoomFunctionHook *)
501 malloc(sizeof(struct RoomFunctionHook));
502 newfcn->next = RoomHookTable;
503 newfcn->fcn_ptr = fcn_ptr;
504 RoomHookTable = newfcn;
506 syslog(LOG_INFO, "Registered a new room function\n");
510 void CtdlUnregisterRoomHook(int (*fcn_ptr)(struct ctdlroom *))
512 struct RoomFunctionHook *cur, *p;
514 for (cur = RoomHookTable; cur != NULL; cur = cur->next) {
515 while (cur != NULL && fcn_ptr == cur->fcn_ptr) {
516 syslog(LOG_INFO, "Unregistered room function\n");
518 if (cur == RoomHookTable) {
528 void CtdlDestroyRoomHooks(void)
530 struct RoomFunctionHook *cur, *p;
535 syslog(LOG_INFO, "Destroyed room function\n");
540 RoomHookTable = NULL;
543 void CtdlRegisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
545 struct NetprocFunctionHook *newfcn;
547 newfcn = (struct NetprocFunctionHook *)
548 malloc(sizeof(struct NetprocFunctionHook));
549 newfcn->next = NetprocHookTable;
550 newfcn->h_function_pointer = handler;
551 NetprocHookTable = newfcn;
553 syslog(LOG_INFO, "Registered a new netproc function\n");
557 void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
559 struct NetprocFunctionHook *cur, *p;
561 for (cur = NetprocHookTable; cur != NULL; cur = cur->next) {
562 /* This will also remove duplicates if any */
563 while (cur != NULL &&
564 handler == cur->h_function_pointer ) {
565 syslog(LOG_INFO, "Unregistered netproc function\n");
567 if (cur == NetprocHookTable) {
568 NetprocHookTable = p;
576 void CtdlDestroyNetprocHooks(void)
578 struct NetprocFunctionHook *cur, *p;
580 cur = NetprocHookTable;
583 syslog(LOG_INFO, "Destroyed netproc function\n");
588 NetprocHookTable = NULL;
592 void CtdlRegisterDeleteHook(void (*handler)(char *, long) )
594 struct DeleteFunctionHook *newfcn;
596 newfcn = (struct DeleteFunctionHook *)
597 malloc(sizeof(struct DeleteFunctionHook));
598 newfcn->next = DeleteHookTable;
599 newfcn->h_function_pointer = handler;
600 DeleteHookTable = newfcn;
602 syslog(LOG_INFO, "Registered a new delete function\n");
606 void CtdlUnregisterDeleteHook(void (*handler)(char *, long) )
608 struct DeleteFunctionHook *cur, *p;
610 for (cur = DeleteHookTable; cur != NULL; cur = cur->next) {
611 /* This will also remove duplicates if any */
612 while (cur != NULL &&
613 handler == cur->h_function_pointer ) {
614 syslog(LOG_INFO, "Unregistered delete function\n");
616 if (cur == DeleteHookTable) {
624 void CtdlDestroyDeleteHooks(void)
626 struct DeleteFunctionHook *cur, *p;
628 cur = DeleteHookTable;
631 syslog(LOG_INFO, "Destroyed delete function\n");
636 DeleteHookTable = NULL;
642 void CtdlRegisterFixedOutputHook(char *content_type, void (*handler)(char *, int) )
644 struct FixedOutputHook *newfcn;
646 newfcn = (struct FixedOutputHook *)
647 malloc(sizeof(struct FixedOutputHook));
648 newfcn->next = FixedOutputTable;
649 newfcn->h_function_pointer = handler;
650 safestrncpy(newfcn->content_type, content_type, sizeof newfcn->content_type);
651 FixedOutputTable = newfcn;
653 syslog(LOG_INFO, "Registered a new fixed output function for %s\n", newfcn->content_type);
657 void CtdlUnregisterFixedOutputHook(char *content_type)
659 struct FixedOutputHook *cur, *p;
661 for (cur = FixedOutputTable; cur != NULL; cur = cur->next) {
662 /* This will also remove duplicates if any */
663 while (cur != NULL && (!strcasecmp(content_type, cur->content_type))) {
664 syslog(LOG_INFO, "Unregistered fixed output function for %s\n", content_type);
666 if (cur == FixedOutputTable) {
667 FixedOutputTable = p;
675 void CtdlDestroyFixedOutputHooks(void)
677 struct FixedOutputHook *cur, *p;
679 cur = FixedOutputTable;
682 syslog(LOG_INFO, "Destroyed fixed output function for %s\n", cur->content_type);
688 FixedOutputTable = NULL;
691 /* returns nonzero if we found a hook and used it */
692 int PerformFixedOutputHooks(char *content_type, char *content, int content_length)
694 struct FixedOutputHook *fcn;
696 for (fcn = FixedOutputTable; fcn != NULL; fcn = fcn->next) {
697 if (!strcasecmp(content_type, fcn->content_type)) {
698 (*fcn->h_function_pointer) (content, content_length);
709 void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *, char *), int order)
712 struct XmsgFunctionHook *newfcn;
714 newfcn = (struct XmsgFunctionHook *) malloc(sizeof(struct XmsgFunctionHook));
715 newfcn->next = XmsgHookTable;
716 newfcn->order = order;
717 newfcn->h_function_pointer = fcn_ptr;
718 XmsgHookTable = newfcn;
719 syslog(LOG_INFO, "Registered a new x-msg function (priority %d)\n", order);
723 void CtdlUnregisterXmsgHook(int (*fcn_ptr) (char *, char *, char *, char *), int order)
725 struct XmsgFunctionHook *cur, *p;
727 for (cur = XmsgHookTable; cur != NULL; cur = cur->next) {
728 /* This will also remove duplicates if any */
729 while (cur != NULL &&
730 fcn_ptr == cur->h_function_pointer &&
731 order == cur->order) {
732 syslog(LOG_INFO, "Unregistered x-msg function "
733 "(priority %d)\n", order);
735 if (cur == XmsgHookTable) {
744 void CtdlDestroyXmsgHooks(void)
746 struct XmsgFunctionHook *cur, *p;
751 syslog(LOG_INFO, "Destroyed x-msg function "
752 "(priority %d)\n", cur->order);
758 XmsgHookTable = NULL;
762 void CtdlRegisterServiceHook(int tcp_port,
764 void (*h_greeting_function) (void),
765 void (*h_command_function) (void),
766 void (*h_async_function) (void),
767 const char *ServiceName)
769 struct ServiceFunctionHook *newfcn;
774 newfcn = (struct ServiceFunctionHook *) malloc(sizeof(struct ServiceFunctionHook));
775 message = (char*) malloc (SIZ + SIZ);
777 newfcn->next = ServiceHookTable;
778 newfcn->tcp_port = tcp_port;
779 newfcn->sockpath = sockpath;
780 newfcn->h_greeting_function = h_greeting_function;
781 newfcn->h_command_function = h_command_function;
782 newfcn->h_async_function = h_async_function;
783 newfcn->ServiceName = ServiceName;
785 if (sockpath != NULL) {
786 newfcn->msock = ctdl_uds_server(sockpath, config.c_maxsessions, error);
787 snprintf(message, SIZ, "Unix domain socket '%s': ", sockpath);
789 else if (tcp_port <= 0) { /* port -1 to disable */
790 syslog(LOG_INFO, "Service %s has been manually disabled, skipping\n", ServiceName);
796 newfcn->msock = ctdl_tcp_server(config.c_ip_addr,
798 config.c_maxsessions,
800 snprintf(message, SIZ, "TCP port %s:%d: (%s) ",
801 config.c_ip_addr, tcp_port, ServiceName);
804 if (newfcn->msock > 0) {
805 ServiceHookTable = newfcn;
806 strcat(message, "registered.");
807 syslog(LOG_INFO, "%s\n", message);
810 AddPortError(message, error);
811 strcat(message, "FAILED.");
812 syslog(LOG_CRIT, "%s\n", message);
819 void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
820 void (*h_greeting_function) (void),
821 void (*h_command_function) (void),
822 void (*h_async_function) (void)
825 struct ServiceFunctionHook *cur, *p;
827 cur = ServiceHookTable;
828 while (cur != NULL) {
829 /* This will also remove duplicates if any */
830 while (cur != NULL &&
831 !(sockpath && cur->sockpath &&
832 strcmp(sockpath, cur->sockpath)) &&
833 h_greeting_function == cur->h_greeting_function &&
834 h_command_function == cur->h_command_function &&
835 h_async_function == cur->h_async_function &&
836 tcp_port == cur->tcp_port) {
839 syslog(LOG_INFO, "Closed UNIX domain socket %s\n",
842 } else if (tcp_port) {
843 syslog(LOG_INFO, "Closed TCP port %d\n", tcp_port);
845 syslog(LOG_INFO, "Unregistered service \"%s\"\n", cur->ServiceName);
848 if (cur == ServiceHookTable) {
849 ServiceHookTable = p;
858 void CtdlShutdownServiceHooks(void)
860 /* sort of a duplicate of close_masters() but called earlier */
861 struct ServiceFunctionHook *cur;
863 cur = ServiceHookTable;
866 if (cur->msock != -1)
870 if (cur->sockpath != NULL){
871 syslog(LOG_INFO, "[%s] Closed UNIX domain socket %s\n",
874 unlink(cur->sockpath);
876 syslog(LOG_INFO, "[%s] closing service\n",
884 void CtdlDestroyServiceHook(void)
886 struct ServiceFunctionHook *cur, *p;
888 cur = ServiceHookTable;
893 syslog(LOG_INFO, "Closed UNIX domain socket %s\n",
895 unlink(cur->sockpath);
896 } else if (cur->tcp_port) {
897 syslog(LOG_INFO, "Closed TCP port %d\n", cur->tcp_port);
899 syslog(LOG_INFO, "Destroyed service \"%s\"\n", cur->ServiceName);
905 ServiceHookTable = NULL;
908 void CtdlRegisterSearchFuncHook(void (*fcn_ptr)(int *, long **, const char *), char *name)
910 struct SearchFunctionHook *newfcn;
912 if (!name || !fcn_ptr) {
916 newfcn = (struct SearchFunctionHook *)
917 malloc(sizeof(struct SearchFunctionHook));
918 newfcn->next = SearchFunctionHookTable;
920 newfcn->fcn_ptr = fcn_ptr;
921 SearchFunctionHookTable = newfcn;
923 syslog(LOG_INFO, "Registered a new search function (%s)\n", name);
926 void CtdlUnregisterSearchFuncHook(void (*fcn_ptr)(int *, long **, const char *), char *name)
928 struct SearchFunctionHook *cur, *p;
930 for (cur = SearchFunctionHookTable; cur != NULL; cur = cur->next) {
931 while (fcn_ptr && (cur->fcn_ptr == fcn_ptr) && name && !strcmp(name, cur->name)) {
932 syslog(LOG_INFO, "Unregistered search function(%s)\n", name);
934 if (cur == SearchFunctionHookTable) {
935 SearchFunctionHookTable = p;
943 void CtdlDestroySearchHooks(void)
945 struct SearchFunctionHook *cur, *p;
947 cur = SearchFunctionHookTable;
948 SearchFunctionHookTable = NULL;
949 while (cur != NULL) {
956 void CtdlModuleDoSearch(int *num_msgs, long **search_msgs, const char *search_string, const char *func_name)
958 struct SearchFunctionHook *fcn = NULL;
960 for (fcn = SearchFunctionHookTable; fcn != NULL; fcn = fcn->next) {
961 if (!func_name || !strcmp(func_name, fcn->name)) {
962 (*fcn->fcn_ptr) (num_msgs, search_msgs, search_string);
970 void PerformSessionHooks(int EventType)
972 struct SessionFunctionHook *fcn = NULL;
974 for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
975 if (fcn->eventtype == EventType) {
976 if (EventType == EVT_TIMER) {
977 pthread_setspecific(MyConKey, NULL); /* for every hook */
979 (*fcn->h_function_pointer) ();
984 void PerformUserHooks(struct ctdluser *usbuf, int EventType)
986 struct UserFunctionHook *fcn = NULL;
988 for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
989 if (fcn->eventtype == EventType) {
990 (*fcn->h_function_pointer) (usbuf);
995 int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
997 struct MessageFunctionHook *fcn = NULL;
998 int total_retval = 0;
1000 /* Other code may elect to protect this message from server-side
1001 * handlers; if this is the case, don't do anything.
1002 syslog(LOG_DEBUG, "** Event type is %d, flags are %d\n", EventType, msg->cm_flags);
1004 if (msg->cm_flags & CM_SKIP_HOOKS) {
1005 syslog(LOG_DEBUG, "Skipping hooks\n");
1009 /* Otherwise, run all the hooks appropriate to this event type.
1011 for (fcn = MessageHookTable; fcn != NULL; fcn = fcn->next) {
1012 if (fcn->eventtype == EventType) {
1013 total_retval = total_retval + (*fcn->h_function_pointer) (msg);
1017 /* Return the sum of the return codes from the hook functions. If
1018 * this is an EVT_BEFORESAVE event, a nonzero return code will cause
1019 * the save operation to abort.
1021 return total_retval;
1025 int PerformRoomHooks(struct ctdlroom *target_room)
1027 struct RoomFunctionHook *fcn;
1028 int total_retval = 0;
1030 syslog(LOG_DEBUG, "Performing room hooks for <%s>\n", target_room->QRname);
1032 for (fcn = RoomHookTable; fcn != NULL; fcn = fcn->next) {
1033 total_retval = total_retval + (*fcn->fcn_ptr) (target_room);
1036 /* Return the sum of the return codes from the hook functions.
1038 return total_retval;
1042 int PerformNetprocHooks(struct CtdlMessage *msg, char *target_room)
1044 struct NetprocFunctionHook *fcn;
1045 int total_retval = 0;
1047 for (fcn = NetprocHookTable; fcn != NULL; fcn = fcn->next) {
1048 total_retval = total_retval +
1049 (*fcn->h_function_pointer) (msg, target_room);
1052 /* Return the sum of the return codes from the hook functions.
1053 * A nonzero return code will cause the message to *not* be imported.
1055 return total_retval;
1059 void PerformDeleteHooks(char *room, long msgnum)
1061 struct DeleteFunctionHook *fcn;
1063 for (fcn = DeleteHookTable; fcn != NULL; fcn = fcn->next) {
1064 (*fcn->h_function_pointer) (room, msgnum);
1072 int PerformXmsgHooks(char *sender, char *sender_email, char *recp, char *msg)
1074 struct XmsgFunctionHook *fcn;
1078 for (p=0; p<MAX_XMSG_PRI; ++p) {
1079 for (fcn = XmsgHookTable; fcn != NULL; fcn = fcn->next) {
1080 if (fcn->order == p) {
1082 (*fcn->h_function_pointer)
1083 (sender, sender_email, recp, msg);
1086 /* Break out of the loop if a higher-priority function
1087 * successfully delivered the message. This prevents duplicate
1088 * deliveries to local users simultaneously signed onto
1091 if (total_sent) break;
1098 * Dirty hack until we impliment a hook mechanism for this
1100 void CtdlModuleStartCryptoMsgs(char *ok_response, char *nosup_response, char *error_response)
1103 CtdlStartTLS (ok_response, nosup_response, error_response);