Re: RFC: Experimental patch against libESMTP 0.8.8 to eliminate libltdl




On 2001.12.12 07:55 Brian Stafford wrote:
> (Oops finger trouble - forgot to add CCs to the first copy of this)
> 
> Hi all,
> 
> I pretty much get the impression that libltdl causes more problems 
> for some
> people than it solves.  I've done a quick patch against libESMTP 
> 0.8.8 which
> replaces the lt_dlxxx functions with the more conventional dlxxx ones 
> supplied
> by glibc and some other platforms.  It has had next to no testing yet 
> but any
> feedback on it is appreciated.
> 

I'd agree from a FreeBSD perspective.  :)

> The objective of this patch is to use dlopen() etc directly on 
> systems that
> provide it and only to fall back to libltdl for others.  I'd like to 
> eliminate
> libltdl from the tarball (the patch does this) as it saves bloat 
> (about 70K
> off the bz2 and faster configure!).
> 

Especially given that I consciously go to great lengths (as does every 
other FreeBSD maintainer) to disable any included libtool in favor of 
FreeBSD's devel/libtool port.  It's pure junk space from FreeBSD's 
perspective.

> Key things I'd like to know.
> 
> Dlopen() related:
> Is using dlopen() and friends good enough for most people?
> What libraries might dlopen() ... live in if not -libdl.so?
> What header files might be used if not <dlfcn.h>?
> Is ".so" always the correct extension for these?
> 

dlopen() would be just fine.  Keep in mind that FreeBSD has some subtle 
difference from Linux in the way it's dlopen()/dlsym() work.  (see 
attached gmodule-dl.c and gmodule-dl.c.orig from glib 1.2.10 to see the 
difference).

The header file is dlfcn.h.  The library is libc (non-threaded) or 
libc_r (threaded) under FreeBSD 4.x-STABLE and libc under 5.x-CURRENT.  
Just like Linux, -export-dynamic is required for proper function.  See 
attached man page.  :)

> Shm_XXX related
> Do I need to implement the shm_xxx() stuff or is dlxxx() sufficiently 
> portable?

You probably don't need shm_open() and friends.  But if you choose to 
do so, the headers are sys/types.h and sys/mman.h and the libraries are 
the same as for dlopen() above.  See attached man page.

> ... or would someone like to supply me with a man page for these 
> functions or
> contribute some code?
> What is the correct extension for the shared object/libs?
> 
> LTDL related
> Does it cause problems if libltdl is not distributed in the tarball? 
> (instead
> relying either on the ltdl distributed with the system or forcing the 
> user to
> download it seperately)
> 

NO!  It eliminates problems.  :)

> Should ltdl be supported in any form at all?
> 

Only as a last resort.

