[ this is: http://thread.gmane.org/gmane.comp.gnu.libtool.bugs/5319
or http://lists.gnu.org/archive/html/bug-libtool/2006-03/msg00013.html ]

Hi Behdad, everyone,

Sorry for the delay again.

* Behdad Esfahbod wrote on Thu, Mar 09, 2006 at 04:59:38PM CET:
> On Wed, 1 Mar 2006, Ralf Wildenhues wrote:
> > * Behdad Esfahbod wrote on Wed, Mar 01, 2006 at 05:15:17AM CET:
> > >
> > > This is a feature request for libtool.  Let me describe the
> > > problem as I face it, so you may have a workaround for it
> > > already:  I'm using libtool in the Pango text rendering engine.
> > > The Pango library accesses a file in $prefix/etc/pango/pangorc to
> > > find its modules at run-time.  Now all I want to do is to be able
> > > to run the examples in pango/example when Pango is not installed.
> > >
> > > The easiest way that can be done is to set the PANGO_RC_PATH
> > > envvar to a special pangorc file.  Another is to pass the
> > > --pangorc path-to-pango-rc to the examples if they understand it.
> > > What I need from libtool is to let me do one of these things in
> > > the wrapper it creates for uninstalled binaries.

[ my concerns were: we don't always build a wrapper ATM. ]

> > If we can find an answer to this question to define coherent semantics,
> > I'm all for it.

> Ok, this is my view of the problem:  Running uninstalled programs
> requires some modifications to the environment.  One is to make
> sure that the uninstalled libraries are linked.  Other changes
> may be needed, on a per application basis.  Libtool is free to
> choose how to implement these.  So far it has only supported the
> library path modification, and implemented that using a wrapper
> script on some platforms, or using rpath on others (right?)

More or less, yes.

> The same goes with the other modifications.  They can be easily
> implemented using a wrapper.  So if there are such modifications
> requested, a wrapper should be used.

Yep.  And that's really the easiest solution: as soon as extra arguments
or extra environment variables are passed, we always build a wrapper.

> My current workaround has been making pango-view accept a
> --pangorc path-to-pangorc parameter and defaulting to ./pangorc.
> But that opens up a known security problem...  So I really want
> to "fix" it the right way.

I don't quite understand how this fixes any security problems...
but here you go with a suggestion (against current CVS HEAD).


The attached patch implements two new link flags, -wrapper-arg and
-wrapper-env, to prepend arguments to programs, and modify their
environment.  They will force creating a (shell) wrapper.

Here's the hairy part about it: somebody may eventually want to extend
the C wrapper that is currently used on w32 to encompass all the
functionality that the shell wrapper currently has.  And while I don't
have current plans about this, I still don't want to add any
unnecessary obstackles to it.

So whatever we add to the shell wrapper should be doable easily in a C
wrapper as well.  This led me to add these restrictions:  the
-wrapper-env works like putenv: you pass an argument `var=value', the
variable will be exported, the value will _not_ be interpreted by the
shell any more.  For now you cannot unset variables (this is to cater
for hosts with a shell that does not support `unset'), and, e.g.,
  -wrapper-env 'foo=$bar'

will cause the environment variable `foo' to contain the four characters
$, b, a, and r, not the contents of the variable $bar.

Similarly, -wrapper-arg will add exactly one literal argument to the
exec.  I've put suitable quoting in place for this to work with most
kinds of input, and of course a test to this end.

What do you think?  OK for HEAD right now, or do you think this is too
intrusive now?

I think we should not backport this to 1.5.x, it is a new feature.

Cheers,
Ralf
        Implement setting environment variables and additional arguments
        for shell wrappers to uninstalled programs.  Using this forces
        all uninstalled programs to have wrappers.

        * libltdl/config/ltmain.m4sh (func_mode_link, shell wrapper):
        New variables `wrapper_env', `wrapper_args' for the new link flags
        `-wrapper-arg', `-wrapper-env'.  Cause a shell wrapper to always
        be created for uninstalled programs, put the wrapper_env
        variables in the environment before executing the real program,
        and add the wrapper_args as its first arguments; both with
        suitable quoting for active characters.
        (link mode help): Add the new flags.
        * doc/libtool.texi (Link mode): Document the new flags.  Note
        the override of `-no-install'.
        (Linking executables): Add cross reference to the wrapper script
        discussion.
        * tests/wrapper.at: New test.
        * NEWS, THANKS, Makefile.am: Update.
        Suggested by Behdad Esfahbod.

Index: Makefile.am
===================================================================
RCS file: /cvsroot/libtool/libtool/Makefile.am,v
retrieving revision 1.194
diff -u -r1.194 Makefile.am
--- Makefile.am 15 May 2006 16:14:24 -0000      1.194
+++ Makefile.am 20 May 2006 12:47:09 -0000
@@ -390,6 +390,7 @@
                  tests/link-order.at \
                  tests/fail.at \
                  tests/static.at \
+                 tests/wrapper.at \
                  tests/old-m4-iface.at \
                  tests/am-subdir.at \
                  tests/standalone.at \
Index: NEWS
===================================================================
RCS file: /cvsroot/libtool/libtool/NEWS,v
retrieving revision 1.194
diff -u -r1.194 NEWS
--- NEWS        15 May 2006 16:40:42 -0000      1.194
+++ NEWS        20 May 2006 12:47:09 -0000
@@ -34,6 +34,8 @@
 * Fix error with -version-info on systems with version_type=none, such
   as BeOS.
 * Initial support for the Sun compiler suite on GNU/Linux.
+* New flags -wrapper-args and -wrapper-env to force uninstalled program
+  wrappers and supply extra arguments and environment variables.
 * Bug fixes.
 
 New in 1.9f: 2004-10-23; CVS version 1.9e, Libtool team:
Index: THANKS
===================================================================
RCS file: /cvsroot/libtool/libtool/THANKS,v
retrieving revision 1.56
diff -u -r1.56 THANKS
--- THANKS      14 May 2006 08:20:11 -0000      1.56
+++ THANKS      20 May 2006 12:47:09 -0000
@@ -70,6 +70,7 @@
   Andreas Schwab               [EMAIL PROTECTED]
   Andrey Slepuhin              [EMAIL PROTECTED]
   Aneesh Kumar K.V             [EMAIL PROTECTED]
+  Behdad Esfahbod              [EMAIL PROTECTED]
   Brad Smith                   [EMAIL PROTECTED]
   Bruno Haible                 [EMAIL PROTECTED]
   Carl D. Roth                 [EMAIL PROTECTED]
Index: doc/libtool.texi
===================================================================
RCS file: /cvsroot/libtool/libtool/doc/libtool.texi,v
retrieving revision 1.215
diff -u -r1.215 libtool.texi
--- doc/libtool.texi    18 May 2006 00:10:37 -0000      1.215
+++ doc/libtool.texi    20 May 2006 12:47:10 -0000
@@ -844,6 +844,10 @@
 kilobytes.  So, having a shared @file{libhello} won't be an advantage
 until we link it against at least a few more programs.
 
+There is another point to using wrapper scripts: they allow the
+developer to pass arguments and environment variables to the uninstalled
+program (@pxref{Link mode}).
+
 @node Debugging executables
 @section Debugging executables
 
@@ -1384,7 +1388,8 @@
 
 @item -no-install
 Link an executable @var{output-file} that can't be installed and
-therefore doesn't need a wrapper script.  Useful if the program is only
+therefore doesn't need a wrapper script (unless @option{-wrapper_env}
+or @option{-wrapper-arg} are used also).  Useful if the program is only
 used in the build tree, e.g., for testing or generating other files.
 
 @item -no-undefined
@@ -1472,6 +1477,27 @@
 @itemx -Xlinker @var{flag}
 Pass a linker specific flag directly to the linker.
 
[EMAIL PROTECTED] -wrapper-arg @var{flag}
+If @var{output-file} is a program, then always create a shell wrapper script
+for the uninstalled program.  When the uninstalled program is executed through
+the wrapper, add @samp{flag} to its arguments before all user-provided 
arguments.
+Multiple @option{-wrapper-arg} arguments append more flags.
+
[EMAIL PROTECTED] -wrapper-env @var{var=value}
+If @var{output-file} is a program, then always create a shell wrapper script
+for the uninstalled program.  When the uninstalled program is executed through
+the wrapper, set environment variable @code{var} to @samp{value} for the
+execution of the uninstalled program.  The argument will not be interpreted by
+the shell, so handling is similar to the putenv function.  Multiple
[EMAIL PROTECTED] arguments append more environment variables.
+
+Typically this is used to set some path for uninstalled files or paths:
+
[EMAIL PROTECTED]
+libtool --mode=link $CC -o prog prog.lo \
+        -wrapper-env 'MYDATADIR=../data'
[EMAIL PROTECTED] example
+
 @item -XCClinker @var{flag}
 Pass a link specific flag to the compiler driver (@var{CC}) during linking.
 @end table
Index: libltdl/config/ltmain.m4sh
===================================================================
RCS file: /cvsroot/libtool/libtool/libltdl/config/ltmain.m4sh,v
retrieving revision 1.48
diff -u -r1.48 ltmain.m4sh
--- libltdl/config/ltmain.m4sh  19 May 2006 02:23:04 -0000      1.48
+++ libltdl/config/ltmain.m4sh  20 May 2006 12:55:00 -0000
@@ -383,6 +383,9 @@
   -version-info CURRENT[[:REVISION[:AGE]]]
                     specify library version info [[each variable defaults to 
0]]
   -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -wrapper-arg ARG  Prepend arguments to uninstalled program wrappers
+  -wrapper-env ENV  Add environment variables to uninstalled program wrappers
+                    (-wrapper-arg and -wrapper-env will force wrapper creation)
 
 All other options (arguments beginning with \`-') are ignored.
 
@@ -2256,6 +2259,8 @@
     vinfo=
     vinfo_number=no
     weak_libs=
+    wrapper_env=
+    wrapper_args=
     single_module="${wl}-single_module"
     func_infer_tag $base_compile
 
@@ -2531,6 +2536,24 @@
          prev=
          continue
          ;;
+       wrapper-arg)
+         case $arg in
+         *\'*) wqarg=`$ECHO "X$arg" | $Xsed -e "s/'/'\\\\\\\\''/g"` ;;
+         *) wqarg=$arg ;;
+         esac
+         wrapper_args="$wrapper_args '$wqarg'"
+         prev=
+         continue
+         ;;
+       wrapper-env)
+         wrap_var=`$ECHO "$arg" | $SED '1s/^\([[^=]]*\)=.*/\1/;q'`
+         wrap_val=`$ECHO "$arg" | $SED "1s/^[[^=]]*=//;s/'/'\\\\\\\\''/g"`
+         wrapper_env="$wrapper_env
+      $wrap_var='$wrap_val'
+      export $wrap_var"
+         prev=
+         continue
+         ;;
        xcclinker)
          linker_flags="$linker_flags $qarg"
          compiler_flags="$compiler_flags $qarg"
@@ -2879,6 +2902,16 @@
        arg=$func_stripname_result
        ;;
 
+      -wrapper-arg)
+       prev=wrapper-arg
+       continue
+       ;;
+
+      -wrapper-env)
+       prev=wrapper-env
+       continue
+       ;;
+
       -Xcompiler)
        prev=xcompiler
        continue
@@ -5701,18 +5734,20 @@
       fi
 
       wrappers_required=yes
-      case $host in
-      *cygwin* | *mingw* )
-        if test "$build_libtool_libs" != yes; then
-          wrappers_required=no
-        fi
-        ;;
-      *)
-        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
-          wrappers_required=no
-        fi
-        ;;
-      esac
+      if test -z "$wrapper_args$wrapper_env"; then
+       case $host in
+       *cygwin* | *mingw* )
+         if test "$build_libtool_libs" != yes; then
+           wrappers_required=no
+         fi
+         ;;
+       *)
+         if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+           wrappers_required=no
+         fi
+         ;;
+       esac
+      fi
       if test "$wrappers_required" = no; then
        # Replace the output file specification.
        compile_command=`$ECHO "X$compile_command" | $Xsed -e '[EMAIL 
PROTECTED]@%'"$output"'%g'`
@@ -5758,7 +5793,7 @@
        fi
       fi
 
-      if test "$no_install" = yes; then
+      if test "$no_install$wrapper_args$wrapper_env" = yes; then
        # We don't need to create a wrapper script.
        link_command="$compile_var$compile_command$compile_rpath"
        # Replace the output file specification.
@@ -6368,22 +6403,28 @@
     if test \"\$libtool_execute_magic\" != \"$magic\"; then
       # Run the actual program with our arguments.
 "
+       if test -n "$wrapper_env"; then
+         $ECHO "$wrapper_env" >> $output
+       fi
+       if test -n "$wrapper_args"; then
+         qwrapper_args=`$ECHO "X$wrapper_args" | $Xsed -e "$sed_quote_subst"`
+       fi
        case $host in
        # Backslashes separate directories on plain windows
        *-*-mingw | *-*-os2*)
          $ECHO >> $output "\
-      exec \"\$progdir\\\\\$program\" \${1+\"[EMAIL PROTECTED]"}
+      exec \"\$progdir\\\\\$program\"$wrapper_args \${1+\"[EMAIL PROTECTED]"}
 "
          ;;
 
        *)
          $ECHO >> $output "\
-      exec \"\$progdir/\$program\" \${1+\"[EMAIL PROTECTED]"}
+      exec \"\$progdir/\$program\"$wrapper_args \${1+\"[EMAIL PROTECTED]"}
 "
          ;;
        esac
        $ECHO >> $output "\
-      \$ECHO \"\$0: cannot exec \$program \$*\"
+      \$ECHO \"\$0: cannot exec \$program$qwrapper_args \$*\"
       exit 1
     fi
   else
