bug-bash
[Top][All Lists]
Advanced

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

Re: GROUPS


From: Robert Elz
Subject: Re: GROUPS
Date: Tue, 10 Aug 2021 23:39:47 +0700

    Date:        Tue, 10 Aug 2021 10:22:29 -0400
    From:        Chet Ramey <chet.ramey@case.edu>
    Message-ID:  <731876fc-39c0-4388-0c9e-bf560921bb8c@case.edu>

  | In this case, you are using features outside what POSIX specifies.

Using a variable name that's outside what POSIX specifies is hardly
using a feature that's outside POSIX - if it were then there would be
no safe non-trivial scripts, since any variable name might be made magic
by some shell or other (and no, there's nothing special about all upper
case variable names).    Only those defined by POSIX to have some special
meaning mean something, and even those can be re-used for another purpose
as long as one doesn't expect the special behaviour to function correctly.

That is, it is perfectly OK to write

        for IFS in 1 2 3 4 5 6
        do
                command "${IFS}"
                IFS=$(( IFS  % 3 ))
                if [ "$IFS" -eq 0 ]
                then
                        othercommand "${IFS}"
                fi
        done

as long as there's nothing in there which attempts to use
field splitting (no "read" commands, etc, no unquoted
variable expansions in arg lists, no use of $*) or that one
actually wants the varying value of IFS to actually be the
field separator.  (One can use PATH, CDPATH, PWD, OLDPWD, OPTARG,
OPTIND, HOME, PS1, ..., similarly, with similar restrictions on what is
expected to work, or can be used ... doing "cd" will set PWD and
OLDPWD, so you'd want to avoid that if using PWD or OLDPWD for some
other purpose, and "pwd" is undefined if PWD has been altered, so
you'd need to avoid that as well - similar restrictions for the others.)

I found this when I attempted to make HOSTNAME special (not in bash) in
a similar way to bash has (apparently) with GROUPS - scripts existed
that used HOSTNAME as a variable, and expected that to work ... and that
was entirely reasonable.   (Nb: this is different than HOSTNAME in bash
which is simply a var init'd to the name of the host at shell startup,
my magic var tracks changes to the system's hostname and always returns
the current hostname, ie: it executes gethostname(3) every time it is
expanded).

So, I changed things, and made almost every magic variable
lose its magicness if the script (or the environment) assigns a
value to the variable (or unsets it).   That way scripts are
free to use whatever variable names that they like (POSIX does not
forbid them from doing so).   (And if one wants a bash form of
HOSTNAME variable, one can just do HOSTNAME=${HOSTNAME} ... the
expansion happens when HOSTNAME is still magic, and gets the current
hostname, the assignemnt saves that, and turns off the magicness).

[Aside: I also added a "specialvar" built-in command, which takes
a var name as an arg (or multiple, though that turns out to be less
useful) and turns its specialness back on if it was off - and exits
0 if the var named (or all of them) are known special vars in the
shell, or 1 if not.   That way a script that wants to depend upon
the specialness of HOSTNAME can do:

    if ! specialvar HOSTNAME; then abort "Need shell with HOSTNAME"; fi

(where abort is presumed to be a function which does what is expected)
and then after that, HOSTNAME will have its magic properties (whatever
was its status previously) and everything else that simply wants it to be
a variable can simply not do this, use HOSTNAME as a variable (after giving
it a value however is desired - including inheriting it in the environemnt),
and it will work just like "x" would work as a variable.]

The exceptions to this are those very very few magic vars that need to be
able to be given values in order to work as defined (like RANDOM, to set the
seed) - that set of vars should be kept as limited as possible (and even
those lose the magic if unset, until "specialvar" returns it).

Note: there is no likely compat issue with changing this in bash, any var
defined as "assignments are ignored" isn't going to be having values assigned
to it in any rational script that depends upon its magic properties.
That is, I cannot think of any reason GROUPS in bash, or any of the others
defined similarly (except perhaps the BASH* vars) should not simply work
as vars if used that way.  I can think of even less reason for UID and EUID
to be read only.

kre

ps: of course if the script doesn't mention or use a magic variable at all,
it remains magic without need of "specialvar" but no-one knows or cares.
The one slight oddity is that if one uses a variable without assigning a
value to it, then if it happens to be one of the special ones, weird things
can happen - but that's (kind of) true of anything, any variable might appear
in the environment (not just upper case names), so it is never safe to assume
that any var not set in the script will simply turn into "" if expanded.
Uninit'd variables are as much a potential bug in scripts as they are in C
(or other) programs.





reply via email to

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