NetBSD Problem Report #42828

From www@NetBSD.org  Tue Feb 16 17:50:08 2010
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by www.NetBSD.org (Postfix) with ESMTP id 0EAC763C356
	for <gnats-bugs@gnats.NetBSD.org>; Tue, 16 Feb 2010 17:50:08 +0000 (UTC)
Message-Id: <20100216175005.DCB1063C142@www.NetBSD.org>
Date: Tue, 16 Feb 2010 17:50:05 +0000 (UTC)
From: rhansen@bbn.com
Reply-To: rhansen@bbn.com
To: gnats-bugs@NetBSD.org
Subject: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
X-Send-Pr-Version: www-1.0

>Number:         42828
>Category:       standards
>Synopsis:       Almquist shell always evaluates the contents of ${ENV} even if non-interactive
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    standards-manager
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Feb 16 17:55:00 +0000 2010
>Closed-Date:    Wed Dec 05 08:21:06 +0000 2018
>Last-Modified:  Wed Dec 05 08:21:06 +0000 2018
>Originator:     Richard Hansen
>Release:        5.0
>Organization:
>Environment:
NetBSD deer-netbsd.bbn.com 5.0_STABLE NetBSD 5.0_STABLE (GENERIC) #4: Tue Feb  2 10:43:58 EST 2010  gdt@fnord.ir.bbn.com:/n0/obj/gdt-5/amd64/sys/arch/amd64/compile/GENERIC amd64
>Description:
NetBSD 5.0's /bin/sh always evaluates the contents of the file identified by ${ENV} even if the shell is non-interactive.  This has a few consequences:

  * NetBSD's /bin/sh is not compliant with POSIX:2004 [1] or POSIX:2008 [2] (at least)
  * shell script execution is unnecessarily slow if the ${ENV} file does a lot of stuff
  * if the ${ENV} file executes a shell script, or executes something that executes a shell script, you'll get a fork bomb

[1] <http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_05_03>
[2] <http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03>
>How-To-Repeat:
$ printf '#!/bin/sh\necho bar\n' > bar
$ chmod a+x bar
$ echo './bar' > foo
$ ENV=$(pwd)/foo /bin/sh -i
./bar: Cannot vfork
bar
bar
bar
bar
^C
$ 
>Fix:
The following patch is completely untested (I haven't even compiled it yet).  I'm not sure when iflag is initialized, so this may not be the correct fix:


Index: bin/sh/main.c
===================================================================
RCS file: /cvsroot/src/bin/sh/main.c,v
retrieving revision 1.53
diff -u -p -r1.53 main.c
--- bin/sh/main.c	18 Jan 2009 00:30:54 -0000	1.53
+++ bin/sh/main.c	8 Feb 2010 06:08:26 -0000
@@ -184,7 +184,7 @@ state1:
 	}
 state2:
 	state = 3;
-	if (getuid() == geteuid() && getgid() == getegid()) {
+	if (iflag && getuid() == geteuid() && getgid() == getegid()) {
 		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
 			state = 3;
 			read_profile(shinit);

>Release-Note:

>Audit-Trail:
From: Christos Zoulas <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/42828 CVS commit: src/bin/sh
Date: Wed, 17 Feb 2010 10:57:24 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Wed Feb 17 15:57:24 UTC 2010

 Modified Files:
 	src/bin/sh: main.c

 Log Message:
 PR/42828: Richard Hansen: Don't evaluate ${ENV} if not interactive.
 http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03


 To generate a diff of this commit:
 cvs rdiff -u -r1.53 -r1.54 src/bin/sh/main.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: Matthew Mondor <mm_lists@pulsar-zone.net>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: PR/42828 CVS commit: src/bin/sh
Date: Wed, 17 Feb 2010 13:51:26 -0500

 On Wed, 17 Feb 2010 16:00:07 +0000 (UTC)
 Christos Zoulas <christos@netbsd.org> wrote:

 >  Modified Files:
 >  	src/bin/sh: main.c
 >  
 >  Log Message:
 >  PR/42828: Richard Hansen: Don't evaluate ${ENV} if not interactive.
 >  http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03
 >  
 >  
 >  To generate a diff of this commit:
 >  cvs rdiff -u -r1.53 -r1.54 src/bin/sh/main.c

 Thanks for the fix;

 would this be worthy of a pullup to netbsd-5*?  I've seen occasional
 user complaints about this, although if being careful and adding
 interactive-intended code inside "case "$-" in *i*)" this wasn't a
 major problem.  But I myself got bitten by this long ago when I
 switched from another shell to /bin/sh, yet I didn't know this was a
 standards compatibility issue.

 Thanks,
 -- 
 Matt

From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, standards-manager@netbsd.org, 
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, rhansen@bbn.com
Cc: 
Subject: Re: PR/42828 CVS commit: src/bin/sh
Date: Wed, 17 Feb 2010 14:25:35 -0500

 On Feb 17,  6:55pm, mm_lists@pulsar-zone.net (Matthew Mondor) wrote:
 -- Subject: Re: PR/42828 CVS commit: src/bin/sh

 | The following reply was made to PR standards/42828; it has been noted by GNATS.
 | 
 | From: Matthew Mondor <mm_lists@pulsar-zone.net>
 | To: gnats-bugs@NetBSD.org
 | Cc: 
 | Subject: Re: PR/42828 CVS commit: src/bin/sh
 | Date: Wed, 17 Feb 2010 13:51:26 -0500
 | 
 |  On Wed, 17 Feb 2010 16:00:07 +0000 (UTC)
 |  Christos Zoulas <christos@netbsd.org> wrote:
 |  
 |  >  Modified Files:
 |  >  	src/bin/sh: main.c
 |  >  
 |  >  Log Message:
 |  >  PR/42828: Richard Hansen: Don't evaluate ${ENV} if not interactive.
 |  >  http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_03
 |  >  
 |  >  
 |  >  To generate a diff of this commit:
 |  >  cvs rdiff -u -r1.53 -r1.54 src/bin/sh/main.c
 |  
 |  Thanks for the fix;
 |  
 |  would this be worthy of a pullup to netbsd-5*?  I've seen occasional
 |  user complaints about this, although if being careful and adding
 |  interactive-intended code inside "case "$-" in *i*)" this wasn't a
 |  major problem.  But I myself got bitten by this long ago when I
 |  switched from another shell to /bin/sh, yet I didn't know this was a
 |  standards compatibility issue.

 Sure thing.

 christos

From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Thu, 18 Feb 2010 05:36:43 +0700

 Note that this change makes sh fail to live up to its documentation ...

      If the environment variable ENV is set on entry to a shell, or is set in
      the .profile of a login shell, the shell next reads commands from the
      file named in ENV.  Therefore, a user should place commands that are to
      be executed only at login time in the .profile file, and commands that
      are executed for every shell inside the ENV file.  To set the ENV vari-
      able to some file, place the following line in your .profile of your home
      directory

            ENV=$HOME/.shinit; export ENV

      substituting for ``.shinit'' any filename you wish.  Since the ENV file
      is read for every invocation of the shell, including shell scripts and
      non-interactive shells, the following paradigm is useful for restricting
      commands in the ENV file to interactive invocations.  Place commands
      within the ``case'' and ``esac'' below (these commands are described
      later):

            case $- in *i*)
                  # commands for interactive use only
                  ...
            esac


 In particular, with this being a significant change, it is definitely
 not suitable for a pullup to NetBSD 5 (or any existing released system).

 Further, this is a case where sanity ought to win over standards, there's
 lots of stuff where our shell isn't the same as wha POSIX says it should
 be, some of considerably more importance than this one.

 It is trivial (as the doc says) to make the script be a no-op in
 non-interactive shells, if that's what's needed.   On the other hand,
 if ${ENV} isn't run when *every* shell starts, what is?   If there's
 nothing, ten all that's left is what's in the environment to tailor
 the shell, and not everything can be done there, and even when it can,
 passing around all kinds of shell specific noise in the environment, to
 every process that runs, isn't a sane way of operating.

 What's more, "ENV" is the name of the env var that sets the startup
 script for everthing that's a basically Bourne compatible shell (though
 that shell had no similar concept, of course) - but not all shells are
 the same, and stuff that fits one shell won't fit.  The effect of this
 is that it isn't sane to put just any random script as $ENV, the script
 needs to be aware of why it will be invoked, and in what possible
 environments, and do sane things (for which, running other shell scripts,
 without resetting ENV first, is not included).

 I'd put this pack the way it was.   Screw POSIX in this case.

 kre

