4 * Citadel Dynamic Loading Module
5 * Written by Brian Costello <btx@calyx.net>
13 #include <sys/types.h>
20 #include "serv_extensions.h"
21 #include "sysdep_decls.h"
31 struct LogFunctionHook *LogHookTable = NULL;
32 struct CleanupFunctionHook *CleanupHookTable = NULL;
33 struct SessionFunctionHook *SessionHookTable = NULL;
34 struct UserFunctionHook *UserHookTable = NULL;
35 struct XmsgFunctionHook *XmsgHookTable = NULL;
36 struct MessageFunctionHook *MessageHookTable = NULL;
37 struct NetprocFunctionHook *NetprocHookTable = NULL;
38 struct DeleteFunctionHook *DeleteHookTable = NULL;
39 struct ServiceFunctionHook *ServiceHookTable = NULL;
41 struct ProtoFunctionHook {
42 void (*handler) (char *cmdbuf);
45 struct ProtoFunctionHook *next;
46 } *ProtoHookList = NULL;
48 void CtdlRegisterProtoHook(void (*handler) (char *), char *cmd, char *desc)
50 struct ProtoFunctionHook *p;
52 p = (struct ProtoFunctionHook *)
53 malloc(sizeof(struct ProtoFunctionHook));
56 fprintf(stderr, "can't malloc new ProtoFunctionHook\n");
62 p->next = ProtoHookList;
64 lprintf(CTDL_INFO, "Registered server command %s (%s)\n", cmd, desc);
68 void CtdlUnregisterProtoHook(void (*handler) (char *), char *cmd)
70 struct ProtoFunctionHook *cur, *p;
72 for (cur = ProtoHookList; cur != NULL; cur = cur->next) {
73 /* This will also remove duplicates if any */
75 handler == cur->handler &&
76 !strcmp(cmd, cur->cmd)) {
77 lprintf(CTDL_INFO, "Unregistered server command %s (%s)\n",
80 if (cur == ProtoHookList) {
90 int DLoader_Exec_Cmd(char *cmdbuf)
92 struct ProtoFunctionHook *p;
94 for (p = ProtoHookList; p; p = p->next) {
95 if (!strncasecmp(cmdbuf, p->cmd, 4)) {
96 p->handler(&cmdbuf[5]);
103 void initialize_server_extensions(void)
106 serv_calendar_init();
115 serv_netfilter_init();
123 /* serv_test_init(); */
125 serv_vandelay_init();
131 void CtdlRegisterLogHook(void (*fcn_ptr) (char *), int loglevel)
134 struct LogFunctionHook *newfcn;
136 newfcn = (struct LogFunctionHook *)
137 malloc(sizeof(struct LogFunctionHook));
138 newfcn->next = LogHookTable;
139 newfcn->h_function_pointer = fcn_ptr;
140 newfcn->loglevel = loglevel;
141 LogHookTable = newfcn;
143 lprintf(CTDL_INFO, "Registered a new logging function\n");
147 void CtdlUnregisterLogHook(void (*fcn_ptr) (char *), int loglevel)
149 struct LogFunctionHook *cur, *p;
151 for (cur = LogHookTable; cur != NULL; cur = cur->next) {
152 /* This will also remove duplicates if any */
153 while (cur != NULL &&
154 fcn_ptr == cur->h_function_pointer &&
155 loglevel == cur->loglevel) {
156 lprintf(CTDL_INFO, "Unregistered logging function\n");
158 if (cur == LogHookTable) {
168 void CtdlRegisterCleanupHook(void (*fcn_ptr) (void))
171 struct CleanupFunctionHook *newfcn;
173 newfcn = (struct CleanupFunctionHook *)
174 malloc(sizeof(struct CleanupFunctionHook));
175 newfcn->next = CleanupHookTable;
176 newfcn->h_function_pointer = fcn_ptr;
177 CleanupHookTable = newfcn;
179 lprintf(CTDL_INFO, "Registered a new cleanup function\n");
183 void CtdlUnregisterCleanupHook(void (*fcn_ptr) (void))
185 struct CleanupFunctionHook *cur, *p;
187 for (cur = CleanupHookTable; cur != NULL; cur = cur->next) {
188 /* This will also remove duplicates if any */
189 while (cur != NULL &&
190 fcn_ptr == cur->h_function_pointer) {
191 lprintf(CTDL_INFO, "Unregistered cleanup function\n");
193 if (cur == CleanupHookTable) {
194 CleanupHookTable = p;
203 void CtdlRegisterSessionHook(void (*fcn_ptr) (void), int EventType)
206 struct SessionFunctionHook *newfcn;
208 newfcn = (struct SessionFunctionHook *)
209 malloc(sizeof(struct SessionFunctionHook));
210 newfcn->next = SessionHookTable;
211 newfcn->h_function_pointer = fcn_ptr;
212 newfcn->eventtype = EventType;
213 SessionHookTable = newfcn;
215 lprintf(CTDL_INFO, "Registered a new session function (type %d)\n",
220 void CtdlUnregisterSessionHook(void (*fcn_ptr) (void), int EventType)
222 struct SessionFunctionHook *cur, *p;
224 for (cur = SessionHookTable; cur != NULL; cur = cur->next) {
225 /* This will also remove duplicates if any */
226 while (cur != NULL &&
227 fcn_ptr == cur->h_function_pointer &&
228 EventType == cur->eventtype) {
229 lprintf(CTDL_INFO, "Unregistered session function (type %d)\n",
232 if (cur == SessionHookTable) {
233 SessionHookTable = p;
242 void CtdlRegisterUserHook(void (*fcn_ptr) (struct ctdluser *), int EventType)
245 struct UserFunctionHook *newfcn;
247 newfcn = (struct UserFunctionHook *)
248 malloc(sizeof(struct UserFunctionHook));
249 newfcn->next = UserHookTable;
250 newfcn->h_function_pointer = fcn_ptr;
251 newfcn->eventtype = EventType;
252 UserHookTable = newfcn;
254 lprintf(CTDL_INFO, "Registered a new user function (type %d)\n",
259 void CtdlUnregisterUserHook(void (*fcn_ptr) (struct ctdluser *), int EventType)
261 struct UserFunctionHook *cur, *p;
263 for (cur = UserHookTable; cur != NULL; cur = cur->next) {
264 /* This will also remove duplicates if any */
265 while (cur != NULL &&
266 fcn_ptr == cur->h_function_pointer &&
267 EventType == cur->eventtype) {
268 lprintf(CTDL_INFO, "Unregistered user function (type %d)\n",
271 if (cur == UserHookTable) {
281 void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
285 struct MessageFunctionHook *newfcn;
287 newfcn = (struct MessageFunctionHook *)
288 malloc(sizeof(struct MessageFunctionHook));
289 newfcn->next = MessageHookTable;
290 newfcn->h_function_pointer = handler;
291 newfcn->eventtype = EventType;
292 MessageHookTable = newfcn;
294 lprintf(CTDL_INFO, "Registered a new message function (type %d)\n",
299 void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *),
302 struct MessageFunctionHook *cur, *p;
304 for (cur = MessageHookTable; cur != NULL; cur = cur->next) {
305 /* This will also remove duplicates if any */
306 while (cur != NULL &&
307 handler == cur->h_function_pointer &&
308 EventType == cur->eventtype) {
309 lprintf(CTDL_INFO, "Unregistered message function (type %d)\n",
312 if (cur == MessageHookTable) {
313 MessageHookTable = p;
322 void CtdlRegisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
324 struct NetprocFunctionHook *newfcn;
326 newfcn = (struct NetprocFunctionHook *)
327 malloc(sizeof(struct NetprocFunctionHook));
328 newfcn->next = NetprocHookTable;
329 newfcn->h_function_pointer = handler;
330 NetprocHookTable = newfcn;
332 lprintf(CTDL_INFO, "Registered a new netproc function\n");
336 void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
338 struct NetprocFunctionHook *cur, *p;
340 for (cur = NetprocHookTable; cur != NULL; cur = cur->next) {
341 /* This will also remove duplicates if any */
342 while (cur != NULL &&
343 handler == cur->h_function_pointer ) {
344 lprintf(CTDL_INFO, "Unregistered netproc function\n");
346 if (cur == NetprocHookTable) {
347 NetprocHookTable = p;
356 void CtdlRegisterDeleteHook(void (*handler)(char *, long) )
358 struct DeleteFunctionHook *newfcn;
360 newfcn = (struct DeleteFunctionHook *)
361 malloc(sizeof(struct DeleteFunctionHook));
362 newfcn->next = DeleteHookTable;
363 newfcn->h_function_pointer = handler;
364 DeleteHookTable = newfcn;
366 lprintf(CTDL_INFO, "Registered a new netproc function\n");
370 void CtdlUnregisterDeleteHook(void (*handler)(char *, long) )
372 struct DeleteFunctionHook *cur, *p;
374 for (cur = DeleteHookTable; cur != NULL; cur = cur->next) {
375 /* This will also remove duplicates if any */
376 while (cur != NULL &&
377 handler == cur->h_function_pointer ) {
378 lprintf(CTDL_INFO, "Unregistered netproc function\n");
380 if (cur == DeleteHookTable) {
390 void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
393 struct XmsgFunctionHook *newfcn;
395 newfcn = (struct XmsgFunctionHook *)
396 malloc(sizeof(struct XmsgFunctionHook));
397 newfcn->next = XmsgHookTable;
398 newfcn->order = order;
399 newfcn->h_function_pointer = fcn_ptr;
400 XmsgHookTable = newfcn;
401 lprintf(CTDL_INFO, "Registered a new x-msg function (priority %d)\n", order);
405 void CtdlUnregisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
407 struct XmsgFunctionHook *cur, *p;
409 for (cur = XmsgHookTable; cur != NULL; cur = cur->next) {
410 /* This will also remove duplicates if any */
411 while (cur != NULL &&
412 fcn_ptr == cur->h_function_pointer &&
413 order == cur->order) {
414 lprintf(CTDL_INFO, "Unregistered x-msg function "
415 "(priority %d)\n", order);
417 if (cur == XmsgHookTable) {
427 void CtdlRegisterServiceHook(int tcp_port,
429 void (*h_greeting_function) (void),
430 void (*h_command_function) (void),
431 void (*h_async_function) (void)
434 struct ServiceFunctionHook *newfcn;
437 newfcn = (struct ServiceFunctionHook *)
438 malloc(sizeof(struct ServiceFunctionHook));
439 newfcn->next = ServiceHookTable;
440 newfcn->tcp_port = tcp_port;
441 newfcn->sockpath = sockpath;
442 newfcn->h_greeting_function = h_greeting_function;
443 newfcn->h_command_function = h_command_function;
444 newfcn->h_async_function = h_async_function;
446 if (sockpath != NULL) {
447 newfcn->msock = ig_uds_server(sockpath, config.c_maxsessions);
448 snprintf(message, sizeof message, "Unix domain socket '%s': ", sockpath);
450 else if (tcp_port <= 0) { /* port -1 to disable */
451 lprintf(CTDL_INFO, "Service has been manually disabled, skipping\n");
456 newfcn->msock = ig_tcp_server(config.c_ip_addr,
458 config.c_maxsessions);
459 snprintf(message, sizeof message, "TCP port %d: ", tcp_port);
462 if (newfcn->msock > 0) {
463 ServiceHookTable = newfcn;
464 strcat(message, "registered.");
465 lprintf(CTDL_INFO, "%s\n", message);
468 strcat(message, "FAILED.");
469 lprintf(CTDL_CRIT, "%s\n", message);
475 void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
476 void (*h_greeting_function) (void),
477 void (*h_command_function) (void),
478 void (*h_async_function) (void)
481 struct ServiceFunctionHook *cur, *p;
483 for (cur = ServiceHookTable; cur != NULL; cur = cur->next) {
484 /* This will also remove duplicates if any */
485 while (cur != NULL &&
486 !(sockpath && cur->sockpath &&
487 strcmp(sockpath, cur->sockpath)) &&
488 h_greeting_function == cur->h_greeting_function &&
489 h_command_function == cur->h_command_function &&
490 h_async_function == cur->h_async_function &&
491 tcp_port == cur->tcp_port) {
494 lprintf(CTDL_INFO, "Closed UNIX domain socket %s\n",
496 } else if (tcp_port) {
497 lprintf(CTDL_INFO, "Closed TCP port %d\n", tcp_port);
499 lprintf(CTDL_INFO, "Unregistered unknown service\n");
502 if (cur == ServiceHookTable) {
503 ServiceHookTable = p;
512 void PerformSessionHooks(int EventType)
514 struct SessionFunctionHook *fcn;
516 for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
517 if (fcn->eventtype == EventType) {
518 (*fcn->h_function_pointer) ();
523 void PerformLogHooks(int loglevel, char *logmsg)
525 struct LogFunctionHook *fcn;
527 for (fcn = LogHookTable; fcn != NULL; fcn = fcn->next) {
528 if (fcn->loglevel >= loglevel) {
529 (*fcn->h_function_pointer) (logmsg);
534 void PerformUserHooks(struct ctdluser *usbuf, int EventType)
536 struct UserFunctionHook *fcn;
538 for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
539 if (fcn->eventtype == EventType) {
540 (*fcn->h_function_pointer) (usbuf);
545 int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
547 struct MessageFunctionHook *fcn;
548 int total_retval = 0;
550 /* Other code may elect to protect this message from server-side
551 * handlers; if this is the case, don't do anything.
552 lprintf(CTDL_DEBUG, "** Event type is %d, flags are %d\n",
553 EventType, msg->cm_flags);
555 if (msg->cm_flags & CM_SKIP_HOOKS) {
556 lprintf(CTDL_DEBUG, "Skipping hooks\n");
560 /* Otherwise, run all the hooks appropriate to this event type.
562 for (fcn = MessageHookTable; fcn != NULL; fcn = fcn->next) {
563 if (fcn->eventtype == EventType) {
564 total_retval = total_retval +
565 (*fcn->h_function_pointer) (msg);
569 /* Return the sum of the return codes from the hook functions. If
570 * this is an EVT_BEFORESAVE event, a nonzero return code will cause
571 * the save operation to abort.
578 int PerformNetprocHooks(struct CtdlMessage *msg, char *target_room)
580 struct NetprocFunctionHook *fcn;
581 int total_retval = 0;
583 for (fcn = NetprocHookTable; fcn != NULL; fcn = fcn->next) {
584 total_retval = total_retval +
585 (*fcn->h_function_pointer) (msg, target_room);
588 /* Return the sum of the return codes from the hook functions.
589 * A nonzero return code will cause the message to *not* be imported.
595 void PerformDeleteHooks(char *room, long msgnum)
597 struct DeleteFunctionHook *fcn;
599 for (fcn = DeleteHookTable; fcn != NULL; fcn = fcn->next) {
600 (*fcn->h_function_pointer) (room, msgnum);
606 int PerformXmsgHooks(char *sender, char *recp, char *msg)
608 struct XmsgFunctionHook *fcn;
612 for (p=0; p<MAX_XMSG_PRI; ++p) {
613 for (fcn = XmsgHookTable; fcn != NULL; fcn = fcn->next) {
614 if (fcn->order == p) {
616 (*fcn->h_function_pointer)
620 /* Break out of the loop if a higher-priority function
621 * successfully delivered the message. This prevents duplicate
622 * deliveries to local users simultaneously signed onto
625 if (total_sent) break;