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 mallok(sizeof(struct ProtoFunctionHook));
56 fprintf(stderr, "can't malloc new ProtoFunctionHook\n");
62 p->next = ProtoHookList;
64 lprintf(5, "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(5, "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();
113 serv_netfilter_init();
121 /* serv_test_init(); */
123 serv_vandelay_init();
129 void CtdlRegisterLogHook(void (*fcn_ptr) (char *), int loglevel)
132 struct LogFunctionHook *newfcn;
134 newfcn = (struct LogFunctionHook *)
135 mallok(sizeof(struct LogFunctionHook));
136 newfcn->next = LogHookTable;
137 newfcn->h_function_pointer = fcn_ptr;
138 newfcn->loglevel = loglevel;
139 LogHookTable = newfcn;
141 lprintf(5, "Registered a new logging function\n");
145 void CtdlUnregisterLogHook(void (*fcn_ptr) (char *), int loglevel)
147 struct LogFunctionHook *cur, *p;
149 for (cur = LogHookTable; cur != NULL; cur = cur->next) {
150 /* This will also remove duplicates if any */
151 while (cur != NULL &&
152 fcn_ptr == cur->h_function_pointer &&
153 loglevel == cur->loglevel) {
154 lprintf(5, "Unregistered logging function\n");
156 if (cur == LogHookTable) {
166 void CtdlRegisterCleanupHook(void (*fcn_ptr) (void))
169 struct CleanupFunctionHook *newfcn;
171 newfcn = (struct CleanupFunctionHook *)
172 mallok(sizeof(struct CleanupFunctionHook));
173 newfcn->next = CleanupHookTable;
174 newfcn->h_function_pointer = fcn_ptr;
175 CleanupHookTable = newfcn;
177 lprintf(5, "Registered a new cleanup function\n");
181 void CtdlUnregisterCleanupHook(void (*fcn_ptr) (void))
183 struct CleanupFunctionHook *cur, *p;
185 for (cur = CleanupHookTable; cur != NULL; cur = cur->next) {
186 /* This will also remove duplicates if any */
187 while (cur != NULL &&
188 fcn_ptr == cur->h_function_pointer) {
189 lprintf(5, "Unregistered cleanup function\n");
191 if (cur == CleanupHookTable) {
192 CleanupHookTable = p;
201 void CtdlRegisterSessionHook(void (*fcn_ptr) (void), int EventType)
204 struct SessionFunctionHook *newfcn;
206 newfcn = (struct SessionFunctionHook *)
207 mallok(sizeof(struct SessionFunctionHook));
208 newfcn->next = SessionHookTable;
209 newfcn->h_function_pointer = fcn_ptr;
210 newfcn->eventtype = EventType;
211 SessionHookTable = newfcn;
213 lprintf(5, "Registered a new session function (type %d)\n",
218 void CtdlUnregisterSessionHook(void (*fcn_ptr) (void), int EventType)
220 struct SessionFunctionHook *cur, *p;
222 for (cur = SessionHookTable; cur != NULL; cur = cur->next) {
223 /* This will also remove duplicates if any */
224 while (cur != NULL &&
225 fcn_ptr == cur->h_function_pointer &&
226 EventType == cur->eventtype) {
227 lprintf(5, "Unregistered session function (type %d)\n",
230 if (cur == SessionHookTable) {
231 SessionHookTable = p;
240 void CtdlRegisterUserHook(void (*fcn_ptr) (char *, long), int EventType)
243 struct UserFunctionHook *newfcn;
245 newfcn = (struct UserFunctionHook *)
246 mallok(sizeof(struct UserFunctionHook));
247 newfcn->next = UserHookTable;
248 newfcn->h_function_pointer = fcn_ptr;
249 newfcn->eventtype = EventType;
250 UserHookTable = newfcn;
252 lprintf(5, "Registered a new user function (type %d)\n",
257 void CtdlUnregisterUserHook(void (*fcn_ptr) (char *, long), int EventType)
259 struct UserFunctionHook *cur, *p;
261 for (cur = UserHookTable; cur != NULL; cur = cur->next) {
262 /* This will also remove duplicates if any */
263 while (cur != NULL &&
264 fcn_ptr == cur->h_function_pointer &&
265 EventType == cur->eventtype) {
266 lprintf(5, "Unregistered user function (type %d)\n",
269 if (cur == UserHookTable) {
279 void CtdlRegisterMessageHook(int (*handler)(struct CtdlMessage *),
283 struct MessageFunctionHook *newfcn;
285 newfcn = (struct MessageFunctionHook *)
286 mallok(sizeof(struct MessageFunctionHook));
287 newfcn->next = MessageHookTable;
288 newfcn->h_function_pointer = handler;
289 newfcn->eventtype = EventType;
290 MessageHookTable = newfcn;
292 lprintf(5, "Registered a new message function (type %d)\n",
297 void CtdlUnregisterMessageHook(int (*handler)(struct CtdlMessage *),
300 struct MessageFunctionHook *cur, *p;
302 for (cur = MessageHookTable; cur != NULL; cur = cur->next) {
303 /* This will also remove duplicates if any */
304 while (cur != NULL &&
305 handler == cur->h_function_pointer &&
306 EventType == cur->eventtype) {
307 lprintf(5, "Unregistered message function (type %d)\n",
310 if (cur == MessageHookTable) {
311 MessageHookTable = p;
320 void CtdlRegisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
322 struct NetprocFunctionHook *newfcn;
324 newfcn = (struct NetprocFunctionHook *)
325 mallok(sizeof(struct NetprocFunctionHook));
326 newfcn->next = NetprocHookTable;
327 newfcn->h_function_pointer = handler;
328 NetprocHookTable = newfcn;
330 lprintf(5, "Registered a new netproc function\n");
334 void CtdlUnregisterNetprocHook(int (*handler)(struct CtdlMessage *, char *) )
336 struct NetprocFunctionHook *cur, *p;
338 for (cur = NetprocHookTable; cur != NULL; cur = cur->next) {
339 /* This will also remove duplicates if any */
340 while (cur != NULL &&
341 handler == cur->h_function_pointer ) {
342 lprintf(5, "Unregistered netproc function\n");
344 if (cur == NetprocHookTable) {
345 NetprocHookTable = p;
354 void CtdlRegisterDeleteHook(void (*handler)(char *, long) )
356 struct DeleteFunctionHook *newfcn;
358 newfcn = (struct DeleteFunctionHook *)
359 mallok(sizeof(struct DeleteFunctionHook));
360 newfcn->next = DeleteHookTable;
361 newfcn->h_function_pointer = handler;
362 DeleteHookTable = newfcn;
364 lprintf(5, "Registered a new netproc function\n");
368 void CtdlUnregisterDeleteHook(void (*handler)(char *, long) )
370 struct DeleteFunctionHook *cur, *p;
372 for (cur = DeleteHookTable; cur != NULL; cur = cur->next) {
373 /* This will also remove duplicates if any */
374 while (cur != NULL &&
375 handler == cur->h_function_pointer ) {
376 lprintf(5, "Unregistered netproc function\n");
378 if (cur == DeleteHookTable) {
388 void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
391 struct XmsgFunctionHook *newfcn;
393 newfcn = (struct XmsgFunctionHook *)
394 mallok(sizeof(struct XmsgFunctionHook));
395 newfcn->next = XmsgHookTable;
396 newfcn->order = order;
397 newfcn->h_function_pointer = fcn_ptr;
398 XmsgHookTable = newfcn;
399 lprintf(5, "Registered a new x-msg function (priority %d)\n", order);
403 void CtdlUnregisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
405 struct XmsgFunctionHook *cur, *p;
407 for (cur = XmsgHookTable; 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 order == cur->order) {
412 lprintf(5, "Unregistered x-msg function "
413 "(priority %d)\n", order);
415 if (cur == XmsgHookTable) {
425 void CtdlRegisterServiceHook(int tcp_port,
427 void (*h_greeting_function) (void),
428 void (*h_command_function) (void) )
430 struct ServiceFunctionHook *newfcn;
433 newfcn = (struct ServiceFunctionHook *)
434 mallok(sizeof(struct ServiceFunctionHook));
435 newfcn->next = ServiceHookTable;
436 newfcn->tcp_port = tcp_port;
437 newfcn->sockpath = sockpath;
438 newfcn->h_greeting_function = h_greeting_function;
439 newfcn->h_command_function = h_command_function;
441 if (sockpath != NULL) {
442 newfcn->msock = ig_uds_server(sockpath, config.c_maxsessions);
443 snprintf(message, sizeof message, "Unix domain socket '%s': ", sockpath);
445 else if (tcp_port <= 0) { /* port -1 to disable */
446 lprintf(7, "Service has been manually disabled, skipping\n");
451 newfcn->msock = ig_tcp_server(tcp_port, config.c_maxsessions);
452 snprintf(message, sizeof message, "TCP port %d: ", tcp_port);
455 if (newfcn->msock > 0) {
456 ServiceHookTable = newfcn;
457 strcat(message, "registered.");
458 lprintf(5, "%s\n", message);
461 strcat(message, "FAILED.");
462 lprintf(2, "%s\n", message);
468 void CtdlUnregisterServiceHook(int tcp_port, char *sockpath,
469 void (*h_greeting_function) (void),
470 void (*h_command_function) (void) )
472 struct ServiceFunctionHook *cur, *p;
474 for (cur = ServiceHookTable; cur != NULL; cur = cur->next) {
475 /* This will also remove duplicates if any */
476 while (cur != NULL &&
477 !(sockpath && cur->sockpath &&
478 strcmp(sockpath, cur->sockpath)) &&
479 h_greeting_function == cur->h_greeting_function &&
480 h_command_function == cur->h_command_function &&
481 tcp_port == cur->tcp_port) {
484 lprintf(5, "Closed UNIX domain socket %s\n",
486 } else if (tcp_port) {
487 lprintf(5, "Closed TCP port %d\n", tcp_port);
489 lprintf(5, "Unregistered unknown service\n");
492 if (cur == ServiceHookTable) {
493 ServiceHookTable = p;
502 void PerformSessionHooks(int EventType)
504 struct SessionFunctionHook *fcn;
506 for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
507 if (fcn->eventtype == EventType) {
508 (*fcn->h_function_pointer) ();
513 void PerformLogHooks(int loglevel, char *logmsg)
515 struct LogFunctionHook *fcn;
517 for (fcn = LogHookTable; fcn != NULL; fcn = fcn->next) {
518 if (fcn->loglevel >= loglevel) {
519 (*fcn->h_function_pointer) (logmsg);
524 void PerformUserHooks(char *username, long usernum, int EventType)
526 struct UserFunctionHook *fcn;
528 for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
529 if (fcn->eventtype == EventType) {
530 (*fcn->h_function_pointer) (username, usernum);
535 int PerformMessageHooks(struct CtdlMessage *msg, int EventType)
537 struct MessageFunctionHook *fcn;
538 int total_retval = 0;
540 /* Other code may elect to protect this message from server-side
541 * handlers; if this is the case, don't do anything.
542 lprintf(9, "** Event type is %d, flags are %d\n",
543 EventType, msg->cm_flags);
545 if (msg->cm_flags & CM_SKIP_HOOKS) {
546 lprintf(9, "Skipping hooks\n");
550 /* Otherwise, run all the hooks appropriate to this event type.
552 for (fcn = MessageHookTable; fcn != NULL; fcn = fcn->next) {
553 if (fcn->eventtype == EventType) {
554 total_retval = total_retval +
555 (*fcn->h_function_pointer) (msg);
559 /* Return the sum of the return codes from the hook functions. If
560 * this is an EVT_BEFORESAVE event, a nonzero return code will cause
561 * the save operation to abort.
568 int PerformNetprocHooks(struct CtdlMessage *msg, char *target_room)
570 struct NetprocFunctionHook *fcn;
571 int total_retval = 0;
573 for (fcn = NetprocHookTable; fcn != NULL; fcn = fcn->next) {
574 total_retval = total_retval +
575 (*fcn->h_function_pointer) (msg, target_room);
578 /* Return the sum of the return codes from the hook functions.
579 * A nonzero return code will cause the message to *not* be imported.
585 void PerformDeleteHooks(char *room, long msgnum)
587 struct DeleteFunctionHook *fcn;
589 for (fcn = DeleteHookTable; fcn != NULL; fcn = fcn->next) {
590 (*fcn->h_function_pointer) (room, msgnum);
596 int PerformXmsgHooks(char *sender, char *recp, char *msg)
598 struct XmsgFunctionHook *fcn;
602 for (p=0; p<MAX_XMSG_PRI; ++p) {
603 for (fcn = XmsgHookTable; fcn != NULL; fcn = fcn->next) {
604 if (fcn->order == p) {
606 (*fcn->h_function_pointer)
610 /* Break out of the loop if a higher-priority function
611 * successfully delivered the message. This prevents duplicate
612 * deliveries to local users simultaneously signed onto
615 if (total_sent) break;