]> code.citadel.org Git - citadel.git/blob - citadel/dynloader.c
Fixes for Cygwin (see ChangeLog)
[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    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       if (!(fcn_handle = dlopen(pathbuf, RTLD_NOW)))
103       {
104          dl_error = dlerror();
105          fprintf(stderr, "DLoader_Init dlopen failed (%s)\n", dl_error);
106          continue;
107       }
108       
109       h_init_fcn = (struct DLModule_Info * (*)(void))
110         dlsym(fcn_handle, "Dynamic_Module_Init");
111
112       if ((dl_error = dlerror()) != NULL)
113       {
114          fprintf(stderr,"DLoader_Init dlsym failed (%s)\n", dl_error);
115          continue;
116       }
117       
118       dl_info = h_init_fcn();
119
120       printf("Loaded module %s v%d.%d\nBy %s (%s)\n", dl_info->module_name, 
121              dl_info->major_version, dl_info->minor_version,
122              dl_info->module_author, dl_info->module_author_email);
123    }    /* While */
124 }
125
126
127
128 void CtdlRegisterLogHook(void (*fcn_ptr)(char *), int loglevel) {
129
130         struct LogFunctionHook *newfcn;
131
132         newfcn = (struct LogFunctionHook *)
133                 mallok(sizeof(struct LogFunctionHook));
134         newfcn->next = LogHookTable;
135         newfcn->h_function_pointer = fcn_ptr;
136         newfcn->loglevel = loglevel;
137         LogHookTable = newfcn;
138
139         lprintf(5, "Registered a new logging function\n");
140         }
141
142
143 void CtdlRegisterCleanupHook(void (*fcn_ptr)(void)) {
144
145         struct CleanupFunctionHook *newfcn;
146
147         newfcn = (struct CleanupFunctionHook *)
148                 mallok(sizeof(struct CleanupFunctionHook));
149         newfcn->next = CleanupHookTable;
150         newfcn->h_function_pointer = fcn_ptr;
151         CleanupHookTable = newfcn;
152
153         lprintf(5, "Registered a new cleanup function\n");
154         }
155
156
157 void CtdlRegisterSessionHook(void (*fcn_ptr)(void), int EventType) {
158
159         struct SessionFunctionHook *newfcn;
160
161         newfcn = (struct SessionFunctionHook *)
162                 mallok(sizeof(struct SessionFunctionHook));
163         newfcn->next = SessionHookTable;
164         newfcn->h_function_pointer = fcn_ptr;
165         newfcn->eventtype = EventType;
166         SessionHookTable = newfcn;
167
168         lprintf(5, "Registered a new session function (type %d)\n", 
169                 EventType);
170         }
171
172
173 void CtdlRegisterUserHook(void (*fcn_ptr)(char*, long), int EventType) {
174
175         struct UserFunctionHook *newfcn;
176
177         newfcn = (struct UserFunctionHook *)
178                 mallok(sizeof(struct UserFunctionHook));
179         newfcn->next = UserHookTable;
180         newfcn->h_function_pointer = fcn_ptr;
181         newfcn->eventtype = EventType;
182         UserHookTable = newfcn;
183
184         lprintf(5, "Registered a new user function (type %d)\n", 
185                 EventType);
186         }
187
188
189 void PerformSessionHooks(int EventType) {
190         struct SessionFunctionHook *fcn;
191
192         for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
193                 if (fcn->eventtype == EventType) {
194                         (*fcn->h_function_pointer)();
195                         }
196                 }
197         }
198
199 void PerformLogHooks(int loglevel, char *logmsg) {
200         struct LogFunctionHook *fcn;
201
202         for (fcn = LogHookTable; fcn != NULL; fcn = fcn->next) {
203                 if (fcn->loglevel >= loglevel) {
204                         (*fcn->h_function_pointer)(logmsg);
205                         }
206                 }
207         }
208
209 void PerformUserHooks(char *username, long usernum, int EventType) {
210         struct UserFunctionHook *fcn;
211
212         for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
213                 if (fcn->eventtype == EventType) {
214                         (*fcn->h_function_pointer)(username, usernum);
215                         }
216                 }
217         }
218