Re: RFC: Experimental patch against libESMTP 0.8.8 to eliminate libltdl
- From: John Merryweather Cooper <john_m_cooper yahoo com>
- To: Brian Stafford <brian stafford uklinux net>
- Cc: Balsa List <balsa-list gnome org>,Christophe Lambin <clambin easynet be>
- Subject: Re: RFC: Experimental patch against libESMTP 0.8.8 to eliminate libltdl
- Date: Wed, 12 Dec 2001 13:02:01 -0800
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]