From: christos@zoulas.com (Christos Zoulas)
To: gnats-bugs@NetBSD.org, standards-manager@netbsd.org, 
	gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, rhansen@bbn.com
Cc: 
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Wed, 17 Feb 2010 18:43:02 -0500

 On Feb 17, 10:50pm, kre@munnari.OZ.AU (Robert Elz) wrote:
 -- Subject: Re: standards/42828: Almquist shell always evaluates the contents

 |  I'd put this pack the way it was.   Screw POSIX in this case.
 |  
 |  kre

 I agree with Robert here and I vote to put it back.

 christos

From: Richard Hansen <rhansen@bbn.com>
To: gnats-bugs@NetBSD.org
Cc: standards-manager@netbsd.org, gnats-admin@netbsd.org, 
 netbsd-bugs@netbsd.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents
 of ${ENV} even if non-interactive
Date: Thu, 18 Feb 2010 02:14:07 -0500

 Robert Elz wrote:
 > In particular, with this being a significant change, it is definitely 
 > not suitable for a pullup to NetBSD 5 (or any existing released system).

 Agreed.

 > On the other hand, 
 > if ${ENV} isn't run when *every* shell starts, what is?   If there's 
 > nothing, ten all that's left is what's in the environment to tailor 
 > the shell, and not everything can be done there, and even when it can, 
 > passing around all kinds of shell specific noise in the environment, to 
 > every process that runs, isn't a sane way of operating.

 I agree that the POSIX design is suboptimal, but at this point there is 
 greater value in being compatible than in being right.

 Cross-platform scripts can't rely on NetBSD's nonstandard behavior, so 
 they won't take advantage of it.  NetBSD-targeted scripts that require 
 the nonstandard behavior would be better served by an extension 
 specifically for that purpose (e.g., dot ~/.nbshrc upon every shell 
 invocation).

 It would be unfortunate if an ordinary script ran everywhere except NetBSD.

 > What's more, "ENV" is the name of the env var that sets the startup 
 > script for everthing that's a basically Bourne compatible shell (though 
 > that shell had no similar concept, of course) - but not all shells are 
 > the same,  and stuff that fits one shell won't fit.  The effect of this
 > is that it isn't sane to put just any random script as $ENV,

 These are arguments for standards compliance, not against.

 > I'd put this pack the way it was.   Screw POSIX in this case.

 I think it should be kept, just not pulled into netbsd-5* in order to 
 minimize surprises.  Fixing this bug might raise some issues, but I 
 believe the long-term benefit from standards compliance will outweigh 
 the short-term pain.

 -Richard

From: Robert Elz <kre@munnari.OZ.AU>
To: Richard Hansen <rhansen@bbn.com>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org,
        netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Thu, 18 Feb 2010 19:53:25 +0700

     Date:        Thu, 18 Feb 2010 02:14:07 -0500
     From:        Richard Hansen <rhansen@bbn.com>
     Message-ID:  <4B7CE8BF.3020401@bbn.com>

   | I agree that the POSIX design is suboptimal, but at this point there is 
   | greater value in being compatible than in being right.

 In some cases I might agree, in this one, I don't.

   | Cross-platform scripts can't rely on NetBSD's nonstandard behavior,

 One of us is confused about what $ENV is for?   What scripts are ever going to
 set that (clear(unset) it perhaps, but set it?)   Particularly the way you
 expect it to work - where it applies only to interactive shells, which isn't
 something many scripts ever care about.

 Do you have a real example of something that breaks (other than a conformance 
 test) because of this?   That is, excluding user environments, we know they're
 different.

   | It would be unfortunate if an ordinary script ran everywhere except NetBSD.

 Yes, but there are thousands of scripts around, the only problems I have ever
 seen reported relate to scripts that use non-standard shell features and
 occasionally, an undisputed bug.   I've never seen a report of a problem
 that related to $ENV and a script.

   | but I believe the long-term benefit from standards compliance will outweigh 
   | the short-term pain.

 Better long term benefit would be to convince the standard to be rational.
 We don't achieve that (not any hope of achieving that) if everyone just does
 what they say because they say it, and not because it is the right thing to
 do.   Following the standards is great when it is a matter of a choice between
 two ways of which we could pick either - and sometimes when it is a matter of
 adding something that we don't really see the need for, but does no real harm
 to have - but never when their design is flawed.

 kre

From: Richard Hansen <rhansen@bbn.com>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org, 
 netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents
 of ${ENV} even if non-interactive
Date: Fri, 19 Feb 2010 14:36:53 -0500

 >> Cross-platform scripts can't rely on NetBSD's nonstandard behavior,
 > 
 > One of us is confused about what $ENV is for?   What scripts are ever going to 
 > set that (clear(unset) it perhaps, but set it?)

 My .profile sets ENV.  (By "script" I meant a file containing 
 environment setup commands.  That was not the best word to use, but I 
 couldn't think of a better word and I thought that context would make 
 the meaning clear.  I apologize for the imprecision.  In the future I'll 
 use "script" to only refer to executable files beginning with the 
 '#!/bin/sh' shebang.)

 > Particularly the way you expect it to work

 It's not just me; everyone under the impression that NetBSD conforms to 
 POSIX also expects it.

 > - where it applies only to interactive shells, which isn't 
 > something many scripts ever care about.
 > 
 > Do you have a real example of something that breaks (other than a conformance 
 > test) because of this?   That is, excluding user environments, we know they're 
 > different.

 Why exclude user environments?  The purpose of ${ENV} is to customize 
 the user's interactive shell.

 This bug broke my dot files, which is how I discovered it.  I just 
 installed NetBSD for the first time the other day, and my first 
 experience was watching it lock up after copying my dot files from a 
 Linux machine.  The freeze was thanks to a fork bomb that wouldn't have 
 happened had NetBSD's shell conformed to the POSIX spec.  Ctrl-C 
 eventually worked, but only after several minutes of unwinding the 
 process stack.

 >> but I believe the long-term benefit from standards compliance will outweigh 
 >> the short-term pain.
 > 
 > Better long term benefit would be to convince the standard to be rational.

 Good point.

 > We don't achieve that (not any hope of achieving that) if everyone just does 
 > what they say because they say it, and not because it is the right thing to 
 > do.

 Likewise, the standard won't change because the NetBSD community 
 silently resists it; someone has to fight for change.  I don't have the 
 time to champion the cause.  Would you be willing to take this up with 
 the POSIX working group?

 > Following the standards is great when it is a matter of a choice between 
 > two ways of which we could pick either - and sometimes when it is a matter of 
 > adding something that we don't really see the need for, but does no real harm 
 > to have - but never when their design is flawed.

 I agree that the POSIX design is limited relative to the NetBSD design, 
 but I would not call it flawed.  Suboptimal perhaps, but not flawed. 
 Flawed implies that there are legitimate use cases that are not 
 supported, but I have not yet come across any such use cases.  Can you 
 provide an example where a user needs ${ENV} evaluated upon invocation 
 of every non-interactive shell?

 Perhaps the flaw is in NetBSD's design:  The ${ENV} file can arbitrarily 
 modify the shell execution environment (change the working directory, 
 modify positional parameters, close file descriptors, trap signals, 
 define functions, set shell options, etc.).  This means that shell 
 script writers can't rely on a consistent initial environment.  It is 
 doubtful this would be a significant problem in practice, but in theory 
 this could lead to bugs that appear to be in a script file but are 
 actually caused by the user's ${ENV} file.


 I want to pause and wax introspective for a moment.  A number of BSD 
 fans give Linux users a hard time, but due to this bug my first 
 impression was that NetBSD is half-baked; that it fails to conform to 
 even the pedestrian parts of POSIX.  I know that bugs happen so I'm 
 willing to forgive flaws and even contribute to fixes, but only if the 
 community respectfully deals with legitimate user complaints.  The 
 antagonistic response I've received to this bug is disheartening and 
 makes me disinclined to contribute to NetBSD in the future.

 -Richard

