Index: build-aux/config.libpath =================================================================== RCS file: build-aux/config.libpath diff -N build-aux/config.libpath --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ build-aux/config.libpath 26 Feb 2007 02:11:24 -0000 @@ -0,0 +1,148 @@ +#! /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 , 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=/' <, 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 "$srcdir"/c-ctype.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 Index: build-aux/reloc-ldflags =================================================================== RCS file: build-aux/reloc-ldflags diff -N build-aux/reloc-ldflags --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ build-aux/reloc-ldflags 26 Feb 2007 02:11:25 -0000 @@ -0,0 +1,102 @@ +#! /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 , 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 Index: doc/gnulib.texi =================================================================== RCS file: /cvsroot/gnulib/gnulib/doc/gnulib.texi,v retrieving revision 1.31 diff -u -p -r1.31 gnulib.texi --- doc/gnulib.texi 3 Jan 2007 18:51:20 -0000 1.31 +++ doc/gnulib.texi 26 Feb 2007 02:11:25 -0000 @@ -365,6 +365,7 @@ Of course the license texts themselves s * gcd:: * inet_ntoa:: * Regular expressions:: +* Supporting Relocation:: @end menu @include quote.texi @@ -372,6 +373,7 @@ Of course the license texts themselves s @include ctime.texi @include gcd.texi @include inet_ntoa.texi address@hidden relocatable-maint.texi @node Regular expressions @section Regular expressions Index: doc/relocatable-maint.texi =================================================================== RCS file: doc/relocatable-maint.texi diff -N doc/relocatable-maint.texi --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ doc/relocatable-maint.texi 26 Feb 2007 02:11:25 -0000 @@ -0,0 +1,142 @@ address@hidden Supporting Relocation address@hidden Supporting Relocation + +It has been a pain for many users of GNU packages for a long time that +packages are not relocatable. It means a user cannot copy a program, +installed by another user on the same machine, to his home directory, +and have it work correctly (including i18n). So many users need to go +through @code{configure; make; make install} with all its +dependencies, options, and hurdles. + +Red Hat, Debian, and similar package systems solve the ``ease of +installation'' problem, but they hardwire path names, usually to address@hidden/usr} or @file{/usr/local}. This means that users need root +privileges to install a binary package, and prevents installing two +different versions of the same binary package. + +A relocatable program can be moved or copied to a different location +on the filesystem. It is possible to make symlinks to the installed +and moved programs, and invoke them through the symlink. It is +possible to do the same thing with a hard link @emph{only} if the hard +link file is in the same directory as the real program. + +The @code{relocatable} module aims to ease the process of making a GNU +program relocatable. It helps overcome two obstacles. First, it aids +with relocating the hard-coded references to absolute file names that +GNU programs often contain. These references must be fixed up at +runtime if a program is to be successfully relocated. The address@hidden module provides a function @code{relocate} that +does this job. + +Second, the loader must be able to find shared libraries linked to +relocatable executables or referenced by other shared libraries linked +to relocatable executables. The @code{relocatable} module helps out +here in a platform-specific way: + address@hidden address@hidden +On GNU/Linux, it adds a linker option (@option{-rpath}) that causes +the dynamic linker to search for libraries in a directory relative to +the location of the invoked executable. + address@hidden +On other Unix systems, it installs a wrapper executable. The wrapper +sets the environment variable that controls shared library searching +(usually @env{LD_LIBRARY_PATH}) and then invokes the real executable. + +This approach does not always work. On OpenBSD and OpenServer, +prereleases of Libtool 1.5 put absolute file names of libraries in +executables, which prevents searching any other locations. + address@hidden +On Windows, the executable's own directory is searched for libraries, +so installing shared libraries into the executable's directory is +sufficient. address@hidden itemize + +You can make your program relocatable by following these steps: + address@hidden address@hidden +Import the @code{relocatable} module. + address@hidden +In every program, add to @code{main} as the first statement (even +before setting the locale or doing anything related to libintl): + address@hidden +set_program_name (argv[0]); address@hidden example + +The prototype for this function is in @file{progname.h}. + address@hidden +Everywhere where you use a constant pathname from installation-time, +wrap it in @code{relocate} so it gets translated to the run-time situation. +Example: + address@hidden +bindtextdomain (PACKAGE, LOCALEDIR); address@hidden example + address@hidden +becomes: + address@hidden +bindtextdomain (PACKAGE, relocate (LOCALEDIR)); address@hidden example + +The prototype for this function is in @file{relocatable.h}. + address@hidden +If your package installs shell scripts, also import the address@hidden module. Then, near the beginning of each +shell script that your package installs, add the following: + address@hidden +@@relocatable_sh@@ +if test "@@RELOCATABLE@@" = yes; then + exec_prefix="@@exec_prefix@@" + bindir="@@bindir@@" + orig_installdir="$bindir" # see Makefile.am's *_SCRIPTS variables + func_find_curr_installdir # determine curr_installdir + func_find_prefixes + # Relocate the directory variables that we use. + gettext_dir=`echo "$gettext_dir/" | sed -e +"address@hidden@}/address@hidden@}/%" | sed -e 's,/$,,'` +fi address@hidden example + +You must adapt the definition of @code{orig_installdir}, depending on +where the script gets installed. Also, at the end, instead of address@hidden, transform those variables that you need. + address@hidden +In your @file{Makefile.am}, for every program @command{foo} that gets +installed in, say, @file{$(bindir)}, you add: + address@hidden +foo_CFLAGS = -DINSTALLDIR=\"$(bindir)\" +if RELOCATABLE_VIA_LD +foo_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)` +endif address@hidden example + address@hidden +You may also need to add one or two variable assignments to your address@hidden + +If your package (or any package you rely on, e.g.@: gettext-runtime) +will be relocated together with a set of installed shared libraries, +then set @var{RELOCATABLE_LIBRARY_PATH} to a colon-separated list +of those libraries' directories, e.g. address@hidden +RELOCATABLE_LIBRARY_PATH='$(libdir)' address@hidden example + +If your @file{config.h} is not in @file{$(top_builddir)}, then set address@hidden to its directory, e.g. address@hidden +RELOCATABLE_CONFIG_H_DIR='$(top_builddir)/src' address@hidden example address@hidden enumerate Index: doc/relocatable.texi =================================================================== RCS file: doc/relocatable.texi diff -N doc/relocatable.texi --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ doc/relocatable.texi 26 Feb 2007 02:11:25 -0000 @@ -0,0 +1,41 @@ address@hidden Enabling Relocatability address@hidden Enabling Relocatability + +It has been a pain for many users of GNU packages for a long time that +packages are not relocatable. It means a user cannot copy a program, +installed by another user on the same machine, to his home directory, +and have it work correctly (including i18n). So many users need to go +through @code{configure; make; make install} with all its +dependencies, options, and hurdles. + +Red Hat, Debian, and similar package systems solve the ``ease of +installation'' problem, but they hardwire path names, usually to address@hidden/usr} or @file{/usr/local}. This means that users need root +privileges to install a binary package, and prevents installing two +different versions of the same binary package. + +A relocatable program can be moved or copied to a different location +on the filesystem. It is possible to make symlinks to the installed +and moved programs, and invoke them through the symlink. It is +possible to do the same thing with a hard link @emph{only} if the hard +link file is in the same directory as the real program. + +To configure a program to be relocatable, add address@hidden to the @program{configure} command line. +For reliability, it is best to also give a @option{--prefix} option +pointing to an otherwise unused (and never used again) directory, +e.g.@: @option{--prefix=/tmp/inst$$}. This is recommended because on +some OSes the executables remember the location of shared libraries +and prefer them over any other search path. Therefore, such an +executable will look for its shared libraries first in the original +installation directory and only then in the current installation +directory. + +Installation with @option{--enable-relocatable} will not work for +setuid or setgid executables, because such executables search only +system library paths for security reasons. + +The runtime penalty and size penalty are negligible on GNU/Linux (just +one system call more when an executable is launched), and small on +other systems (the wrapper program just sets an environment variable +and executes the real program). Index: lib/progreloc.c =================================================================== RCS file: /cvsroot/gnulib/gnulib/lib/progreloc.c,v retrieving revision 1.11 diff -u -p -r1.11 progreloc.c --- lib/progreloc.c 14 Jan 2007 11:32:10 -0000 1.11 +++ lib/progreloc.c 26 Feb 2007 02:11:26 -0000 @@ -27,9 +27,7 @@ #include #include #include -#if HAVE_UNISTD_H -# include -#endif +#include #include /* Get declaration of _NSGetExecutablePath on MacOS X 10.2 or newer. */ @@ -174,7 +172,7 @@ find_executable (const char *argv0) { char *link; - link = xreadlink ("/proc/self/exe"); + link = xreadlink ("/proc/self/exe", 4096); if (link != NULL && link[0] != '[') return link; if (executable_fd < 0) @@ -183,7 +181,7 @@ find_executable (const char *argv0) { char buf[6+10+5]; sprintf (buf, "/proc/%d/exe", getpid ()); - link = xreadlink (buf); + link = xreadlink (buf, 4096); if (link != NULL && link[0] != '[') return link; if (executable_fd < 0) Index: lib/relocatable.c =================================================================== RCS file: lib/relocatable.c diff -N lib/relocatable.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/relocatable.c 26 Feb 2007 02:11:26 -0000 @@ -0,0 +1,464 @@ +/* Provide relocatable packages. + Copyright (C) 2003-2006, 2007 Free Software Foundation, Inc. + Written by Bruno Haible , 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. */ + +#include + +/* Specification. */ +#include "relocatable.h" + +#if ENABLE_RELOCATABLE + +#include +#include +#include +#include + +#ifdef NO_XMALLOC +# define xmalloc malloc +#else +# include "xalloc.h" +#endif + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#if DEPENDS_ON_LIBCHARSET +# include +#endif +#if DEPENDS_ON_LIBICONV && HAVE_ICONV +# include +#endif +#if DEPENDS_ON_LIBINTL && ENABLE_NLS +# include +#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) + { + unsigned char c1, c2; + + 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. */ + c1 = *rpi; + c2 = *cpi; +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Win32, Cygwin, OS/2, DOS - case insignificant filesystem */ + if (c_toupper (c1) != c_toupper (c2)) + break; +#else + if (c1 != c2) + 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 Index: lib/relocatable.h =================================================================== RCS file: lib/relocatable.h diff -N lib/relocatable.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/relocatable.h 26 Feb 2007 02:11:26 -0000 @@ -0,0 +1,79 @@ +/* Provide relocatable packages. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + Written by Bruno Haible , 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 */ Index: lib/relocatable.sh.in =================================================================== RCS file: lib/relocatable.sh.in diff -N lib/relocatable.sh.in --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/relocatable.sh.in 26 Feb 2007 02:11:26 -0000 @@ -0,0 +1,103 @@ +# From gettext/gettext-tools/misc/gettextize.in. +# +# The functions in this file provide support for relocatability of +# shell scripts. They should be included near the beginning of each +# shell script in a relocatable program, by adding @relocatable_sh@ +# and causing the script to be expanded with AC_CONFIG_FILES. A +# small amount of additional code must be added and adapted to the +# package by hand; see doc/relocatable-maint.texi (in Gnulib) for +# details. +# +# Copyright (C) 1995-1998, 2000-2006, 2007 Free Software Foundation, Inc. +# +# 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. +# + +# Support for relocatability. +func_find_curr_installdir () +{ + # Determine curr_installdir, even taking into account symlinks. + curr_executable="$0" + case "$curr_executable" in + */* | *\\*) ;; + *) # Need to look in the PATH. + if test "${PATH_SEPARATOR+set}" != set; then + func_tmpdir + { echo "#! /bin/sh"; echo "exit 0"; } > "$tmp"/conf.sh + chmod +x "$tmp"/conf.sh + if (PATH="/nonexistent;$tmp"; conf.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -rf "$tmp" + fi + save_IFS="$IFS"; IFS="$PATH_SEPARATOR" + for dir in $PATH; do + IFS="$save_IFS" + test -z "$dir" && dir=. + for exec_ext in ''; do + if test -f "$dir/$curr_executable$exec_ext"; then + curr_executable="$dir/$curr_executable$exec_ext" + break 2 + fi + done + done + IFS="$save_IFS" + ;; + esac + # Make absolute. + case "$curr_executable" in + /* | ?:/* | ?:\\*) ;; + *) curr_executable=`pwd`/"$curr_executable" ;; + esac + # Resolve symlinks. + sed_dirname='s,/[^/]*$,,' + sed_linkdest='s,^.* -> \(.*\),\1,p' + while : ; do + lsline=`LC_ALL=C ls -l "$curr_executable"` + case "$lsline" in + *" -> "*) + linkdest=`echo "$lsline" | sed -n -e "$sed_linkdest"` + case "$linkdest" in + /* | ?:/* | ?:\\*) curr_executable="$linkdest" ;; + *) curr_executable=`echo "$curr_executable" | sed -e "$sed_dirname"`/"$linkdest" ;; + esac ;; + *) break ;; + esac + done + curr_installdir=`echo "$curr_executable" | sed -e 's,/[^/]*$,,'` + # Canonicalize. + curr_installdir=`cd "$curr_installdir" && pwd` +} +func_find_prefixes () +{ + # Compute the original/current installation prefixes by stripping the + # trailing directories off the original/current installation directories. + orig_installprefix="$orig_installdir" + curr_installprefix="$curr_installdir" + while true; do + orig_last=`echo "$orig_installprefix" | sed -n -e 's,^.*/\([^/]*\)$,\1,p'` + curr_last=`echo "$curr_installprefix" | sed -n -e 's,^.*/\([^/]*\)$,\1,p'` + if test -z "$orig_last" || test -z "$curr_last"; then + break + fi + if test "$orig_last" != "$curr_last"; then + break + fi + orig_installprefix=`echo "$orig_installprefix" | sed -e 's,/[^/]*$,,'` + curr_installprefix=`echo "$curr_installprefix" | sed -e 's,/[^/]*$,,'` + done +} Index: lib/relocwrapper.c =================================================================== RCS file: lib/relocwrapper.c diff -N lib/relocwrapper.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/relocwrapper.c 26 Feb 2007 02:11:26 -0000 @@ -0,0 +1,193 @@ +/* Relocating wrapper program. + Copyright (C) 2003, 2005-2006, 2007 Free Software Foundation, Inc. + Written by Bruno Haible , 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 + -> c-ctype + + 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 + +#include +#include +#include +#include +#include + +#include "progname.h" +#include "relocatable.h" +#include "setenv.h" +#include "c-ctype.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 (c_tolower (c1) != c_tolower (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); +} Index: m4/relocatable-lib.m4 =================================================================== RCS file: m4/relocatable-lib.m4 diff -N m4/relocatable-lib.m4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m4/relocatable-lib.m4 26 Feb 2007 02:11:27 -0000 @@ -0,0 +1,38 @@ +# relocatable-lib.m4 serial 1 +dnl Copyright (C) 2003, 2005-2006, 2007 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 relocatable libraries. +AC_DEFUN([gl_RELOCATABLE_LIBRARY], +[ + AC_REQUIRE([gl_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([gl_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]) +]) + Index: m4/relocatable.m4 =================================================================== RCS file: m4/relocatable.m4 diff -N m4/relocatable.m4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m4/relocatable.m4 26 Feb 2007 02:11:27 -0000 @@ -0,0 +1,99 @@ +# relocatable.m4 serial 8 +dnl Copyright (C) 2003, 2005-2006, 2007 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 gl_RELOCATABLE([RELOCWRAPPER-DIR]) +dnl ---------------------------------------------------------- +dnl Support for relocatable programs. +dnl Supply RELOCWRAPPER-DIR as the directory where relocwrapper.c may be found. +AC_DEFUN([gl_RELOCATABLE], +[ + AC_REQUIRE([gl_RELOCATABLE_BODY]) + if test $RELOCATABLE = yes; then + AC_LIBOBJ([relocatable]) + fi + : ${RELOCATABLE_CONFIG_H_DIR='$(top_builddir)'} + RELOCATABLE_SRC_DIR="\$(top_srcdir)/$gl_source_base" + RELOCATABLE_BUILD_DIR="\$(top_builddir)/$gl_source_base" +]) +dnl The guts of gl_RELOCATABLE. Needs to be expanded only once. +AC_DEFUN([gl_RELOCATABLE_BODY], +[ + AC_REQUIRE([AC_PROG_INSTALL]) + dnl This AC_BEFORE invocation leads to unjustified autoconf warnings + dnl when gl_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],[gl_RELOCATABLE_BODY]) + AC_REQUIRE([AC_LIB_LIBPATH]) + AC_REQUIRE([gl_RELOCATABLE_LIBRARY]) + 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([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 + RELOCATABLE_LDFLAGS=: + AC_SUBST([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 + RELOCATABLE_LDFLAGS="\"$reloc_ldflags\" \"\$(host)\" \"\$(RELOCATABLE_LIBRARY_PATH)\"" + AC_SUBST([RELOCATABLE_LDFLAGS]) + 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. + 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\"" + AC_SUBST([INSTALL_PROGRAM_ENV]) + case "$ac_aux_dir" in + /*) INSTALL_PROGRAM="$ac_aux_dir/install-reloc" ;; + *) INSTALL_PROGRAM="\$(top_builddir)/$ac_aux_dir/install-reloc" ;; + esac + fi + fi + fi + AM_CONDITIONAL([RELOCATABLE_VIA_LD], + [test $is_noop = yes || test $use_elf_origin_trick = yes]) + + AC_SUBST([RELOCATABLE_LIBRARY_PATH]) + AC_SUBST([RELOCATABLE_SRC_DIR]) + AC_SUBST([RELOCATABLE_BUILD_DIR]) + AC_SUBST([RELOCATABLE_CONFIG_H_DIR]) +]) + +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" +]) Index: modules/relocatable =================================================================== RCS file: modules/relocatable diff -N modules/relocatable --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/relocatable 26 Feb 2007 02:11:28 -0000 @@ -0,0 +1,37 @@ +Description: +Help make programs relocatable, that is, to allow them to function +properly when copied to an arbitrary directory. + +Files: +build-aux/config.libpath +build-aux/install-reloc +build-aux/reloc-ldflags +lib/progreloc.c +lib/relocwrapper.c +m4/relocatable.m4 + +Depends-on: +relocatable-lib +canonicalize +c-ctype +extensions +progname +setenv +strerror +unistd + +configure.ac: +gl_RELOCATABLE([$gl_source_base]) + +Makefile.am: +DEFS += -DEXEEXT=\"$(EXEEXT)\" +lib_SOURCES += progreloc.c + +Include: +"progname.h" + +License: +GPL + +Maintainer: + Index: modules/relocatable-lib =================================================================== RCS file: modules/relocatable-lib diff -N modules/relocatable-lib --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/relocatable-lib 26 Feb 2007 02:11:28 -0000 @@ -0,0 +1,24 @@ +Description: +Help make libraries relocatable, that is, to allow them to function +properly when copied to an arbitrary directory. + +Files: +doc/relocatable.texi +lib/relocatable.c +lib/relocatable.h +m4/relocatable-lib.m4 + +Depends-on: + +configure.ac: + +Makefile.am: +lib_SOURCES += relocatable.c relocatable.h + +Include: +"relocatable.h" + +License: +LGPL + +Maintainer: Index: modules/relocatable-script =================================================================== RCS file: modules/relocatable-script diff -N modules/relocatable-script --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/relocatable-script 26 Feb 2007 02:11:28 -0000 @@ -0,0 +1,23 @@ +Description: +Help make shell scripts relocatable, that is, to allow them to +function properly when copied to an arbitrary directory. + +Files: +lib/relocatable.sh.in + +Depends-on: +relocatable + +configure.ac: +AC_SUBST_FILE(relocatable_sh) +relocatable_sh=$gl_source_base/relocatable.sh.in + +Makefile.am: + +Include: + +License: +GPL + +Maintainer: +