0f492be0bd71985ccb85edfa8f79a797dccb038e
[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 (!strncmp(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 = dlsym(fcn_handle, "Dynamic_Module_Init");
104       if ((dl_error = dlerror()) != NULL)
105       {
106          fprintf(stderr,"DLoader_Init dlsym failed (%s)\n", dl_error);
107          continue;
108       }
109       
110       dl_info = h_init_fcn();
111
112       printf("Loaded module %s v%d.%d\nBy %s (%s)\n", dl_info->module_name, 
113              dl_info->major_version, dl_info->minor_version,
114              dl_info->module_author, dl_info->module_author_email);
115    }    /* While */
116 }
117
118
119
120 void CtdlRegisterCleanupHook(void *fcn_ptr) {
121
122         struct CleanupFunctionHook *newfcn;
123
124         newfcn = (struct CleanupFunctionHook *)
125                 malloc(sizeof(struct CleanupFunctionHook));
126         newfcn->next = CleanupHookTable;
127         newfcn->h_function_pointer = fcn_ptr;
128         CleanupHookTable = newfcn;
129
130         lprintf(5, "Registered a new cleanup function\n");
131         }
132
133
134 void CtdlRegisterSessionHook(void *fcn_ptr, int EventType) {
135
136         struct SessionFunctionHook *newfcn;
137
138         newfcn = (struct SessionFunctionHook *)
139                 malloc(sizeof(struct SessionFunctionHook));
140         newfcn->next = SessionHookTable;
141         newfcn->h_function_pointer = fcn_ptr;
142         newfcn->eventtype = EventType;
143         SessionHookTable = newfcn;
144
145         lprintf(5, "Registered a new session function (type %d)\n", 
146                 EventType);
147         }
148
149
150 void CtdlRegisterUserHook(void *fcn_ptr, int EventType) {
151
152         struct UserFunctionHook *newfcn;
153
154         newfcn = (struct UserFunctionHook *)
155                 malloc(sizeof(struct UserFunctionHook));
156         newfcn->next = UserHookTable;
157         newfcn->h_function_pointer = fcn_ptr;
158         newfcn->eventtype = EventType;
159         UserHookTable = newfcn;
160
161         lprintf(5, "Registered a new user function (type %d)\n", 
162                 EventType);
163         }
164
165
166 void PerformSessionHooks(int EventType) {
167         struct SessionFunctionHook *fcn;
168
169         for (fcn = SessionHookTable; fcn != NULL; fcn = fcn->next) {
170                 if (fcn->eventtype == EventType) {
171                         (*fcn->h_function_pointer)();
172                         }
173                 }
174         }
175
176 void PerformUserHooks(char *username, long usernum, int EventType) {
177         struct UserFunctionHook *fcn;
178
179         for (fcn = UserHookTable; fcn != NULL; fcn = fcn->next) {
180                 if (fcn->eventtype == EventType) {
181                         (*fcn->h_function_pointer)(username, usernum);
182                         }
183                 }
184         }
185