+2007-02-28 Bruno Haible <bruno@clisp.org>
+
+ Import --enable-relocatable infrastructure.
+ * build-aux/config.libpath: New file, from GNU gettext.
+ * build-aux/install-reloc: New file, from GNU gettext.
+ * build-aux/reloc-ldflags: New file, from GNU gettext.
+ * lib/relocatable.h: New file, from GNU gettext.
+ * lib/relocatable.c: New file, from GNU gettext.
+ * lib/relocwrapper.c: New file, from GNU gettext.
+ * m4/relocatable.m4: New file, from GNU gettext.
+
2007-02-28 Bruno Haible <bruno@clisp.org>
* MODULES.html.sh (File system functions): Add xreadlink-with-size.
--- /dev/null
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable at run time.
+#
+# Copyright 1996-2005 Free Software Foundation, Inc.
+# Taken from GNU libtool, 2003
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variable LD should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+shlibpath_var=
+case $host_os in
+ aix3*)
+ shlibpath_var=LIBPATH
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+ beos*)
+ shlibpath_var=LIBRARY_PATH
+ ;;
+ bsdi4*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ cygwin* | mingw* | pw32*)
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+ darwin* | rhapsody*)
+ shlibpath_var=DYLD_LIBRARY_PATH
+ ;;
+ freebsd1*)
+ ;;
+ kfreebsd*-gnu)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ freebsd*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ gnu*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ shlibpath_var=SHLIB_PATH
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $host_os in
+ irix5* | nonstopux*)
+ shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 ") shlibsuff= ;;
+ *-n32|*"-n32 ") shlibsuff=N32 ;;
+ *-64|*"-64 ") shlibsuff=64 ;;
+ *) shlibsuff= ;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ ;;
+ linux-gnu*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ knetbsd*-gnu)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ netbsd*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ newsos6)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ openbsd*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ os2*)
+ shlibpath_var=LIBPATH
+ ;;
+ osf3* | osf4* | osf5*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ sco3.2v5*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ solaris*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ sunos4*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ uts4*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ dgux*)
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+esac
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+EOF
--- /dev/null
+#!/bin/sh
+# install-reloc - install a program including a relocating wrapper
+# Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc.
+# Written by Bruno Haible <bruno@clisp.org>, 2003.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage:
+# install-reloc library_path_var library_path_value prefix compile_command srcdir config_h_dir exeext install_command... destprog
+# where
+# - library_path_var is the platform dependent runtime library path variable
+# - library_path_value is a colon separated list of directories that contain
+# the libraries at installation time (use this instead of -rpath)
+# - prefix is the base directory at installation time
+# - compile_command is a C compiler compilation and linking command
+# - srcdir is the directory where to find relocwrapper.c and its dependencies
+# - builddir is the directory where to find built dependencies (namely,
+# alloca.h and stdbool.h)
+# - config_h_dir is the directory where to find config.h
+# - exeext is platform dependent suffix of executables
+# - install-command is the install command line, excluding the final destprog
+# - destprog is the destination program name
+# install-reloc renames destprog to destprog.bin and installs a relocating
+# wrapper in the place of destprog.
+
+progname=$0
+
+if test $# -eq 2; then
+ # Get arguments from environment variables.
+ library_path_var=$RELOC_LIBRARY_PATH_VAR
+ library_path_value=$RELOC_LIBRARY_PATH_VALUE
+ prefix=$RELOC_PREFIX
+ compile_command=$RELOC_COMPILE_COMMAND
+ srcdir=$RELOC_SRCDIR
+ builddir=$RELOC_BUILDDIR
+ config_h_dir=$RELOC_CONFIG_H_DIR
+ exeext=$RELOC_EXEEXT
+ install_prog=$RELOC_INSTALL_PROG # including the "-c" option
+else
+ if test $# -ge 9; then
+ # Get fixed position arguments.
+ library_path_var=$1
+ library_path_value=$2
+ prefix=$3
+ compile_command=$4
+ srcdir=$5
+ builddir=$6
+ config_h_dir=$7
+ exeext=$8
+ install_prog=$9 # maybe not including the "-c" option
+ shift
+ shift
+ shift
+ shift
+ shift
+ shift
+ shift
+ shift
+ shift
+ else
+ echo "Usage: $0 library_path_var library_path_value prefix compile_command srcdir builddir config_h_dir exeext install_command... destprog" 1>&2
+ exit 1
+ fi
+fi
+
+# Get destprog, last argument.
+destprog=
+for arg
+do
+ destprog=$arg
+done
+# Remove trailing $exeext, if present.
+if test -n "$exeext"; then
+ sedexpr='s|'`echo "$exeext" | sed -e 's,\.,\\\.,g'`'$||'
+ destprog=`echo "$destprog" | sed -e "$sedexpr"`
+fi
+
+# Outputs a command and runs it.
+func_verbose ()
+{
+ echo "$@"
+ "$@"
+}
+
+# Run install_command.
+func_verbose $install_prog "$@" || exit $?
+
+# If the platform doesn't support LD_LIBRARY_PATH or similar, we cannot build
+# a wrapper.
+test -n "$library_path_var" || exit 0
+
+libdirs=
+save_IFS="$IFS"; IFS=":"
+for dir in $library_path_value; do
+ IFS="$save_IFS"
+ if test -n "$dir"; then
+ case "$libdirs" in
+ *"\"$dir\""*) ;; # remove duplicate
+ *) libdirs="$libdirs\"$dir\"," ;;
+ esac
+ fi
+done
+IFS="$save_IFS"
+# If there are no library directories to add at runtime, we don't need a
+# wrapper.
+test -n "$libdirs" || exit 0
+
+# Compile wrapper.
+installdir=`echo "$destprog" | sed -e 's,/[^/]*$,,'`
+func_verbose $compile_command -I"$builddir" -I"$srcdir" -I"$config_h_dir" -DHAVE_CONFIG_H -DIN_RELOCWRAPPER -DNO_XMALLOC -D"INSTALLPREFIX=\"$prefix\"" -D"INSTALLDIR=\"$installdir\"" -D"LIBPATHVAR=\"$library_path_var\"" -D"LIBDIRS=$libdirs" -D"EXEEXT=\"$exeext\"" "$srcdir"/relocwrapper.c "$srcdir"/progname.c "$srcdir"/progreloc.c "$srcdir"/xreadlink.c "$srcdir"/readlink.c "$srcdir"/canonicalize-lgpl.c "$srcdir"/allocsa.c "$srcdir"/relocatable.c "$srcdir"/setenv.c "$srcdir"/strerror.c -o "$destprog.wrapper$exeext" || exit $?
+
+# Rename $destprog.wrapper -> $destprog -> $destprog.bin.
+ln -f "$destprog$exeext" "$destprog.bin$exeext" \
+ || { rm -f "$destprog.bin$exeext" && cp -p "$destprog$exeext" "$destprog.bin$exeext"; } \
+ || exit 1
+mv "$destprog.wrapper$exeext" "$destprog$exeext" || exit 1
+
+exit 0
--- /dev/null
+#! /bin/sh
+# Output a system dependent linker command for putting a relocatable library
+# search path into an executable.
+#
+# Copyright 2003 Free Software Foundation, Inc.
+# Written by Bruno Haible <bruno@clisp.org>, 2003.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variable LD should be set by the caller.
+#
+# The second argument is a colon separated list of directories that contain
+# the libraries at installation time.
+#
+# The third argument is the directory into which the executable is going to be
+# installed.
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+library_path_value=$2
+
+installdir=$3
+
+# Verify that installdir is absolute.
+case "$installdir" in
+ /*) ;;
+ *)
+ echo "installdir is not absolute: $installdir" 1>&2
+ exit 1
+ ;;
+esac
+
+case "$host_os" in
+ linux*) # Supported since Linux 2.1 and glibc 2.1.
+ rpath=
+ save_IFS="$IFS"; IFS=":"
+ for dir in $library_path_value; do
+ IFS="$save_IFS"
+ case "$dir" in
+ /*)
+ # Make dir relative to installdir. (Works only if dir is absolute.)
+ idir="$installdir"
+ while true; do
+ dfirst=`echo "$dir" | sed -n -e 's,^//*\([^/]*\).*$,/\1,p'`
+ ifirst=`echo "$idir" | sed -n -e 's,^//*\([^/]*\).*$,/\1,p'`
+ if test -z "$dfirst" || test -z "$ifirst"; then
+ break
+ fi
+ if test "$dfirst" != "$ifirst"; then
+ break
+ fi
+ dir=`echo "$dir" | sed -e 's,^//*[^/]*,,'`
+ idir=`echo "$idir" | sed -e 's,^//*[^/]*,,'`
+ done
+ dir="\$ORIGIN"`echo "$idir" | sed -e 's,//*[^/]*,/..,g'`"$dir"
+ # Add dir to rpath.
+ rpath="${rpath}${rpath:+ }$dir"
+ ;;
+ *)
+ if test -n "$dir"; then
+ echo "libdir is not absolute: $dir" 1>&2
+ fi
+ ;;
+ esac
+ done
+ IFS="$save_IFS"
+ # Output it.
+ if test -n "$rpath"; then
+ echo "-Wl,-rpath,$rpath"
+ fi
+ ;;
+ *)
+ echo "relocation via rpath not supported on this system: $host" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
--- /dev/null
+/* Provide relocatable packages.
+ Copyright (C) 2003-2006 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+
+/* Tell glibc's <stdio.h> to provide a prototype for getline().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#include <config.h>
+
+/* Specification. */
+#include "relocatable.h"
+
+#if ENABLE_RELOCATABLE
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NO_XMALLOC
+# define xmalloc malloc
+#else
+# include "xalloc.h"
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#if DEPENDS_ON_LIBCHARSET
+# include <libcharset.h>
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV
+# include <iconv.h>
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS
+# include <libintl.h>
+#endif
+
+/* Faked cheap 'bool'. */
+#undef bool
+#undef false
+#undef true
+#define bool int
+#define false 0
+#define true 1
+
+/* Pathname support.
+ ISSLASH(C) tests whether C is a directory separator character.
+ IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+ && (P)[1] == ':')
+# define IS_PATH_WITH_DIR(P) \
+ (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+# define FILE_SYSTEM_PREFIX_LEN(P) 0
+#endif
+
+/* Original installation prefix. */
+static char *orig_prefix;
+static size_t orig_prefix_len;
+/* Current installation prefix. */
+static char *curr_prefix;
+static size_t curr_prefix_len;
+/* These prefixes do not end in a slash. Anything that will be concatenated
+ to them must start with a slash. */
+
+/* Sets the original and the current installation prefix of this module.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+static void
+set_this_relocation_prefix (const char *orig_prefix_arg,
+ const char *curr_prefix_arg)
+{
+ if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
+ /* Optimization: if orig_prefix and curr_prefix are equal, the
+ relocation is a nop. */
+ && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
+ {
+ /* Duplicate the argument strings. */
+ char *memory;
+
+ orig_prefix_len = strlen (orig_prefix_arg);
+ curr_prefix_len = strlen (curr_prefix_arg);
+ memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
+#ifdef NO_XMALLOC
+ if (memory != NULL)
+#endif
+ {
+ memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
+ orig_prefix = memory;
+ memory += orig_prefix_len + 1;
+ memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
+ curr_prefix = memory;
+ return;
+ }
+ }
+ orig_prefix = NULL;
+ curr_prefix = NULL;
+ /* Don't worry about wasted memory here - this function is usually only
+ called once. */
+}
+
+/* Sets the original and the current installation prefix of the package.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+void
+set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
+{
+ set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+
+ /* Now notify all dependent libraries. */
+#if DEPENDS_ON_LIBCHARSET
+ libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
+ libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
+ libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+}
+
+#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR)
+
+/* Convenience function:
+ Computes the current installation prefix, based on the original
+ installation prefix, the original installation directory of a particular
+ file, and the current pathname of this file. Returns NULL upon failure. */
+#ifdef IN_LIBRARY
+#define compute_curr_prefix local_compute_curr_prefix
+static
+#endif
+const char *
+compute_curr_prefix (const char *orig_installprefix,
+ const char *orig_installdir,
+ const char *curr_pathname)
+{
+ const char *curr_installdir;
+ const char *rel_installdir;
+
+ if (curr_pathname == NULL)
+ return NULL;
+
+ /* Determine the relative installation directory, relative to the prefix.
+ This is simply the difference between orig_installprefix and
+ orig_installdir. */
+ if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
+ != 0)
+ /* Shouldn't happen - nothing should be installed outside $(prefix). */
+ return NULL;
+ rel_installdir = orig_installdir + strlen (orig_installprefix);
+
+ /* Determine the current installation directory. */
+ {
+ const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
+ const char *p = curr_pathname + strlen (curr_pathname);
+ char *q;
+
+ while (p > p_base)
+ {
+ p--;
+ if (ISSLASH (*p))
+ break;
+ }
+
+ q = (char *) xmalloc (p - curr_pathname + 1);
+#ifdef NO_XMALLOC
+ if (q == NULL)
+ return NULL;
+#endif
+ memcpy (q, curr_pathname, p - curr_pathname);
+ q[p - curr_pathname] = '\0';
+ curr_installdir = q;
+ }
+
+ /* Compute the current installation prefix by removing the trailing
+ rel_installdir from it. */
+ {
+ const char *rp = rel_installdir + strlen (rel_installdir);
+ const char *cp = curr_installdir + strlen (curr_installdir);
+ const char *cp_base =
+ curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
+
+ while (rp > rel_installdir && cp > cp_base)
+ {
+ bool same = false;
+ const char *rpi = rp;
+ const char *cpi = cp;
+
+ while (rpi > rel_installdir && cpi > cp_base)
+ {
+ rpi--;
+ cpi--;
+ if (ISSLASH (*rpi) || ISSLASH (*cpi))
+ {
+ if (ISSLASH (*rpi) && ISSLASH (*cpi))
+ same = true;
+ break;
+ }
+ /* Do case-insensitive comparison if the filesystem is always or
+ often case-insensitive. It's better to accept the comparison
+ if the difference is only in case, rather than to fail. */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS - case insignificant filesystem */
+ if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
+ != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
+ break;
+#else
+ if (*rpi != *cpi)
+ break;
+#endif
+ }
+ if (!same)
+ break;
+ /* The last pathname component was the same. opi and cpi now point
+ to the slash before it. */
+ rp = rpi;
+ cp = cpi;
+ }
+
+ if (rp > rel_installdir)
+ /* Unexpected: The curr_installdir does not end with rel_installdir. */
+ return NULL;
+
+ {
+ size_t curr_prefix_len = cp - curr_installdir;
+ char *curr_prefix;
+
+ curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
+#ifdef NO_XMALLOC
+ if (curr_prefix == NULL)
+ return NULL;
+#endif
+ memcpy (curr_prefix, curr_installdir, curr_prefix_len);
+ curr_prefix[curr_prefix_len] = '\0';
+
+ return curr_prefix;
+ }
+ }
+}
+
+#endif /* !IN_LIBRARY || PIC */
+
+#if defined PIC && defined INSTALLDIR
+
+/* Full pathname of shared library, or NULL. */
+static char *shared_library_fullname;
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+
+/* Determine the full pathname of the shared library when it is loaded. */
+
+BOOL WINAPI
+DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
+{
+ (void) reserved;
+
+ if (event == DLL_PROCESS_ATTACH)
+ {
+ /* The DLL is being loaded into an application's address range. */
+ static char location[MAX_PATH];
+
+ if (!GetModuleFileName (module_handle, location, sizeof (location)))
+ /* Shouldn't happen. */
+ return FALSE;
+
+ if (!IS_PATH_WITH_DIR (location))
+ /* Shouldn't happen. */
+ return FALSE;
+
+ {
+#if defined __CYGWIN__
+ /* On Cygwin, we need to convert paths coming from Win32 system calls
+ to the Unix-like slashified notation. */
+ static char location_as_posix_path[2 * MAX_PATH];
+ /* There's no error return defined for cygwin_conv_to_posix_path.
+ See cygwin-api/func-cygwin-conv-to-posix-path.html.
+ Does it overflow the buffer of expected size MAX_PATH or does it
+ truncate the path? I don't know. Let's catch both. */
+ cygwin_conv_to_posix_path (location, location_as_posix_path);
+ location_as_posix_path[MAX_PATH - 1] = '\0';
+ if (strlen (location_as_posix_path) >= MAX_PATH - 1)
+ /* A sign of buffer overflow or path truncation. */
+ return FALSE;
+ shared_library_fullname = strdup (location_as_posix_path);
+#else
+ shared_library_fullname = strdup (location);
+#endif
+ }
+ }
+
+ return TRUE;
+}
+
+#else /* Unix except Cygwin */
+
+static void
+find_shared_library_fullname ()
+{
+#if defined __linux__ && __GLIBC__ >= 2
+ /* Linux has /proc/self/maps. glibc 2 has the getline() function. */
+ FILE *fp;
+
+ /* Open the current process' maps file. It describes one VMA per line. */
+ fp = fopen ("/proc/self/maps", "r");
+ if (fp)
+ {
+ unsigned long address = (unsigned long) &find_shared_library_fullname;
+ for (;;)
+ {
+ unsigned long start, end;
+ int c;
+
+ if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
+ break;
+ if (address >= start && address <= end - 1)
+ {
+ /* Found it. Now see if this line contains a filename. */
+ while (c = getc (fp), c != EOF && c != '\n' && c != '/')
+ continue;
+ if (c == '/')
+ {
+ size_t size;
+ int len;
+
+ ungetc (c, fp);
+ shared_library_fullname = NULL; size = 0;
+ len = getline (&shared_library_fullname, &size, fp);
+ if (len >= 0)
+ {
+ /* Success: filled shared_library_fullname. */
+ if (len > 0 && shared_library_fullname[len - 1] == '\n')
+ shared_library_fullname[len - 1] = '\0';
+ }
+ }
+ break;
+ }
+ while (c = getc (fp), c != EOF && c != '\n')
+ continue;
+ }
+ fclose (fp);
+ }
+#endif
+}
+
+#endif /* (WIN32 or Cygwin) / (Unix except Cygwin) */
+
+/* Return the full pathname of the current shared library.
+ Return NULL if unknown.
+ Guaranteed to work only on Linux, Cygwin and Woe32. */
+static char *
+get_shared_library_fullname ()
+{
+#if !(defined _WIN32 || defined __WIN32__ || defined __CYGWIN__)
+ static bool tried_find_shared_library_fullname;
+ if (!tried_find_shared_library_fullname)
+ {
+ find_shared_library_fullname ();
+ tried_find_shared_library_fullname = true;
+ }
+#endif
+ return shared_library_fullname;
+}
+
+#endif /* PIC */
+
+/* Returns the pathname, relocated according to the current installation
+ directory. */
+const char *
+relocate (const char *pathname)
+{
+#if defined PIC && defined INSTALLDIR
+ static int initialized;
+
+ /* Initialization code for a shared library. */
+ if (!initialized)
+ {
+ /* At this point, orig_prefix and curr_prefix likely have already been
+ set through the main program's set_program_name_and_installdir
+ function. This is sufficient in the case that the library has
+ initially been installed in the same orig_prefix. But we can do
+ better, to also cover the cases that 1. it has been installed
+ in a different prefix before being moved to orig_prefix and (later)
+ to curr_prefix, 2. unlike the program, it has not moved away from
+ orig_prefix. */
+ const char *orig_installprefix = INSTALLPREFIX;
+ const char *orig_installdir = INSTALLDIR;
+ const char *curr_prefix_better;
+
+ curr_prefix_better =
+ compute_curr_prefix (orig_installprefix, orig_installdir,
+ get_shared_library_fullname ());
+ if (curr_prefix_better == NULL)
+ curr_prefix_better = curr_prefix;
+
+ set_relocation_prefix (orig_installprefix, curr_prefix_better);
+
+ initialized = 1;
+ }
+#endif
+
+ /* Note: It is not necessary to perform case insensitive comparison here,
+ even for DOS-like filesystems, because the pathname argument was
+ typically created from the same Makefile variable as orig_prefix came
+ from. */
+ if (orig_prefix != NULL && curr_prefix != NULL
+ && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
+ {
+ if (pathname[orig_prefix_len] == '\0')
+ /* pathname equals orig_prefix. */
+ return curr_prefix;
+ if (ISSLASH (pathname[orig_prefix_len]))
+ {
+ /* pathname starts with orig_prefix. */
+ const char *pathname_tail = &pathname[orig_prefix_len];
+ char *result =
+ (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
+
+#ifdef NO_XMALLOC
+ if (result != NULL)
+#endif
+ {
+ memcpy (result, curr_prefix, curr_prefix_len);
+ strcpy (result + curr_prefix_len, pathname_tail);
+ return result;
+ }
+ }
+ }
+ /* Nothing to relocate. */
+ return pathname;
+}
+
+#endif
--- /dev/null
+/* Provide relocatable packages.
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _RELOCATABLE_H
+#define _RELOCATABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* This can be enabled through the configure --enable-relocatable option. */
+#if ENABLE_RELOCATABLE
+
+/* When building a DLL, we must export some functions. Note that because
+ this is a private .h file, we don't need to use __declspec(dllimport)
+ in any case. */
+#if HAVE_VISIBILITY && BUILDING_DLL
+# define RELOCATABLE_DLL_EXPORTED __attribute__((__visibility__("default")))
+#elif defined _MSC_VER && BUILDING_DLL
+# define RELOCATABLE_DLL_EXPORTED __declspec(dllexport)
+#else
+# define RELOCATABLE_DLL_EXPORTED
+#endif
+
+/* Sets the original and the current installation prefix of the package.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+extern RELOCATABLE_DLL_EXPORTED void
+ set_relocation_prefix (const char *orig_prefix,
+ const char *curr_prefix);
+
+/* Returns the pathname, relocated according to the current installation
+ directory. */
+extern const char * relocate (const char *pathname);
+
+/* Memory management: relocate() leaks memory, because it has to construct
+ a fresh pathname. If this is a problem because your program calls
+ relocate() frequently, think about caching the result. */
+
+/* Convenience function:
+ Computes the current installation prefix, based on the original
+ installation prefix, the original installation directory of a particular
+ file, and the current pathname of this file. Returns NULL upon failure. */
+extern const char * compute_curr_prefix (const char *orig_installprefix,
+ const char *orig_installdir,
+ const char *curr_pathname);
+
+#else
+
+/* By default, we use the hardwired pathnames. */
+#define relocate(pathname) (pathname)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RELOCATABLE_H */
--- /dev/null
+/* Relocating wrapper program.
+ Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Dependencies:
+ relocwrapper
+ -> progname
+ -> progreloc
+ -> xreadlink
+ -> readlink
+ -> canonicalize
+ -> allocsa
+ -> relocatable
+ -> setenv
+ -> allocsa
+ -> strerror
+
+ Macros that need to be set while compiling this file:
+ - ENABLE_RELOCATABLE 1
+ - INSTALLPREFIX the base installation directory
+ - INSTALLDIR the directory into which this program is installed
+ - LIBPATHVAR the platform dependent runtime library path variable
+ - LIBDIRS a comma-terminated list of strings representing the list of
+ directories that contain the libraries at installation time
+
+ We don't want to internationalize this wrapper because then it would
+ depend on libintl and therefore need relocation itself. So use only
+ libc functions, no gettext(), no error(), no xmalloc(), no xsetenv().
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <errno.h>
+
+#include "progname.h"
+#include "relocatable.h"
+#include "setenv.h"
+
+/* Return a copy of the filename, with an extra ".bin" at the end.
+ More generally, it replaces "${EXEEXT}" at the end with ".bin${EXEEXT}". */
+static char *
+add_dotbin (const char *filename)
+{
+ size_t filename_len = strlen (filename);
+ char *result = (char *) malloc (filename_len + 4 + 1);
+
+ if (result != NULL)
+ {
+ if (sizeof (EXEEXT) > sizeof (""))
+ {
+ /* EXEEXT handling. */
+ const size_t exeext_len = sizeof (EXEEXT) - sizeof ("");
+ static const char exeext[] = EXEEXT;
+ if (filename_len > exeext_len)
+ {
+ /* Compare using an inlined copy of c_strncasecmp(), because
+ the filenames may have undergone a case conversion since
+ they were packaged. In other words, EXEEXT may be ".exe"
+ on one system and ".EXE" on another. */
+ const char *s1 = filename + filename_len - exeext_len;
+ const char *s2 = exeext;
+ for (; *s1 != '\0'; s1++, s2++)
+ {
+ unsigned char c1 = *s1;
+ unsigned char c2 = *s2;
+ if ((c1 >= 'A' && c1 <= 'Z' ? c1 - 'A' + 'a' : c1)
+ != (c2 >= 'A' && c2 <= 'Z' ? c2 - 'A' + 'a' : c2))
+ goto simple_append;
+ }
+ /* Insert ".bin" before EXEEXT or its equivalent. */
+ memcpy (result, filename, filename_len - exeext_len);
+ memcpy (result + filename_len - exeext_len, ".bin", 4);
+ memcpy (result + filename_len - exeext_len + 4,
+ filename + filename_len - exeext_len,
+ exeext_len + 1);
+ return result;
+ }
+ }
+ simple_append:
+ /* Simply append ".bin". */
+ memcpy (result, filename, filename_len);
+ memcpy (result + filename_len, ".bin", 4 + 1);
+ return result;
+ }
+ else
+ {
+ fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
+ exit (1);
+ }
+}
+
+/* List of directories that contain the libraries. */
+static const char *libdirs[] = { LIBDIRS NULL };
+/* Verify that at least one directory is given. */
+typedef int verify1[2 * (sizeof (libdirs) / sizeof (libdirs[0]) > 1) - 1];
+
+/* Relocate the list of directories that contain the libraries. */
+static void
+relocate_libdirs ()
+{
+ size_t i;
+
+ for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++)
+ libdirs[i] = relocate (libdirs[i]);
+}
+
+/* Activate the list of directories in the LIBPATHVAR. */
+static void
+activate_libdirs ()
+{
+ const char *old_value;
+ size_t total;
+ size_t i;
+ char *value;
+ char *p;
+
+ old_value = getenv (LIBPATHVAR);
+ if (old_value == NULL)
+ old_value = "";
+
+ total = 0;
+ for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++)
+ total += strlen (libdirs[i]) + 1;
+ total += strlen (old_value) + 1;
+
+ value = (char *) malloc (total);
+ if (value == NULL)
+ {
+ fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
+ exit (1);
+ }
+ p = value;
+ for (i = 0; i < sizeof (libdirs) / sizeof (libdirs[0]) - 1; i++)
+ {
+ size_t len = strlen (libdirs[i]);
+ memcpy (p, libdirs[i], len);
+ p += len;
+ *p++ = ':';
+ }
+ if (old_value[0] != '\0')
+ strcpy (p, old_value);
+ else
+ p[-1] = '\0';
+
+ if (setenv (LIBPATHVAR, value, 1) < 0)
+ {
+ fprintf (stderr, "%s: %s\n", program_name, "memory exhausted");
+ exit (1);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ char *full_program_name;
+
+ /* Set the program name and perform preparations for
+ get_full_program_name() and relocate(). */
+ set_program_name_and_installdir (argv[0], INSTALLPREFIX, INSTALLDIR);
+
+ /* Get the full program path. (Important if accessed through a symlink.) */
+ full_program_name = get_full_program_name ();
+ if (full_program_name == NULL)
+ full_program_name = argv[0];
+
+ /* Invoke the real program, with suffix ".bin". */
+ argv[0] = add_dotbin (full_program_name);
+ relocate_libdirs ();
+ activate_libdirs ();
+ execv (argv[0], argv);
+ fprintf (stderr, "%s: could not execute %s: %s\n",
+ program_name, argv[0], strerror (errno));
+ exit (127);
+}
--- /dev/null
+# relocatable.m4 serial 7 (gettext-0.16)
+dnl Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl Support for relocateble programs.
+AC_DEFUN([AC_RELOCATABLE],
+[
+ AC_REQUIRE([AC_RELOCATABLE_BODY])
+ if test $RELOCATABLE = yes; then
+ AC_LIBOBJ([relocatable])
+ fi
+])
+dnl The guts of AC_RELOCATABLE. Needs to be expanded only once.
+AC_DEFUN([AC_RELOCATABLE_BODY],
+[
+ AC_REQUIRE([AC_PROG_INSTALL])
+ dnl This AC_BEFORE invocation leads to unjustified autoconf warnings
+ dnl when AC_RELOCATABLE_BODY is invoked more than once.
+ dnl We need this AC_BEFORE because AC_PROG_INSTALL is documented to
+ dnl overwrite earlier settings of INSTALL and INSTALL_PROGRAM (even
+ dnl though in autoconf-2.52..2.60 it doesn't do so), but we want this
+ dnl macro's setting of INSTALL_PROGRAM to persist.
+ AC_BEFORE([AC_PROG_INSTALL],[AC_RELOCATABLE_BODY])
+ AC_REQUIRE([AC_LIB_LIBPATH])
+ AC_REQUIRE([AC_RELOCATABLE_LIBRARY])
+ AC_REQUIRE([AC_EXEEXT])
+ is_noop=no
+ use_elf_origin_trick=no
+ if test $RELOCATABLE = yes; then
+ # --enable-relocatable implies --disable-rpath
+ enable_rpath=no
+ AC_DEFINE([ENABLE_RELOCATABLE], 1,
+ [Define to 1 if the package shall run at any location in the filesystem.])
+ AC_CHECK_HEADERS([unistd.h mach-o/dyld.h])
+ AC_CHECK_FUNCS([_NSGetExecutablePath])
+ case "$host_os" in
+ mingw*) is_noop=yes ;;
+ linux*) use_elf_origin_trick=yes ;;
+ esac
+ if test $is_noop = yes; then
+ SET_RELOCATABLE="RELOCATABLE_LDFLAGS = :"
+ else
+ if test $use_elf_origin_trick = yes; then
+ dnl Use the dynamic linker's support for relocatable programs.
+ case "$ac_aux_dir" in
+ /*) reloc_ldflags="$ac_aux_dir/reloc-ldflags" ;;
+ *) reloc_ldflags="\$(top_builddir)/$ac_aux_dir/reloc-ldflags" ;;
+ esac
+ SET_RELOCATABLE="RELOCATABLE_LDFLAGS = \"$reloc_ldflags\" \"\$(host)\" \"\$(RELOCATABLE_LIBRARY_PATH)\""
+ else
+ dnl Unfortunately we cannot define INSTALL_PROGRAM to a command
+ dnl consisting of more than one word - libtool doesn't support this.
+ dnl So we abuse the INSTALL_PROGRAM_ENV hook, originally meant for the
+ dnl 'install-strip' target.
+ SET_RELOCATABLE="INSTALL_PROGRAM_ENV = RELOC_LIBRARY_PATH_VAR=\"$shlibpath_var\" RELOC_LIBRARY_PATH_VALUE=\"\$(RELOCATABLE_LIBRARY_PATH)\" RELOC_PREFIX=\"\$(prefix)\" RELOC_COMPILE_COMMAND=\"\$(CC) \$(CPPFLAGS) \$(CFLAGS) \$(LDFLAGS)\" RELOC_SRCDIR=\"\$(RELOCATABLE_SRC_DIR)\" RELOC_BUILDDIR=\"\$(RELOCATABLE_BUILD_DIR)\" RELOC_CONFIG_H_DIR=\"\$(RELOCATABLE_CONFIG_H_DIR)\" RELOC_EXEEXT=\"\$(EXEEXT)\" RELOC_INSTALL_PROG=\"$INSTALL_PROGRAM\""
+ case "$ac_aux_dir" in
+ /*) INSTALL_PROGRAM="$ac_aux_dir/install-reloc" ;;
+ *) INSTALL_PROGRAM="\$(top_builddir)/$ac_aux_dir/install-reloc" ;;
+ esac
+ fi
+ fi
+ else
+ SET_RELOCATABLE=
+ fi
+ AC_SUBST([SET_RELOCATABLE])
+ AM_CONDITIONAL([RELOCATABLE_VIA_LD],
+ [test $is_noop = yes || test $use_elf_origin_trick = yes])
+])
+
+dnl Support for relocatable libraries.
+AC_DEFUN([AC_RELOCATABLE_LIBRARY],
+[
+ AC_REQUIRE([AC_RELOCATABLE_NOP])
+ dnl Easier to put this here once, instead of into the DEFS of each Makefile.
+ if test "X$prefix" = "XNONE"; then
+ reloc_final_prefix="$ac_default_prefix"
+ else
+ reloc_final_prefix="$prefix"
+ fi
+ AC_DEFINE_UNQUOTED([INSTALLPREFIX], ["${reloc_final_prefix}"],
+ [Define to the value of ${prefix}, as a string.])
+])
+
+dnl Support for relocatable packages for which it is a nop.
+AC_DEFUN([AC_RELOCATABLE_NOP],
+[
+ AC_MSG_CHECKING([whether to activate relocatable installation])
+ AC_ARG_ENABLE(relocatable,
+ [ --enable-relocatable install a package that can be moved in the filesystem],
+ [if test "$enableval" != no; then
+ RELOCATABLE=yes
+ else
+ RELOCATABLE=no
+ fi
+ ], RELOCATABLE=no)
+ AC_SUBST(RELOCATABLE)
+ AC_MSG_RESULT([$RELOCATABLE])
+])
+
+dnl Determine the platform dependent parameters needed to use relocatability:
+dnl shlibpath_var.
+AC_DEFUN([AC_LIB_LIBPATH],
+[
+ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
+ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+ AC_CACHE_CHECK([for shared library path variable], acl_cv_libpath, [
+ LD="$LD" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.libpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_libpath=${acl_cv_shlibpath_var:-none}
+ ])
+ shlibpath_var="$acl_cv_shlibpath_var"
+])