]> code.citadel.org Git - citadel.git/blob - citadel/dynloader.c
1998-09-15 Nathan Bryant <bryant@cs.usm.maine.edu>
[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 "dynloader.h"
19 #include "citadel.h"
20 #include "server.h"
21 #include "sysdep_decls.h"
22
23 symtab *global_symtab;
24
25 struct FunctionHook *HookTable = NULL;
26
27 int DLoader_Exec_Cmd(char *cmdbuf)
28 {
29    symtab *t_sym;
30    void *fcn_handle;
31    char *dl_error;
32    void (*cmd_ptr)(void *);
33    
34    for (t_sym = global_symtab; ((t_sym) && (strncmp(t_sym->server_cmd, cmdbuf, strlen(t_sym->server_cmd))) ); t_sym=t_sym->next)
35       ;
36       
37    if (t_sym)
38    {
39       if (!(fcn_handle = dlopen(t_sym->module_path, RTLD_NOW)))
40       {
41          dl_error = dlerror();
42          syslog(LOG_NOTICE, "WARNING: module %s failed to load", t_sym->module_path);
43          return(0);
44       }
45       
46       cmd_ptr = dlsym(fcn_handle, t_sym->fcn_name);
47       if ((dl_error = dlerror()) != NULL)
48       {
49          syslog(LOG_NOTICE, "dlsym error: %s - %s", dl_error, t_sym->module_path);
50          return(0);
51       }
52       (*cmd_ptr)(&cmdbuf[5]);
53       dlclose(fcn_handle);
54       if ((dl_error = dlerror()) != NULL)
55       {
56          syslog(LOG_NOTICE, "dlclose error: %s", dl_error);
57          return(0);
58       }
59       return(1);
60    }  /* If symbol found */
61
62    return(0);
63 }
64
65 void add_symbol(char *fcn_name, char *server_cmd, char *info_msg, symtab **first_symtab)
66 {
67    symtab *new_symtab, *t_sym, *last_sym;
68    
69    if (!(new_symtab = malloc(sizeof(symtab))))
70    {
71       perror("Malloc new symtab");
72       exit(1);
73    }
74    
75    new_symtab->fcn_name = strdup(fcn_name);
76    new_symtab->server_cmd = strdup(server_cmd);
77    new_symtab->info_msg = strdup(info_msg);
78    new_symtab->next = NULL;
79    
80    if (!(*first_symtab))
81       (*first_symtab) = new_symtab;
82    else
83    {
84       last_sym = NULL;
85       for (t_sym = (*first_symtab); (t_sym); t_sym = t_sym->next)
86          last_sym = t_sym;
87       last_sym->next = new_symtab;
88    }
89 }
90
91 void DLoader_Init(char *pathname, symtab **my_symtab)
92 {
93    void *fcn_handle;
94    void (*h_init_fcn)(struct DLModule_Info *);
95    void (*h_get_symtab)(symtab **);
96    char *dl_error;
97    char *filename;
98    DIR *dir;
99    struct dirent *dptr;
100    
101    char pathbuf[512];
102    struct DLModule_Info dl_info;
103    symtab *stab = NULL;
104    symtab *t_sym;
105    
106    global_symtab = NULL;                        /* Global symbol table */
107    
108    if ((dir = opendir(pathname))==NULL)
109    {
110       perror("opendir");
111       exit(1);
112    }
113    
114    while ((dptr=readdir(dir))!= NULL)
115    {
116       if (dptr->d_name[0] == '.')
117          continue;
118    
119       filename = strdup(dptr->d_name);
120       snprintf(pathbuf, 512, "%s/%s", pathname, filename);
121       if (!(fcn_handle = dlopen(pathbuf, RTLD_NOW)))
122       {
123          dl_error = dlerror();
124          fprintf(stderr, "DLoader_Init dlopen failed (%s)", dl_error);
125          continue;
126       }
127       
128       h_init_fcn = dlsym(fcn_handle, "Dynamic_Module_Init");
129       if ((dl_error = dlerror()) != NULL)
130       {
131          fprintf(stderr,"DLoader_Init dlsym failed (%s)", dl_error);
132          continue;
133       }
134       
135       (*h_init_fcn)(&dl_info);
136
137       printf("Loaded module %s v%d.%d\nBy %s (%s)\n", dl_info.module_name, 
138                                                      dl_info.major_version,
139                                                      dl_info.minor_version,
140                                                      dl_info.module_author,
141                                                      dl_info.module_author_email);
142
143       h_get_symtab = dlsym(fcn_handle, "Get_Symtab");
144       if ((dl_error = dlerror()) != NULL)
145       {
146          fprintf(stderr,"DLoader_Init dlsym failed for Get_Symtab (%s) on module %s", dl_error, dl_info.module_name);
147          continue;
148       }
149       
150 /* Get the symbol table for the current module and link it on */      
151       
152       (*h_get_symtab)(&stab);
153       if (!(*my_symtab))
154       {
155          (*my_symtab) = global_symtab = stab;
156       }
157       else
158       {
159          for (t_sym = (*my_symtab) ; t_sym->next; t_sym=t_sym->next);
160             ;
161          t_sym->next = stab;
162       }
163       for (t_sym = stab; t_sym; t_sym=t_sym->next)
164          t_sym->module_path = (char *)strdup(pathbuf);
165       dlclose(fcn_handle);
166       if ((dl_error = dlerror()) != NULL)
167       {
168          fprintf(stderr,"DLoader_Init dlclose failed (%s)", dl_error);
169          continue;
170       }
171       
172    }    /* While */
173    
174 }
175
176
177
178 void CtdlRegisterHook(void *fcn_ptr, int fcn_type) {
179
180         struct FunctionHook *newfcn;
181
182         newfcn = (struct FunctionHook *) malloc(sizeof(struct FunctionHook));
183         newfcn->next = HookTable;
184         newfcn->h_function_pointer = fcn_ptr;
185         newfcn->h_type = fcn_type;
186
187         HookTable = newfcn;
188
189         lprintf(5, "Registered a new function (type %d)\n", fcn_type);
190         }