> If I can resolve these issues in the next few weeks or so, they will 
> be
> incorporated into the next libESMTP release.
> 
> Cheers,
> Brian Stafford
> 
> diff -rub libesmtp-0.8.8/Makefile.am libesmtp/Makefile.am
> --- libesmtp-0.8.8/Makefile.am	Fri Oct 19 09:06:34 2001
> +++ libesmtp/Makefile.am	Wed Dec 12 14:30:15 2001
> @@ -1,7 +1,7 @@
>  ## Process this file with automake to produce Makefile.in
>  AUTOMAKE_OPTIONS = gnu dist-bzip2
> 
> -INCLUDES = -I$(srcdir) $(VERSION_FLAGS) $(INCLTDL)
> +INCLUDES = -I$(srcdir) $(VERSION_FLAGS)
>  SUBDIRS = @subdirs@ @SASL_PLUGINS@
>  CFLAGS = @CFLAGS@ @EXTRA_CFLAGS@
> 
> @@ -18,7 +18,7 @@
>  		      getaddrinfo.h gethostbyname.h
>  libesmtp_la_LIBADD = @LTLIBOBJS@
> 
> -libesmtp_la_LDFLAGS = $(LIBLTDL) -export-dynamic \
> +libesmtp_la_LDFLAGS = -export-dynamic \
>  		      -version-info $(LIBESMTP_VERSION)
> 
>  include_HEADERS = libesmtp.h auth-client.h auth-plugin.h
> diff -rub libesmtp-0.8.8/auth-client.c libesmtp/auth-client.c
> --- libesmtp-0.8.8/auth-client.c	Wed Oct 17 08:16:54 2001
> +++ libesmtp/auth-client.c	Wed Dec 12 15:14:47 2001
> @@ -29,7 +29,24 @@
>  #ifdef USE_PTHREADS
>  #include <pthread.h>
>  #endif
> -#include <ltdl.h>
> +
> +#if HAVE_DLSYM
> +# include <dlfcn.h>
> +# ifndef DLEXT
> +#  define DLEXT ".so"
> +# endif
> +typedef void *dlhandle_t;
> +#elif WITH_LTDL
> +# include <ltdl.h>
> +# ifndef DLEXT
> +#  define DLEXT ""
> +# endif
> +typedef lt_dlhandle dlhandle_t;
> +# define dlopen(n,f)	lt_dlopenext((n))
> +# define dlsym(h,s)	lt_dlsym((h),(s))
> +# define dlclose(h)	lt_dlclose((h))
> +#endif
> +
>  #include <stdlib.h>
>  #include <string.h>
>  #include <ctype.h>
> @@ -45,7 +62,7 @@
>  struct auth_plugin
>    {
>      struct auth_plugin *next;
> -    lt_dlhandle module;
> +    dlhandle_t module;
>      const struct auth_client_plugin *info;
>    };
>  static struct auth_plugin *client_plugins, *end_client_plugins;
> @@ -64,25 +81,33 @@
>  #define mechanism_disabled(p,a,f)		\
>  	  (((p)->flags & AUTH_PLUGIN_##f) && !((a)->flags &
> AUTH_PLUGIN_##f))
> 
> +#if !WITH_LTDL && defined AUTHPLUGINDIR
> +# define PLUGIN_DIR AUTHPLUGINDIR "/"
> +#else
> +# define PLUGIN_DIR
> +#endif
> +
>  static const char *
>  plugin_name (char *buf, size_t buflen, const char *str)
>  {
>    char *p;
> -  static const char prefix[] = "sasl-";
> +  static const char prefix[] = PLUGIN_DIR "sasl-";
> 
> -  assert (buf != NULL && buflen > sizeof prefix && str != NULL);
> +  assert (buf != NULL
> +          && str != NULL
> +          && buflen > sizeof prefix + strlen (str) + sizeof DLEXT);
> 
>    strcpy (buf, prefix);
>    p = buf + sizeof prefix - 1;
>    buflen -= sizeof prefix;
>    while (*str != '\0' && buflen-- > 0)
>      *p++ = tolower (*str++);
> -  *p = '\0';
> +  strcpy (p, DLEXT);
>    return buf;
>  }
> 
>  static int
> -append_plugin (lt_dlhandle module, const struct auth_client_plugin
> *info)
> +append_plugin (dlhandle_t module, const struct auth_client_plugin
> *info)
>  {
>    struct auth_plugin *auth_plugin;
> 
> @@ -108,7 +133,7 @@
>  static const struct auth_client_plugin *
>  load_client_plugin (auth_context_t context, const char *name)
>  {
> -  lt_dlhandle module;
> +  dlhandle_t module;
>    char buf[32];
>    const char *plugin;
>    const struct auth_client_plugin *info;
> @@ -117,14 +142,14 @@
> 
>    /* Try searching for a plugin. */
>    plugin = plugin_name (buf, sizeof buf, name);
> -  module = lt_dlopenext (plugin);
> +  module = dlopen (plugin, RTLD_NOW);
>    if (module == NULL)
>      return NULL;
> 
> -  info = lt_dlsym (module, "sasl_client");
> +  info = dlsym (module, "sasl_client");
>    if (info == NULL || info->response == NULL)
>      {
> -      lt_dlclose (module);
> +      dlclose (module);
>        return NULL;
>      }
> 
> @@ -135,7 +160,7 @@
>        || mechanism_disabled (info, context, ANONYMOUS)
>        || mechanism_disabled (info, context, PLAIN))
>      {
> -      lt_dlclose (module);
> +      dlclose (module);
>        return NULL;
>      }
> 
> @@ -143,7 +168,7 @@
>     */
>    if (!append_plugin (module, info))
>      {
> -      lt_dlclose (module);
> +      dlclose (module);
>        return NULL;
>      }
> 
> @@ -153,6 +178,7 @@
>  void
>  auth_client_init (void)
>  {
> +#if WITH_LTDL
>  #ifdef USE_PTHREADS
>    pthread_mutex_lock (&plugin_mutex);
>  #endif
> @@ -164,6 +190,7 @@
>  #ifdef USE_PTHREADS
>    pthread_mutex_unlock (&plugin_mutex);
>  #endif
> +#endif
>  }
> 
>  void
> @@ -171,7 +198,7 @@
>  {
>    struct auth_plugin *plugin, *next;
> 
> -  /* Scan the auth_plugin array and lt_dlclose() the modules */
> +  /* Scan the auth_plugin array and dlclose() the modules */
>  #ifdef USE_PTHREADS
>    pthread_mutex_lock (&plugin_mutex);
>  #endif
> @@ -179,11 +206,13 @@
>      {
>        next = plugin->next;
>        if (plugin->module != NULL)
> -	lt_dlclose (plugin->module);
> +	dlclose (plugin->module);
>        free (plugin);
>      }
>    client_plugins = end_client_plugins = NULL;
> +#if WITH_LTDL
>    lt_dlexit ();
> +#endif
>  #ifdef USE_PTHREADS
>    pthread_mutex_unlock (&plugin_mutex);
>  #endif
> diff -rub libesmtp-0.8.8/configure.in libesmtp/configure.in
> --- libesmtp-0.8.8/configure.in	Thu Nov 29 12:39:33 2001
> +++ libesmtp/configure.in	Wed Dec 12 15:01:52 2001
> @@ -42,6 +42,7 @@
> 
>  LIBESMTP_VERSION="$LIB_CURRENT:$LIB_REVISION:$LIB_AGE"
>  AC_SUBST(LIBESMTP_VERSION)
> +subdirs=
> 
>  dnl 
> #########################################################################
>  dnl Miscellaneous stuff
> @@ -102,6 +103,7 @@
>  AC_PROG_INSTALL
>  AC_PROG_LN_S
>  AC_PROG_MAKE_SET
> +AM_PROG_LIBTOOL
> 
>  dnl 
> #########################################################################
>  dnl Checks for libraries and options.
> @@ -111,16 +113,34 @@
>                ,
>                enable_all=no)
> 
> -AC_ARG_ENABLE([ltdl-install],ACX_HELP_STRING([--enable-ltdl-install],[install
> libltdl]))
> -AC_LIBLTDL_INSTALLABLE
> -dnl When the installable (or installed) libltdl is used, programs
> linked
> -dnl with -lesmtp also need -lltdl
> -LIBADD_LTDL=-lltdl
> -
> -AC_LTDL_DLLIB
> -AC_LIBTOOL_DLOPEN
> -AM_PROG_LIBTOOL
> -AC_CONFIG_SUBDIRS(libltdl)
> +AC_ARG_WITH([ltdl],ACX_HELP_STRING([--with-ltdl=DIR], [use ltdl in
> preference to dl]),
> +              ,
> +              with_ltdl=no)
> +have_dl=no
> +if test x$with_ltdl = xno ; then
> +	AC_SEARCH_LIBS(dlsym, dl svdl, [
> +		AC_DEFINE([HAVE_DLSYM],1,[the dlsym() function is
> available])
> +		have_dl=yes
> +	])
> +	dnl
> +	dnl FIXME: try shm_load() or whatever if no dlopen() ...
> +	dnl
> +else
> +dnl # WARNING: I don't know what libraries ltdl depends on.  I just
> assume
> +dnl #          that if the punter asks for it, then it must be
> installed and
> +dnl #          the dynamic linker will sort the dependencies at link
> time.
> +	if test x$with_ltdl != xyes ; then
> +		CPPFLAGS="-I${with_ltdl}/include $CPPFLAGS"
> +		LDFLAGS="-L${with_ltdl}/lib $LDFLAGS"
> +	fi
> +	LIBS="$LIBS -lltdl"
> +	AC_DEFINE([WITH_LTDL],1,[the ltdl library is used])
> +	with_ltdl=yes
> +	have_dl=yes
> +fi
> +if test x$have_dl = xno ; then
> +	AC_MSG_ERROR([No runtime dynamic loader found.  Hint: try
> --with-ltdl])
> +fi
> 
>  dnl 
> #########################################################################
>  dnl Check if using Posix Threads
> @@ -131,17 +151,6 @@
>    	      ,
>    	      enable_pthreads=auto)
> 
> -dnl if test x"$enable_pthreads" != xno ; then
> -dnl 	AC_SEARCH_LIBS(pthread_create, pthread pthreads c_r cr,
> -dnl 		       enable_pthreads=yes,
> -dnl 		       if test x"$enable_pthreads" = xyes ; then
> -dnl 		       		AC_MSG_ERROR([Cannot find
> the pthread library.])
> -dnl 		       else
> -dnl 		       		enable_pthreads=no
> -dnl 		       fi
> -dnl 	)
> -dnl fi
> -
>  if test x"$enable_pthreads" != xno ; then
>  	ACX_PTHREAD(enable_pthreads=yes,
>  		       if test x"$enable_pthreads" = xyes ; then
> @@ -526,9 +535,6 @@
> 
>  AC_SUBST(SASL_PLUGINS)
>  AC_SUBST(LIBTOOL_DEPS)
> -AC_SUBST(INCLTDL)
> -AC_SUBST(LIBLTDL)
> -AC_SUBST(LIBADD_LTDL)
>  AC_SUBST(LIBS)
>  AC_SUBST(CFLAGS)
>  AC_SUBST(EXTRA_CFLAGS)
> diff -rub libesmtp-0.8.8/crammd5/Makefile.in
> libesmtp/crammd5/Makefile.in
> --- libesmtp-0.8.8/crammd5/Makefile.in	Tue Dec  4 10:51:00 2001
> +++ libesmtp/crammd5/Makefile.in	Wed Dec 12 15:03:08 2001
> @@ -68,12 +68,8 @@
>  ECHO = @ECHO@
>  EXEEXT = @EXEEXT@
>  EXTRA_CFLAGS = @EXTRA_CFLAGS@
> -INCLTDL = @INCLTDL@
>  INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
> -LIBADD_DL = @LIBADD_DL@
> -LIBADD_LTDL = @LIBADD_LTDL@
>  LIBESMTP_VERSION = @LIBESMTP_VERSION@
> -LIBLTDL = @LIBLTDL@
>  LIBS = @LIBS@
>  LIBTOOL = @LIBTOOL@
>  LIBTOOL_DEPS = @LIBTOOL_DEPS@
> diff -rub libesmtp-0.8.8/libesmtp-config.in
> libesmtp/libesmtp-config.in
> --- libesmtp-0.8.8/libesmtp-config.in	Mon Nov 12 14:59:17 2001
> +++ libesmtp/libesmtp-config.in	Wed Dec 12 14:30:37 2001
> @@ -69,7 +69,7 @@
>         	;;
> 
>      --libs)
> -       	echo @PTHREAD_LDFLAGS@ -L@libdir@ -lesmtp @LIBS@
> @LIBADD_LTDL@ @LIBADD_DL@ @PTHREAD_LIBS@
> +       	echo @PTHREAD_LDFLAGS@ -L@libdir@ -lesmtp @LIBS@
> @PTHREAD_LIBS@
>         	;;
> 
>      --plugindir)
> diff -rub libesmtp-0.8.8/login/Makefile.in libesmtp/login/Makefile.in
> --- libesmtp-0.8.8/login/Makefile.in	Tue Dec  4 10:51:01 2001
> +++ libesmtp/login/Makefile.in	Wed Dec 12 15:03:00 2001
> @@ -68,12 +68,8 @@
>  ECHO = @ECHO@
>  EXEEXT = @EXEEXT@
>  EXTRA_CFLAGS = @EXTRA_CFLAGS@
> -INCLTDL = @INCLTDL@
>  INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
> -LIBADD_DL = @LIBADD_DL@
> -LIBADD_LTDL = @LIBADD_LTDL@
>  LIBESMTP_VERSION = @LIBESMTP_VERSION@
> -LIBLTDL = @LIBLTDL@
>  LIBS = @LIBS@
>  LIBTOOL = @LIBTOOL@
>  LIBTOOL_DEPS = @LIBTOOL_DEPS@
> diff -rub libesmtp-0.8.8/plain/Makefile.in libesmtp/plain/Makefile.in
> --- libesmtp-0.8.8/plain/Makefile.in	Tue Dec  4 10:51:01 2001
> +++ libesmtp/plain/Makefile.in	Wed Dec 12 15:03:04 2001
> @@ -68,12 +68,8 @@
>  ECHO = @ECHO@
>  EXEEXT = @EXEEXT@
>  EXTRA_CFLAGS = @EXTRA_CFLAGS@
> -INCLTDL = @INCLTDL@
>  INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
> -LIBADD_DL = @LIBADD_DL@
> -LIBADD_LTDL = @LIBADD_LTDL@
>  LIBESMTP_VERSION = @LIBESMTP_VERSION@
> -LIBLTDL = @LIBLTDL@
>  LIBS = @LIBS@
>  LIBTOOL = @LIBTOOL@
>  LIBTOOL_DEPS = @LIBTOOL_DEPS@
> 
-- 
jmc                               ||  MacroHard --                   \
                                   ||     the perfection of form over |
----------------------------------||     substance, marketing over   |
Web:  http://www.borgsdemons.com  ||     performance, and greed over |
                                   ||     design . . .                |
=====================================================================/
Public Key:  http://www.borgsdemons.com/Personal/pgpkey.asc          |
=====================================================================\
DLOPEN(3)	       FreeBSD Library Functions Manual 	     DLOPEN(3)

NNAAMMEE
     ddllooppeenn, ddllssyymm, ddlleerrrroorr, ddllcclloossee - programmatic interface to the dynamic
     linker

LLIIBBRRAARRYY
     Standard C Library (libc, -lc)

SSYYNNOOPPSSIISS
     ##iinncclluuddee <<ddllffccnn..hh>>

     _v_o_i_d _*
     ddllooppeenn(_c_o_n_s_t _c_h_a_r _*_p_a_t_h, _i_n_t _m_o_d_e);

     _v_o_i_d _*
     ddllssyymm(_v_o_i_d _*_h_a_n_d_l_e, _c_o_n_s_t _c_h_a_r _*_s_y_m_b_o_l);

     _c_o_n_s_t _c_h_a_r _*
     ddlleerrrroorr(_v_o_i_d);

     _i_n_t
     ddllcclloossee(_v_o_i_d _*_h_a_n_d_l_e);

DDEESSCCRRIIPPTTIIOONN
     These functions provide a simple programmatic interface to the services
     of the dynamic linker.  Operations are provided to add new shared objects
     to a program's address space, to obtain the address bindings of symbols
     defined by such objects, and to remove such objects when their use is no
     longer required.

     ddllooppeenn() provides access to the shared object in _p_a_t_h, returning a
     descriptor that can be used for later references to the object in calls
     to ddllssyymm() and ddllcclloossee().	If _p_a_t_h was not in the address space prior to
     the call to ddllooppeenn(), it is placed in the address space.  When an object
     is first loaded into the address space in this way, its function __iinniitt(),
     if any, is called by the dynamic linker.  If _p_a_t_h has already been placed
     in the address space in a previous call to ddllooppeenn(), it is not added a
     second time, although a reference count of ddllooppeenn() operations on _p_a_t_h is
     maintained.  A null pointer supplied for _p_a_t_h is interpreted as a refer-
     ence to the main executable of the process.  _m_o_d_e controls the way in
     which external function references from the loaded object are bound to
     their referents.  It must contain one of the following values, possibly
     ORed with additional flags which will be described subsequently:

     RTLD_LAZY	 Each external function reference is resolved when the func-
		 tion is first called.

     RTLD_NOW	 All external function references are bound immediately by
		 ddllooppeenn().

     RTLD_LAZY is normally preferred, for reasons of efficiency.  However,
     RTLD_NOW is useful to ensure that any undefined symbols are discovered
     during the call to ddllooppeenn().

     One of the following flags may be ORed into the _m_o_d_e argument:

     RTLD_GLOBAL   Symbols from this shared object and its directed acyclic
		   graph (DAG) of needed objects will be available for resolv-
		   ing undefined references from all other shared objects.

     RTLD_LOCAL    Symbols in this shared object and its DAG of needed objects
		   will be available for resolving undefined references only
		   from other objects in the same DAG.	This is the default,
		   but it may be specified explicitly with this flag.

     If ddllooppeenn() fails, it returns a null pointer, and sets an error condition
     which may be interrogated with ddlleerrrroorr().

     ddllssyymm() returns the address binding of the symbol described in the null-
     terminated character string _s_y_m_b_o_l, as it occurs in the shared object
     identified by _h_a_n_d_l_e.  The symbols exported by objects added to the
     address space by ddllooppeenn() can be accessed only through calls to ddllssyymm().
     Such symbols do not supersede any definition of those symbols already
     present in the address space when the object is loaded, nor are they
     available to satisfy normal dynamic linking references.

     If ddllssyymm() is called with the special _h_a_n_d_l_e NULL, it is interpreted as a
     reference to the executable or shared object from which the call is being
     made.  Thus a shared object can reference its own symbols.

     If ddllssyymm() is called with the special _h_a_n_d_l_e RTLD_DEFAULT, the search for
     the symbol follows the algorithm used for resolving undefined symbols
     when objects are loaded.  The objects searched are as follows, in the
     given order:

     1.   The referencing object itself (or the object from which the call to
	  ddllssyymm() is made), if that object was linked using the --WWssyymmbboolliicc
	  option to ld(1).

     2.   All objects loaded at program start-up.

     3.   All objects loaded via ddllooppeenn() which are in needed-object DAGs that
	  also contain the referencing object.

     4.   All objects loaded via ddllooppeenn() with the RTLD_GLOBAL flag set in the
	  _m_o_d_e argument.

     If ddllssyymm() is called with the special _h_a_n_d_l_e RTLD_NEXT, then the search
     for the symbol is limited to the shared objects which were loaded after
     the one issuing the call to ddllssyymm().  Thus, if the function is called
     from the main program, all the shared libraries are searched.  If it is
     called from a shared library, all subsequent shared libraries are
     searched.	RTLD_NEXT is useful for implementing wrappers around library
     functions.  For example, a wrapper function ggeettppiidd() could access the
     ``real'' ggeettppiidd() with dlsym(RTLD_NEXT, "getpid").

     ddllssyymm() returns a null pointer if the symbol cannot be found, and sets an
     error condition which may be queried with ddlleerrrroorr().

     ddlleerrrroorr() returns a null-terminated character string describing the last
     error that occurred during a call to ddllooppeenn(), ddllssyymm(), or ddllcclloossee().  If
     no such error has occurred, ddlleerrrroorr() returns a null pointer.  At each
     call to ddlleerrrroorr(), the error indication is reset.	Thus in the case of
     two calls to ddlleerrrroorr(), where the second call follows the first immedi-
     ately, the second call will always return a null pointer.

     ddllcclloossee() deletes a reference to the shared object referenced by _h_a_n_d_l_e.
     If the reference count drops to 0, the object is removed from the address
     space, and _h_a_n_d_l_e is rendered invalid.  Just before removing a shared
     object in this way, the dynamic linker calls the object's __ffiinnii() func-
     tion, if such a function is defined by the object.  If ddllcclloossee() is suc-
     cessful, it returns a value of 0.	Otherwise it returns -1, and sets an
     error condition that can be interrogated with ddlleerrrroorr().

     The object-intrinsic functions __iinniitt() and __ffiinnii() are called with no
     arguments, and are not expected to return values.

NNOOTTEESS
     ELF executables need to be linked using the --eexxppoorrtt--ddyynnaammiicc option to
     ld(1) for symbols defined in the executable to become visible to ddllssyymm().

     In previous implementations, it was necessary to prepend an underscore to
     all external symbols in order to gain symbol compatibility with object
     code compiled from the C language.  This is still the case when using the
     (obsolete) --aaoouutt option to the C language compiler.

EERRRROORRSS
     ddllooppeenn() and ddllssyymm() return the null pointer in the event of errors.
     ddllcclloossee() returns 0 on success, or -1 if an error occurred.  Whenever an
     error has been detected, a message detailing it can be retrieved via a
     call to ddlleerrrroorr().

SSEEEE AALLSSOO
     ld(1), rtld(1), dladdr(3), link(5)

FreeBSD 4.4		      September 24, 1989		   FreeBSD 4.4
SHM_OPEN(3)	       FreeBSD Library Functions Manual 	   SHM_OPEN(3)

NNAAMMEE
     sshhmm__ooppeenn - open or create a shared memory object sshhmm__uunnlliinnkk - remove a
     shared memory object

LLIIBBRRAARRYY
     Standard C Library (libc, -lc)

SSYYNNOOPPSSIISS
     ##iinncclluuddee <<ssyyss//ttyyppeess..hh>>
     ##iinncclluuddee <<ssyyss//mmmmaann..hh>>

     _i_n_t
     sshhmm__ooppeenn(_c_o_n_s_t _c_h_a_r _*_p_a_t_h, _i_n_t _f_l_a_g_s, _m_o_d_e___t _m_o_d_e);

     _i_n_t
     sshhmm__uunnlliinnkk(_c_o_n_s_t _c_h_a_r _*_p_a_t_h);

DDEESSCCRRIIPPTTIIOONN
     The sshhmm__ooppeenn() function opens (or optionally creates) a POSIX shared mem-
     ory object named _p_a_t_h.  The sshhmm__uunnlliinnkk() function removes a shared memory
     object named _p_a_t_h.

     In the FreeBSD implementation, POSIX shared memory objects are imple-
     mented as ordinary files.	The sshhmm__ooppeenn() and sshhmm__uunnlliinnkk() act as wrap-
     pers around the open(2) and unlink(2) routines, and _p_a_t_h, _f_l_a_g_s, and _m_o_d_e
     arguments are as specified for those functions.  The _f_l_a_g_s argument is
     checked to ensure that the access mode specified is not O_WRONLY (which
     is not defined for shared memory objects).

     In addition, the FreeBSD implementation causes mmmmaapp() of a descriptor
     returned by sshhmm__ooppeenn() to behave as if the MAP_NOSYNC flag had been spec-
     ified to mmap(2).	(It does so by setting a special file flag using
     fcntl(2).)

     The sshhmm__uunnlliinnkk() function makes no effort to ensure that _p_a_t_h refers to a
     shared memory object.

CCOOMMPPAATTIIBBIILLIITTYY
     The _p_a_t_h argument does not necessarily represent a pathname (although it
     does in this and most other implementations).  Two processes opening the
     same _p_a_t_h are guaranteed to access the same shared memory object if and
     only if _p_a_t_h begins with a slash (`/') character.

     Only the O_RDONLY, O_RDWR, O_CREAT, O_EXCL, and O_TRUNC flags may be used
     in portable programs.

     The result of using open(2), read(2), or write(2) on a shared memory
     object, or on the descriptor returned by sshhmm__ooppeenn(), is undefined.  It is
     also undefined whether the shared memory object itself, or its contents,
     persist across reboots.

RREETTUURRNN VVAALLUUEESS
     If successful, sshhmm__ooppeenn() returns a non-negative integer; sshhmm__uunnlliinnkk()
     returns zero.  Both functions return -1 on failure, and set _e_r_r_n_o to
     indicate the error.

EERRRROORRSS
     The sshhmm__ooppeenn() and sshhmm__uunnlliinnkk() functions can fail with any error defined
     for ooppeenn() and uunnlliinnkk(), respectively.  In addition, the following errors
     are defined for sshhmm__ooppeenn():

     [EINVAL]		The object named by _p_a_t_h is not a shared memory object
			(i.e., it is not a regular file).

     [EINVAL]		The _f_l_a_g_s argument to sshhmm__ooppeenn() specifies an access
			mode of O_WRONLY.

SSEEEE AALLSSOO
     mmap(2), munmap(2), open(2), unlink(2)

SSTTAANNDDAARRDDSS
     The sshhmm__ooppeenn() and sshhmm__uunnlliinnkk() functions are believed to conform to IEEE
     Std 1003.1b-1993 (``POSIX.1'').

HHIISSTTOORRYY
     The sshhmm__ooppeenn() and sshhmm__uunnlliinnkk() functions first appeared in FreeBSD 4.3.

AAUUTTHHOORRSS
     Garrett A. Wollman <wollman@FreeBSD.org> (C library support and this man-
     ual page)

     Matthew Dillon <dillon@FreeBSD.org> (MAP_NOSYNC)

FreeBSD 4.4			March 24, 2000			   FreeBSD 4.4
/* GMODULE - GLIB wrapper code for dynamic module loading
 * Copyright (C) 1998, 2000 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
 * file for a list of people on the GLib Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
 */

/* 
 * MT safe
 */

#include <dlfcn.h>

/* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systmes? */


/* dlerror() is not implemented on all systems
 */
#ifndef	G_MODULE_HAVE_DLERROR
#  ifdef __NetBSD__
#    define dlerror()	g_strerror (errno)
#  else /* !__NetBSD__ */
/* could we rely on errno's state here? */
#    define dlerror()	"unknown dl-error"
#  endif /* !__NetBSD__ */
#endif	/* G_MODULE_HAVE_DLERROR */

/* some flags are missing on some systems, so we provide
 * harmless defaults.
 * The Perl sources say, RTLD_LAZY needs to be defined as (1),
 * at least for Solaris 1.
 *
 * Mandatory:
 * RTLD_LAZY   - resolve undefined symbols as code from the dynamic library
 *		 is executed.
 * RTLD_NOW    - resolve all undefined symbols before dlopen returns, and fail
 *		 if this cannot be done.
 * Optionally:
 * RTLD_GLOBAL - the external symbols defined in the library will be made
 *		 available to subsequently loaded libraries.
 */
#ifndef	RTLD_LAZY
#define	RTLD_LAZY	1
#endif	/* RTLD_LAZY */
#ifndef	RTLD_NOW
#define	RTLD_NOW	0
#endif	/* RTLD_NOW */
/* some systems (OSF1 V5.0) have broken RTLD_GLOBAL linkage */
#ifdef G_MODULE_BROKEN_RTLD_GLOBAL
#undef  RTLD_GLOBAL
#endif /* G_MODULE_BROKEN_RTLD_GLOBAL */
#ifndef	RTLD_GLOBAL
#define	RTLD_GLOBAL	0
#endif	/* RTLD_GLOBAL */


/* --- functions --- */
static gchar*
fetch_dlerror (void)
{
  gchar *msg = dlerror ();

  /* make sure we always return an error message != NULL */

  return msg ? msg : "unknown dl-error";
}

static gpointer
_g_module_open (const gchar *file_name,
		gboolean     bind_lazy)
{
  gpointer handle;
  
  handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
  if (!handle)
    g_module_set_error (fetch_dlerror ());
  
  return handle;
}

static gpointer
_g_module_self (void)
{
#ifndef __FreeBSD__
  gpointer handle;
  
  /* to query symbols from the program itself, special link options
   * are required on some systems.
   */
  
  handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
  if (!handle)
    g_module_set_error (fetch_dlerror ());
  
  return handle;
#else
  return RTLD_DEFAULT;
#endif
}

static void
_g_module_close (gpointer handle,
		 gboolean is_unref)
{
  /* are there any systems out there that have dlopen()/dlclose()
   * without a reference count implementation?
   */
  is_unref |= 1;
  
  if (is_unref)
    {
      if (dlclose (handle) != 0)
	g_module_set_error (fetch_dlerror ());
    }
}

static gpointer
_g_module_symbol (gpointer     handle,
		  const gchar *symbol_name)
{
  gpointer p;
  
  p = dlsym (handle, symbol_name);
  if (!p)
    g_module_set_error (fetch_dlerror ());
  
  return p;
}

static gchar*
_g_module_build_path (const gchar *directory,
		      const gchar *module_name)
{
  if (directory && *directory) {
    if (strncmp (module_name, "lib", 3) == 0)
      return g_strconcat (directory, "/", module_name, NULL);
    else
      return g_strconcat (directory, "/lib", module_name, ".so", NULL);
  } else if (strncmp (module_name, "lib", 3) == 0)
    return g_strdup (module_name);
  else
    return g_strconcat ("lib", module_name, ".so", NULL);
}

gmodule-dl.c.orig



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]