From: Robert Elz <kre@munnari.OZ.AU>
To: Richard Hansen <rhansen@bbn.com>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org,
        netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Sun, 21 Feb 2010 20:52:23 +0700

     Date:        Fri, 19 Feb 2010 14:36:53 -0500
     From:        Richard Hansen <rhansen@bbn.com>
     Message-ID:  <4B7EE855.1050108@bbn.com>

   | My .profile sets ENV.  (By "script" I meant a file containing 
   | environment setup commands.

 Ah, OK, fine (my .profile sets ENV as well...)

   | Why exclude user environments?  The purpose of ${ENV} is to customize 
   | the user's interactive shell.

 Because it is a different degree of problem than I thought you were
 suggesting.   With the use of $ENV that we're agreeing on, you get to
 decide what's in it, and you know the environments where it will be used,
 and you can read the doc for those environments and make sure that your
 setup applies there.

 Now that you know how NetBSD applies $ENV, I would assume that you have
 no further problems - ie: for this usage, the difference from other systems
 is a minor annoyance, not a serious impediment.

 On the other hand, for "scripts" with the other (more common usage),
 the author doesn't know all the environments where the script will be
 used, and for that, it is far more important that anything that is
 reasonably relying upon some standard behaviour gets what they're expecting.

 If you had examples of the latter where NetBSD's application of $ENV
 was a problem I'd be much more tempted to agree to a change, for the sake of
 compatibility, for just user setup files, I'm not.

   | Would you be willing to take this up with the POSIX working group?

 I don't have the time either ... and in any case, I've pretty much given
 up on the current set of standards bodies - they've all become full of
 people for whom the standard is what is most important, rather than the
 systems that are built using the standard (ie: making the standard itself
 seem better looks to me to be of greater importance than making the system
 that uses the standard actually work better.)

   | Flawed implies that there are legitimate use cases that are not 
   | supported,

 flawed just implies there is a defect - something that could be improved,
 or which is less than perfect.

   | but I have not yet come across any such use cases.  Can you 
   | provide an example where a user needs ${ENV} evaluated upon invocation 
   | of every non-interactive shell?

 "of every non-interactive shell" ?  No, of course not, but that's not
 what is needed - the converse of "only used by non-interactive shells"
 is "used by at least one non-interactive shell" (ie: the opposite of
 "none" is "one" not "all").

 And that's easy - I make scripts (personal use scripts) all the time
 by simply cut and paste from my history - that is, whenever I detect that
 I'm going to re-execute a set of commands that I have done in the not
 too distant past, I assume that if I'm doing it twice, I'm going to be
 doing it again, so I simply take what I did and stick it in a script, then
 run the script.   That's a non-interactive shell running the script, and
 in order to run correctly, it needs to run with the same environment that
 my interactive shell where I first ran the commands had - that is, it
 needs to have access to whatever is in ${ENV} because my interactive shell
 had that access as well.

 And yes, of course, I can ". ${ENV}" in the script, but then I need to
 remember I have to add that, every time.

 Another use, that is less common for me, but I have done on occasion,
 is to define shell functions that replace standard commands, and either do 
 something compatible, but in a different way (like turning "rm" into
 a "mv" to a trash directory) or add trace/debugging to what is happening,
 so allow debugging of complex sets of scripts to find out just where the
 script is doing something it shouldn't be doing, and why.  For that, I
 can set ENV so a suitable environment is established for the scripts that
 I want to investigate - but only if they respect it.

   | Perhaps the flaw is in NetBSD's design:  The ${ENV} file can arbitrarily 
   | modify the shell execution environment (change the working directory, 
   | modify positional parameters, close file descriptors, trap signals, 
   | define functions, set shell options, etc.).  This means that shell 
   | script writers can't rely on a consistent initial environment.

 Huh?   They can't rely upon most of that anyway - when the shell that starts
 the script begins, the environment can be anything.   Of your list, about all
 that can't be done is trapped signals, but signals can be ignored, which is
 close enough to the same, and (I think) defined functions (or can they come 
 from the environment?), which is one of the very things I want to be able to do.

 Any of that that is important to the script needs to be explicitly either
 tested, or set, in the script, to ensure the environment is as it expects.
 Whether the change came from something done in $ENV, or was established
 before the shell running the script began is largely irrelevant.

   | It is doubtful this would be a significant problem in practice, but in
   | theory this could lead to bugs that appear to be in a script file but are 
   | actually caused by the user's ${ENV} file.

 Yes, of course it can.   If you put stuff in there that breaks things, you
 get what you deserve (just the same as if you put commands in directories early
 in your PATH with standard names but which don't do what the standard commands
 with the same names do).    You're entitled to break things if you want to.
 So is any other user.

   | but only if the 
   | community respectfully deals with legitimate user complaints.

 I agree, but you need to understand that there's more than one way to
 deal with a problem - simply making every change everyone asks for,
 regardless of whether that change makes things better or not would
 hardly be a responsible attitude, would it?   Nor does it mean that
 whatever POSIX says is necessarily correct for us.

 I don't think there's been anyone here who has been antagonistic, just
 not agreeing with what you're asking - there is a difference.

 Lastly, you're mostly just hearing from me, and I do not represent NetBSD,
 I'm just offering an opinion - what will actually happens in NetBSD will
 end up being decided by someone else.

 kre

From: Richard Hansen <rhansen@bbn.com>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org, 
 netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents
 of ${ENV} even if non-interactive
Date: Mon, 22 Feb 2010 18:07:46 -0500

 > Now that you know how NetBSD applies $ENV, I would assume that you have 
 > no further problems - ie: for this usage, the difference from other systems 
 > is a minor annoyance, not a serious impediment.

 Correct; it's an annoyance and not a serious impediment.  I'm arguing 
 for a fix to remove that annoyance.

 > If you had examples of the latter where NetBSD's application of $ENV 
 > was a problem I'd be much more tempted to agree to a change, for the sake of 
 > compatibility, for just user setup files, I'm not.

 The annoyance is the problem.  It's not a severe or urgent problem, but 
 it is a problem.

 I would like to reach consensus on whether the benefits of fixing the 
 annoyance outweigh the costs.  The benefits aren't huge because the 
 annoyance isn't huge, but I argue that the costs of fixing this are small.

 Benefits:
    * reduced risk of login shell freezes caused by fork bombs
    * faster shell invocation for scripts
    * standards compliance/meets user expectations
    * reliable initial execution environment for scripts

 Costs:
    * implementing the fix (already done)
    * backward incompatibility (only affects users that have code in 
 their ${ENV} file that is evaluated by non-interactive shells)
    * makes some tasks less convenient

 Is there anything I'm forgetting?

 > 
 >> Would you be willing to take this up with the POSIX working group?
 > 
 > I don't have the time either ... and in any case, I've pretty much given 
 > up on the current set of standards bodies - they've all become full of 
 > people for whom the standard is what is most important, rather than the 
 > systems that are built using the standard (ie: making the standard itself 
 > seem better looks to me to be of greater importance than making the system 
 > that uses the standard actually work better.)

 This criticism brings up a broader question:  How much should NetBSD 
 care about POSIX compliance?

 I agree that standards committees can sometimes fail to appreciate 
 real-world issues in their zeal to create a theoretically better world 
 (see the controversy around C++98's 'export' feature [1]), but I do 
 appreciate the uniformity and long-term perspective they provide.

 I think a POSIX violation should be classified as a bug.  It might not 
 be fixed if there isn't enough manpower or user interest, but it should 
 still be considered a bug.

 [1] <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf>

 > 
 >> Flawed implies that there are legitimate use cases that are not 
 >> supported,
 > 
 > flawed just implies there is a defect - something that could be improved, 
 > or which is less than perfect.

 I like to distinguish "design flaw" from "implementation flaw".  I 
 define a design flaw as something that precludes any implementation from 
 meeting a requirement (such as a use case that must be supported).

 I don't think there is a requirement to evaluate ${ENV} for 
 non-interactive shells.  It might be handy in some cases, but I can't 
 think of a case where it would be needed.  That's why I prefer the word 
 "suboptimal" over "flawed".

 > 
 >> but I have not yet come across any such use cases.  Can you 
 >> provide an example where a user needs ${ENV} evaluated upon invocation 
 >> of every non-interactive shell?
 > 
 > "of every non-interactive shell" ?  No, of course not, but that's not 
 > what is needed - the converse of "only used by non-interactive shells" 
 > is "used by at least one non-interactive shell" (ie: the opposite of 
 > "none" is "one" not "all").

 Let me rephrase by using an example:  Suppose a user needed to change 
 the behavior of one particular shell script.  In NetBSD, there are three 
 ways this might be done:

    1.  modify the script
    2.  via ${ENV}
    3.  change the invoker's environment (e.g., export environment 
 variables, open/close file descriptors, etc.) before running the script

 Option #1 may not be available.  Maybe the file is not writable, or 
 maybe modifications are too impractical (e.g., upgrading the package 
 providing the script will revert any changes).  Option #2 is not 
 available on other platforms and may have unintended consequences in 
 other scripts.  Option #3 may not be powerful enough.

 The big question:  Do options #1 and #3 provide enough flexibility in 
 practice?  If so, then option #2 is not needed and we should fix this 
 bug.  Certainly options #1 and #3 are insufficient in come cases, but I 
 would argue that those cases are rare and the result of an exceptional 
 flaw that should be dealt with in another way.

 > 
 > And that's easy - I make scripts (personal use scripts) all the time 
 > by simply cut and paste from my history - that is, whenever I detect that 
 > I'm going to re-execute a set of commands that I have done in the not 
 > too distant past, I assume that if I'm doing it twice, I'm going to be 
 > doing it again, so I simply take what I did and stick it in a script, then 
 > run the script.   That's a non-interactive shell running the script, and 
 > in order to run correctly, it needs to run with the same environment that 
 > my interactive shell where I first ran the commands had - that is, it 
 > needs to have access to whatever is in ${ENV} because my interactive shell 
 > had that access as well.
 > 
 > And yes, of course, I can ". ${ENV}" in the script, but then I need to 
 > remember I have to add that, every time.

 This is an example of where NetBSD's behavior is handy but not needed. 
 If this bug was fixed, you could still make your scripts work.

 For this particular example, current behavior vs. fixed is a tradeoff 
 between having to remember to add the following at the top of the ${ENV} 
 file:

    case "$-" in *i*);; *) return;; esac

 versus having the remember to add the following to the scripts:

    [ -r "${ENV}" ] && . "${ENV}"

 Either one is annoying, but fixing it is standards compliant and won't 
 cause your login shell to lock up if you forget the magic line.

 > 
 > Another use, that is less common for me, but I have done on occasion, 
 > is to define shell functions that replace standard commands, and either do 
 > something compatible, but in a different way (like turning "rm" into 
 > a "mv" to a trash directory) or add trace/debugging to what is happening, 
 > so allow debugging of complex sets of scripts to find out just where the 
 > script is doing something it shouldn't be doing, and why.  For that, I 
 > can set ENV so a suitable environment is established for the scripts that 
 > I want to investigate - but only if they respect it.

 This is another example of where NetBSD's behavior is handy but not 
 needed.  The same results can be achieved by prepending a special 
 directory to PATH and populating that directory with custom versions of 
 standard commands.

 > 
 >> Perhaps the flaw is in NetBSD's design:  The ${ENV} file can arbitrarily 
 >> modify the shell execution environment (change the working directory, 
 >> modify positional parameters, close file descriptors, trap signals, 
 >> define functions, set shell options, etc.).  This means that shell 
 >> script writers can't rely on a consistent initial environment.
 > 
 > Huh?   They can't rely upon most of that anyway - when the shell that starts 
 > the script begins, the environment can be anything.

 You're right about file descriptors, but the others have well-defined 
 initial values.  Changing them in ${ENV} could cause problems.  Here are 
 some (somewhat silly) examples to illustrate the potential danger:

    * working directory:  Initially the current directory matches the 
 working directory of the invoker.  If the user adds 'cd "${HOME}"' to 
 the ${ENV} file, then every shell script will assume it was invoked from 
 ${HOME}.

    * positional parameters:  Initially the positional parameters match 
 the command line arguments passed by the invoker.  If the user adds 
 'shift' somewhere in the ${ENV} file, all shell scripts will ignore the 
 first command line argument.

    * shell options:  Initially they're all turned off.  If the user adds 
 'set -C' to ${ENV}, '>' will no longer work as expected for every shell 
 script.

 > Any of that that is important to the script needs to be explicitly either 
 > tested, or set, in the script, to ensure the environment is as it expects.  

 Shell scripts could use $- to test for sane shell options, but none of 
 them do.  (Why would they?  The POSIX spec says they're all turned off 
 by default.)  Shell scripts can't tell if the current working directory 
 or positional parameters were modified so there's nothing to test or set.

 >> It is doubtful this would be a significant problem in practice, but in 
 >> theory this could lead to bugs that appear to be in a script file but are 
 >> actually caused by the user's ${ENV} file.
 > 
 > Yes, of course it can.   If you put stuff in there that breaks things, you 
 > get what you deserve (just the same as if you put commands in directories early 
 > in your PATH with standard names but which don't do what the standard commands 
 > with the same names do).    You're entitled to break things if you want to.  
 > So is any other user.

 If a user's ${ENV} file follows the POSIX spec, it is reasonable for the 
 user to expect it to work; the user doesn't "deserve" to have the login 
 shell lock up.

 > 
 >> but only if the 
 >> community respectfully deals with legitimate user complaints.
 > 
 > I agree, but you need to understand that there's more than one way to 
 > deal with a problem - simply making every change everyone asks for, 
 > regardless of whether that change makes things better or not would 
 > hardly be a responsible attitude, would it?   Nor does it mean that 
 > whatever POSIX says is necessarily correct for us.

 I do not mean for respect to entail capitulation, only that the tone be 
 professional and not condescending or dismissive.

 -Richard

