92dc1c2aad183bb502948bea538af2c45a8a420e
[citadel.git] / citadel / dynloader.c
1 /*******************************************************
2  *
3  * Citadel Dynamic Loading Module
4  * Written by Brian Costello
5  * btx@calyx.net
6  *
7  ******************************************************/
8
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <dlfcn.h>
13 #include <sys/types.h>
14 #include <dirent.h>
15 #include <strings.h>
16 #include <syslog.h>
17 #include <pthread.h>
18 #include <limits.h>
19 #include "dynloader.h"
20 #include "citadel.h"
21 #include "server.h"
22 #include "sysdep_decls.h"
23
24 #ifndef HAVE_SNPRINTF
25 #include <stdarg.h>
26 #include "snprintf.h"
27 #endif
28
29 struct CleanupFunctionHook *CleanupHookTable = NULL;
30 struct SessionFunctionHook *SessionHookTable = NULL;
31 struct UserFunctionHook *UserHookTable = NULL;
32
33 struct ProtoFunctionHook
34 {
35   void (*handler)(char *cmdbuf);
36   char *cmd;
37   char *desc;
38   struct ProtoFunctionHook *next;
39 } *ProtoHookList = NULL;
40
41 void CtdlRegisterProtoHook(void (*handler)(char *), char *cmd, char *desc)
42 {
43   struct ProtoFunctionHook *p = malloc(sizeof *p);
44   
45   if (p == NULL)
46     {
47       fprintf(stderr, "can't malloc new ProtoFunctionHook\n");
48       exit(EXIT_FAILURE);
49     }
50
51   p->handler = handler;
52   p->cmd = cmd;
53   p->desc = desc;
54   p->next = ProtoHookList;
55   ProtoHookList = p;
56 }
57
58 int DLoader_Exec_Cmd(char *cmdbuf)
59 {
60   struct ProtoFunctionHook *p;
61
62   for (p = ProtoHookList; p; p = p->next)
63     {
64       if (!strncasecmp(cmdbuf, p->cmd, 4))
65         {
66           p->handler(&cmdbuf[5]);
67           return 1;
68         }
69     }
70   return 0;
71 }
72
73 void DLoader_Init(char *pathname)
74 {
75    void *fcn_handle;
76    char *dl_error;
77    DIR *dir;
78    struct dirent *dptr;
79    struct DLModule_Info* (*h_init_fcn)(void);
80    struct DLModule_Info *dl_info;
81
82    char pathbuf[PATH_MAX];
83    
84    if ((dir = opendir(pathname))==NULL)
85    {
86       perror("opendir");
87       exit(1);
88    }
89    
90    while ((dptr=readdir(dir))!= NULL)
91    {
92       if (dptr->d_name[0] == '.')
93          continue;
94    
95       snprintf(pathbuf, PATH_MAX, "%s/%s", pathname, dptr->d_name);
96       if (!(fcn_handle = dlopen(pathbuf, RTLD_NOW)))
97       {
98          dl_error = dlerror();
99          fprintf(stderr, "DLoader_Init dlopen failed (%s)\n", dl_error);
100          continue;
101       }
102       
103       h_init_fcn = (struct DLModule_Info * (*)(void))
104         dlsym(fcn_handle, "Dynamic_Module_Init");
105
106       if ((dl_error = dlerror()) != NULL)
107       {
108          fprintf(stderr,"DLoader_Init dlsym failed (%s)\n", dl_error);
109          continue;
110       }
111       
112       dl_info = h_init_fcn();
113
114       printf("Loaded module %s v%d.%d\nBy %s (%s)\n", dl_info->module_name, 
115              dl_info->major_version, dl_info->minor_version,
116              dl_info->module_author, dl_info->module_author_email);
117    }    /* While */
118 }
119
120
121
122 void CtdlRegisterCleanupHook(void (*fcn_ptr)(void)) {
123
124         struct CleanupFunctionHook *newfcn;
125
126         newfcn = (struct CleanupFunctionHook *)
127                 malloc(sizeof(struct CleanupFunctionHook));
128         newfcn->next = CleanupHookTable;
129         newfcn->h_function_pointer = fcn_ptr;
130         CleanupHookTable = newfcn;
131
132         lprintf(5, "Registered a new cleanup function\n");
133         }
134
135
136 void CtdlRegisterSessionHook(void (*fcn_ptr)(void), int EventType) {
137
138         struct SessionFunctionHook *newfcn;
139
140         newfcn = (struct SessionFunctionHook *)
141                 malloc(sizeof(struct SessionFunctionHook));
142         newfcn->next = SessionHookTable;
143         newfcn->h_function_pointer = fcn_ptr;
144         newfcn->eventtype = EventType;
145         SessionHookTable = newfcn;
146
147         lprintf(5, "Registered a new session function (type %d)\n", 
148                 EventType);
149         }
150
151
152 void CtdlRegisterUserHook(void (*fcn_ptr)(char*, long), int EventType) {
153
154         struct UserFunctionHook *newfcn;
155
156         newfcn = (struct UserFunctionHook *)
157                 malloc(sizeof(struct UserFunctionHook));
158         newfcn->next = UserHookTable;
159         newfcn->h_function_pointer = fcn_ptr;
160         newfcn->eventtype = EventType;
161         UserHookTable = newfcn;
162
163         lprintf(5, "Registered a new user function (type %d)\n", 
164                 EventType);
165         }
166
167
168 void PerformSessionHooks(int EventType) {
169         struct SessionFunctionHook *fcn;
170
171         for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
172                 if (fcn->eventtype == EventType) {
173                         (*fcn->h_function_pointer)();
174                         }
175                 }
176         }
177
178 void PerformUserHooks(char *username, long usernum, int EventType) {
179         struct UserFunctionHook *fcn;
180
181         for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
182                 if (fcn->eventtype == EventType) {
183                         (*fcn->h_function_pointer)(username, usernum);
184                         }
185                 }
186         }
187