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