From: Robert Elz <kre@munnari.OZ.AU>
To: Richard Hansen <rhansen@bbn.com>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org,
        netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Tue, 23 Feb 2010 21:30:38 +0700

     Date:        Mon, 22 Feb 2010 18:07:46 -0500
     From:        Richard Hansen <rhansen@bbn.com>
     Message-ID:  <4B830E42.9060504@bbn.com>

   | I would like to reach consensus on whether the benefits of fixing the 
   | annoyance outweigh the costs.

 Yes, that would be good - and that's never going to happen as long as it is
 just the two of us having this discussion, so after this message I'm going to
 leave it for others to give an opinion, and will (probably) say no more.

   | This criticism brings up a broader question:  How much should NetBSD 
   | care about POSIX compliance?

 I suspect my opinion on that one is clear, so I'll dodge that bullet...

   | I like to distinguish "design flaw" from "implementation flaw".

 That's reasonable, but I'm not sure it is material.

   | I don't think there is a requirement to evaluate ${ENV} for 
   | non-interactive shells.

 My take is that if ${ENV} isn't wanted for non-interactive shells, it can
 make itself a no-op.   On the other hand, if it is, other than adding some
 other way to do the same thing to the shell, there is no remedy.

   | Let me rephrase by using an example:  Suppose a user needed to change 
   | the behavior of one particular shell script.  In NetBSD, there are three 
   | ways this might be done:
   | 
   |    1.  modify the script
   |    2.  via ${ENV}
   |    3.  change the invoker's environment (e.g., export environment 
   | variables, open/close file descriptors, etc.) before running the script
   | 
   | Option #1 may not be available.  Maybe the file is not writable, or 
   | maybe modifications are too impractical (e.g., upgrading the package 
   | providing the script will revert any changes).

 Yes, and in cases that sometimes matter, it isn't clear which script needs
 to be modified in any case - the whole point of using ${ENV} is so the
 modifications apply to every script, which might then allow the actual
 change that's needed to be detected.

   | The big question:  Do options #1 and #3 provide enough flexibility in 
   | practice?

 No, or not without considerable work (one can always replace /bin/sh
 with something else, that does whatever is required, and then exec's the
 real /bin/sh from its new location - but that's rarely convenient...)

   | Certainly options #1 and #3 are insufficient in come cases, but I 
   | would argue that those cases are rare and the result of an exceptional 
   | flaw that should be dealt with in another way.

 What other way?

   | This is an example of where NetBSD's behavior is handy but not needed. 
   | If this bug was fixed, you could still make your scripts work.

 Yes, but ...

   | For this particular example, current behavior vs. fixed is a tradeoff 
   | between having to remember to add the following at the top of the ${ENV} 
   | file:
   | 
   |    case "$-" in *i*);; *) return;; esac
   | 
   | versus having the remember to add the following to the scripts:
   | 
   |    [ -r "${ENV}" ] && . "${ENV}"
   | 
   | Either one is annoying, but fixing it is standards compliant and won't 
   | cause your login shell to lock up if you forget the magic line.

 My login shell (nor any other shell) has never locked up, so that isn't
 a problem I'm particularly worried about - perhaps just because I'm a little
 more conservative about what I have the shell do in ${ENV}

 But for those two remedies, the former (modifying ${ENV}) you do exactly
 once (once in all time) - the other (adding a line to the script) needs to
 be repeated for every script that is created, which can be several times
 a day.

 That is, this is hardly a "add a line here vs add a line there, which is
 better?" debate (if it were, that's exactly the kind of place where following
 the standards - ie: doing what others have already decided is best - is the
 better way).   The alternatives you're suggesting are not comparable that
 way however, there's a big difference between a one off, and a repeat forever. 

   | This is another example of where NetBSD's behavior is handy but not 
   | needed.  The same results can be achieved by prepending a special 
   | directory to PATH and populating that directory with custom versions of 
   | standard commands.

 No, that doesn't work, built in commands are executed before commands
 found in $PATH, so that doesn't work to override stuff like test, let
 alone the built in commands that can't go in $PATH (like cd) which happens
 to be one of the commands I most often want to override.   That can be
 done by defining a cd() function, and that works in ${ENV}.

   |    * working directory:  Initially the current directory matches the 
   | working directory of the invoker.  If the user adds 'cd "${HOME}"' to 
   | the ${ENV} file, then every shell script will assume it was invoked from 
   | ${HOME}.

 Of course, and it would be, and if that's what the user wanted to happen
 (which we can assume they must have when they put that in ${ENV}) then
 what's the problem?   If that causes things to break, the user who added
 the cd can remove it (or make it conditional).

   |    * positional parameters:  Initially the positional parameters match 
   | the command line arguments passed by the invoker.  If the user adds 
   | 'shift' somewhere in the ${ENV} file, all shell scripts will ignore the 
   | first command line argument.

 But those parameters all depend upon how the script is invoked anyway?
 I can just invoke any script without its first parameter, can't I?
 The script needs to handle that possibility in some rational way, and if
 it does that, then I don't see that it matters that ${ENV} could do the
 same thing (though in normal circumstances, I don't really see that
 as a problem I'd typically worry about - that is, I don't think it's
 very likely that a normal ${ENV} will just randomly decide that a shift
 or two might be nice...)

 On the other hand, the ability to rearrange parameters allows for version
 shift variances to be handled: if you have two packages X and Y. where X
 needs stuff from Y, upgrades are available for both, and the new X wants
 the new Y, but while you need the new X (bug fixes, or new features) you
 don't want the new Y (platform not supported, or has new bugs that break
 your work, or just cost) then you might (OK, it is a stretch) be able to
 massage the exec from X into a script from Y to rearrange the args to
 be what the older Y expects rather than what the newer X is handing it.

 Perhaps not very plausible, but it is the kind of thing that only works when
 it is possible to alter the environment of every script that runs.

   |    * shell options:  Initially they're all turned off.  If the user adds 
   | 'set -C' to ${ENV}, '>' will no longer work as expected for every shell 
   | script.

 And if I run the script as "sh -C script" ???
 Or for that matter, if I run the script as "sh -i script" ?

 Options are only all off initially if the script is invoked as "./script"
 (or whatever) and even that's only true if the #! line doesn't set any

 	#! /bin/sh -C

 should work (but that's not relevant to our discussion).

   | Shell scripts could use $- to test for sane shell options, but none of 
   | them do.  (Why would they?  The POSIX spec says they're all turned off 
   | by default.)

 By default, yes, but the script is not required to be run "by default".
 And while I totally understand that there's no particularly good reason
 that a script author needs to necessarily anticipate some idiot running
 a script with "sh -C script" when the script doesn't expect noclobber mode,
 there's also no real reason to anticipate that someone will do set -C
 in ${ENV} (outside a test for an interactive shell).

   | Shell scripts can't tell if the current working directory 
   | or positional parameters were modified so there's nothing to test or set.

 They cannot tell that they were modified, but nor can they control the
 environment from which they were invoked.   If a script needs to be in
 a particular directory, or to have some options set, or reset, it needs
 to make those things happen itself.   It always needs to test its parameters
 for sanity (correct number, types, ...)   If a script just wants to operate
 upon whatever happens to be ${PWD} when it starts, it should just do that,
 and whether that was altered as a result of
 	(cd /some/where && ./script)
 or as a result of
 	case "$0" in script) cd /some/where;; esac
 in $ENV shouldn't matter very much, should it?

   | If a user's ${ENV} file follows the POSIX spec,

 Local system documentation trumps the POSIX spec every time.   Remember
 here you're asking for NetBSD to alter its documented behaviour, not to
 alter the way some undocumented event is handled, nor to actually comply
 with what it documents about itself.

   | I do not mean for respect to entail capitulation, only that the tone be 
   | professional and not condescending or dismissive.

 I apologise if I ever sounded condescending, that wasn't the intent.
 However, I don't think your proposal should be implemented, so dismissive,
 yes - but that's just me, and I have nothing more than an opinion here,
 nothing I can do can do more than perhaps influence others (I don't get to
 make the change, or prevent it.)

 kre

 ps: If there's anyone else bothering to read all of this stuff, sometime
 around now would be a good time to offer opinions.

