changed the return type for the GModuleCheckInit function to be a string,
[platform/upstream/glib.git] / gmodule / gmodule.c
1 /* GMODULE - GLIB wrapper code for dynamic module loading
2  * Copyright (C) 1998 Tim Janik
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include        "gmodule.h"
20 #include        "gmoduleconf.h"
21 #include        <errno.h>
22 #include        <string.h>
23
24
25 /* We maintain a list of modules, so we can reference count them.
26  * That's needed because some platforms don't support refernce counts on
27  * modules e.g. the shl_* implementation of HP-UX
28  * (http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html).
29  * Also, the module for the program itself is kept seperatedly for
30  * faster access and because it has special semantics.
31  */
32
33
34 /* --- structures --- */
35 struct _GModule
36 {
37   gchar *file_name;
38   gpointer handle;
39   guint ref_count;
40   GModuleDeInit de_init;
41   GModule *next;
42 };
43
44
45 /* --- prototypes --- */
46 static gpointer         _g_module_open          (const gchar    *file_name,
47                                                  gboolean        bind_lazy);
48 static void             _g_module_close         (gpointer        handle,
49                                                  gboolean        is_unref);
50 static gpointer         _g_module_self          (void);
51 static gpointer         _g_module_symbol        (gpointer        handle,
52                                                  const gchar    *symbol_name);
53 static inline void      g_module_set_error      (const gchar    *error);
54 static inline GModule*  g_module_find_by_handle (gpointer        handle);
55 static inline GModule*  g_module_find_by_name   (const gchar    *name);
56
57
58 /* --- variables --- */
59 const char      *g_log_domain_gmodule = "GModule";
60 static GModule  *modules = NULL;
61 static GModule  *main_module = NULL;
62 static gchar    *module_error = NULL;
63
64
65 /* --- inline functions --- */
66 static inline GModule*
67 g_module_find_by_handle (gpointer handle)
68 {
69   GModule *module;
70   
71   if (main_module && main_module->handle == handle)
72     return main_module;
73   
74   for (module = modules; module; module = module->next)
75     if (handle == module->handle)
76       return module;
77   return NULL;
78 }
79
80 static inline GModule*
81 g_module_find_by_name (const gchar *name)
82 {
83   GModule *module;
84   
85   for (module = modules; module; module = module->next)
86     if (strcmp (name, module->file_name) == 0)
87       return module;
88   return NULL;
89 }
90
91 static inline void
92 g_module_set_error (const gchar *error)
93 {
94   if (module_error)
95     g_free (module_error);
96   if (error)
97     module_error = g_strdup (error);
98   else
99     module_error = NULL;
100   errno = 0;
101 }
102
103
104 /* --- include platform specifc code --- */
105 #define CHECK_ERROR(rv) { g_module_set_error (NULL); }
106 #if     (G_MODULE_IMPL == G_MODULE_IMPL_DL)
107 #include "gmodule-dl.c"
108 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
109 #include "gmodule-dld.c"
110 #else
111 #undef  CHECK_ERROR
112 #define CHECK_ERROR(rv) { g_module_set_error ("unsupported"); return rv; }
113 #endif  /* no implementation */
114
115
116 /* --- functions --- */
117 gboolean
118 g_module_supported (void)
119 {
120   CHECK_ERROR (FALSE);
121   
122   return TRUE;
123 }
124
125 GModule*
126 g_module_open (const gchar    *file_name,
127                GModuleFlags    flags)
128 {
129   GModule *module;
130   gpointer handle;
131   
132   CHECK_ERROR (NULL);
133   
134   if (!file_name)
135     {
136       if (!main_module)
137         {
138           handle = _g_module_self ();
139           if (handle)
140             {
141               main_module = g_new (GModule, 1);
142               main_module->file_name = NULL;
143               main_module->handle = handle;
144               main_module->ref_count = 1;
145               main_module->de_init = NULL;
146               main_module->next = NULL;
147             }
148         }
149       
150       return main_module;
151     }
152   
153   /* we first search the module list by name */
154   module = g_module_find_by_name (file_name);
155   if (module)
156     {
157       module->ref_count++;
158       
159       return module;
160     }
161   
162   /* open the module */
163   handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
164   if (handle)
165     {
166       gchar *saved_error;
167       GModuleCheckInit check_init;
168       const gchar *check_failed = NULL;
169       
170       /* search the module list by handle, since file names are not unique */
171       module = g_module_find_by_handle (handle);
172       if (module)
173         {
174           _g_module_close (module->handle, TRUE);
175           module->ref_count++;
176           g_module_set_error (NULL);
177           
178           return module;
179         }
180       
181       saved_error = module_error;
182       module_error = NULL;
183       g_module_set_error (NULL);
184       
185       module = g_new (GModule, 1);
186       module->file_name = g_strdup (file_name);
187       module->handle = handle;
188       module->ref_count = 1;
189       module->de_init = NULL;
190       module->next = modules;
191       modules = module;
192       
193       /* check initialization */
194       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
195         check_failed = check_init (module);
196       
197       /* we don't call de_init() if the initialization check failed. */
198       if (!check_failed)
199         g_module_symbol (module, "g_module_de_init", (gpointer) &module->de_init);
200       
201       if (check_failed)
202         {
203           gchar *error;
204
205           error = g_strconcat ("GModule initialization check failed: ", check_failed, NULL);
206           g_module_close (module);
207           module = NULL;
208           g_module_set_error (error);
209           g_free (error);
210         }
211       else
212         g_module_set_error (saved_error);
213       g_free (saved_error);
214     }
215   
216   return module;
217 }
218
219 gboolean
220 g_module_close (GModule        *module)
221 {
222   CHECK_ERROR (FALSE);
223   
224   g_return_val_if_fail (module != NULL, FALSE);
225   g_return_val_if_fail (module->ref_count > 0, FALSE);
226   
227   if (module != main_module)
228     module->ref_count--;
229   
230   if (!module->ref_count && module->de_init)
231     module->de_init (module);
232   if (!module->ref_count)
233     {
234       GModule *last;
235       GModule *node;
236       
237       last = NULL;
238       node = modules;
239       while (node)
240         {
241           if (node == module)
242             {
243               if (last)
244                 last->next = node->next;
245               else
246                 modules = node->next;
247               break;
248             }
249           last = node;
250           node = last->next;
251         }
252       module->next = NULL;
253       
254       _g_module_close (module->handle, FALSE);
255       g_free (module->file_name);
256       
257       g_free (module);
258     }
259   
260   return module_error == NULL;
261 }
262
263 gchar*
264 g_module_error (void)
265 {
266   return module_error;
267 }
268
269 gboolean
270 g_module_symbol (GModule        *module,
271                  const gchar    *symbol_name,
272                  gpointer       *symbol)
273 {
274   if (symbol)
275     *symbol = NULL;
276   CHECK_ERROR (FALSE);
277   
278   g_return_val_if_fail (module != NULL, FALSE);
279   g_return_val_if_fail (symbol_name != NULL, FALSE);
280   g_return_val_if_fail (symbol != NULL, FALSE);
281   
282 #ifdef  G_MODULE_NEED_USCORE
283   symbol_name = g_strconcat ("_", symbol_name, NULL);
284   *symbol = _g_module_symbol (module->handle, symbol_name);
285   g_free (symbol_name);
286 #else   /* !G_MODULE_NEED_USCORE */
287   *symbol = _g_module_symbol (module->handle, symbol_name);
288 #endif  /* !G_MODULE_NEED_USCORE */
289   
290   if (module_error)
291     {
292       gchar *error;
293
294       error = g_strconcat ("`", symbol_name, "': ", module_error, NULL);
295       g_module_set_error (error);
296       g_free (error);
297       *symbol = NULL;
298       return FALSE;
299     }
300   
301   return TRUE;
302 }
303
304 gchar*
305 g_module_name (GModule *module)
306 {
307   g_return_val_if_fail (module != NULL, NULL);
308   
309   if (module == main_module)
310     return "main";
311   
312   return module->file_name;
313 }