4 * Citadel Dynamic Loading Module
5 * Written by Brian Costello <btx@calyx.net>
13 #include <sys/types.h>
21 #include "dynloader.h"
22 #include "sysdep_decls.h"
32 struct LogFunctionHook *LogHookTable = NULL;
33 struct CleanupFunctionHook *CleanupHookTable = NULL;
34 struct SessionFunctionHook *SessionHookTable = NULL;
35 struct UserFunctionHook *UserHookTable = NULL;
36 struct XmsgFunctionHook *XmsgHookTable = NULL;
37 struct MessageFunctionHook *MessageHookTable = NULL;
38 struct NetprocFunctionHook *NetprocHookTable = NULL;
39 struct DeleteFunctionHook *DeleteHookTable = NULL;
40 struct ServiceFunctionHook *ServiceHookTable = NULL;
42 struct ProtoFunctionHook {
43 void (*handler) (char *cmdbuf);
46 struct ProtoFunctionHook *next;
47 } *ProtoHookList = NULL;
49 void CtdlRegisterProtoHook(void (*handler) (char *), char *cmd, char *desc)
51 struct ProtoFunctionHook *p;
53 p = (struct ProtoFunctionHook *)
54 mallok(sizeof(struct ProtoFunctionHook));
57 fprintf(stderr, "can't malloc new ProtoFunctionHook\n");
63 p->next = ProtoHookList;
65 lprintf(5, "Registered server command %s (%s)\n", cmd, desc);
69 void CtdlUnregisterProtoHook(void (*handler) (char *), char *cmd)
71 struct ProtoFunctionHook *cur, *p;
73 for (cur = ProtoHookList; cur != NULL; cur = cur->next) {
74 /* This will also remove duplicates if any */
76 handler == cur->handler &&
77 !strcmp(cmd, cur->cmd)) {
78 lprintf(5, "Unregistered server command %s (%s)\n",
81 if (cur == ProtoHookList) {
91 int DLoader_Exec_Cmd(char *cmdbuf)
93 struct ProtoFunctionHook *p;
95 for (p = ProtoHookList; p; p = p->next) {
96 if (!strncasecmp(cmdbuf, p->cmd, 4)) {
97 p->handler(&cmdbuf[5]);
104 void initialize_server_extensions(void)
107 serv_calendar_init();
114 serv_netfilter_init();
122 /* serv_test_init(); */
124 serv_vandelay_init();
130 void CtdlRegisterLogHook(void (*fcn_ptr) (char *), int loglevel)
133 struct LogFunctionHook *newfcn;
135 newfcn = (struct LogFunctionHook *)
136 mallok(sizeof(struct LogFunctionHook));
137 newfcn->next = LogHookTable;
138 newfcn->h_function_pointer = fcn_ptr;
139 newfcn->loglevel = loglevel;
140 LogHookTable = newfcn;
142 lprintf(5, "Registered a new logging function\n");
146 void CtdlUnregisterLogHook(void (*fcn_ptr) (char *), int loglevel)
148 struct LogFunctionHook *cur, *p;
150 for (cur = LogHookTable; cur != NULL; cur = cur->next) {
151 /* This will also remove duplicates if any */
152 while (cur != NULL &&
153 fcn_ptr == cur->h_function_pointer &&
154 loglevel == cur->loglevel) {
155 lprintf(5, "Unregistered logging function\n");
157 if (cur == LogHookTable) {
167 void CtdlRegisterCleanupHook(void (*fcn_ptr) (void))
170 struct CleanupFunctionHook *newfcn;
172 newfcn = (struct CleanupFunctionHook *)
173 mallok(sizeof(struct CleanupFunctionHook));
174 newfcn->next = CleanupHookTable;
175 newfcn->h_function_pointer = fcn_ptr;
176 CleanupHookTable = newfcn;
178 lprintf(5, "Registered a new cleanup function\n");
182 void CtdlUnregisterCleanupHook(void (*fcn_ptr) (void))
184 struct CleanupFunctionHook *cur, *p;
186 for (cur = CleanupHookTable; cur != NULL; cur = cur->next) {
187 /* This will also remove duplicates if any */
188 while (cur != NULL &&
189 fcn_ptr == cur->h_function_pointer) {
190 lprintf(5, "Unregistered cleanup function\n");
192 if (cur == CleanupHookTable) {
193 CleanupHookTable = p;
202 void CtdlRegisterSessionHook(void (*fcn_ptr) (void), int EventType)
205 struct SessionFunctionHook *newfcn;
207 newfcn = (struct SessionFunctionHook *)
208 mallok(sizeof(struct SessionFunctionHook));
209 newfcn->next = SessionHookTable;
210 newfcn->h_function_pointer = fcn_ptr;
211 newfcn->eventtype = EventType;
212 SessionHookTable = newfcn;
214 lprintf(5, "Registered a new session function (type %d)\n",
219 void CtdlUnregisterSessionHook(void (*fcn_ptr) (void), int EventType)
221 struct SessionFunctionHook *cur, *p;
223 for (cur = SessionHookTable; cur != NULL; cur = cur->next) {
224 /* This will also remove duplicates if any */
225 while (cur != NULL &&
226 fcn_ptr == cur->h_function_pointer &&
227 EventType == cur->eventtype) {
228 lprintf(5, "Unregistered session function (type %d)\n",
231 if (cur == SessionHookTable) {
232 SessionHookTable = p;
241 void CtdlRegisterUserHook(void (*fcn_ptr) (char *, long), int EventType)
244 struct UserFunctionHook *newfcn;
246 newfcn = (struct UserFunctionHook *)
247 mallok(sizeof(struct UserFunctionHook));
248 newfcn->next = UserHookTable;
249 newfcn->h_function_pointer = fcn_ptr;
250 newfcn->eventtype = EventType;
251 UserHookTable = newfcn;
253 lprintf(5, "Registered a new user function (type %d)\n",
258 void CtdlUnregisterUserHook(void (*fcn_ptr) (char *, long), int EventType)
260 struct UserFunctionHook *cur, *p;
262 for (cur = UserHookTable; cur != NULL; cur = cur->next) {
263 /* This will also remove duplicates if any */
264 while (cur != NULL &&
265 fcn_ptr == cur->h_function_pointer &&
266 EventType == cur->eventtype) {
267 lprintf(5, "Unregistered user function (type %d)\n",
270 if (cur == UserHookTable) {
280 void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
284 struct MessageFunctionHook *newfcn;
286 newfcn = (struct MessageFunctionHook *)
287 mallok(sizeof(struct MessageFunctionHook));
288 newfcn->next = MessageHookTable;
289 newfcn->h_function_pointer = handler;
290 newfcn->eventtype = EventType;
291 MessageHookTable = newfcn;
293 lprintf(5, "Registered a new message function (type %d)\n",
298 void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *),
301 struct MessageFunctionHook *cur, *p;
303 for (cur = MessageHookTable; cur != NULL; cur = cur->next) {
304 /* This will also remove duplicates if any */
305 while (cur != NULL &&
306 handler == cur->h_function_pointer &&
307 EventType == cur->eventtype) {
308 lprintf(5, "Unregistered message function (type %d)\n",
311 if (cur == MessageHookTable) {
312 MessageHookTable = p;
321 void CtdlRegisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
323 struct NetprocFunctionHook *newfcn;
325 newfcn = (struct NetprocFunctionHook *)
326 mallok(sizeof(struct NetprocFunctionHook));
327 newfcn->next = NetprocHookTable;
328 newfcn->h_function_pointer = handler;
329 NetprocHookTable = newfcn;
331 lprintf(5, "Registered a new netproc function\n");
335 void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
337 struct NetprocFunctionHook *cur, *p;
339 for (cur = NetprocHookTable; cur != NULL; cur = cur->next) {
340 /* This will also remove duplicates if any */
341 while (cur != NULL &&
342 handler == cur->h_function_pointer ) {
343 lprintf(5, "Unregistered netproc function\n");
345 if (cur == NetprocHookTable) {
346 NetprocHookTable = p;
355 void CtdlRegisterDeleteHook(void (*handler)(char *, long) )
357 struct DeleteFunctionHook *newfcn;
359 newfcn = (struct DeleteFunctionHook *)
360 mallok(sizeof(struct DeleteFunctionHook));
361 newfcn->next = DeleteHookTable;
362 newfcn->h_function_pointer = handler;
363 DeleteHookTable = newfcn;
365 lprintf(5, "Registered a new netproc function\n");
369 void CtdlUnregisterDeleteHook(void (*handler)(char *, long) )
371 struct DeleteFunctionHook *cur, *p;
373 for (cur = DeleteHookTable; cur != NULL; cur = cur->next) {
374 /* This will also remove duplicates if any */
375 while (cur != NULL &&
376 handler == cur->h_function_pointer ) {
377 lprintf(5, "Unregistered netproc function\n");
379 if (cur == DeleteHookTable) {
389 void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
392 struct XmsgFunctionHook *newfcn;
394 newfcn = (struct XmsgFunctionHook *)
395 mallok(sizeof(struct XmsgFunctionHook));
396 newfcn->next = XmsgHookTable;
397 newfcn->order = order;
398 newfcn->h_function_pointer = fcn_ptr;
399 XmsgHookTable = newfcn;
400 lprintf(5, "Registered a new x-msg function (priority %d)\n", order);
404 void CtdlUnregisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
406 struct XmsgFunctionHook *cur, *p;
408 for (cur = XmsgHookTable; cur != NULL; cur = cur->next) {
409 /* This will also remove duplicates if any */
410 while (cur != NULL &&
411 fcn_ptr == cur->h_function_pointer &&
412 order == cur->order) {
413 lprintf(5, "Unregistered x-msg function "
414 "(priority %d)\n", order);
416 if (cur == XmsgHookTable) {
426 void CtdlRegisterServiceHook(int tcp_port,
428 void (*h_greeting_function) (void),
429 void (*h_command_function) (void) )
431 struct ServiceFunctionHook *newfcn;
434 newfcn = (struct ServiceFunctionHook *)
435 mallok(sizeof(struct ServiceFunctionHook));
436 newfcn->next = ServiceHookTable;
437 newfcn->tcp_port = tcp_port;
438 newfcn->sockpath = sockpath;
439 newfcn->h_greeting_function = h_greeting_function;
440 newfcn->h_command_function = h_command_function;
442 if (sockpath != NULL) {
443 newfcn->msock = ig_uds_server(sockpath, config.c_maxsessions);
444 snprintf(message, sizeof message, "Unix domain socket '%s': ", sockpath);
446 else if (tcp_port <= 0) { /* port -1 to disable */
447 lprintf(7, "Service has been manually disabled, skipping\n");
452 newfcn->msock = ig_tcp_server(tcp_port, config.c_maxsessions);
453 snprintf(message, sizeof message, "TCP port %d: ", tcp_port);
456 if (newfcn->msock > 0) {
457 ServiceHookTable = newfcn;
458 strcat(message, "registered.");
459 lprintf(5, "%s\n", message);
462 strcat(message, "FAILED.");
463 lprintf(2, "%s\n", message);
469 void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
470 void (*h_greeting_function) (void),
471 void (*h_command_function) (void) )
473 struct ServiceFunctionHook *cur, *p;
475 for (cur = ServiceHookTable; cur != NULL; cur = cur->next) {
476 /* This will also remove duplicates if any */
477 while (cur != NULL &&
478 !(sockpath && cur->sockpath &&
479 strcmp(sockpath, cur->sockpath)) &&
480 h_greeting_function == cur->h_greeting_function &&
481 h_command_function == cur->h_command_function &&
482 tcp_port == cur->tcp_port) {
485 lprintf(5, "Closed UNIX domain socket %s\n",
487 } else if (tcp_port) {
488 lprintf(5, "Closed TCP port %d\n", tcp_port);
490 lprintf(5, "Unregistered unknown service\n");
493 if (cur == ServiceHookTable) {
494 ServiceHookTable = p;
503 void PerformSessionHooks(int EventType)
505 struct SessionFunctionHook *fcn;
507 for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
508 if (fcn->eventtype == EventType) {
509 (*fcn->h_function_pointer) ();
514 void PerformLogHooks(int loglevel, char *logmsg)
516 struct LogFunctionHook *fcn;
518 for (fcn = LogHookTable; fcn != NULL; fcn = fcn->next) {
519 if (fcn->loglevel >= loglevel) {
520 (*fcn->h_function_pointer) (logmsg);
525 void PerformUserHooks(char *username, long usernum, int EventType)
527 struct UserFunctionHook *fcn;
529 for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
530 if (fcn->eventtype == EventType) {
531 (*fcn->h_function_pointer) (username, usernum);
536 int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
538 struct MessageFunctionHook *fcn;
539 int total_retval = 0;
541 /* Other code may elect to protect this message from server-side
542 * handlers; if this is the case, don't do anything.
543 lprintf(9, "** Event type is %d, flags are %d\n",
544 EventType, msg->cm_flags);
546 if (msg->cm_flags & CM_SKIP_HOOKS) {
547 lprintf(9, "Skipping hooks\n");
551 /* Otherwise, run all the hooks appropriate to this event type.
553 for (fcn = MessageHookTable; fcn != NULL; fcn = fcn->next) {
554 if (fcn->eventtype == EventType) {
555 total_retval = total_retval +
556 (*fcn->h_function_pointer) (msg);
560 /* Return the sum of the return codes from the hook functions. If
561 * this is an EVT_BEFORESAVE event, a nonzero return code will cause
562 * the save operation to abort.
569 int PerformNetprocHooks(struct CtdlMessage *msg, char *target_room)
571 struct NetprocFunctionHook *fcn;
572 int total_retval = 0;
574 for (fcn = NetprocHookTable; fcn != NULL; fcn = fcn->next) {
575 total_retval = total_retval +
576 (*fcn->h_function_pointer) (msg, target_room);
579 /* Return the sum of the return codes from the hook functions.
580 * A nonzero return code will cause the message to *not* be imported.
586 void PerformDeleteHooks(char *room, long msgnum)
588 struct DeleteFunctionHook *fcn;
590 for (fcn = DeleteHookTable; fcn != NULL; fcn = fcn->next) {
591 (*fcn->h_function_pointer) (room, msgnum);
597 int PerformXmsgHooks(char *sender, char *recp, char *msg)
599 struct XmsgFunctionHook *fcn;
603 for (p=0; p<MAX_XMSG_PRI; ++p) {
604 for (fcn = XmsgHookTable; fcn != NULL; fcn = fcn->next) {
605 if (fcn->order == p) {
607 (*fcn->h_function_pointer)
611 /* Break out of the loop if a higher-priority function
612 * successfully delivered the message. This prevents duplicate
613 * deliveries to local users simultaneously signed onto
616 if (total_sent) break;