From: Bernd Ernesti <netbsd@lists.veego.de>
To: gnats-bugs@NetBSD.org
Cc: Robert Elz <kre@munnari.OZ.AU>
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Tue, 23 Feb 2010 18:35:19 +0100

 On Tue, Feb 23, 2010 at 09:30:38PM +0700, Robert Elz wrote:
 [..]

 > ps: If there's anyone else bothering to read all of this stuff, sometime
 > around now would be a good time to offer opinions.

 It would be nice to have a summary on tech-userlevel@NetBSD.org and not in
 a pr.

 Bernd

From: matthew green <mrg@eterna.com.au>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org,
    netbsd-bugs@NetBSD.org, Richard Hansen <rhansen@bbn.com>
Subject: re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Wed, 24 Feb 2010 08:12:52 +1100


    ps: If there's anyone else bothering to read all of this stuff, sometime
    around now would be a good time to offer opinions.

 i dunno about all this stuff, but i'm glad that christos has changed
 our /bin/sh back to how it was, but made it handle POSIXLY_CORRECT.


 .mrg.

From: Richard Hansen <rhansen@bbn.com>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: gnats-bugs@NetBSD.org, standards-manager@NetBSD.org, 
 netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents
 of ${ENV} even if non-interactive
Date: Wed, 24 Feb 2010 00:37:55 -0500

 >> The same results can be achieved by prepending a special 
 >> directory to PATH and populating that directory with custom versions of 
 >> standard commands.
 > 
 > No, that doesn't work, built in commands are executed before commands 
 > found in $PATH, so that doesn't work to override stuff like test, let 
 > alone the built in commands that can't go in $PATH (like cd) which happens 
 > to be one of the commands I most often want to override.   That can be 
 > done by defining a cd() function, and that works in ${ENV}.

 Ah ha!  That's what I was looking for.  I can see how overriding 
 built-ins could be useful, and the POSIX design makes it impossible. 
 Now I see the benefit of evaluating a file at the start of 
 non-interactive shells (I just couldn't think of a practical use for the 
 non-standard behavior).

 So, my opinion is that NetBSD's functionality should be preserved, just 
 moved elsewhere (such as a different environment variable) so that it 
 doesn't conflict with POSIX.

 >>    * working directory:  Initially the current directory matches the 
 >> working directory of the invoker.  If the user adds 'cd "${HOME}"' to 
 >> the ${ENV} file, then every shell script will assume it was invoked from 
 >> ${HOME}.
 > 
 > Of course, and it would be, and if that's what the user wanted to happen 
 > (which we can assume they must have when they put that in ${ENV}) then 
 > what's the problem?

 I'm coming from the perspective of users that expect POSIX compliance. 
 They might add 'cd "${HOME}"' not realizing that it also affects shell 
 scripts.

 > there's also no real reason to anticipate that someone will do set -C 
 > in ${ENV} (outside a test for an interactive shell).

 I think there is a reason:  users like me that assume POSIX compliance 
 and fail to test for an interactive shell.  They might not realize that 
 errors in 3rd party scripts are their fault.  They might not even see 
 the errors if the script is executed by an X application.

 > Local system documentation trumps the POSIX spec every time.

 Good point.  But aren't users expecting POSIX more and more?  Perhaps 
 it's time to take another small step toward compliance.

 -Richard

