Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore / ecore_plugin.c
1 /*
2  * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include <stdlib.h>
10 #include <stdio.h>
11
12 #ifdef HAVE_DLFCN_H
13 # include <dlfcn.h>
14 #endif
15
16 #ifdef HAVE_EVIL_H
17 # include <evil.h>
18 #endif
19
20 #include "Ecore_Data.h"
21 #include "Ecore_Str.h"
22 #include "ecore_private.h"
23
24
25 static Ecore_List *loaded_plugins = NULL;
26
27 /**
28  * @defgroup Ecore_Plugin Plugin Functions
29  *
30  * Functions that load modules of compiled code into memory.
31  */
32
33 /**
34  * Loads the specified plugin from the specified path group.
35  * @param   group       The path group to search for the plugin to load
36  * @param   plugin_name The name of the plugin to load.
37  * @param   version     The interface version of the plugin. With version
38  *                      equal to NULL the default will be loaded.
39  * @return  A pointer to the newly loaded plugin on success, @c NULL on
40  *          failure.
41  * @ingroup Ecore_Plugin
42  */
43 EAPI Ecore_Plugin *
44 ecore_plugin_load(Ecore_Path_Group *group, const char *plugin_name, const char *version)
45 {
46    char *path;
47    char temp[PATH_MAX];
48
49    Ecore_Plugin *plugin;
50    void *handle = NULL;
51
52    CHECK_PARAM_POINTER_RETURN("plugin_name", plugin_name, NULL);
53
54    if (!version || *version == '\0')
55      snprintf(temp, sizeof(temp), "%s" SHARED_LIB_SUFFIX, plugin_name);
56    else
57      snprintf(temp, sizeof(temp), "%s" SHARED_LIB_SUFFIX ".%s", plugin_name, version);
58
59    path = ecore_path_group_find(group, temp);
60
61    if (!path && version)
62      {
63         /* if this file doesn't exist try a different order */
64         snprintf(temp, sizeof(temp), "%s.%s" SHARED_LIB_SUFFIX, plugin_name, version);
65         path = ecore_path_group_find(group, temp);
66      }
67
68    if (!path)
69      return NULL;
70
71    handle = dlopen(path, RTLD_LAZY);
72    if (!handle)
73      {
74         FREE(path);
75         return NULL;
76      }
77
78    /*
79     * Allocate the new plugin and initialize it's fields
80     */
81    plugin = malloc(sizeof(Ecore_Plugin));
82    if (!plugin)
83      {
84        dlclose(handle);
85        FREE(path);
86        return NULL;
87      }
88    memset(plugin, 0, sizeof(Ecore_Plugin));
89
90    plugin->handle = handle;
91
92    /*
93     * Now add it to the list of the groups loaded plugins
94     */
95    if (!loaded_plugins)
96      loaded_plugins = ecore_list_new();
97
98    ecore_list_append(loaded_plugins, plugin);
99
100    FREE(path);
101
102    return plugin;
103 }
104
105 /**
106  * Unloads the given plugin from memory.
107  * @param   plugin The given plugin.
108  * @ingroup Ecore_Plugin
109  */
110 EAPI void
111 ecore_plugin_unload(Ecore_Plugin *plugin)
112 {
113    CHECK_PARAM_POINTER("plugin", plugin);
114
115    if (!plugin->handle)
116      return;
117
118    if (ecore_list_goto(loaded_plugins, plugin))
119      ecore_list_remove(loaded_plugins);
120
121    if (ecore_list_empty_is(loaded_plugins))
122      {
123         ecore_list_destroy(loaded_plugins);
124         loaded_plugins = NULL;
125      }
126
127    dlclose(plugin->handle);
128
129    FREE(plugin);
130 }
131
132 /*
133  * Searches for the specified symbol in the given plugin.
134  * @param   plugin      The given plugin.
135  * @param   symbol_name The symbol to search for.
136  * @return  Address of the given symbol if successful.  Otherwise, @c NULL.
137  * @ingroup Ecore_Plugin
138  */
139 EAPI void *
140 ecore_plugin_symbol_get(Ecore_Plugin *plugin, const char *symbol_name)
141 {
142    void *ret;
143
144    CHECK_PARAM_POINTER_RETURN("plugin", plugin, NULL);
145    CHECK_PARAM_POINTER_RETURN("symbol_name", symbol_name, NULL);
146
147    if (!plugin->handle)
148      return NULL;
149
150    ret = dlsym(plugin->handle, symbol_name);
151
152    return ret;
153 }
154
155 /**
156  * Retrieves a list of all available plugins in the given path.
157  * @param   group_id The identifier for the given path.
158  * @return  A pointer to a newly allocated list of all plugins found in the
159  *          paths identified by @p group_id.  @c NULL otherwise.
160  * @ingroup Ecore_Plugin
161  */
162 EAPI Ecore_List *
163 ecore_plugin_available_get(Ecore_Path_Group *group)
164 {
165    Ecore_List *avail = NULL;
166    Ecore_Hash *plugins = NULL;
167    char *path;
168
169    CHECK_PARAM_POINTER_RETURN("group", group, NULL);
170
171    if (!group->paths || ecore_list_empty_is(group->paths))
172      return NULL;
173
174    ecore_list_first_goto(group->paths);
175    plugins = ecore_hash_new(ecore_str_hash, ecore_str_compare);
176    ecore_hash_free_key_cb_set(plugins, free);
177
178    while ((path = ecore_list_next(group->paths)) != NULL)
179      {
180         DIR *dir;
181         struct stat st;
182         struct dirent *d;
183
184         if (stat(path, &st) < 0)
185           continue;
186
187         if (!S_ISDIR(st.st_mode))
188           continue;
189
190         dir = opendir(path);
191
192         if (!dir)
193           continue;
194
195         while ((d = readdir(dir)) != NULL)
196           {
197              char ppath[PATH_MAX];
198              char *ext;
199
200              if (*d->d_name == '.')
201                continue;
202
203              if (!ecore_str_has_suffix(d->d_name, SHARED_LIB_SUFFIX))
204                continue;
205
206              snprintf(ppath, PATH_MAX, "%s/%s", path, d->d_name);
207
208              stat(ppath, &st);
209
210              if (!S_ISREG(st.st_mode))
211                continue;
212
213              ecore_strlcpy(ppath, d->d_name, sizeof(ppath));
214              ext = strrchr(ppath, '.');
215              *ext = '\0';
216
217              if (!ecore_hash_get(plugins, ppath))
218                {
219                   char *key;
220
221                   key = strdup(ppath);
222                   ecore_hash_set(plugins, key, key);
223                }
224           }
225         closedir(dir);
226      }
227
228    ecore_hash_free_key_cb_set(plugins, NULL);
229    avail = ecore_hash_keys(plugins);
230    ecore_list_free_cb_set(avail, free);
231    ecore_hash_destroy(plugins);
232
233    return avail;
234 }
235