Home | History | Annotate | Download | only in gmodule
      1 /* GMODULE - GLIB wrapper code for dynamic module loading
      2  * Copyright (C) 1998, 2000 Tim Janik
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Lesser 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  * Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser 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 
     20 /*
     21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
     22  * file for a list of people on the GLib Team.  See the ChangeLog
     23  * files for a list of changes.  These files are distributed with
     24  * GLib at ftp://ftp.gtk.org/pub/gtk/.
     25  */
     26 
     27 /*
     28  * MT safe
     29  */
     30 #include "config.h"
     31 
     32 #include <dlfcn.h>
     33 
     34 /* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systmes? */
     35 
     36 
     37 /* dlerror() is not implemented on all systems
     38  */
     39 #ifndef	G_MODULE_HAVE_DLERROR
     40 /* could we rely on errno's state here? */
     41 #  define dlerror()	"unknown dl-error"
     42 #endif	/* G_MODULE_HAVE_DLERROR */
     43 
     44 /* some flags are missing on some systems, so we provide
     45  * harmless defaults.
     46  * The Perl sources say, RTLD_LAZY needs to be defined as (1),
     47  * at least for Solaris 1.
     48  *
     49  * Mandatory:
     50  * RTLD_LAZY   - resolve undefined symbols as code from the dynamic library
     51  *		 is executed.
     52  * RTLD_NOW    - resolve all undefined symbols before dlopen returns, and fail
     53  *		 if this cannot be done.
     54  * Optionally:
     55  * RTLD_GLOBAL - the external symbols defined in the library will be made
     56  *		 available to subsequently loaded libraries.
     57  */
     58 #ifndef	RTLD_GLOBAL
     59 #define	RTLD_GLOBAL	0
     60 #endif	/* RTLD_GLOBAL */
     61 #ifndef	RTLD_LAZY
     62 #define	RTLD_LAZY	1
     63 #endif	/* RTLD_LAZY */
     64 #ifndef	RTLD_NOW
     65 #define	RTLD_NOW	0
     66 #endif	/* RTLD_NOW */
     67 
     68 
     69 /* --- functions --- */
     70 static gpointer
     71 _g_module_open (const gchar    *file_name,
     72 		gboolean	bind_lazy,
     73 		gboolean	bind_local)
     74 {
     75   gpointer handle;
     76 
     77   handle = dlopen (file_name,
     78 	(bind_local ? 0 : RTLD_GLOBAL) | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
     79   if (!handle)
     80     g_module_set_error (dlerror ());
     81 
     82   return handle;
     83 }
     84 
     85 static gpointer
     86 _g_module_self (void)
     87 {
     88   gpointer handle;
     89 
     90   /* to query symbols from the program itself, special link options
     91    * are required on some systems.
     92    */
     93 
     94   /* XXX, not supported */
     95   handle = NULL;
     96   g_module_set_error ("module handle for self not supported");
     97 
     98   return handle;
     99 }
    100 
    101 static void
    102 _g_module_close (gpointer handle,
    103 		 gboolean is_unref)
    104 {
    105   /* are there any systems out there that have dlopen()/dlclose()
    106    * without a reference count implementation?
    107    */
    108   is_unref |= 1;
    109 
    110   if (is_unref)
    111     {
    112       /* XXX, no return code */
    113       dlclose (handle);
    114     }
    115 }
    116 
    117 static gpointer
    118 _g_module_symbol (gpointer     handle,
    119 		  const gchar *symbol_name)
    120 {
    121   gpointer p;
    122 
    123   p = dlsym (handle, symbol_name);
    124   if (!p)
    125     g_module_set_error (dlerror ());
    126 
    127   return p;
    128 }
    129 
    130 static gchar*
    131 _g_module_build_path (const gchar *directory,
    132 		      const gchar *module_name)
    133 {
    134   gchar *suffix = strrchr(module_name, '.');
    135   if (directory && *directory)
    136     if (suffix && (stricmp (suffix, ".dll") == 0))
    137       return g_strconcat (directory, "/", module_name, NULL);
    138     else
    139       return g_strconcat (directory, "/", module_name, ".dll", NULL);
    140   else if (suffix && (stricmp (suffix, ".dll") == 0))
    141     return g_strdup (module_name);
    142   else
    143     return g_strconcat (module_name, ".dll", NULL);
    144 }
    145