From: David Laight <david@l8s.co.uk>
To: Richard Hansen <rhansen@bbn.com>
Cc: Robert Elz <kre@munnari.OZ.AU>, gnats-bugs@NetBSD.org,
	standards-manager@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Wed, 24 Feb 2010 20:44:36 +0000

 On Wed, Feb 24, 2010 at 12:37:55AM -0500, Richard Hansen wrote:
 > >
 > >No, that doesn't work, built in commands are executed before commands 
 > >found in $PATH, so that doesn't work to override stuff like test, let 
 > >alone the built in commands that can't go in $PATH (like cd) which happens 
 > >to be one of the commands I most often want to override.   That can be 
 > >done by defining a cd() function, and that works in ${ENV}.
 > 
 > Ah ha!  That's what I was looking for.  I can see how overriding 
 > built-ins could be useful, and the POSIX design makes it impossible. 
 > Now I see the benefit of evaluating a file at the start of 
 > non-interactive shells (I just couldn't think of a practical use for the 
 > non-standard behavior).

 Actually, for non-special builtins, posix requires that the builtin version
 only be used if the one that would be executed when $PATH is searched
 would be the systems 'standard' version.
 Which would mean that the builtin 'echo' could only be used if the
 shells command hash table contained /usr/bin/echo.
 Netbsd's /bin/sh doesn't behave that way!
 (and I'm not going to change it!)

 	David

 -- 
 David Laight: david@l8s.co.uk

From: Richard Hansen <rhansen@bbn.com>
To: Richard Hansen <rhansen@bbn.com>, Robert Elz <kre@munnari.OZ.AU>, 
 gnats-bugs@NetBSD.org, standards-manager@NetBSD.org, 
 netbsd-bugs@NetBSD.org, david@l8s.co.uk
Cc: 
Subject: Re: standards/42828: Almquist shell always evaluates the contents
 of ${ENV} even if non-interactive
Date: Wed, 24 Feb 2010 17:20:56 -0500

 David Laight wrote:
 > Actually, for non-special builtins, posix requires that the builtin version 
 > only be used if the one that would be executed when $PATH is searched 
 > would be the systems 'standard' version.

 I'm not 100% sure that's true...  I stared at the "Command Search and 
 Execution" section [1] for a while (it's not easy to grok!) and came 
 away with the impression that if the system had echo as a regular 
 built-in, the built-in would be invoked instead of ~/bin/echo even if 
 ~/bin was first in PATH.

 Here's how I interpret the logic:
    1.  'echo' doesn't contain any slashes, so rule 1. applies
    2.  echo is not a special built-in, so rule 1.a. doesn't apply
    3.  there is no function named echo, so rule 1.b. doesn't apply
    4.  echo is not in the exception list, so 1.c. doesn't apply
    5.  rule 1.d. applies and the PATH is searched for echo
    6.  echo is in the PATH (in ~/bin), so rule 1.d.i. applies
    7.  echo is implemented as a regular built-in, so rule 1.d.i.a. 
 applies and the built-in version is invoked

 I hope I'm misunderstanding POSIX because I'd prefer the algorithm you 
 described.

 On a related note:  It's unclear what POSIX says should happen if a user 
 defines a function whose name matches the name of a regular built-in 
 (e.g., 'cd' or 'echo').  Specifically, rule 1.b. is awkward:  Either the 
 shell must be able to distinguish implementation-provided functions from 
 user-defined functions (my interpretation) or it's undefined which one 
 wins (rule 1.d.i.a. doesn't break ties between regular built-ins and 
 shell functions).

 [1] 
 <http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01_01>

 -Richard

From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: standards/42828: Almquist shell always evaluates the contents
	of ${ENV} even if non-interactive
Date: Sun, 28 Feb 2010 23:27:51 +0000

 On Wed, Feb 24, 2010 at 10:25:03PM +0000, Richard Hansen wrote:
  >  I hope I'm misunderstanding POSIX because I'd prefer the algorithm you 
  >  described.

 There are lots of things wrong with POSIX; it would be nice in theory
 (although I doubt anyone reading this has the time or energy) to
 collect them up somewhere for reference.

 The shell-related thing I've run across is that the behavior
 specification for -e mode is so poorly written that it's nearly
 impossible to tell what it's supposed to be, let alone test any given
 implementation for conformance. And some of the parts that are clear
 are at variance with common sense and historical practice.

 NetBSD is in general more committed to maintaining historical practice
 (and to correctness) than to strict compliance. And since the POSIX
 folks seem to be running somewhat off the track lately (e.g. on
 getline) I suspect that we will start to diverge somewhat more from
 conformance too...

 -- 
 David A. Holland
 dholland@netbsd.org

From: "Greg A. Woods" <woods@planix.ca>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: Richard Hansen <rhansen@bbn.com>,
	NetBSD GNATS <gnats-bugs@NetBSD.org>,
	standards-manager@NetBSD.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Wed, 03 Mar 2010 14:18:10 -0500

 --pgp-sign-Multipart_Wed_Mar__3_14:18:10_2010-1
 Content-Type: text/plain; charset=US-ASCII
 Content-Transfer-Encoding: quoted-printable

 At Tue, 23 Feb 2010 21:30:38 +0700, Robert Elz <kre@munnari.OZ.AU> wrote:
 Subject: Re: standards/42828: Almquist shell always evaluates the contents =
 of ${ENV} even if non-interactive
 >=20
 > ps: If there's anyone else bothering to read all of this stuff, sometime
 > around now would be a good time to offer opinions.

 I haven't caught up to the full discussion yet, but I've skimmed through
 and I'd like to offer a few of my observations of related issues gleaned
 over the past 20 years or so.  :-)

 > My take is that if ${ENV} isn't wanted for non-interactive shells, it can
 > make itself a no-op.   On the other hand, if it is, other than adding some
 > other way to do the same thing to the shell, there is no remedy.

 I think this is sort of the way it was originally intended, if I
 understand correctly, and if I understand all the history and lore
 correctly too.

 I've had the following in my ~/.kshlogin file for some time now, which
 sets ENV in such a way that it will only be the appropriate filename IFF
 the shell is running in interactive mode.  Some comments and
 explanations are included.

 Unfortunately this does not, or at least did not, work with /bin/sh (due
 to lack of support for arrays), but perhaps it should (support arrays,
 that is, despite them not being required by POSIX).  In fact I think the
 failure of POSIX to also include arrays in the shell is one of the
 reasons why the definition of ENV got bunged up, since without arrays
 the shell cannot support the de facto standard way of managing
 interactive vs. non-interactive ENV variants.

 See also my PR#33693.

 Note that my ~/.profile sources an appropriately named ~/.*login file
 based on what it thinks the type of shell being used is.  Thus=20

 if [ ${RANDOM:-0} -ne ${RANDOM:-0} -a -z "${BASH}" ] ; then
 	# TODO: try to remember why we don't trust this...
 	SHELL=3D""
 	[ -x $PKG/bin/ksh ] && export SHELL=3D"$PKG/bin/ksh"
 	[ -x $CONTRIB/bin/ksh ] && export SHELL=3D"$CONTRIB/bin/ksh"
 	[ -x $LOCAL/bin/ksh ] && export SHELL=3D"$LOCAL/bin/ksh"
 	[ -z "$SHELL" -a -x /usr/bin/ksh ] && export SHELL=3D"/usr/bin/ksh"
 	[ -z "$SHELL" -a -x /bin/ksh ] && export SHELL=3D"/bin/ksh"
 	if [ -r $HOME/.kshlogin ] ; then
 		. $HOME/.kshlogin
 	fi
 elif ....


 #
 #	.kshlogin - login shell startup for ksh
 #
 #ident	"@(#)HOME:.kshlogin	29.1	09/04/09 20:45:32 (woods)"

 set -o ignoreeof	# we only do this for our login shell....

 export FPATH=3D$HOME/lib/ksh

 # this may be a good idea (from Frederick Bruckman <fredb@immanent.net>)
 #
 #for func in $(ls "$FPATH"); do
 #	autoload $func
 #done

 export FCEDIT=3D"$(whence ed)"

 export ENVFILE=3D$HOME/.kshrc

 if [ -n "$ENVFILE" -a -r "$ENVFILE" ] ; then
 	#
 	# This magic expression prevents a non-interactive Ksh
 	# instance from even trying to open and read any file.
 	#
 	# The original Korn & Bolsky book [1989] suggests....
 	#
 	#export ENV=3D'${ENVFILE[(_$-=3D0)+(_=3D1)-_${-%%*i*}]}'
 	#
 	# However the expression below is better as it handles the
 	# empty $- case, which the one above fails on (0+1-1 =3D 0).
 	#
 	# According to a post by Jon H. LaBadie to comp.unix.questions
 	# on 1989/12/06 (with the Message-ID <826@jonlab.UUCP>) the
 	# one below is what David Korn actually suggested to him.  I'm
 	# reasonably certain I read a post by Korn suggesting this
 	# expression as well, but I may simply have read Jon's post.
 	#
 	# It does work with all the versions of Ksh I've run across,
 	# including ksh-85 and the one AIX-3.2, as well as pdksh.
 	#
 	export ENV=3D'${ENVFILE[(_$-=3D1)+(_=3D0)-(_$-!=3D_${-%%*i*})]}'

 	# The following explanation is derived from a Usenet post by
 	# David Young to comp.sys.apollo (of all places) 1992/10/21:
 	#
 	# The idea behind this scheme is to set up an array (ENVFILE)
 	# whose first element is the file we want executed at startup,
 	# and whose second element is empty.  Note that any string
 	# variable can be accessed as an array with one element in the
 	# first (zero) position and any attempt to access other
 	# elements will result in an empty value.
 	#
 	#	$ export ENVFILE=3D'~/.envfile'
 	#	$ echo $ENVFILE[0]
 	#	~/.envfile
 	#	$ echo $ENVFILE[1]
 	#=09
 	#	$=20
 	#
 	# So, we want to expand $ENV, when it is referenced by the
 	# shell during startup, to ENVFILE[0] for interactive shells
 	# and to ENVFILE[1] for non-interactive shells.  To do this we
 	# need an expression that will evaluate to "0" for an
 	# interactive shell but which will evaluate to "1" for a
 	# non-interactive shell.
 	#
 	# Keep in mind the two environment variables ENV and PS1 are
 	# special in Ksh insofar as they get evaluated when they are
 	# used!  So if we assign the value of ENV using single quotes
 	# as a fixed string it will only be evaluated when it is used
 	# by the shell.
 	#
 	# Also remember that arithmetic expressions are evaluated
 	# inside array index references (i.e. inside the square
 	# brackets), but only after '$' variable refs are expanded.
 	#
 	# The flags variable ($-) is the key to forming our magic
 	# expression.  If the shell is interactive, the flags will
 	# contain an 'i'.  The expression used as the index consists
 	# of three parts that are combined using normal arithmetic
 	# operators to form the final index value:
 	#
 	#	(_$-=3D1) + (_=3D0) - (_$- !=3D _${-%%*i*})
 	#
 	# (_$-=3D1)	This creates a variable named "_BLAH", where
 	#		"BLAH" is the value of the variable "$-", and
 	#		assigns it the value "1".  The expression has
 	#		the result "1" as well.
 	#
 	# (_=3D0)		This creates a variable named "_" and assigns
 	#		it the value "0".  The expression has the result
 	#		"0" as well.
 	#
 	# (_$- !=3D _${-%%*i*})	This compares the value of _BLAH with
 	#			the value of another variable that
 	#			will either have the same name (and
 	#			thus the same value), or the name "_".
 	#
 	# For an interactive shell these variables will be guaranteed
 	# to have different names, i.e. the first variable will have
 	# the name of the variable created in the first expression
 	# ("_BLAH") and the second will have name of the variable
 	# created in the second expression ("_"), respectively.  Since
 	# the first variable has been assigned the value "1" and the
 	# second one has the value "0", result of this last expression
 	# will always be 1 for any interactive shell.
 	#
 	# For a non-interactive shell this last expression will have
 	# the value 0 because both parameters will have the same name
 	# (there was no "i" to match when forming the name of the
 	# second var, regardless of whether $- is empty or not).
 	#
 	# So for an interactive shell, e.g. when $- is "i", the index is:
 	#
 	#	(_i=3D1) + (_=3D0) - (_i !=3D _)
 	#	 1     +  0    - (1 !=3D 0)
 	#	i.e. 0, thus $ENV[0], for the first and only element
 	#
 	# and for a non-interactive shell (e.g. $i is "BLAH") the index is:
 	#
 	#	(_BLAH=3D1) + (_=3D0) - (_BLAH !=3D _BLAH)
 	#	 1        +  0    - (0 !=3D 0)
 	#	i.e. 1, thus $ENV[1], for the second, empty, element
 	#
 	# or for a non-interactive shell where $i is "", the index is:
 	#
 	#	(_=3D1) + (_=3D0) - (_ !=3D _)
 	#	 1     +  0   - (0 !=3D 0)
 	#	i.e. 1, thus $ENV[1], for the second, empty, element
 	#
 	# Remember class, the test is tomorrow!
 fi

 export HISTSIZE=3D2000

 # we could set HISTFILE if we wanted persistent history, but we may
 # only want it for login shells, not all interactive shells....
 #
 # NOTE:  many implementations have HISTFILE inter-locking bugs!
 #
 #HISTFILE=3D$HOME/.ksh_history

 if [ -z "$LOGNAME" ] ; then
 	# some systems won't allow this...
 	export LOGNAME=3D${HOME##*/}
 fi

 # for emacs timeclock.el
 #
 if [ ! -f ~/.timelog ] ; then
 	touch ~/.timelog
 fi

 # note this depends on and requires the "cd" at the end of ~/.profile
 #
 export PWD=3D$HOME
 export OLDPWD=3D$HOME

 --=20
 						Greg A. Woods
 						Planix, Inc.

 <woods@planix.com>       +1 416 218 0099        http://www.planix.com/

 --pgp-sign-Multipart_Wed_Mar__3_14:18:10_2010-1
 Content-Type: application/pgp-signature
 Content-Transfer-Encoding: 7bit

 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.9 (NetBSD)

 iD8DBQBLjrXyZn1xt3i/9H8RArxDAKDVv7k93f+57bYehaFebDVdsE1UWwCgutOS
 Rcia2aEzpON+iilR+VVKWfs=
 =eOfT
 -----END PGP SIGNATURE-----

 --pgp-sign-Multipart_Wed_Mar__3_14:18:10_2010-1--

From: "Greg A. Woods" <woods@planix.ca>
To: gnats-bugs@NetBSD.org
Cc: standards-manager@netbsd.org,
	rhansen@bbn.com
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Wed, 03 Mar 2010 14:41:25 -0500

 --pgp-sign-Multipart_Wed_Mar__3_14:41:25_2010-1
 Content-Type: text/plain; charset=US-ASCII
 Content-Transfer-Encoding: quoted-printable

 At Wed,  3 Mar 2010 19:20:03 +0000 (UTC), "Greg A. Woods" <woods@planix.ca>=
  wrote:
 Subject: Re: standards/42828: Almquist shell always evaluates the contents =
 of ${ENV} even if non-interactive
 >=20
 >  Unfortunately this does not, or at least did not, work with /bin/sh (due
 >  to lack of support for arrays), but perhaps it should (support arrays,
 >  that is, despite them not being required by POSIX).  In fact I think the
 >  failure of POSIX to also include arrays in the shell is one of the
 >  reasons why the definition of ENV got bunged up, since without arrays
 >  the shell cannot support the de facto standard way of managing
 >  interactive vs. non-interactive ENV variants.

 Perhaps I should be more clear that the advantage to the trick using
 arrays in KSH is the following:

 >  	# This magic expression prevents a non-interactive Ksh
 >  	# instance from even trying to open and read any file.

 This same advantage is preserved with the strict POSIX requirements for
 $ENV, but it is lost entirely in NetBSD (at least without the recent fix
 and without POSIXLY_CORRECT being set).

 Worse, with default NetBSD behaviour not only must the shell try to open
 the file referenced by $ENV, it must also read possibly the entire
 contents and, if I'm not mistaken, parse much of what it reads as well.

 At least the POSIX requirement maintained the efficiency of not using
 $ENV for non-interactive shells, though it also destroys the possibility
 of using $ENV for non-interactive shells.

 With arrays both possibilities are easily and compatibly (to KSH at
 least, and perhaps Bash too) maintained without any necessary sacrifice
 to efficiency.

 --=20
 						Greg A. Woods
 						Planix, Inc.

 <woods@planix.com>       +1 416 218 0099        http://www.planix.com/

 --pgp-sign-Multipart_Wed_Mar__3_14:41:25_2010-1
 Content-Type: application/pgp-signature
 Content-Transfer-Encoding: 7bit

 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.9 (NetBSD)

 iD8DBQBLjrtlZn1xt3i/9H8RAlWBAKDTF24+npxK2O74K2JPfLNui8/cgACfblIb
 7TikiT8LTIakGBLzW4gwYRs=
 =6l6y
 -----END PGP SIGNATURE-----

 --pgp-sign-Multipart_Wed_Mar__3_14:41:25_2010-1--

From: Richard Hansen <rhansen@bbn.com>
To: "Greg A. Woods" <woods@planix.ca>
Cc: gnats-bugs@NetBSD.org, standards-manager@netbsd.org
Subject: Re: standards/42828: Almquist shell always evaluates the contents
 of ${ENV} even if non-interactive
Date: Wed, 03 Mar 2010 15:39:54 -0500

 Greg A. Woods wrote:
 > With arrays both possibilities are easily and compatibly (to KSH at 
 > least, and perhaps Bash too) maintained without any necessary sacrifice 
 > to efficiency.

 I'm not sure I understand...  Are you suggesting that ${ENV[0]} (or the 
 equivalent ${ENV}) be used for interactive shells and ${ENV[1]} be used 
 for non-interactive shells?

 If so, I like it.  It's POSIX compliant and it allows us to maintain 
 NetBSD's functionality (but not backward compatibility) without having 
 to come up with a new environment variable that could collide with 
 someone else.

 Plus it would mean arrays.  :)  Lack of arrays is my biggest gripe with 
 the POSIX shell spec ("set -e" ambiguity is a close second).  However, 
 adding array support would be a *huge* change.  It'd be a challenge to 
 get community buy-in.

 -Richard

