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