Index: tests/testsuite.at
===================================================================
RCS file: /cvsroot/libtool/libtool/tests/testsuite.at,v
retrieving revision 1.41
diff -u -r1.41 testsuite.at
--- tests/testsuite.at  15 May 2006 16:14:24 -0000      1.41
+++ tests/testsuite.at  20 May 2006 12:47:10 -0000
@@ -139,10 +139,10 @@
 ])
 
 
-# LT_AT_EXEC_CHECK(EXECUTABLE, [STATUS = 0], [STDOUT], [STDERR])
-# --------------------------------------------------------------
+# LT_AT_EXEC_CHECK(EXECUTABLE, [STATUS = 0], [STDOUT], [STDERR], [ARGS])
+# ----------------------------------------------------------------------
 m4_define([LT_AT_EXEC_CHECK],
-[AT_CHECK([$1; lt_status=$?; if test $lt_status -eq 0; then :;
+[AT_CHECK([$1 $5; lt_status=$?; if test $lt_status -eq 0; then :;
           elif test "X$host" != "X$build" && \
                { test -x "$1" || test -x "$1"$EXEEXT; }
           then (exit 77); else (exit $lt_status); fi],[$2],[$3],[$4])
--- /dev/null   1970-01-01 00:00:01.000000000 +0200
+++ tests/wrapper.at    2006-05-20 17:23:10.000000000 +0200
@@ -0,0 +1,83 @@
+# Hand crafted tests for GNU Libtool.                         -*- Autotest -*-
+# Copyright 2006 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.
+
+AT_SETUP([wrapper flags and environment])
+AT_KEYWORDS([libtool])
+
+AT_DATA([prog.c],
+[[#include <stdio.h>
+#include <stdlib.h>
+int main(int argc, char **argv)
+{
+  int i = 1;
+  char *p = getenv ("FOO");
+  while (i < argc)
+    {
+      puts (argv[i++]);
+    }
+  printf ("FOO:%s\n", p != NULL ? p : "");
+  return 0;
+}
+]])
+
+AT_CHECK([$CC $CPPFLAGS $CFLAGS -c prog.c], [], [ignore], [ignore])
+
+# First, check to make sure our program works.
+$as_unset FOO || FOO=
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o prog prog.$OBJEXT],
+        [], [ignore], [ignore])
+LT_AT_EXEC_CHECK([./prog], [],
+[-foo
+FOO:
+], [], [-foo])
+
+# Check that -wrapper-arg works.
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -wrapper-arg -bar \
+          -wrapper-arg '-option with args  "and quotes '\'' and $special 
char\s' \
+         -o prog prog.$OBJEXT],
+        [], [ignore], [ignore])
+LT_AT_EXEC_CHECK([./prog], [],
+[-bar
+-option with args  "and quotes ' and $special char\s
+-foo
+FOO:
+], [], [-foo])
+
+# Now check that the installed program doesn't have these
+# and also (important!) that relinking is not triggered here!
+AT_CHECK([$LIBTOOL --mode=install cp prog `pwd`/prog-installed], [], [ignore])
+LT_AT_EXEC_CHECK([./prog-installed], [],
+[-foo
+FOO:
+], [], [-foo])
+
+# Check wrapper-env; also check that we override -no-install.
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS \
+         -wrapper-env 'FOO=X  "y'\'' $specia\l' -no-install -o prog 
prog.$OBJEXT],
+        [], [ignore], [ignore])
+LT_AT_EXEC_CHECK([./prog], [],
+[FOO:X  "y' $specia\l
+])
+
+AT_CHECK([$LIBTOOL --mode=install cp prog `pwd`/prog-installed], [], [ignore])
+LT_AT_EXEC_CHECK([./prog-installed], [],
+[-foo
+FOO:
+], [], [-foo])
+
+AT_CLEANUP

Reply via email to