From: David Laight <david@l8s.co.uk>
To: gnats-bugs@NetBSD.org
Cc: standards-manager@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org, rhansen@bbn.com
Subject: Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive
Date: Wed, 3 Mar 2010 21:21:20 +0000

 On Wed, Mar 03, 2010 at 08:40:03PM +0000, Richard Hansen wrote:
 >  
 >  Plus it would mean arrays.  :)  Lack of arrays is my biggest gripe with 
 >  the POSIX shell spec ("set -e" ambiguity is a close second).  However, 
 >  adding array support would be a *huge* change.  It'd be a challenge to 
 >  get community buy-in.

 Especially since, to a large extent, they can be simulated using eval.

 	David

 -- 
 David Laight: david@l8s.co.uk

State-Changed-From-To: open->closed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Wed, 05 Dec 2018 08:21:06 +0000
State-Changed-Why:
It has been over 8 years now, and nothing else has changed, nor
(as best I can tell) have there been more complaints about the
NetBSD behaviour.

Unlike when the original discussion was held, I am now in a position
where I could change things, but I am no more inclined to now than
I was (would have been, if able) then.

The current situation is that $ENV is read by all sh startups,
interactive or not, unless the posix option is set - either by
"-o posix" or by having POSIXLY_CORRECT in the environment.

I also know more about the POSIX standards process now than I did
then, and am a bit less disenchanted with that group than some
others around - however from that I have also discovered that a
system is supposed to document what is needed for it to be POSIX
conformant, and that it is not simply to be assumed that any
random system will offer a posix conformant environment by
default.

That is, if you want posix conformance, you need to read the
system doc, and do whatever it says is required to obtain that.

In this case, for at least this issue, that is to include
POSIXLY_CORRECT in your environment (which can be done in
.profile).   That will not make the NetBSD shell conform
to POSIX, but it will in this particular case.

I was idly wondering whether there was anything else I could
do which would improve things, but I have concluded that there
is nothing which would not break backward compatibility that
would be any simpler than this.

There is no point keeping this PR open any longer, there does
not seem to be much chance of any more progress than that which
has already been made.

kre

ps: on the other hand, the companion PR (42829) which requests
parameter expansion on $ENV is likely to see some action soon.
I see no particularly good reason that one should not be handled.
The NetBSD shell finally has the internal mechanisms to allow
that to be done without a lot (more) messing around.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.