-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
plugins.c
162 lines (138 loc) · 3.87 KB
/
plugins.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "arch.h"
#include "plugins.h"
#ifdef DYNAMIC_PLUGINS
#include <dlfcn.h>
#include <glob.h>
#endif
struct plugin_list {
const SetupPlugin *plugin;
void *dl; /* Dynamic library handle */
struct plugin_list *next;
};
/* The list of registered plugins */
static struct plugin_list *plugins = NULL;
/** Find the plugin structure associated with a file (looks through the list of registered extensions
* @param path file name
* @param suffix if non-NULL assume the file has this suffix to force a certain plugin
* @returns pointer to plugin or NULL if none matches
*/
const SetupPlugin *FindPluginForFile(const char *path, const char* suffix)
{
const char* p = suffix?suffix:path;
unsigned plen = strlen(p);
unsigned i;
struct plugin_list *plug = plugins;
for(plug = plugins; plug; plug = plug->next)
{
for ( i = 0; i < plug->plugin->num_extensions; ++i ) {
const char* ext = plug->plugin->extensions[i];
unsigned len = strlen(ext);
if(plen < len)
continue;
if(!strcmp(p+plen-len, ext))
return plug->plugin;
}
}
return NULL;
}
/* Register a plugin */
int RegisterPlugin(const SetupPlugin *plugin, void *handle)
{
struct plugin_list *plg = (struct plugin_list *) malloc(sizeof(struct plugin_list));
plg->plugin = plugin;
plg->dl = handle;
plg->next = plugins;
plugins = plg;
/* Call the plugin's init function, if any */
if ( plugin->InitPlugin ) {
return plugin->InitPlugin();
}
return 1;
}
/* Free all registered plugins, returns the number of successfully freed plugins */
int FreePlugins(void)
{
struct plugin_list *plg = plugins, *prev;
int ret = 0;
while ( plg ) {
if ( plg->plugin->FreePlugin ) {
ret += plg->plugin->FreePlugin();
}
#ifdef DYNAMIC_PLUGINS
if ( plg->dl ) {
dlclose(plg->dl);
}
#endif
prev = plg;
plg = plg->next;
free(prev);
}
return ret;
}
/* Dumps info on a file about all registered plugins */
void DumpPlugins(FILE *f)
{
int i;
struct plugin_list *plg = plugins;
fprintf(f, _("Registered plugins :\n\n"));
while ( plg ) {
fprintf(f, _("\tDescription: %s\n\tVersion: %s\n\tAuthor: %s\n"),
plg->plugin->description, plg->plugin->version, plg->plugin->author);
if ( ! plg->dl ) {
fprintf(f, _("\tPlugin is statically linked.\n"));
}
fprintf(f, _("\tRecognizes %d extensions: "), plg->plugin->num_extensions);
for ( i = 0; i < plg->plugin->num_extensions; ++i ) {
fprintf(f,"%s ", plg->plugin->extensions[i]);
}
fprintf(f,"\n\n");
plg = plg->next;
}
}
/* Include the plugin definitions for the list of plugins to statically initialize */
#include "plugins/plugindefs.h"
/* Initialize static and dynamic plugins */
int InitPlugins(void)
{
int i;
/* Static plugins */
for( i = 0; static_plugins[i]; ++i) {
RegisterPlugin(static_plugins[i], NULL);
}
#ifdef DYNAMIC_PLUGINS
/* Dynamic plugins */
{
glob_t glb;
const char *arch = detect_arch(), *libc = detect_libc();
char pattern[128];
/* First look for glibc-specific plugins */
snprintf(pattern, sizeof(pattern), "setup.data/bin/%s/%s/plugins/*.so", arch, libc);
glob(pattern, 0, NULL, &glb);
/* Then look for arch-specific plugins */
snprintf(pattern, sizeof(pattern), "setup.data/bin/%s/plugins/*.so", arch);
glob(pattern, GLOB_APPEND, NULL, &glb);
for( i = 0; i < glb.gl_pathc; ++i ) {
void *dl = dlopen(glb.gl_pathv[i], RTLD_NOW | RTLD_GLOBAL );
if ( dl ) {
char *error;
GetSetupPluginPtr fnc = dlsym(dl,"GetSetupPlugin");
error = dlerror();
if ( error ) {
fprintf(stderr, _("Error registering %s plugin: %s\n"), glb.gl_pathv[i], error);
} else {
if ( ! RegisterPlugin(fnc(), dl) ) {
fprintf(stderr, _("Error initializing %s plugin"), glb.gl_pathv[i] );
}
}
} else {
fprintf(stderr, _("Error trying to load %s plugin: %s\n"), glb.gl_pathv[i], dlerror());
}
}
globfree(&glb);
}
#endif
return 1;
}