4 * Citadel Dynamic Loading Module
5 * Written by Brian Costello <btx@calyx.net>
13 #include <sys/types.h>
18 #include <libcitadel.h>
21 #include "serv_extensions.h"
22 #include "sysdep_decls.h"
26 #include "modules/crypto/serv_crypto.h" /* Needed until a universal crypto startup hook is implimented for CtdlStartTLS */
28 #include "ctdl_module.h"
35 struct CleanupFunctionHook
*CleanupHookTable
= NULL
;
36 struct SessionFunctionHook
*SessionHookTable
= NULL
;
37 struct UserFunctionHook
*UserHookTable
= NULL
;
38 struct XmsgFunctionHook
*XmsgHookTable
= NULL
;
39 struct MessageFunctionHook
*MessageHookTable
= NULL
;
40 struct NetprocFunctionHook
*NetprocHookTable
= NULL
;
41 struct DeleteFunctionHook
*DeleteHookTable
= NULL
;
42 struct ServiceFunctionHook
*ServiceHookTable
= NULL
;
43 struct FixedOutputHook
*FixedOutputTable
= NULL
;
44 struct RoomFunctionHook
*RoomHookTable
= NULL
;
45 struct SearchFunctionHook
*SearchFunctionHookTable
= NULL
;
47 struct ProtoFunctionHook
{
48 void (*handler
) (char *cmdbuf
);
51 struct ProtoFunctionHook
*next
;
52 } *ProtoHookList
= NULL
;
55 struct DirectoryServiceHook
{
56 int (*handler
) (char *cn
, char *ou
, void **object
);
59 struct DirectoryServiceHook
*next
;
60 } *DirectoryServiceHookList
= NULL
;
62 struct DirectoryObject
{
65 struct DirectoryObject
*next
;
68 #define ERR_PORT (1 << 1)
71 static char *portlist
= NULL
;
72 static size_t nSizPort
= 0;
74 static char *errormessages
= NULL
;
75 size_t nSizErrmsg
= 0;
78 long DetailErrorFlags
;
80 char *ErrSubject
= "Startup Problems";
81 char *ErrGeneral
= "Citadel had trouble on starting up. %s This means, citadel won't be the service provider for a specific service you configured it to.\n\n"
82 "If you don't want citadel to provide these services, turn them off in WebCit via %s%s\n\n%s\n\n"
83 "To make both ways actualy take place restart the citserver with \"sendcommand down\"\n\n"
84 "The errors returned by the system were:\n%s\n"
85 "You can recheck the above if you follow this faq item:\n"
86 "http://www.citadel.org/doku.php/faq:mastering_your_os:net#netstat";
89 char *ErrPortShort
= "We couldn't bind all ports you configured to be provided by citadel server.";
90 char *ErrPortWhere
= "Admin->System Preferences->Network.\n\nThe failed ports and sockets are: ";
91 char *ErrPortHint
= "If you want citadel to provide you with that functionality, "
92 "check the output of \"netstat -lnp\" on linux Servers or \"netstat -na\" on *BSD"
93 " and stop the programm, that binds these ports. You should eventually remove "
94 " their initscripts in /etc/init.d so that you won't get this trouble once more.\n"
95 " After that goto Administration -> Shutdown Citadel to make Citadel retry to bind this port.\n";
98 void LogPrintMessages(long err
)
100 char *List
, *DetailList
, *Short
, *Where
, *Hint
, *Message
;
101 int n
= nSizPort
+ nSizErrmsg
+ 5;
103 Message
= (char*) malloc(n
* SIZ
);
108 Short
= ErrPortShort
;
109 Where
= ErrPortWhere
;
112 DetailList
= errormessages
;
123 snprintf(Message
, n
* SIZ
, ErrGeneral
, Short
, Where
, List
, Hint
, DetailList
);
125 CtdlLogPrintf(0,Message
);
126 CtdlLogPrintf(0,ErrSubject
);
127 quickie_message("Citadel", NULL
, NULL
, AIDEROOM
, Message
, FMT_FIXED
, ErrSubject
);
128 if (errormessages
!=NULL
) free (errormessages
);
129 errormessages
= NULL
;
130 if (portlist
!=NULL
) free (portlist
);
137 void AppendString(char **target
, char *append
, size_t *len
, size_t rate
)
143 AddLen
= strlen(append
);
149 *target
= (char*)malloc (*len
* SIZ
);
153 oLen
= strlen(*target
);
154 RelPtr
= strlen(*target
);
155 if (oLen
+ AddLen
+ 2 > *len
* SIZ
)
157 char *Buff
= *target
;
158 size_t NewSiz
= *len
+ 10;
159 *target
= malloc (NewSiz
* SIZ
);
160 memcpy (*target
, Buff
, NewSiz
* SIZ
);
164 memcpy (*target
+ oLen
, append
, AddLen
);
165 (*target
)[oLen
+ AddLen
+ 1] = '\n';
166 (*target
)[oLen
+ AddLen
+ 2] = '\0';
169 void AddPortError(char *Port
, char *ErrorMessage
)
174 DetailErrorFlags
|= ERR_PORT
;
176 AppendString(&errormessages
, ErrorMessage
, &nSizErrmsg
, 10);
177 AppendString(&portlist
, Port
, &nSizPort
, 2);
179 pos
= strchr (portlist
, ':');
180 if (pos
!= NULL
) *pos
= ';';
182 len
= strlen (errormessages
);
183 if (nSizErrmsg
* SIZ
> len
+ 3)
185 errormessages
[len
] = ';';
186 errormessages
[len
+1] = ' ';
187 errormessages
[len
+2] = '\0';
192 int DLoader_Exec_Cmd(char *cmdbuf
)
194 struct ProtoFunctionHook
*p
;
196 for (p
= ProtoHookList
; p
; p
= p
->next
) {
197 if (!strncasecmp(cmdbuf
, p
->cmd
, 4)) {
198 p
->handler(&cmdbuf
[5]);
206 void CtdlRegisterProtoHook(void (*handler
) (char *), char *cmd
, char *desc
)
208 struct ProtoFunctionHook
*p
;
210 p
= (struct ProtoFunctionHook
*)
211 malloc(sizeof(struct ProtoFunctionHook
));
214 fprintf(stderr
, "can't malloc new ProtoFunctionHook\n");
217 p
->handler
= handler
;
220 p
->next
= ProtoHookList
;
222 CtdlLogPrintf(CTDL_INFO
, "Registered server command %s (%s)\n", cmd
, desc
);
226 void CtdlUnregisterProtoHook(void (*handler
) (char *), char *cmd
)
228 struct ProtoFunctionHook
*cur
= NULL
;
229 struct ProtoFunctionHook
*p
= NULL
;
230 struct ProtoFunctionHook
*lastcur
= NULL
;
232 for (cur
= ProtoHookList
;
234 cur
= (cur
!= NULL
)? cur
->next
: NULL
) {
235 /* This will also remove duplicates if any */
236 while (cur
!= NULL
&&
237 handler
== cur
->handler
&&
238 !strcmp(cmd
, cur
->cmd
)) {
239 CtdlLogPrintf(CTDL_INFO
, "Unregistered server command %s (%s)\n",
242 if (cur
== ProtoHookList
) {
245 else if (lastcur
!= NULL
)
256 void CtdlDestroyProtoHooks(void)
258 struct ProtoFunctionHook
*cur
, *p
;
263 CtdlLogPrintf(CTDL_INFO
, "Destroyed server command %s (%s)\n",
264 cur
->cmd
, cur
->desc
);
269 ProtoHookList
= NULL
;
273 void CtdlRegisterCleanupHook(void (*fcn_ptr
) (void))
276 struct CleanupFunctionHook
*newfcn
;
278 newfcn
= (struct CleanupFunctionHook
*)
279 malloc(sizeof(struct CleanupFunctionHook
));
280 newfcn
->next
= CleanupHookTable
;
281 newfcn
->h_function_pointer
= fcn_ptr
;
282 CleanupHookTable
= newfcn
;
284 CtdlLogPrintf(CTDL_INFO
, "Registered a new cleanup function\n");
288 void CtdlUnregisterCleanupHook(void (*fcn_ptr
) (void))
290 struct CleanupFunctionHook
*cur
, *p
;
292 for (cur
= CleanupHookTable
; cur
!= NULL
; cur
= cur
->next
) {
293 /* This will also remove duplicates if any */
294 while (cur
!= NULL
&&
295 fcn_ptr
== cur
->h_function_pointer
) {
296 CtdlLogPrintf(CTDL_INFO
, "Unregistered cleanup function\n");
298 if (cur
== CleanupHookTable
) {
299 CleanupHookTable
= p
;
307 void CtdlDestroyCleanupHooks(void)
309 struct CleanupFunctionHook
*cur
, *p
;
311 cur
= CleanupHookTable
;
314 CtdlLogPrintf(CTDL_INFO
, "Destroyed cleanup function\n");
319 CleanupHookTable
= NULL
;
323 void CtdlRegisterSessionHook(void (*fcn_ptr
) (void), int EventType
)
326 struct SessionFunctionHook
*newfcn
;
328 newfcn
= (struct SessionFunctionHook
*)
329 malloc(sizeof(struct SessionFunctionHook
));
330 newfcn
->next
= SessionHookTable
;
331 newfcn
->h_function_pointer
= fcn_ptr
;
332 newfcn
->eventtype
= EventType
;
333 SessionHookTable
= newfcn
;
335 CtdlLogPrintf(CTDL_INFO
, "Registered a new session function (type %d)\n",
340 void CtdlUnregisterSessionHook(void (*fcn_ptr
) (void), int EventType
)
342 struct SessionFunctionHook
*cur
, *p
;
344 for (cur
= SessionHookTable
; cur
!= NULL
; cur
= cur
->next
) {
345 /* This will also remove duplicates if any */
346 while (cur
!= NULL
&&
347 fcn_ptr
== cur
->h_function_pointer
&&
348 EventType
== cur
->eventtype
) {
349 CtdlLogPrintf(CTDL_INFO
, "Unregistered session function (type %d)\n",
352 if (cur
== SessionHookTable
) {
353 SessionHookTable
= p
;
361 void CtdlDestroySessionHooks(void)
363 struct SessionFunctionHook
*cur
, *p
;
365 cur
= SessionHookTable
;
368 CtdlLogPrintf(CTDL_INFO
, "Destroyed session function\n");
373 SessionHookTable
= NULL
;
377 void CtdlRegisterUserHook(void (*fcn_ptr
) (struct ctdluser
*), int EventType
)
380 struct UserFunctionHook
*newfcn
;
382 newfcn
= (struct UserFunctionHook
*)
383 malloc(sizeof(struct UserFunctionHook
));
384 newfcn
->next
= UserHookTable
;
385 newfcn
->h_function_pointer
= fcn_ptr
;
386 newfcn
->eventtype
= EventType
;
387 UserHookTable
= newfcn
;
389 CtdlLogPrintf(CTDL_INFO
, "Registered a new user function (type %d)\n",
394 void CtdlUnregisterUserHook(void (*fcn_ptr
) (struct ctdluser
*), int EventType
)
396 struct UserFunctionHook
*cur
, *p
;
398 for (cur
= UserHookTable
; cur
!= NULL
; cur
= cur
->next
) {
399 /* This will also remove duplicates if any */
400 while (cur
!= NULL
&&
401 fcn_ptr
== cur
->h_function_pointer
&&
402 EventType
== cur
->eventtype
) {
403 CtdlLogPrintf(CTDL_INFO
, "Unregistered user function (type %d)\n",
406 if (cur
== UserHookTable
) {
415 void CtdlDestroyUserHooks(void)
417 struct UserFunctionHook
*cur
, *p
;
422 CtdlLogPrintf(CTDL_INFO
, "Destroyed user function \n");
427 UserHookTable
= NULL
;
431 void CtdlRegisterMessageHook(int (*handler
)(struct CtdlMessage
*),
435 struct MessageFunctionHook
*newfcn
;
437 newfcn
= (struct MessageFunctionHook
*)
438 malloc(sizeof(struct MessageFunctionHook
));
439 newfcn
->next
= MessageHookTable
;
440 newfcn
->h_function_pointer
= handler
;
441 newfcn
->eventtype
= EventType
;
442 MessageHookTable
= newfcn
;
444 CtdlLogPrintf(CTDL_INFO
, "Registered a new message function (type %d)\n",
449 void CtdlUnregisterMessageHook(int (*handler
)(struct CtdlMessage
*),
452 struct MessageFunctionHook
*cur
, *p
;
454 for (cur
= MessageHookTable
; cur
!= NULL
; cur
= cur
->next
) {
455 /* This will also remove duplicates if any */
456 while (cur
!= NULL
&&
457 handler
== cur
->h_function_pointer
&&
458 EventType
== cur
->eventtype
) {
459 CtdlLogPrintf(CTDL_INFO
, "Unregistered message function (type %d)\n",
462 if (cur
== MessageHookTable
) {
463 MessageHookTable
= p
;
471 void CtdlDestroyMessageHook(void)
473 struct MessageFunctionHook
*cur
, *p
;
475 cur
= MessageHookTable
;
478 CtdlLogPrintf(CTDL_INFO
, "Destroyed message function (type %d)\n", cur
->eventtype
);
483 MessageHookTable
= NULL
;
487 void CtdlRegisterRoomHook(int (*fcn_ptr
)(struct ctdlroom
*))
489 struct RoomFunctionHook
*newfcn
;
491 newfcn
= (struct RoomFunctionHook
*)
492 malloc(sizeof(struct RoomFunctionHook
));
493 newfcn
->next
= RoomHookTable
;
494 newfcn
->fcn_ptr
= fcn_ptr
;
495 RoomHookTable
= newfcn
;
497 CtdlLogPrintf(CTDL_INFO
, "Registered a new room function\n");
501 void CtdlUnregisterRoomHook(int (*fcn_ptr
)(struct ctdlroom
*))
503 struct RoomFunctionHook
*cur
, *p
;
505 for (cur
= RoomHookTable
; cur
!= NULL
; cur
= cur
->next
) {
506 while (cur
!= NULL
&& fcn_ptr
== cur
->fcn_ptr
) {
507 CtdlLogPrintf(CTDL_INFO
, "Unregistered room function\n");
509 if (cur
== RoomHookTable
) {
519 void CtdlDestroyRoomHooks(void)
521 struct RoomFunctionHook
*cur
, *p
;
526 CtdlLogPrintf(CTDL_INFO
, "Destroyed room function\n");
531 RoomHookTable
= NULL
;
534 void CtdlRegisterNetprocHook(int (*handler
)(struct CtdlMessage
*, char *) )
536 struct NetprocFunctionHook
*newfcn
;
538 newfcn
= (struct NetprocFunctionHook
*)
539 malloc(sizeof(struct NetprocFunctionHook
));
540 newfcn
->next
= NetprocHookTable
;
541 newfcn
->h_function_pointer
= handler
;
542 NetprocHookTable
= newfcn
;
544 CtdlLogPrintf(CTDL_INFO
, "Registered a new netproc function\n");
548 void CtdlUnregisterNetprocHook(int (*handler
)(struct CtdlMessage
*, char *) )
550 struct NetprocFunctionHook
*cur
, *p
;
552 for (cur
= NetprocHookTable
; cur
!= NULL
; cur
= cur
->next
) {
553 /* This will also remove duplicates if any */
554 while (cur
!= NULL
&&
555 handler
== cur
->h_function_pointer
) {
556 CtdlLogPrintf(CTDL_INFO
, "Unregistered netproc function\n");
558 if (cur
== NetprocHookTable
) {
559 NetprocHookTable
= p
;
567 void CtdlDestroyNetprocHooks(void)
569 struct NetprocFunctionHook
*cur
, *p
;
571 cur
= NetprocHookTable
;
574 CtdlLogPrintf(CTDL_INFO
, "Destroyed netproc function\n");
579 NetprocHookTable
= NULL
;
583 void CtdlRegisterDeleteHook(void (*handler
)(char *, long) )
585 struct DeleteFunctionHook
*newfcn
;
587 newfcn
= (struct DeleteFunctionHook
*)
588 malloc(sizeof(struct DeleteFunctionHook
));
589 newfcn
->next
= DeleteHookTable
;
590 newfcn
->h_function_pointer
= handler
;
591 DeleteHookTable
= newfcn
;
593 CtdlLogPrintf(CTDL_INFO
, "Registered a new delete function\n");
597 void CtdlUnregisterDeleteHook(void (*handler
)(char *, long) )
599 struct DeleteFunctionHook
*cur
, *p
;
601 for (cur
= DeleteHookTable
; cur
!= NULL
; cur
= cur
->next
) {
602 /* This will also remove duplicates if any */
603 while (cur
!= NULL
&&
604 handler
== cur
->h_function_pointer
) {
605 CtdlLogPrintf(CTDL_INFO
, "Unregistered delete function\n");
607 if (cur
== DeleteHookTable
) {
615 void CtdlDestroyDeleteHooks(void)
617 struct DeleteFunctionHook
*cur
, *p
;
619 cur
= DeleteHookTable
;
622 CtdlLogPrintf(CTDL_INFO
, "Destroyed delete function\n");
627 DeleteHookTable
= NULL
;
633 void CtdlRegisterFixedOutputHook(char *content_type
, void (*handler
)(char *, int) )
635 struct FixedOutputHook
*newfcn
;
637 newfcn
= (struct FixedOutputHook
*)
638 malloc(sizeof(struct FixedOutputHook
));
639 newfcn
->next
= FixedOutputTable
;
640 newfcn
->h_function_pointer
= handler
;
641 safestrncpy(newfcn
->content_type
, content_type
, sizeof newfcn
->content_type
);
642 FixedOutputTable
= newfcn
;
644 CtdlLogPrintf(CTDL_INFO
, "Registered a new fixed output function for %s\n", newfcn
->content_type
);
648 void CtdlUnregisterFixedOutputHook(char *content_type
)
650 struct FixedOutputHook
*cur
, *p
;
652 for (cur
= FixedOutputTable
; cur
!= NULL
; cur
= cur
->next
) {
653 /* This will also remove duplicates if any */
654 while (cur
!= NULL
&& (!strcasecmp(content_type
, cur
->content_type
))) {
655 CtdlLogPrintf(CTDL_INFO
, "Unregistered fixed output function for %s\n", content_type
);
657 if (cur
== FixedOutputTable
) {
658 FixedOutputTable
= p
;
666 void CtdlDestroyFixedOutputHooks(void)
668 struct FixedOutputHook
*cur
, *p
;
670 cur
= FixedOutputTable
;
673 CtdlLogPrintf(CTDL_INFO
, "Destroyed fixed output function for %s\n", cur
->content_type
);
679 FixedOutputTable
= NULL
;
682 /* returns nonzero if we found a hook and used it */
683 int PerformFixedOutputHooks(char *content_type
, char *content
, int content_length
)
685 struct FixedOutputHook
*fcn
;
687 for (fcn
= FixedOutputTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
688 if (!strcasecmp(content_type
, fcn
->content_type
)) {
689 (*fcn
->h_function_pointer
) (content
, content_length
);
700 void CtdlRegisterXmsgHook(int (*fcn_ptr
) (char *, char *, char *, char *), int order
)
703 struct XmsgFunctionHook
*newfcn
;
705 newfcn
= (struct XmsgFunctionHook
*) malloc(sizeof(struct XmsgFunctionHook
));
706 newfcn
->next
= XmsgHookTable
;
707 newfcn
->order
= order
;
708 newfcn
->h_function_pointer
= fcn_ptr
;
709 XmsgHookTable
= newfcn
;
710 CtdlLogPrintf(CTDL_INFO
, "Registered a new x-msg function (priority %d)\n", order
);
714 void CtdlUnregisterXmsgHook(int (*fcn_ptr
) (char *, char *, char *, char *), int order
)
716 struct XmsgFunctionHook
*cur
, *p
;
718 for (cur
= XmsgHookTable
; cur
!= NULL
; cur
= cur
->next
) {
719 /* This will also remove duplicates if any */
720 while (cur
!= NULL
&&
721 fcn_ptr
== cur
->h_function_pointer
&&
722 order
== cur
->order
) {
723 CtdlLogPrintf(CTDL_INFO
, "Unregistered x-msg function "
724 "(priority %d)\n", order
);
726 if (cur
== XmsgHookTable
) {
735 void CtdlDestroyXmsgHooks(void)
737 struct XmsgFunctionHook
*cur
, *p
;
742 CtdlLogPrintf(CTDL_INFO
, "Destroyed x-msg function "
743 "(priority %d)\n", cur
->order
);
749 XmsgHookTable
= NULL
;
753 void CtdlRegisterServiceHook(int tcp_port
,
755 void (*h_greeting_function
) (void),
756 void (*h_command_function
) (void),
757 void (*h_async_function
) (void),
758 const char *ServiceName
)
760 struct ServiceFunctionHook
*newfcn
;
765 newfcn
= (struct ServiceFunctionHook
*)
766 malloc(sizeof(struct ServiceFunctionHook
));
767 message
= (char*) malloc (SIZ
);
769 newfcn
->next
= ServiceHookTable
;
770 newfcn
->tcp_port
= tcp_port
;
771 newfcn
->sockpath
= sockpath
;
772 newfcn
->h_greeting_function
= h_greeting_function
;
773 newfcn
->h_command_function
= h_command_function
;
774 newfcn
->h_async_function
= h_async_function
;
775 newfcn
->ServiceName
= ServiceName
;
777 if (sockpath
!= NULL
) {
778 newfcn
->msock
= ig_uds_server(sockpath
, config
.c_maxsessions
, &error
);
779 snprintf(message
, SIZ
, "Unix domain socket '%s': ", sockpath
);
781 else if (tcp_port
<= 0) { /* port -1 to disable */
782 CtdlLogPrintf(CTDL_INFO
, "Service %s has been manually disabled, skipping\n", ServiceName
);
788 newfcn
->msock
= ig_tcp_server(config
.c_ip_addr
,
790 config
.c_maxsessions
,
792 snprintf(message
, SIZ
, "TCP port %s:%d: (%s) ",
793 config
.c_ip_addr
, tcp_port
, ServiceName
);
796 if (newfcn
->msock
> 0) {
797 ServiceHookTable
= newfcn
;
798 strcat(message
, "registered.");
799 CtdlLogPrintf(CTDL_INFO
, "%s\n", message
);
802 AddPortError(message
, error
);
803 strcat(message
, "FAILED.");
804 CtdlLogPrintf(CTDL_CRIT
, "%s\n", message
);
812 void CtdlUnregisterServiceHook(int tcp_port
, char *sockpath
,
813 void (*h_greeting_function
) (void),
814 void (*h_command_function
) (void),
815 void (*h_async_function
) (void)
818 struct ServiceFunctionHook
*cur
, *p
;
820 for (cur
= ServiceHookTable
; cur
!= NULL
; cur
= cur
->next
) {
821 /* This will also remove duplicates if any */
822 while (cur
!= NULL
&&
823 !(sockpath
&& cur
->sockpath
&&
824 strcmp(sockpath
, cur
->sockpath
)) &&
825 h_greeting_function
== cur
->h_greeting_function
&&
826 h_command_function
== cur
->h_command_function
&&
827 h_async_function
== cur
->h_async_function
&&
828 tcp_port
== cur
->tcp_port
) {
831 CtdlLogPrintf(CTDL_INFO
, "Closed UNIX domain socket %s\n",
833 } else if (tcp_port
) {
834 CtdlLogPrintf(CTDL_INFO
, "Closed TCP port %d\n", tcp_port
);
836 CtdlLogPrintf(CTDL_INFO
, "Unregistered service \"%s\"\n", cur
->ServiceName
);
839 if (cur
== ServiceHookTable
) {
840 ServiceHookTable
= p
;
848 void CtdlDestroyServiceHook(void)
850 struct ServiceFunctionHook
*cur
, *p
;
852 cur
= ServiceHookTable
;
857 CtdlLogPrintf(CTDL_INFO
, "Closed UNIX domain socket %s\n",
859 } else if (cur
->tcp_port
) {
860 CtdlLogPrintf(CTDL_INFO
, "Closed TCP port %d\n", cur
->tcp_port
);
862 CtdlLogPrintf(CTDL_INFO
, "Destroyed service \"%s\"\n", cur
->ServiceName
);
868 ServiceHookTable
= NULL
;
871 void CtdlRegisterSearchFuncHook(void (*fcn_ptr
)(int *, long **, char *), char *name
)
873 struct SearchFunctionHook
*newfcn
;
875 if (!name
|| !fcn_ptr
) {
879 newfcn
= (struct SearchFunctionHook
*)
880 malloc(sizeof(struct SearchFunctionHook
));
881 newfcn
->next
= SearchFunctionHookTable
;
883 newfcn
->fcn_ptr
= fcn_ptr
;
884 SearchFunctionHookTable
= newfcn
;
886 CtdlLogPrintf(CTDL_INFO
, "Registered a new search function (%s)\n", name
);
889 void CtdlUnregisterSearchFuncHook(void (*fcn_ptr
)(int *, long **, char *), char *name
)
891 struct SearchFunctionHook
*cur
, *p
;
893 for (cur
= SearchFunctionHookTable
; cur
!= NULL
; cur
= cur
->next
) {
894 while (fcn_ptr
&& (cur
->fcn_ptr
== fcn_ptr
) && name
&& !strcmp(name
, cur
->name
)) {
895 CtdlLogPrintf(CTDL_INFO
, "Unregistered search function(%s)\n", name
);
897 if (cur
== SearchFunctionHookTable
) {
898 SearchFunctionHookTable
= p
;
906 void CtdlModuleDoSearch(int *num_msgs
, long **search_msgs
, char *search_string
, char *func_name
)
908 struct SearchFunctionHook
*fcn
= NULL
;
910 for (fcn
= SearchFunctionHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
911 if (!func_name
|| !strcmp(func_name
, fcn
->name
)) {
912 (*fcn
->fcn_ptr
) (num_msgs
, search_msgs
, search_string
);
920 void PerformSessionHooks(int EventType
)
922 struct SessionFunctionHook
*fcn
= NULL
;
924 for (fcn
= SessionHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
925 if (fcn
->eventtype
== EventType
) {
926 (*fcn
->h_function_pointer
) ();
931 void PerformUserHooks(struct ctdluser
*usbuf
, int EventType
)
933 struct UserFunctionHook
*fcn
= NULL
;
935 for (fcn
= UserHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
936 if (fcn
->eventtype
== EventType
) {
937 (*fcn
->h_function_pointer
) (usbuf
);
942 int PerformMessageHooks(struct CtdlMessage
*msg
, int EventType
)
944 struct MessageFunctionHook
*fcn
= NULL
;
945 int total_retval
= 0;
947 /* Other code may elect to protect this message from server-side
948 * handlers; if this is the case, don't do anything.
949 CtdlLogPrintf(CTDL_DEBUG, "** Event type is %d, flags are %d\n",
950 EventType, msg->cm_flags);
952 if (msg
->cm_flags
& CM_SKIP_HOOKS
) {
953 CtdlLogPrintf(CTDL_DEBUG
, "Skipping hooks\n");
957 /* Otherwise, run all the hooks appropriate to this event type.
959 for (fcn
= MessageHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
960 if (fcn
->eventtype
== EventType
) {
961 total_retval
= total_retval
+
962 (*fcn
->h_function_pointer
) (msg
);
966 /* Return the sum of the return codes from the hook functions. If
967 * this is an EVT_BEFORESAVE event, a nonzero return code will cause
968 * the save operation to abort.
974 int PerformRoomHooks(struct ctdlroom
*target_room
)
976 struct RoomFunctionHook
*fcn
;
977 int total_retval
= 0;
979 CtdlLogPrintf(CTDL_DEBUG
, "Performing room hooks for <%s>\n", target_room
->QRname
);
981 for (fcn
= RoomHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
982 total_retval
= total_retval
+ (*fcn
->fcn_ptr
) (target_room
);
985 /* Return the sum of the return codes from the hook functions.
991 int PerformNetprocHooks(struct CtdlMessage
*msg
, char *target_room
)
993 struct NetprocFunctionHook
*fcn
;
994 int total_retval
= 0;
996 for (fcn
= NetprocHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
997 total_retval
= total_retval
+
998 (*fcn
->h_function_pointer
) (msg
, target_room
);
1001 /* Return the sum of the return codes from the hook functions.
1002 * A nonzero return code will cause the message to *not* be imported.
1004 return total_retval
;
1008 void PerformDeleteHooks(char *room
, long msgnum
)
1010 struct DeleteFunctionHook
*fcn
;
1012 for (fcn
= DeleteHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
1013 (*fcn
->h_function_pointer
) (room
, msgnum
);
1021 int PerformXmsgHooks(char *sender
, char *sender_email
, char *recp
, char *msg
)
1023 struct XmsgFunctionHook
*fcn
;
1027 for (p
=0; p
<MAX_XMSG_PRI
; ++p
) {
1028 for (fcn
= XmsgHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
1029 if (fcn
->order
== p
) {
1031 (*fcn
->h_function_pointer
)
1032 (sender
, sender_email
, recp
, msg
);
1035 /* Break out of the loop if a higher-priority function
1036 * successfully delivered the message. This prevents duplicate
1037 * deliveries to local users simultaneously signed onto
1040 if (total_sent
) break;
1048 int CtdlRegisterDirectoryServiceFunc(int (*func
)(char *cn
, char *ou
, void **object
), int cmd
, char *module
)
1050 struct DirectoryServiceHook
*newfcn
;
1052 newfcn
= DirectoryServiceHookList
;
1055 if (newfcn
->cmd
== cmd
&& !strcmp(newfcn
->module
, module
))
1057 CtdlLogPrintf(CTDL_ERR
, "Directory service function already handled by module %s\n", module
);
1060 newfcn
= newfcn
->next
;
1063 newfcn
= (struct DirectoryServiceHook
*) malloc (sizeof(struct DirectoryServiceHook
));
1064 newfcn
->handler
= func
;
1066 newfcn
->module
= module
;
1067 newfcn
->next
= DirectoryServiceHookList
;
1068 DirectoryServiceHookList
= newfcn
;
1070 CtdlLogPrintf(CTDL_INFO
, "Registered a new directory service function from module %s\n", module
);
1074 int CtdlDoDirectoryServiceFunc(char *cn
, char *ou
, void **object
, char *module
, int cmd
)
1076 struct DirectoryServiceHook
*curfcn
;
1077 struct DirectoryObject
*our_object_list
= NULL
;
1078 struct DirectoryObject
*newobject
= NULL
;
1079 struct DirectoryObject
*oldobject
= NULL
;
1082 curfcn
= DirectoryServiceHookList
;
1084 our_object_list
= (struct DirectoryObject
*) *object
;
1088 if (curfcn
->cmd
== cmd
)
1092 if (cmd
== DIRECTORY_CREATE_OBJECT
)
1094 newobject
= (struct DirectoryObject
*) malloc (sizeof(struct DirectoryObject
));
1095 newobject
->module
= curfcn
->module
;
1096 newobject
->object
= NULL
;
1097 newobject
->next
= our_object_list
;
1098 our_object_list
= newobject
;
1100 if (our_object_list
)
1102 for(newobject
= our_object_list
; newobject
; newobject
=newobject
->next
)
1104 if (!strcmp(newobject
->module
, curfcn
->module
))
1105 (void) curfcn
->handler(cn
, ou
, &newobject
->object
);
1109 (void) curfcn
->handler(cn
, ou
, NULL
);
1115 if(!strcmp(curfcn
->module
, module
))
1117 if (cmd
== DIRECTORY_CREATE_OBJECT
)
1119 newobject
= (struct DirectoryObject
*) malloc (sizeof(struct DirectoryObject
));
1120 newobject
->module
= module
;
1121 newobject
->object
= NULL
;
1122 newobject
->next
= our_object_list
;
1123 our_object_list
= newobject
;
1125 if (our_object_list
)
1127 for(newobject
= our_object_list
; newobject
; newobject
=newobject
->next
)
1129 if (!strcmp(newobject
->module
, curfcn
->module
))
1130 (void) curfcn
->handler(cn
, ou
, &newobject
->object
);
1134 (void) (curfcn
->handler(cn
, ou
, NULL
));
1140 curfcn
=curfcn
->next
;
1142 if (our_object_list
)
1144 *object
= our_object_list
;
1145 if (cmd
== DIRECTORY_FREE_OBJECT
)
1146 { // The objects pointed to by the list should have been freed by the module that created it
1147 for(newobject
= our_object_list
; newobject
; )
1149 oldobject
=newobject
;
1150 newobject
=newobject
->next
;
1159 void CtdlDestroyDirectoryServiceFuncs(void)
1161 struct DirectoryServiceHook
*cur
, *next
;
1163 cur
= DirectoryServiceHookList
;
1164 DirectoryServiceHookList
= NULL
;
1168 CtdlLogPrintf(CTDL_INFO
, "Destroyed directory service function for module %s.\n", cur
->module
);
1175 * Dirty hack until we impliment a hook mechanism for this
1177 void CtdlModuleStartCryptoMsgs(char *ok_response
, char *nosup_response
, char *error_response
)
1180 CtdlStartTLS (ok_response
, nosup_response
, error_response
);