NetBSD-Bugs archive

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

Re: standards/42828: Almquist shell always evaluates the contents of ${ENV} even if non-interactive

The following reply was made to PR standards/42828; it has been noted by GNATS.

From: "Greg A. Woods" <>
To: Robert Elz <kre%munnari.OZ.AU@localhost>
Cc: Richard Hansen <>,
        NetBSD GNATS <>,
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

 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@localhost> 
 Subject: Re: standards/42828: Almquist shell always evaluates the contents =
 of ${ENV} even if non-interactive
 > 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...
        [ -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
 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 
 #for func in $(ls "$FPATH"); do
 #      autoload $func
 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@localhost>) 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]
        #       $=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!
 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!
 if [ -z "$LOGNAME" ] ; then
        # some systems won't allow this...
        export LOGNAME=3D${HOME##*/}
 # for emacs timeclock.el
 if [ ! -f ~/.timelog ] ; then
        touch ~/.timelog
 # note this depends on and requires the "cd" at the end of ~/.profile
 export PWD=3D$HOME
 export OLDPWD=3D$HOME
                                                Greg A. Woods
                                                Planix, Inc.
 <>       +1 416 218 0099
 Content-Type: application/pgp-signature
 Content-Transfer-Encoding: 7bit
 Version: GnuPG v1.4.9 (NetBSD)

Home | Main Index | Thread Index | Old Index