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