version bump to 1.1.3, binary age 0, interface age 0.
[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       gboolean check_failed = FALSE;
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           g_module_close (module);
204           module = NULL;
205           g_module_set_error ("GModule initialization check failed");
206         }
207       else
208         g_module_set_error (saved_error);
209       g_free (saved_error);
210     }
211   
212   return module;
213 }
214
215 gboolean
216 g_module_close (GModule        *module)
217 {
218   CHECK_ERROR (FALSE);
219   
220   g_return_val_if_fail (module != NULL, FALSE);
221   g_return_val_if_fail (module->ref_count > 0, FALSE);
222   
223   if (module != main_module)
224     module->ref_count--;
225   
226   if (!module->ref_count && module->de_init)
227     module->de_init (module);
228   if (!module->ref_count)
229     {
230       GModule *last;
231       GModule *node;
232       
233       last = NULL;
234       node = modules;
235       while (node)
236         {
237           if (node == module)
238             {
239               if (last)
240                 last->next = node->next;
241               else
242                 modules = node->next;
243               break;
244             }
245           last = node;
246           node = last->next;
247         }
248       module->next = NULL;
249       
250       _g_module_close (module->handle, FALSE);
251       g_free (module->file_name);
252       
253       g_free (module);
254     }
255   
256   return module_error == NULL;
257 }
258
259 gchar*
260 g_module_error (void)
261 {
262   return module_error;
263 }
264
265 gboolean
266 g_module_symbol (GModule        *module,
267                  const gchar    *symbol_name,
268                  gpointer       *symbol)
269 {
270   if (symbol)
271     *symbol = NULL;
272   CHECK_ERROR (FALSE);
273   
274   g_return_val_if_fail (module != NULL, FALSE);
275   g_return_val_if_fail (symbol_name != NULL, FALSE);
276   g_return_val_if_fail (symbol != NULL, FALSE);
277   
278 #ifdef  G_MODULE_NEED_USCORE
279   symbol_name = g_strconcat ("_", symbol_name, NULL);
280   *symbol = _g_module_symbol (module->handle, symbol_name);
281   g_free (symbol_name);
282 #else   /* !G_MODULE_NEED_USCORE */
283   *symbol = _g_module_symbol (module->handle, symbol_name);
284 #endif  /* !G_MODULE_NEED_USCORE */
285   
286   if (module_error)
287     {
288       *symbol = NULL;
289       return FALSE;
290     }
291   
292   return TRUE;
293 }
294
295 gchar*
296 g_module_name (GModule *module)
297 {
298   g_return_val_if_fail (module != NULL, NULL);
299   
300   if (module == main_module)
301     return "main";
302   
303   return module->file_name;
304 }