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