gmodule.c revision fac803a223b47d7abbfbf3a2adee2f1862382582
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 --- */ 35struct _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 --- */ 46static gpointer _g_module_open (const gchar *file_name, 47 gboolean bind_lazy); 48static void _g_module_close (gpointer handle, 49 gboolean is_unref); 50static gpointer _g_module_self (void); 51static gpointer _g_module_symbol (gpointer handle, 52 const gchar *symbol_name); 53static inline void g_module_set_error (const gchar *error); 54static inline GModule* g_module_find_by_handle (gpointer handle); 55static inline GModule* g_module_find_by_name (const gchar *name); 56 57 58/* --- variables --- */ 59static GModule *modules = NULL; 60static GModule *main_module = NULL; 61static gchar *module_error = NULL; 62 63 64/* --- inline functions --- */ 65static inline GModule* 66g_module_find_by_handle (gpointer handle) 67{ 68 GModule *module; 69 70 if (main_module && main_module->handle == handle) 71 return main_module; 72 73 for (module = modules; module; module = module->next) 74 if (handle == module->handle) 75 return module; 76 return NULL; 77} 78 79static inline GModule* 80g_module_find_by_name (const gchar *name) 81{ 82 GModule *module; 83 84 for (module = modules; module; module = module->next) 85 if (strcmp (name, module->file_name) == 0) 86 return module; 87 return NULL; 88} 89 90static inline void 91g_module_set_error (const gchar *error) 92{ 93 if (module_error) 94 g_free (module_error); 95 if (error) 96 module_error = g_strdup (error); 97 else 98 module_error = NULL; 99 errno = 0; 100} 101 102 103/* --- include platform specifc code --- */ 104#define CHECK_ERROR(rv) { g_module_set_error (NULL); } 105#if (G_MODULE_IMPL == G_MODULE_IMPL_DL) 106#include "gmodule-dl.c" 107#elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD) 108#include "gmodule-dld.c" 109#else 110#undef CHECK_ERROR 111#define CHECK_ERROR(rv) { g_module_set_error ("unsupported"); return rv; } 112#endif /* no implementation */ 113 114 115/* --- functions --- */ 116gboolean 117g_module_supported (void) 118{ 119 CHECK_ERROR (FALSE); 120 121 return TRUE; 122} 123 124GModule* 125g_module_open (const gchar *file_name, 126 GModuleFlags flags) 127{ 128 GModule *module; 129 gpointer handle; 130 131 CHECK_ERROR (NULL); 132 133 if (!file_name) 134 { 135 if (!main_module) 136 { 137 handle = _g_module_self (); 138 if (handle) 139 { 140 main_module = g_new (GModule, 1); 141 main_module->file_name = NULL; 142 main_module->handle = handle; 143 main_module->ref_count = 1; 144 main_module->de_init = NULL; 145 main_module->next = NULL; 146 } 147 } 148 149 return main_module; 150 } 151 152 /* we first search the module list by name */ 153 module = g_module_find_by_name (file_name); 154 if (module) 155 { 156 module->ref_count++; 157 158 return module; 159 } 160 161 /* open the module */ 162 handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0); 163 if (handle) 164 { 165 gchar *saved_error; 166 GModuleCheckInit check_init; 167 gboolean check_failed = FALSE; 168 169 /* search the module list by handle, since file names are not unique */ 170 module = g_module_find_by_handle (handle); 171 if (module) 172 { 173 _g_module_close (module->handle, TRUE); 174 module->ref_count++; 175 g_module_set_error (NULL); 176 177 return module; 178 } 179 180 saved_error = module_error; 181 module_error = NULL; 182 g_module_set_error (NULL); 183 184 module = g_new (GModule, 1); 185 module->file_name = g_strdup (file_name); 186 module->handle = handle; 187 module->ref_count = 1; 188 module->de_init = NULL; 189 module->next = modules; 190 modules = module; 191 192 /* check initialization */ 193 if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init)) 194 check_failed = check_init (module); 195 196 /* we don't call de_init() if the initialization check failed. */ 197 if (!check_failed) 198 g_module_symbol (module, "g_module_de_init", (gpointer) &module->de_init); 199 200 if (check_failed) 201 { 202 g_module_close (module); 203 module = NULL; 204 g_module_set_error ("GModule initialization check failed"); 205 } 206 else 207 g_module_set_error (saved_error); 208 g_free (saved_error); 209 } 210 211 return module; 212} 213 214gboolean 215g_module_close (GModule *module) 216{ 217 CHECK_ERROR (FALSE); 218 219 g_return_val_if_fail (module != NULL, FALSE); 220 g_return_val_if_fail (module->ref_count > 0, FALSE); 221 222 if (module != main_module) 223 module->ref_count--; 224 225 if (!module->ref_count && module->de_init) 226 module->de_init (module); 227 if (!module->ref_count) 228 { 229 GModule *last; 230 GModule *node; 231 232 last = NULL; 233 node = modules; 234 while (node) 235 { 236 if (node == module) 237 { 238 if (last) 239 last->next = node->next; 240 else 241 modules = node->next; 242 break; 243 } 244 last = node; 245 node = last->next; 246 } 247 module->next = NULL; 248 249 _g_module_close (module->handle, FALSE); 250 g_free (module->file_name); 251 252 g_free (module); 253 } 254 255 return module_error == NULL; 256} 257 258gchar* 259g_module_error (void) 260{ 261 return module_error; 262} 263 264gboolean 265g_module_symbol (GModule *module, 266 const gchar *symbol_name, 267 gconstpointer *symbol) 268{ 269 if (symbol) 270 *symbol = NULL; 271 CHECK_ERROR (FALSE); 272 273 g_return_val_if_fail (module != NULL, FALSE); 274 g_return_val_if_fail (symbol_name != NULL, FALSE); 275 g_return_val_if_fail (symbol != NULL, FALSE); 276 277#ifdef G_MODULE_NEED_USCORE 278 symbol_name = g_strconcat ("_", symbol_name, NULL); 279 *symbol = _g_module_symbol (module->handle, symbol_name); 280 g_free (symbol_name); 281#else /* !G_MODULE_NEED_USCORE */ 282 *symbol = _g_module_symbol (module->handle, symbol_name); 283#endif /* !G_MODULE_NEED_USCORE */ 284 285 if (module_error) 286 { 287 *symbol = NULL; 288 return FALSE; 289 } 290 291 return TRUE; 292} 293 294gchar* 295g_module_name (GModule *module) 296{ 297 g_return_val_if_fail (module != NULL, NULL); 298 299 if (module == main_module) 300 return "main"; 301 302 return module->file_name; 303} 304