bug-gnulib
[Top][All Lists]
Advanced

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

Re: POSIXLY_CORRECT not correctly unset in getopt.m4?


From: Eric Blake
Subject: Re: POSIXLY_CORRECT not correctly unset in getopt.m4?
Date: Tue, 07 Sep 2010 09:17:08 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100827 Red Hat/3.1.3-1.el6 Mnenhy/0.8.3 Thunderbird/3.1.3

On 09/07/2010 08:51 AM, Dustin J. Mitchell wrote:
On Tue, Sep 7, 2010 at 9:16 AM, Eric Blake<address@hidden>  wrote:
Thanks for the report.  However, I fail to see how getopt.m4 sets
POSIXLY_CORRECT in perpetuity, because it is immediately followed by
AS_UNSET if it was determined that POSIXLY_CORRECT was not set prior to the
test.  While I appreciate the patch, I'd need more convincing why your patch
helps matters, and why the existing attempt at unsetting POSIXLY_CORRECT is
not working for you.

I explained in the first email: at the beginning of the macro,

Which macro?  You didn't mention that in the first email.

POSIXLY_CORRECT is set but not exported.  As far as I can tell, this
is the normal means of operation for bash when run as /bin/sh.

Yes, /bin/sh has two namespaces - exported vs. locally-set variables, but they are inter-related, effectively making variable tracking a three-state system.

The gnulib getopt macro then sees that POSIXLY_CORRECT is set and
exports it.  *That* is the bug.

Not necessarily. Generally, POSIXLY_CORRECT should be exported (not just set), because it should affect all children, not just the parent. I'd almost argue that the bug is in the outer macro (which one?) that's setting it locally only in the first place.

 There's no portable way that I can
see to "un-export" an environment variable,

Yes there is - unset it, then reassign (but not export) it. The state transitions mandated by POSIX and honored by shells are:

undefined -> local      via assignment
undefined -> exported via export (portable), or export + assignment (required by POSIX, but not portable) local -> exported via export (portable), or export + assignment (required by POSIX, but not portable)
local -> undefined      via unset
exported -> undefined   via unset

Some shells, like bash, provide extensions like unexport to flush out the remaining transitions, but portable shell code can't rely on those.

so I chose the alternate
solution of not exporting it at all, and just setting the variable in
the C program where it is required.

But since setenv() is not portable, we'd have to make sure that the C code that plays with the variable is bullet-proof. I find it far easier to come up with a solution that works using just shell code.

Does the (minimally-tested) patch below work better for you?

Meanwhile, the only other uses of export in gnulib/m4 are:

gnulib-common.m4: LIBC_FATAL_STDERR
javaexec.m4: CLASSPATH
unlink.m4: GL_SUBDIR_FOR_UNLINK

Hopefully none of those need a similar treatment.

diff --git i/m4/getopt.m4 w/m4/getopt.m4
index caa5df4..55e6421 100644
--- i/m4/getopt.m4
+++ w/m4/getopt.m4
@@ -213,7 +213,13 @@ main ()
# optstring is necessary for programs like m4 that have POSIX-mandated
        # semantics for supporting options interspersed with files.
        # Also, since getopt_long is a GNU extension, we require optind=0.
-       gl_had_POSIXLY_CORRECT=${POSIXLY_CORRECT:+yes}
+       # Some people want to run sh in POSIX mode, but not child processes,
+       # so we must be able to revert to the correct (non-)export state.
+ case ${POSIXLY_CORRECT:+x}`/bin/sh -c 'echo ${POSIXLY_CORRECT:+x}'` in
+         xx) gl_had_POSIXLY_CORRECT=exported ;;
+         x)  gl_had_POSIXLY_CORRECT=yes      ;;
+         *)  gl_had_POSIXLY_CORRECT=         ;;
+       esac
        POSIXLY_CORRECT=1
        export POSIXLY_CORRECT
        AC_RUN_IFELSE(
@@ -278,9 +284,11 @@ main ()
            *)                   gl_cv_func_getopt_gnu=yes;;
          esac
         ])
-       if test "$gl_had_POSIXLY_CORRECT" != yes; then
-         AS_UNSET([POSIXLY_CORRECT])
-       fi
+       case $gl_had_POSIXLY_CORRECT in
+         exported) ;;
+         yes) AS_UNSET([POSIXLY_CORRECT]); POSIXLY_CORRECT=1 ;;
+         *) AS_UNSET([POSIXLY_CORRECT]) ;;
+       esac
       ])
     if test "$gl_cv_func_getopt_gnu" = "no"; then
       gl_replace_getopt=yes


--
Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library http://libvirt.org



reply via email to

[Prev in Thread] Current Thread [Next in Thread]